mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-16 12:14:14 +02:00
slate-hyperscript tests and decorations (#1777)
* initial simple decorations (mark-like), many tests added * allow decorators to be set by focus, anchor tags - add tests * handle one more edge case with decorations in hyperscript * apply prettier cleanup * apply linting rules * update changelog * ensure always normalize decoration ranges * reapply prettier after latest adjustments * update in response to review * drop unnecessarily committed add'l file * remove the need for explicit anchor, focus prop on decoration tags
This commit is contained in:
committed by
Ian Storm Taylor
parent
184722bdbf
commit
0dc2a4feab
125
packages/slate-hyperscript/test/custom/custom-tags.js
Normal file
125
packages/slate-hyperscript/test/custom/custom-tags.js
Normal file
@@ -0,0 +1,125 @@
|
||||
/** @jsx h */
|
||||
|
||||
import { createHyperscript } from '../..'
|
||||
|
||||
const h = createHyperscript({
|
||||
blocks: {
|
||||
paragraph: 'paragraph',
|
||||
image: {
|
||||
type: 'image',
|
||||
isVoid: true,
|
||||
},
|
||||
},
|
||||
inlines: {
|
||||
link: 'link',
|
||||
},
|
||||
marks: {
|
||||
b: 'bold',
|
||||
},
|
||||
})
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>
|
||||
A string of <b>bold</b> in a <link src="http://slatejs.org">Slate</link>{' '}
|
||||
editor!
|
||||
</paragraph>
|
||||
<image src="https://..." />
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'A string of ',
|
||||
marks: [],
|
||||
},
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'bold',
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'bold',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'leaf',
|
||||
text: ' in a ',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'inline',
|
||||
type: 'link',
|
||||
isVoid: false,
|
||||
data: {
|
||||
src: 'http://slatejs.org',
|
||||
},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'Slate',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: ' editor!',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
type: 'image',
|
||||
isVoid: true,
|
||||
data: {
|
||||
src: 'https://...',
|
||||
},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: '',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
87
packages/slate-hyperscript/test/decorations/across-blocks.js
Normal file
87
packages/slate-hyperscript/test/decorations/across-blocks.js
Normal file
@@ -0,0 +1,87 @@
|
||||
/** @jsx h */
|
||||
|
||||
import { createHyperscript } from '../..'
|
||||
|
||||
const h = createHyperscript({
|
||||
blocks: {
|
||||
paragraph: 'paragraph',
|
||||
},
|
||||
decorators: {
|
||||
highlight: 'highlight',
|
||||
},
|
||||
})
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>
|
||||
This is one <highlight key="a" />block.
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
This is block<highlight key="a" /> two.
|
||||
</paragraph>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is one block.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is block two.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectDecorations = [
|
||||
{
|
||||
anchorOffset: 12,
|
||||
focusOffset: 13,
|
||||
anchorKey: input.document.nodes.get(0).getFirstText().key,
|
||||
focusKey: input.document.nodes.get(1).getFirstText().key,
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'highlight',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
89
packages/slate-hyperscript/test/decorations/across-marks.js
Normal file
89
packages/slate-hyperscript/test/decorations/across-marks.js
Normal file
@@ -0,0 +1,89 @@
|
||||
/** @jsx h */
|
||||
|
||||
import { createHyperscript } from '../..'
|
||||
|
||||
const h = createHyperscript({
|
||||
blocks: {
|
||||
paragraph: 'paragraph',
|
||||
},
|
||||
marks: {
|
||||
b: 'bold',
|
||||
},
|
||||
decorators: {
|
||||
highlight: 'highlight',
|
||||
},
|
||||
})
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<block type="paragraph">
|
||||
This is a{' '}
|
||||
<highlight>
|
||||
paragraph <b>with</b>
|
||||
</highlight>{' '}
|
||||
a cursor position <cursor />(closed selection).
|
||||
</block>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is a paragraph ',
|
||||
marks: [],
|
||||
},
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'with',
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'bold',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'leaf',
|
||||
text: ' a cursor position (closed selection).',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectDecorations = [
|
||||
{
|
||||
anchorOffset: 10,
|
||||
focusOffset: 24,
|
||||
anchorKey: input.texts.get(0).key,
|
||||
focusKey: input.texts.get(0).key,
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'highlight',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
104
packages/slate-hyperscript/test/decorations/deep-anchors.js
Normal file
104
packages/slate-hyperscript/test/decorations/deep-anchors.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/** @jsx h */
|
||||
|
||||
import { createHyperscript } from '../..'
|
||||
|
||||
const h = createHyperscript({
|
||||
blocks: {
|
||||
ul: 'ul',
|
||||
li: 'li',
|
||||
},
|
||||
decorators: {
|
||||
highlight: 'highlight',
|
||||
},
|
||||
})
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<ul>
|
||||
<li>
|
||||
Item <highlight key="a" />one.
|
||||
</li>
|
||||
<li>
|
||||
Item<highlight key="a" /> two.
|
||||
</li>
|
||||
</ul>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'ul',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'li',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'Item one.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
type: 'li',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'Item two.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectDecorations = [
|
||||
{
|
||||
anchorOffset: 5,
|
||||
focusOffset: 4,
|
||||
anchorKey: input.document
|
||||
.filterDescendants(n => n.type === 'li')
|
||||
.get(0)
|
||||
.getFirstText().key,
|
||||
focusKey: input.document
|
||||
.filterDescendants(n => n.type === 'li')
|
||||
.get(1)
|
||||
.getFirstText().key,
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'highlight',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
@@ -0,0 +1,89 @@
|
||||
/** @jsx h */
|
||||
|
||||
import { createHyperscript } from '../..'
|
||||
|
||||
const h = createHyperscript({
|
||||
blocks: {
|
||||
paragraph: 'paragraph',
|
||||
},
|
||||
marks: {
|
||||
b: 'bold',
|
||||
},
|
||||
decorators: {
|
||||
highlight: 'highlight',
|
||||
},
|
||||
})
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<block type="paragraph">
|
||||
This is a <highlight key="c" />paragraph{' '}
|
||||
<b>
|
||||
with<highlight key="c" />
|
||||
</b>{' '}
|
||||
a highlight.
|
||||
</block>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is a paragraph ',
|
||||
marks: [],
|
||||
},
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'with',
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'bold',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'leaf',
|
||||
text: ' a highlight.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectDecorations = [
|
||||
{
|
||||
anchorOffset: 10,
|
||||
focusOffset: 24,
|
||||
anchorKey: input.texts.get(0).key,
|
||||
focusKey: input.texts.get(0).key,
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'highlight',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
81
packages/slate-hyperscript/test/decorations/multiple.js
Normal file
81
packages/slate-hyperscript/test/decorations/multiple.js
Normal file
@@ -0,0 +1,81 @@
|
||||
/** @jsx h */
|
||||
|
||||
import { createHyperscript } from '../..'
|
||||
|
||||
const h = createHyperscript({
|
||||
blocks: {
|
||||
paragraph: 'paragraph',
|
||||
},
|
||||
decorators: {
|
||||
highlight: 'highlight',
|
||||
lowlight: 'lowlight',
|
||||
},
|
||||
})
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<block type="paragraph">
|
||||
This is a <highlight>paragraph with</highlight> two{' '}
|
||||
<lowlight>decorations</lowlight>.
|
||||
</block>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is a paragraph with two decorations.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectDecorations = [
|
||||
{
|
||||
anchorOffset: 10,
|
||||
focusOffset: 24,
|
||||
anchorKey: input.texts.get(0).key,
|
||||
focusKey: input.texts.get(0).key,
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'highlight',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
anchorOffset: 29,
|
||||
focusOffset: 40,
|
||||
anchorKey: input.texts.get(0).key,
|
||||
focusKey: input.texts.get(0).key,
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'lowlight',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
100
packages/slate-hyperscript/test/decorations/nested.js
Normal file
100
packages/slate-hyperscript/test/decorations/nested.js
Normal file
@@ -0,0 +1,100 @@
|
||||
/** @jsx h */
|
||||
|
||||
import { createHyperscript } from '../..'
|
||||
|
||||
const h = createHyperscript({
|
||||
blocks: {
|
||||
paragraph: 'paragraph',
|
||||
},
|
||||
decorators: {
|
||||
highlight: 'highlight',
|
||||
},
|
||||
})
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>
|
||||
<highlight key="a" />This is one <highlight key="b" />block.
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<highlight key="b" />This is block<highlight key="a" /> two.
|
||||
</paragraph>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is one block.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is block two.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectDecorations = [
|
||||
{
|
||||
anchorOffset: 12,
|
||||
focusOffset: 0,
|
||||
anchorKey: input.document.nodes.get(0).getFirstText().key,
|
||||
focusKey: input.document.nodes.get(1).getFirstText().key,
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'highlight',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
anchorOffset: 0,
|
||||
focusOffset: 13,
|
||||
anchorKey: input.document.nodes.get(0).getFirstText().key,
|
||||
focusKey: input.document.nodes.get(1).getFirstText().key,
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'highlight',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
100
packages/slate-hyperscript/test/decorations/overlapping.js
Normal file
100
packages/slate-hyperscript/test/decorations/overlapping.js
Normal file
@@ -0,0 +1,100 @@
|
||||
/** @jsx h */
|
||||
|
||||
import { createHyperscript } from '../..'
|
||||
|
||||
const h = createHyperscript({
|
||||
blocks: {
|
||||
paragraph: 'paragraph',
|
||||
},
|
||||
decorators: {
|
||||
highlight: 'highlight',
|
||||
},
|
||||
})
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>
|
||||
<highlight key="a" />This is one <highlight key="b" />block.
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<highlight key="a" />This is block<highlight key="b" /> two.
|
||||
</paragraph>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is one block.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is block two.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectDecorations = [
|
||||
{
|
||||
anchorOffset: 0,
|
||||
focusOffset: 0,
|
||||
anchorKey: input.document.nodes.get(0).getFirstText().key,
|
||||
focusKey: input.document.nodes.get(1).getFirstText().key,
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'highlight',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
anchorOffset: 12,
|
||||
focusOffset: 13,
|
||||
anchorKey: input.document.nodes.get(0).getFirstText().key,
|
||||
focusKey: input.document.nodes.get(1).getFirstText().key,
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'highlight',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
68
packages/slate-hyperscript/test/decorations/single.js
Normal file
68
packages/slate-hyperscript/test/decorations/single.js
Normal file
@@ -0,0 +1,68 @@
|
||||
/** @jsx h */
|
||||
|
||||
import { createHyperscript } from '../..'
|
||||
|
||||
const h = createHyperscript({
|
||||
blocks: {
|
||||
paragraph: 'paragraph',
|
||||
},
|
||||
decorators: {
|
||||
highlight: 'highlight',
|
||||
},
|
||||
})
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<block type="paragraph">
|
||||
This is a <highlight>paragraph with</highlight> a cursor position{' '}
|
||||
<cursor />(closed selection).
|
||||
</block>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text:
|
||||
'This is a paragraph with a cursor position (closed selection).',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectDecorations = [
|
||||
{
|
||||
anchorOffset: 10,
|
||||
focusOffset: 24,
|
||||
anchorKey: input.texts.get(0).key,
|
||||
focusKey: input.texts.get(0).key,
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'highlight',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
34
packages/slate-hyperscript/test/default/single-block.js
Normal file
34
packages/slate-hyperscript/test/default/single-block.js
Normal file
@@ -0,0 +1,34 @@
|
||||
/** @jsx h */
|
||||
|
||||
import h from '../..'
|
||||
|
||||
export const input = (
|
||||
<document>
|
||||
<block type="paragraph">Single block</block>
|
||||
</document>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'Single block',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
@@ -0,0 +1,112 @@
|
||||
/** @jsx h */
|
||||
|
||||
import h from '../..'
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<block type="paragraph">
|
||||
A string of <mark type="bold">bold</mark> in a{' '}
|
||||
<inline type="link" data={{ src: 'http://slatejs.org' }}>
|
||||
Slate
|
||||
</inline>{' '}
|
||||
editor!
|
||||
</block>
|
||||
<block type="image" data={{ src: 'https://...' }} isVoid />
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'A string of ',
|
||||
marks: [],
|
||||
},
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'bold',
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'bold',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'leaf',
|
||||
text: ' in a ',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'inline',
|
||||
type: 'link',
|
||||
isVoid: false,
|
||||
data: {
|
||||
src: 'http://slatejs.org',
|
||||
},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'Slate',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: ' editor!',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
type: 'image',
|
||||
isVoid: true,
|
||||
data: {
|
||||
src: 'https://...',
|
||||
},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: '',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
@@ -1,75 +1,128 @@
|
||||
/** @jsx h */
|
||||
/**
|
||||
* Dependencies.
|
||||
*/
|
||||
|
||||
import h from '../'
|
||||
import assert from 'assert'
|
||||
import { Value, Document, Block, Text } from 'slate'
|
||||
import fs from 'fs'
|
||||
import { Value } from 'slate'
|
||||
import { basename, extname, resolve } from 'path'
|
||||
|
||||
/**
|
||||
* Tests.
|
||||
*/
|
||||
|
||||
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')],
|
||||
}),
|
||||
],
|
||||
})
|
||||
describe('default settings', () => {
|
||||
const dir = resolve(__dirname, './default')
|
||||
const tests = fs
|
||||
.readdirSync(dir)
|
||||
.filter(t => t[0] != '.')
|
||||
.map(t => basename(t, extname(t)))
|
||||
|
||||
assert.deepEqual(output.toJSON(), expected.toJSON())
|
||||
for (const test of tests) {
|
||||
it(test, async () => {
|
||||
const module = require(resolve(dir, test))
|
||||
const { input, output } = module
|
||||
|
||||
const actual = input.toJSON()
|
||||
const expected = Value.isValue(output) ? output.toJSON() : output
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
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')],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
})
|
||||
describe('custom tags', () => {
|
||||
const dir = resolve(__dirname, './custom')
|
||||
const tests = fs
|
||||
.readdirSync(dir)
|
||||
.filter(t => t[0] != '.')
|
||||
.map(t => basename(t, extname(t)))
|
||||
|
||||
assert.deepEqual(output.toJSON(), expected.toJSON())
|
||||
for (const test of tests) {
|
||||
it(test, async () => {
|
||||
const module = require(resolve(dir, test))
|
||||
const { input, output } = module
|
||||
|
||||
const actual = input.toJSON()
|
||||
const expected = Value.isValue(output) ? output.toJSON() : output
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
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 }
|
||||
)
|
||||
describe('selections', () => {
|
||||
const dir = resolve(__dirname, './selections')
|
||||
const tests = fs
|
||||
.readdirSync(dir)
|
||||
.filter(t => t[0] != '.')
|
||||
.map(t => basename(t, extname(t)))
|
||||
|
||||
assert.deepEqual(output.toJSON(), expected.toJSON())
|
||||
for (const test of tests) {
|
||||
it(test, async () => {
|
||||
const module = require(resolve(dir, test))
|
||||
const { input, output, expectSelection } = module
|
||||
|
||||
// ensure deserialization was okay
|
||||
const actual = input.toJSON()
|
||||
const expected = Value.isValue(output) ? output.toJSON() : output
|
||||
assert.deepEqual(actual, expected)
|
||||
|
||||
// ensure expected properties of selection match
|
||||
Object.keys(expectSelection).forEach(prop => {
|
||||
assert.equal(input.selection[prop], expectSelection[prop])
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
describe('decorations', () => {
|
||||
const dir = resolve(__dirname, './decorations')
|
||||
const tests = fs
|
||||
.readdirSync(dir)
|
||||
.filter(t => t[0] != '.')
|
||||
.map(t => basename(t, extname(t)))
|
||||
|
||||
for (const test of tests) {
|
||||
it(test, async () => {
|
||||
const module = require(resolve(dir, test))
|
||||
const { input, output, expectDecorations } = module
|
||||
|
||||
// ensure deserialization was okay
|
||||
const actual = input.toJSON()
|
||||
const expected = Value.isValue(output) ? output.toJSON() : output
|
||||
assert.deepEqual(actual, expected)
|
||||
|
||||
// ensure expected properties of decorations match
|
||||
// note: they are expected to match order in test result
|
||||
expectDecorations.forEach((decoration, i) => {
|
||||
Object.keys(decoration).forEach(prop => {
|
||||
assert.deepEqual(
|
||||
decoration[prop],
|
||||
input.decorations.toJS()[i][prop],
|
||||
`decoration ${i} had incorrect prop: ${prop}`
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
describe('normalize', () => {
|
||||
const dir = resolve(__dirname, './normalize')
|
||||
const tests = fs
|
||||
.readdirSync(dir)
|
||||
.filter(t => t[0] != '.')
|
||||
.map(t => basename(t, extname(t)))
|
||||
|
||||
for (const test of tests) {
|
||||
it(test, async () => {
|
||||
const module = require(resolve(dir, test))
|
||||
const { input, output } = module
|
||||
|
||||
const actual = Value.isValue(input) ? input.toJSON() : input
|
||||
const expected = Value.isValue(output) ? output.toJSON() : output
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
24
packages/slate-hyperscript/test/normalize/on-by-default.js
Normal file
24
packages/slate-hyperscript/test/normalize/on-by-default.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/** @jsx h */
|
||||
|
||||
import h from '../..'
|
||||
import { Value, Document, Block, Text } from 'slate'
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<block type="paragraph">Valid block</block>
|
||||
<text>Invalid text</text>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = Value.create({
|
||||
document: Document.create({
|
||||
nodes: [
|
||||
Block.create({
|
||||
type: 'paragraph',
|
||||
nodes: [Text.create('Valid block')],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
})
|
@@ -0,0 +1,28 @@
|
||||
/** @jsx h */
|
||||
|
||||
import h from '../..'
|
||||
import { Value, Document, Block, Text } from 'slate'
|
||||
|
||||
export const input = (
|
||||
<value normalize={false}>
|
||||
<document>
|
||||
<block type="paragraph">Valid block</block>
|
||||
<text>Invalid text</text>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = Value.fromJSON(
|
||||
{
|
||||
document: Document.create({
|
||||
nodes: [
|
||||
Block.create({
|
||||
type: 'paragraph',
|
||||
nodes: [Text.create('Valid block')],
|
||||
}),
|
||||
Text.create('Invalid text'),
|
||||
],
|
||||
}),
|
||||
},
|
||||
{ normalize: false }
|
||||
)
|
@@ -0,0 +1,50 @@
|
||||
/** @jsx h */
|
||||
|
||||
import h from '../..'
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<block type="paragraph">
|
||||
This is a paragraph with a cursor position <cursor />(closed selection).
|
||||
</block>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text:
|
||||
'This is a paragraph with a cursor position (closed selection).',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectSelection = {
|
||||
isCollapsed: true,
|
||||
anchorOffset: 43,
|
||||
focusOffset: 43,
|
||||
anchorKey: input.texts.get(0).key,
|
||||
focusKey: input.texts.get(0).key,
|
||||
}
|
97
packages/slate-hyperscript/test/selections/cursor-in-mark.js
Normal file
97
packages/slate-hyperscript/test/selections/cursor-in-mark.js
Normal file
@@ -0,0 +1,97 @@
|
||||
/** @jsx h */
|
||||
|
||||
import { createHyperscript } from '../..'
|
||||
|
||||
const h = createHyperscript({
|
||||
blocks: {
|
||||
paragraph: 'paragraph',
|
||||
},
|
||||
marks: {
|
||||
b: 'bold',
|
||||
},
|
||||
})
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>First paragraph</paragraph>
|
||||
<paragraph>
|
||||
This is a paragraph with a cursor{' '}
|
||||
<b>
|
||||
positi<cursor />on
|
||||
</b>{' '}
|
||||
within a mark.
|
||||
</paragraph>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'First paragraph',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is a paragraph with a cursor ',
|
||||
marks: [],
|
||||
},
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'position',
|
||||
marks: [
|
||||
{
|
||||
object: 'mark',
|
||||
type: 'bold',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'leaf',
|
||||
text: ' within a mark.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectSelection = {
|
||||
isCollapsed: true,
|
||||
anchorOffset: 40,
|
||||
focusOffset: 40,
|
||||
anchorKey: input.texts.get(0).key,
|
||||
focusKey: input.texts.get(0).key,
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
/** @jsx h */
|
||||
|
||||
import h from '../..'
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<block type="paragraph">
|
||||
This is one <anchor />block.
|
||||
</block>
|
||||
<block type="paragraph">
|
||||
This is block<focus /> two.
|
||||
</block>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is one block.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is block two.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectSelection = {
|
||||
isCollapsed: false,
|
||||
anchorOffset: 12,
|
||||
focusOffset: 13,
|
||||
anchorKey: input.texts.get(0).key,
|
||||
focusKey: input.texts.get(1).key,
|
||||
}
|
49
packages/slate-hyperscript/test/selections/range-in-block.js
Normal file
49
packages/slate-hyperscript/test/selections/range-in-block.js
Normal file
@@ -0,0 +1,49 @@
|
||||
/** @jsx h */
|
||||
|
||||
import h from '../..'
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<block type="paragraph">
|
||||
This is a <anchor />paragraph<focus /> with an open selection.
|
||||
</block>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text: 'This is a paragraph with an open selection.',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectSelection = {
|
||||
isCollapsed: false,
|
||||
anchorOffset: 10,
|
||||
focusOffset: 19,
|
||||
anchorKey: input.texts.get(0).key,
|
||||
focusKey: input.texts.get(0).key,
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
/** @jsx h */
|
||||
|
||||
import h from '../..'
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<block type="paragraph">
|
||||
<text>
|
||||
This is{' '}
|
||||
<text key="100">
|
||||
a paragraph with a cursor position (closed selection).
|
||||
</text>
|
||||
</text>
|
||||
</block>
|
||||
</document>
|
||||
<selection
|
||||
anchorKey="100"
|
||||
anchorOffset={30}
|
||||
focusKey="100"
|
||||
focusOffset={30}
|
||||
/>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = {
|
||||
object: 'value',
|
||||
document: {
|
||||
object: 'document',
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
text:
|
||||
'This is a paragraph with a cursor position (closed selection).',
|
||||
marks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const expectSelection = {
|
||||
isCollapsed: true,
|
||||
anchorOffset: 30,
|
||||
focusOffset: 30,
|
||||
anchorKey: input.texts.get(0).key,
|
||||
focusKey: input.texts.get(0).key,
|
||||
}
|
Reference in New Issue
Block a user