1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-13 18:53:59 +02:00

slate-hyperscript: Fix extra empty text at the end of children (#1379)

* Add failing test

* Don't push extra text node at the end of children

* Fix keys in tests

* Add option `normalize` to <value>

* Write Changelog

* Changelog on correct  package

* Fix preserve keys test

* Fix tests (which make more sense now)

* Mark failing test as skipped

* Account for skip option

* Lint and fix changelog version

* Use Unreleased instead of version

* Lint markdown
This commit is contained in:
Nicolas Gaborit
2018-04-27 22:16:11 +02:00
committed by Ian Storm Taylor
parent a943eada85
commit 099c6ada72
19 changed files with 131 additions and 27 deletions

View File

@@ -4,6 +4,14 @@ This document maintains a list of changes to the `slate-hyperscript` package wit
--- ---
### Unreleased
* Accept `normalize` option for `<value>` tag. This allows to write
invalid values, on purpose, for example to test validation logic.
* Fixed a bug that added extra text nodes. You would not encounter these if you always wrapped things in a `<value>` tag, that was running a normalization.
---
### `0.5.0` — January 4, 2018 ### `0.5.0` — January 4, 2018
###### BREAKING ###### BREAKING

View File

@@ -64,7 +64,7 @@ const CREATORS = {
}, },
value(tagName, attributes, children) { value(tagName, attributes, children) {
const { data } = attributes const { data, normalize = true } = attributes
const document = children.find(Document.isDocument) const document = children.find(Document.isDocument)
let selection = children.find(Range.isRange) || Range.create() let selection = children.find(Range.isRange) || Range.create()
const props = {} const props = {}
@@ -103,7 +103,7 @@ const CREATORS = {
selection = selection.merge(props).normalize(document) selection = selection.merge(props).normalize(document)
} }
const value = Value.create({ data, document, selection }) const value = Value.fromJSON({ data, document, selection }, { normalize })
return value return value
}, },
@@ -176,14 +176,15 @@ function createChildren(children, options = {}) {
node = next node = next
} }
children.forEach(child => { children.forEach((child, index) => {
const isLast = index === children.length - 1
// If the child is a non-text node, push the current node and the new child // If the child is a non-text node, push the current node and the new child
// onto the array, then creating a new node for future selection tracking. // onto the array, then creating a new node for future selection tracking.
if (Node.isNode(child) && !Text.isText(child)) { if (Node.isNode(child) && !Text.isText(child)) {
if (node.text.length || node.__anchor != null || node.__focus != null) if (node.text.length || node.__anchor != null || node.__focus != null)
array.push(node) array.push(node)
array.push(child) array.push(child)
node = Text.create() node = isLast ? null : Text.create()
length = 0 length = 0
} }
@@ -223,7 +224,9 @@ function createChildren(children, options = {}) {
}) })
// Make sure the most recent node is added. // Make sure the most recent node is added.
array.push(node) if (node != null) {
array.push(node)
}
return array return array
} }

View File

@@ -0,0 +1,75 @@
/** @jsx h */
import h from '../'
import assert from 'assert'
import { Value, Document, Block, Text } from 'slate'
describe('slate-hyperscript', () => {
it('should create a document with a single block', () => {
const output = (
<document>
<block type="paragraph">Single block</block>
</document>
)
const expected = Document.create({
nodes: [
Block.create({
type: 'paragraph',
nodes: [Text.create('Single block')],
}),
],
})
assert.deepEqual(output.toJSON(), expected.toJSON())
})
it('should normalize a value by default', () => {
const output = (
<value>
<document>
<block type="paragraph">Valid block</block>
<text>Invalid text</text>
</document>
</value>
)
const expected = Value.create({
document: Document.create({
nodes: [
Block.create({
type: 'paragraph',
nodes: [Text.create('Valid block')],
}),
],
}),
})
assert.deepEqual(output.toJSON(), expected.toJSON())
})
it('should not normalize a value, given the option', () => {
const output = (
<value normalize={false}>
<document>
<block type="paragraph">Valid block</block>
<text>Invalid text</text>
</document>
</value>
)
const expected = Value.fromJSON(
{
document: Document.create({
nodes: [
Block.create({
type: 'paragraph',
nodes: [Text.create('Valid block')],
}),
Text.create('Invalid text'),
],
}),
},
{ normalize: false }
)
assert.deepEqual(output.toJSON(), expected.toJSON())
})
})

View File

@@ -22,14 +22,13 @@ export const input = (
</value> </value>
) )
// TODO: this output selection should be at the end of the block
export const output = ( export const output = (
<value> <value>
<document> <document>
<paragraph>wordone</paragraph> <paragraph>wordone</paragraph>
<quote>two</quote> <quote>two</quote>
<quote> <quote>
<cursor />three three<cursor />
</quote> </quote>
</document> </document>
</value> </value>

View File

@@ -24,7 +24,7 @@ export const output = (
<value> <value>
<document> <document>
<paragraph> <paragraph>
word<cursor />fragment wordfragment<cursor />
</paragraph> </paragraph>
</document> </document>
</value> </value>

View File

@@ -27,7 +27,7 @@ export const output = (
<document> <document>
<paragraph> <paragraph>
<link>word</link> <link>word</link>
<cursor />fragment fragment<cursor />
</paragraph> </paragraph>
</document> </document>
</value> </value>

View File

@@ -26,7 +26,7 @@ export const output = (
<document> <document>
<paragraph>woone</paragraph> <paragraph>woone</paragraph>
<quote> <quote>
<cursor />tword two<cursor />rd
</quote> </quote>
</document> </document>
</value> </value>

View File

@@ -29,7 +29,7 @@ export const output = (
<paragraph>woone</paragraph> <paragraph>woone</paragraph>
<quote> <quote>
<quote> <quote>
<cursor />tword two<cursor />rd
</quote> </quote>
</quote> </quote>
</document> </document>

View File

@@ -24,7 +24,7 @@ export const output = (
<value> <value>
<document> <document>
<paragraph> <paragraph>
wo<cursor />fragmentrd wofragment<cursor />rd
</paragraph> </paragraph>
</document> </document>
</value> </value>

View File

@@ -27,7 +27,8 @@ export const output = (
<document> <document>
<paragraph> <paragraph>
<link>wo</link> <link>wo</link>
<cursor />fragment<link>rd</link> fragment<cursor />
<link>rd</link>
</paragraph> </paragraph>
</document> </document>
</value> </value>

View File

@@ -32,7 +32,7 @@ export const output = (
<paragraph>woone</paragraph> <paragraph>woone</paragraph>
<quote> <quote>
<quote> <quote>
<cursor />tword two<cursor />rd
</quote> </quote>
</quote> </quote>
</quote> </quote>

View File

@@ -28,7 +28,7 @@ export const output = (
<paragraph>one</paragraph> <paragraph>one</paragraph>
<quote>two</quote> <quote>two</quote>
<quote> <quote>
<cursor />threeword three<cursor />word
</quote> </quote>
</document> </document>
</value> </value>

View File

@@ -24,7 +24,7 @@ export const output = (
<value> <value>
<document> <document>
<paragraph> <paragraph>
<cursor />fragmentword fragment<cursor />word
</paragraph> </paragraph>
</document> </document>
</value> </value>

View File

@@ -26,10 +26,26 @@ export const output = (
<value> <value>
<document> <document>
<paragraph> <paragraph>
fragment<link> fragment<cursor />
<cursor />word <link>word</link>
</link>
</paragraph> </paragraph>
</document> </document>
</value> </value>
) )
// The result has an invalid selection for now:
//
// "selection": {
// "anchorOffset": 8
// "anchorPath": [
// 0
// 1
// 0
// ]
// "focusOffset": 8
// "focusPath": [
// 0
// 1
// 0
// ]
export const skip = true

View File

@@ -26,7 +26,7 @@ export const output = (
<document> <document>
<paragraph>word</paragraph> <paragraph>word</paragraph>
<paragraph> <paragraph>
<cursor />fragmentanother fragment<cursor />another
</paragraph> </paragraph>
</document> </document>
</value> </value>

View File

@@ -27,7 +27,7 @@ export const output = (
<value> <value>
<document> <document>
<paragraph> <paragraph>
wo<cursor />fragmentother wofragment<cursor />other
</paragraph> </paragraph>
</document> </document>
</value> </value>

View File

@@ -27,10 +27,12 @@ describe('changes', async () => {
.map(t => basename(t, extname(t))) .map(t => basename(t, extname(t)))
for (const test of tests) { for (const test of tests) {
it(test, async () => { const module = require(resolve(testDir, test))
const module = require(resolve(testDir, test)) const { input, output, skip } = module
const { input, output } = module const fn = module.default
const fn = module.default const t = skip ? it.skip : it
t(test, async () => {
const change = input.change() const change = input.change()
fn(change) fn(change)
const opts = { preserveSelection: true, preserveData: true } const opts = { preserveSelection: true, preserveData: true }

View File

@@ -14,7 +14,7 @@ export const output = {
object: 'value', object: 'value',
document: { document: {
object: 'document', object: 'document',
key: '4', key: '3',
data: {}, data: {},
nodes: [ nodes: [
{ {

View File

@@ -14,7 +14,7 @@ export const output = {
object: 'value', object: 'value',
document: { document: {
object: 'document', object: 'document',
key: '4', key: '3',
data: {}, data: {},
nodes: [ nodes: [
{ {