1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-03-06 05:49:47 +01:00

a handful of performance improvements (#705)

* update large example

* pass block down to <Text> for performance, closes #700

* add get-ranges benchmark

* optimize getRanges(), closes #699

* add serialization benchmarks

* optimize Raw.deserializeRanges() by computing marks once, closes #701

* change .merge calls to .set for performance

* change updateDescendant() to use getAncestors() for memoization

* change getPath() to use getAncestors() for memoization

* switch getTexts() and friends to use arrays while iterating

* rename split-block benchmark

* update benchmark compare script
This commit is contained in:
Ian Storm Taylor 2017-04-02 14:57:36 -07:00 committed by GitHub
parent 8687fac1a2
commit 059ee96db8
30 changed files with 3071 additions and 147 deletions

View File

@ -22,6 +22,8 @@ baseline.forEach((suite, i) => {
suite.benchmarks.forEach((base, j) => { suite.benchmarks.forEach((base, j) => {
const comp = comparison[i].benchmarks[j] const comp = comparison[i].benchmarks[j]
if (!comp) return
const b = base.iterations / base.elapsed * 100 const b = base.iterations / base.elapsed * 100
const c = comp.iterations / comp.elapsed * 100 const c = comp.iterations / comp.elapsed * 100
const threshold = b * THRESHOLD const threshold = b * THRESHOLD

View File

@ -0,0 +1,17 @@
import { __clear } from '../../../../lib/utils/memoize'
export default function ({ state, text }) {
state.document.getPath(text.key)
}
export function before(state) {
const text = state.document.getLastText()
__clear()
return { state, text }
}
export function after() {
__clear()
}

View File

@ -0,0 +1,17 @@
import { __clear } from '../../../../lib/utils/memoize'
export default function (text) {
text.getRanges()
}
export function before(state) {
const text = state.document.getFirstText()
__clear()
return text
}
export function after() {
__clear()
}

View File

@ -0,0 +1,19 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'

View File

@ -0,0 +1,20 @@
import { __clear } from '../../../../lib/utils/memoize'
export default function ({ state, next }) {
state.document.updateDescendant(next)
}
export function before(state) {
const texts = state.document.getTexts()
const { size } = texts
const text = texts.get(Math.round(size / 2))
const next = text.insertText(0, 'some text')
__clear()
return { state, next }
}
export function after() {
__clear()
}

View File

@ -0,0 +1,683 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
key: _cursor_
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'

View File

@ -0,0 +1,10 @@
import { Raw } from '../../../..'
export default function (json) {
Raw.deserialize(json, { normalize: false })
}
export function before(state) {
return Raw.serialize(state)
}

View File

@ -0,0 +1,683 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
key: _cursor_
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'

View File

@ -0,0 +1,6 @@
import { Raw } from '../../../..'
export default function (state) {
Raw.serialize(state)
}

View File

@ -0,0 +1,683 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
key: _cursor_
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'

View File

@ -0,0 +1,683 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
key: _cursor_
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'This is editable '
- text: 'rich'
marks:
- type: bold
- text: ' text, '
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'much'
marks:
- type: italic
- text: ' better than a '
- text: '<textarea>'
marks:
- type: code
- text: '!'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: 'Since it''s rich text, you can do things like turn a selection of text '
- text: 'bold'
marks:
- type: bold
- text: ', or add a semantically rendered block quote in the middle of the page,
like this:'
- kind: block
type: block-quote
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'A wise quote.'
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
text: 'Try it out for yourself!'

View File

@ -17,6 +17,23 @@ const schema = {
nodes: { nodes: {
'heading': props => <h1 {...props.attributes}>{props.children}</h1>, 'heading': props => <h1 {...props.attributes}>{props.children}</h1>,
'paragraph': props => <p {...props.attributes} style={{ marginBottom: 20 }}>{props.children}</p>, 'paragraph': props => <p {...props.attributes} style={{ marginBottom: 20 }}>{props.children}</p>,
},
marks: {
bold: {
fontWeight: 'bold'
},
code: {
fontFamily: 'monospace',
backgroundColor: '#eee',
padding: '3px',
borderRadius: '4px'
},
italic: {
fontStyle: 'italic'
},
underlined: {
textDecoration: 'underline'
}
} }
} }
@ -55,7 +72,7 @@ class LargeDocument extends React.Component {
constructor() { constructor() {
super() super()
console.time('deserializeLargeDocument') console.time('deserializeLargeDocument')
this.state = { state: Raw.deserialize({ nodes }, { terse: true }) } this.state = { state: Raw.deserialize({ nodes }, { normalize: false, terse: true }) }
console.timeEnd('deserializeLargeDocument') console.timeEnd('deserializeLargeDocument')
} }
@ -69,6 +86,45 @@ class LargeDocument extends React.Component {
this.setState({ state }) this.setState({ state })
} }
/**
* On key down, if it's a formatting command toggle a mark.
*
* @param {Event} e
* @param {Object} data
* @param {State} state
* @return {State}
*/
onKeyDown = (e, data, state) => {
if (!data.isMod) return
let mark
switch (data.key) {
case 'b':
mark = 'bold'
break
case 'i':
mark = 'italic'
break
case 'u':
mark = 'underlined'
break
case '`':
mark = 'code'
break
default:
return
}
state = state
.transform()
.toggleMark(mark)
.apply()
e.preventDefault()
return state
}
/** /**
* Render the editor. * Render the editor.
* *
@ -83,6 +139,7 @@ class LargeDocument extends React.Component {
spellCheck={false} spellCheck={false}
state={this.state.state} state={this.state.state}
onChange={this.onChange} onChange={this.onChange}
onKeyDown={this.onKeyDown}
/> />
) )
} }

View File

@ -726,7 +726,7 @@ class Content extends React.Component {
// If there are no ranges, the editor was blurred natively. // If there are no ranges, the editor was blurred natively.
if (!native.rangeCount) { if (!native.rangeCount) {
data.selection = selection.merge({ isFocused: false }) data.selection = selection.set('isFocused', false)
data.isNative = true data.isNative = true
} }

View File

@ -29,6 +29,7 @@ class Leaf extends React.Component {
*/ */
static propTypes = { static propTypes = {
block: React.PropTypes.object.isRequired,
editor: React.PropTypes.object.isRequired, editor: React.PropTypes.object.isRequired,
index: React.PropTypes.number.isRequired, index: React.PropTypes.number.isRequired,
marks: React.PropTypes.object.isRequired, marks: React.PropTypes.object.isRequired,
@ -129,7 +130,7 @@ class Leaf extends React.Component {
*/ */
renderText(props) { renderText(props) {
const { node, state, parent, text, index, ranges } = props const { block, node, parent, text, index, ranges } = props
// COMPAT: If the text is empty and it's the only child, we need to render a // COMPAT: If the text is empty and it's the only child, we need to render a
// <br/> to get the block to have the proper height. // <br/> to get the block to have the proper height.
@ -147,7 +148,6 @@ class Leaf extends React.Component {
// COMPAT: Browsers will collapse trailing new lines at the end of blocks, // COMPAT: Browsers will collapse trailing new lines at the end of blocks,
// so we need to add an extra trailing new lines to prevent that. // so we need to add an extra trailing new lines to prevent that.
const block = state.document.getClosestBlock(node.key)
const lastText = block.getLastText() const lastText = block.getLastText()
const lastChar = text.charAt(text.length - 1) const lastChar = text.charAt(text.length - 1)
const isLastText = node == lastText const isLastText = node == lastText

View File

@ -32,6 +32,7 @@ class Node extends React.Component {
*/ */
static propTypes = { static propTypes = {
block: React.PropTypes.object,
editor: React.PropTypes.object.isRequired, editor: React.PropTypes.object.isRequired,
node: React.PropTypes.object.isRequired, node: React.PropTypes.object.isRequired,
parent: React.PropTypes.object.isRequired, parent: React.PropTypes.object.isRequired,
@ -229,6 +230,7 @@ class Node extends React.Component {
<Node <Node
key={child.key} key={child.key}
node={child} node={child}
block={this.props.node.kind == 'block' ? this.props.node : this.props.block}
parent={this.props.node} parent={this.props.node}
editor={this.props.editor} editor={this.props.editor}
readOnly={this.props.readOnly} readOnly={this.props.readOnly}
@ -247,9 +249,7 @@ class Node extends React.Component {
renderElement = () => { renderElement = () => {
const { editor, node, parent, readOnly, state } = this.props const { editor, node, parent, readOnly, state } = this.props
const { Component } = this.state const { Component } = this.state
const children = node.nodes const children = node.nodes.map(this.renderNode).toArray()
.map(child => this.renderNode(child))
.toArray()
// Attributes that the developer must to mix into the element in their // Attributes that the developer must to mix into the element in their
// custom node renderer component. // custom node renderer component.
@ -321,12 +321,13 @@ class Node extends React.Component {
*/ */
renderLeaf = (ranges, range, index, offset) => { renderLeaf = (ranges, range, index, offset) => {
const { node, parent, schema, state, editor } = this.props const { block, node, parent, schema, state, editor } = this.props
const { text, marks } = range const { text, marks } = range
return ( return (
<Leaf <Leaf
key={`${node.key}-${index}`} key={`${node.key}-${index}`}
block={block}
editor={editor} editor={editor}
index={index} index={index}
marks={marks} marks={marks}

View File

@ -214,12 +214,23 @@ const Node = {
*/ */
getBlocks() { getBlocks() {
return this.nodes.reduce((blocks, node) => { const array = this.getBlocksAsArray()
if (node.kind != 'block') return blocks return new List(array)
return node.isLeafBlock() },
? blocks.push(node)
: blocks.concat(node.getBlocks()) /**
}, new List()) * Get the leaf block descendants of the node.
*
* @return {List<Node>}
*/
getBlocksAsArray() {
return this.nodes.reduce((array, child) => {
if (child.kind != 'block') return array
if (!child.isLeafBlock()) return array.concat(child.getBlocksAsArray())
array.push(child)
return array
}, [])
}, },
/** /**
@ -635,12 +646,29 @@ const Node = {
*/ */
getInlines() { getInlines() {
return this.nodes.reduce((inlines, node) => { const array = this.getInlinesAsArray()
if (node.kind == 'text') return inlines return new List(array)
return node.isLeafInline() },
? inlines.push(node)
: inlines.concat(node.getInlines()) /**
}, new List()) * Get the closest inline nodes for each text node in the node, as an array.
*
* @return {List<Node>}
*/
getInlinesAsArray() {
let array = []
this.nodes.forEach((child) => {
if (child.kind == 'text') return
if (child.isLeafInline()) {
array.push(child)
} else {
array = array.concat(child.getInlinesAsArray())
}
})
return array
}, },
/** /**
@ -909,27 +937,17 @@ const Node = {
*/ */
getPath(key) { getPath(key) {
key = Normalize.key(key) let child = this.assertNode(key)
const ancestors = this.getAncestors(key)
if (key == this.key) return []
const path = [] const path = []
let childKey = key
let parent
// Efficient with getParent memoization ancestors.reverse().forEach((ancestor) => {
while (parent = this.getParent(childKey)) { const index = ancestor.nodes.indexOf(child)
const index = parent.nodes.findIndex(n => n.key === childKey)
path.unshift(index) path.unshift(index)
childKey = parent.key child = ancestor
} })
if (childKey === key) {
// Did not loop once, meaning we could not find the child
throw new Error(`Could not find a descendant node with key "${key}".`)
} else {
return path return path
}
}, },
/** /**
@ -1043,11 +1061,28 @@ const Node = {
*/ */
getTexts() { getTexts() {
return this.nodes.reduce((texts, node) => { const array = this.getTextsAsArray()
return node.kind == 'text' return new List(array)
? texts.push(node) },
: texts.concat(node.getTexts())
}, new List()) /**
* Recursively get all the leaf text nodes in order of appearance, as array.
*
* @return {List<Node>}
*/
getTextsAsArray() {
let array = []
this.nodes.forEach((node) => {
if (node.kind == 'text') {
array.push(node)
} else {
array = array.concat(node.getTextsAsArray())
}
})
return array
}, },
/** /**
@ -1136,7 +1171,7 @@ const Node = {
} }
const nodes = this.nodes.insert(index, node) const nodes = this.nodes.insert(index, node)
return this.merge({ nodes }) return this.set('nodes', nodes)
}, },
/** /**
@ -1187,7 +1222,7 @@ const Node = {
if (second.kind == 'text') { if (second.kind == 'text') {
let { characters } = first let { characters } = first
characters = characters.concat(second.characters) characters = characters.concat(second.characters)
first = first.merge({ characters }) first = first.set('characters', characters)
} }
else { else {
@ -1224,7 +1259,7 @@ const Node = {
if (ret != node) nodes = nodes.set(ret.key, ret) if (ret != node) nodes = nodes.set(ret.key, ret)
}) })
return this.merge({ nodes }) return this.set('nodes', nodes)
}, },
/** /**
@ -1248,7 +1283,7 @@ const Node = {
nodes = nodes.set(index, ret) nodes = nodes.set(index, ret)
}) })
return this.merge({ nodes }) return this.set('nodes', nodes)
}, },
/** /**
@ -1258,7 +1293,8 @@ const Node = {
*/ */
regenerateKey() { regenerateKey() {
return this.merge({ key: generateKey() }) const key = generateKey()
return this.set('key', key)
}, },
/** /**
@ -1279,11 +1315,8 @@ const Node = {
const isParent = node == parent const isParent = node == parent
const nodes = parent.nodes.splice(index, 1) const nodes = parent.nodes.splice(index, 1)
parent = parent.merge({ nodes }) parent = parent.set('nodes', nodes)
node = isParent node = isParent ? parent : node.updateDescendant(parent)
? parent
: node.updateDescendant(parent)
return node return node
}, },
@ -1296,7 +1329,7 @@ const Node = {
removeNode(index) { removeNode(index) {
const nodes = this.nodes.splice(index, 1) const nodes = this.nodes.splice(index, 1)
return this.merge({ nodes }) return this.set('nodes', nodes)
}, },
/** /**
@ -1356,8 +1389,8 @@ const Node = {
const { characters } = child const { characters } = child
const oneChars = characters.take(i) const oneChars = characters.take(i)
const twoChars = characters.skip(i) const twoChars = characters.skip(i)
one = child.merge({ characters: oneChars }) one = child.set('characters', oneChars)
two = child.merge({ characters: twoChars }).regenerateKey() two = child.set('characters', twoChars).regenerateKey()
} }
else { else {
@ -1369,8 +1402,8 @@ const Node = {
oneNodes = (oneNodes.size == (nodes.size - 1) && one == nodes.last()) ? nodes : oneNodes.push(one) oneNodes = (oneNodes.size == (nodes.size - 1) && one == nodes.last()) ? nodes : oneNodes.push(one)
const twoNodes = nodes.skipUntil(n => n.key == one.key).rest().unshift(two) const twoNodes = nodes.skipUntil(n => n.key == one.key).rest().unshift(two)
one = child.merge({ nodes: oneNodes }) one = child.set('nodes', oneNodes)
two = child.merge({ nodes: twoNodes }).regenerateKey() two = child.set('nodes', twoNodes).regenerateKey()
} }
child = base.getParent(child.key) child = base.getParent(child.key)
@ -1404,8 +1437,8 @@ const Node = {
const oneNodes = nodes.take(count) const oneNodes = nodes.take(count)
const twoNodes = nodes.skip(count) const twoNodes = nodes.skip(count)
const one = node.merge({ nodes: oneNodes }) const one = node.set('nodes', oneNodes)
const two = node.merge({ nodes: twoNodes }).regenerateKey() const two = node.set('nodes', twoNodes).regenerateKey()
const nodeIndex = parent.nodes.indexOf(node) const nodeIndex = parent.nodes.indexOf(node)
@ -1425,22 +1458,19 @@ const Node = {
*/ */
updateDescendant(node) { updateDescendant(node) {
let found = false let child = this.assertDescendant(node.key)
const ancestors = this.getAncestors(node.key)
const result = this.mapDescendants((d) => { ancestors.reverse().forEach((parent) => {
if (d.key == node.key) { let { nodes } = parent
found = true const index = nodes.indexOf(child)
return node child = parent
} else { nodes = nodes.set(index, node)
return d parent = parent.set('nodes', nodes)
} node = parent
}) })
if (!found) { return node
throw new Error(`Could not update descendant node with key "${node.key}".`)
} else {
return result
}
}, },
/** /**
@ -1478,7 +1508,7 @@ const Node = {
concatChildren(nodes) { concatChildren(nodes) {
warn('The `Node.concatChildren(nodes)` method is deprecated.') warn('The `Node.concatChildren(nodes)` method is deprecated.')
nodes = this.nodes.concat(nodes) nodes = this.nodes.concat(nodes)
return this.merge({ nodes }) return this.set('nodes', nodes)
}, },
/** /**
@ -1620,6 +1650,7 @@ memoize(Node, [
'areDescendantsSorted', 'areDescendantsSorted',
'getAncestors', 'getAncestors',
'getBlocks', 'getBlocks',
'getBlocksAsArray',
'getBlocksAtRange', 'getBlocksAtRange',
'getBlocksByType', 'getBlocksByType',
'getCharacters', 'getCharacters',
@ -1645,6 +1676,7 @@ memoize(Node, [
'getFurthestAncestor', 'getFurthestAncestor',
'getFurthestOnlyChildAncestor', 'getFurthestOnlyChildAncestor',
'getInlines', 'getInlines',
'getInlinesAsArray',
'getInlinesAtRange', 'getInlinesAtRange',
'getInlinesByType', 'getInlinesByType',
'getKeys', 'getKeys',
@ -1667,6 +1699,7 @@ memoize(Node, [
'getTextAtOffset', 'getTextAtOffset',
'getTextDirection', 'getTextDirection',
'getTexts', 'getTexts',
'getTextsAsArray',
'getTextsAtRange', 'getTextsAtRange',
'hasChild', 'hasChild',
'hasDescendant', 'hasDescendant',

View File

@ -4,7 +4,7 @@ import Mark from './mark'
import Range from './range' import Range from './range'
import memoize from '../utils/memoize' import memoize from '../utils/memoize'
import generateKey from '../utils/generate-key' import generateKey from '../utils/generate-key'
import { List, Record, OrderedSet, Set } from 'immutable' import { List, Record, OrderedSet, Set, is } from 'immutable'
/** /**
* Default properties. * Default properties.
@ -118,8 +118,7 @@ class Text extends new Record(DEFAULTS) {
*/ */
get text() { get text() {
return this.characters return this.characters.reduce((string, char) => string + char.text, '')
.reduce((result, char) => result + char.text, '')
} }
/** /**
@ -137,11 +136,11 @@ class Text extends new Record(DEFAULTS) {
if (i >= index + length) return char if (i >= index + length) return char
let { marks } = char let { marks } = char
marks = marks.add(mark) marks = marks.add(mark)
char = char.merge({ marks }) char = char.set('marks', marks)
return char return char
}) })
return this.merge({ characters }) return this.set('characters', characters)
} }
/** /**
@ -223,43 +222,51 @@ class Text extends new Record(DEFAULTS) {
*/ */
getRanges(decorators = []) { getRanges(decorators = []) {
const list = new List()
const characters = this.getDecorations(decorators) const characters = this.getDecorations(decorators)
let ranges = []
// PERF: cache previous values for faster lookup.
let prevChar
let prevRange
// If there are no characters, return one empty range. // If there are no characters, return one empty range.
if (characters.size == 0) { if (characters.size == 0) {
return list.push(new Range()) ranges.push({})
} }
// Convert the now-decorated characters into ranges. // Otherwise, loop the characters and build the ranges...
const ranges = characters.reduce((memo, char, i) => { else {
characters.forEach((char, i) => {
const { marks, text } = char const { marks, text } = char
// The first one can always just be created. // The first one can always just be created.
if (i == 0) { if (i == 0) {
return memo.push(new Range({ text, marks })) prevChar = char
prevRange = { text, marks }
ranges.push(prevRange)
return
} }
// Otherwise, compare to the previous and see if a new range should be // Otherwise, compare the current and previous marks.
// created, or whether the text should be added to the previous range. const prevMarks = prevChar.marks
const previous = characters.get(i - 1) const isSame = is(marks, prevMarks)
const prevMarks = previous.marks
const added = marks.filterNot(mark => prevMarks.includes(mark))
const removed = prevMarks.filterNot(mark => marks.includes(mark))
const isSame = !added.size && !removed.size
// If the marks are the same, add the text to the previous range. // If the marks are the same, add the text to the previous range.
if (isSame) { if (isSame) {
const index = memo.size - 1 prevChar = char
let prevRange = memo.get(index) prevRange.text += text
let prevText = prevRange.get('text') return
prevRange = prevRange.set('text', prevText += text)
return memo.set(index, prevRange)
} }
// Otherwise, create a new range. // Otherwise, create a new range.
return memo.push(new Range({ text, marks })) prevChar = char
}, list) prevRange = { text, marks }
ranges.push(prevRange)
}, [])
}
// PERF: convert the ranges to immutable objects after iterating.
ranges = new List(ranges.map(object => new Range(object)))
// Return the ranges. // Return the ranges.
return ranges return ranges
@ -294,7 +301,7 @@ class Text extends new Record(DEFAULTS) {
.concat(chars) .concat(chars)
.concat(characters.slice(index)) .concat(characters.slice(index))
return this.merge({ characters }) return this.set('characters', characters)
} }
/** /**
@ -304,7 +311,8 @@ class Text extends new Record(DEFAULTS) {
*/ */
regenerateKey() { regenerateKey() {
return this.merge({ key: generateKey() }) const key = generateKey()
return this.set('key', key)
} }
/** /**
@ -322,11 +330,11 @@ class Text extends new Record(DEFAULTS) {
if (i >= index + length) return char if (i >= index + length) return char
let { marks } = char let { marks } = char
marks = marks.remove(mark) marks = marks.remove(mark)
char = char.merge({ marks }) char = char.set('marks', marks)
return char return char
}) })
return this.merge({ characters }) return this.set('characters', characters)
} }
/** /**
@ -342,7 +350,7 @@ class Text extends new Record(DEFAULTS) {
const start = index const start = index
const end = index + length const end = index + length
characters = characters.filterNot((char, i) => start <= i && i < end) characters = characters.filterNot((char, i) => start <= i && i < end)
return this.merge({ characters }) return this.set('characters', characters)
} }
/** /**
@ -363,11 +371,11 @@ class Text extends new Record(DEFAULTS) {
if (!marks.has(mark)) return char if (!marks.has(mark)) return char
marks = marks.remove(mark) marks = marks.remove(mark)
marks = marks.add(newMark) marks = marks.add(newMark)
char = char.merge({ marks }) char = char.set('marks', marks)
return char return char
}) })
return this.merge({ characters }) return this.set('characters', characters)
} }
/** /**

View File

@ -85,7 +85,7 @@ class Transform {
if (save) this.save({ merge }) if (save) this.save({ merge })
// Return the new state with the `isNative` flag set. // Return the new state with the `isNative` flag set.
return this.state.merge({ isNative: !!isNative }) return this.state.set('isNative', !!isNative)
} }
} }

View File

@ -167,7 +167,7 @@ function Plugin(options = {}) {
// Add the `isNative` flag directly, so we don't have to re-transform. // Add the `isNative` flag directly, so we don't have to re-transform.
if (isNative) { if (isNative) {
next = next.merge({ isNative }) next = next.set('isNative', isNative)
} }
// If not native, prevent default so that the DOM remains untouched. // If not native, prevent default so that the DOM remains untouched.

View File

@ -134,14 +134,16 @@ const Raw = {
deserializeRange(object, options = {}) { deserializeRange(object, options = {}) {
if (options.terse) object = Raw.untersifyRange(object) if (options.terse) object = Raw.untersifyRange(object)
const marks = Mark.createSet(object.marks.map((mark) => {
return Raw.deserializeMark(mark, options)
}))
return Character.createList(object.text return Character.createList(object.text
.split('') .split('')
.map((char) => { .map((char) => {
return Character.create({ return Character.create({
text: char, text: char,
marks: Mark.createSet(object.marks.map((mark) => { marks,
return Raw.deserializeMark(mark, options)
}))
}) })
})) }))
}, },

View File

@ -78,7 +78,7 @@ function addMark(state, operation) {
let node = document.assertPath(path) let node = document.assertPath(path)
node = node.addMark(offset, length, mark) node = node.addMark(offset, length, mark)
document = document.updateDescendant(node) document = document.updateDescendant(node)
state = state.merge({ document }) state = state.set('document', document)
return state return state
} }
@ -97,7 +97,7 @@ function insertNode(state, operation) {
const isParent = document == parent const isParent = document == parent
parent = parent.insertNode(index, node) parent = parent.insertNode(index, node)
document = isParent ? parent : document.updateDescendant(parent) document = isParent ? parent : document.updateDescendant(parent)
state = state.merge({ document }) state = state.set('document', document)
return state return state
} }
@ -127,7 +127,7 @@ function insertText(state, operation) {
selection = selection.moveFocus(text.length) selection = selection.moveFocus(text.length)
} }
state = state.merge({ document, selection }) state = state.set('document', document).set('selection', selection)
return state return state
} }
@ -171,7 +171,7 @@ function joinNode(state, operation) {
} }
} }
state = state.merge({ document, selection }) state = state.set('document', document).set('selection', selection)
return state return state
} }
@ -201,7 +201,7 @@ function moveNode(state, operation) {
target = target.insertNode(newIndex, node) target = target.insertNode(newIndex, node)
document = isTarget ? target : document.updateDescendant(target) document = isTarget ? target : document.updateDescendant(target)
state = state.merge({ document }) state = state.set('document', document)
return state return state
} }
@ -219,7 +219,7 @@ function removeMark(state, operation) {
let node = document.assertPath(path) let node = document.assertPath(path)
node = node.removeMark(offset, length, mark) node = node.removeMark(offset, length, mark)
document = document.updateDescendant(node) document = document.updateDescendant(node)
state = state.merge({ document }) state = state.set('document', document)
return state return state
} }
@ -278,7 +278,7 @@ function removeNode(state, operation) {
document = isParent ? parent : document.updateDescendant(parent) document = isParent ? parent : document.updateDescendant(parent)
// Update the document and selection. // Update the document and selection.
state = state.merge({ document, selection }) state = state.set('document', document).set('selection', selection)
return state return state
} }
@ -307,7 +307,7 @@ function removeText(state, operation) {
node = node.removeText(offset, length) node = node.removeText(offset, length)
document = document.updateDescendant(node) document = document.updateDescendant(node)
state = state.merge({ document, selection }) state = state.set('document', document).set('selection', selection)
return state return state
} }
@ -325,7 +325,7 @@ function setMark(state, operation) {
let node = document.assertPath(path) let node = document.assertPath(path)
node = node.updateMark(offset, length, mark, newMark) node = node.updateMark(offset, length, mark, newMark)
document = document.updateDescendant(node) document = document.updateDescendant(node)
state = state.merge({ document }) state = state.set('document', document)
return state return state
} }
@ -356,7 +356,7 @@ function setNode(state, operation) {
node = node.merge(properties) node = node.merge(properties)
document = node.kind === 'document' ? node : document.updateDescendant(node) document = node.kind === 'document' ? node : document.updateDescendant(node)
state = state.merge({ document }) state = state.set('document', document)
return state return state
} }
@ -388,7 +388,7 @@ function setSelection(state, operation) {
selection = selection.merge(properties) selection = selection.merge(properties)
selection = selection.normalize(document) selection = selection.normalize(document)
state = state.merge({ selection }) state = state.set('selection', selection)
return state return state
} }
@ -411,7 +411,7 @@ function splitNode(state, operation) {
// If there's no offset, it's using the `count` instead. // If there's no offset, it's using the `count` instead.
if (offset == null) { if (offset == null) {
document = document.splitNodeAfter(path, count) document = document.splitNodeAfter(path, count)
state = state.merge({ document }) state = state.set('document', document)
return state return state
} }
@ -446,7 +446,7 @@ function splitNode(state, operation) {
} }
} }
state = state.merge({ document, selection }) state = state.set('document', document).set('selection', selection)
return state return state
} }

View File

@ -28,13 +28,13 @@ Transforms.addMark = (transform, mark) => {
if (selection.marks) { if (selection.marks) {
const marks = selection.marks.add(mark) const marks = selection.marks.add(mark)
const sel = selection.merge({ marks }) const sel = selection.set('marks', marks)
transform.select(sel) transform.select(sel)
return return
} }
const marks = document.getMarksAtRange(selection).add(mark) const marks = document.getMarksAtRange(selection).add(mark)
const sel = selection.merge({ marks }) const sel = selection.set('marks', marks)
transform.select(sel) transform.select(sel)
} }
@ -341,13 +341,13 @@ Transforms.removeMark = (transform, mark) => {
if (selection.marks) { if (selection.marks) {
const marks = selection.marks.remove(mark) const marks = selection.marks.remove(mark)
const sel = selection.merge({ marks }) const sel = selection.set('marks', marks)
transform.select(sel) transform.select(sel)
return return
} }
const marks = document.getMarksAtRange(selection).remove(mark) const marks = document.getMarksAtRange(selection).remove(mark)
const sel = selection.merge({ marks }) const sel = selection.set('marks', marks)
transform.select(sel) transform.select(sel)
} }

View File

@ -1058,7 +1058,7 @@ Transforms.unwrapInlineAtRange = (transform, range, properties, options = {}) =>
Transforms.wrapBlockAtRange = (transform, range, block, options = {}) => { Transforms.wrapBlockAtRange = (transform, range, block, options = {}) => {
block = Normalize.block(block) block = Normalize.block(block)
block = block.merge({ nodes: block.nodes.clear() }) block = block.set('nodes', block.nodes.clear())
const { normalize = true } = options const { normalize = true } = options
const { state } = transform const { state } = transform
@ -1144,7 +1144,7 @@ Transforms.wrapInlineAtRange = (transform, range, inline, options = {}) => {
} }
inline = Normalize.inline(inline) inline = Normalize.inline(inline)
inline = inline.merge({ nodes: inline.nodes.clear() }) inline = inline.set('nodes', inline.nodes.clear())
const blocks = document.getBlocksAtRange(range) const blocks = document.getBlocksAtRange(range)
let startBlock = document.getClosestBlock(startKey) let startBlock = document.getClosestBlock(startKey)

View File

@ -401,7 +401,7 @@ Transforms.unwrapNodeByKey = (transform, key, options = {}) => {
Transforms.wrapInlineByKey = (transform, key, inline, options) => { Transforms.wrapInlineByKey = (transform, key, inline, options) => {
inline = Normalize.inline(inline) inline = Normalize.inline(inline)
inline = inline.merge({ nodes: inline.nodes.clear() }) inline = inline.set('nodes', inline.nodes.clear())
const { document } = transform.state const { document } = transform.state
const node = document.assertDescendant(key) const node = document.assertDescendant(key)
@ -424,7 +424,7 @@ Transforms.wrapInlineByKey = (transform, key, inline, options) => {
Transforms.wrapBlockByKey = (transform, key, block, options) => { Transforms.wrapBlockByKey = (transform, key, block, options) => {
block = Normalize.block(block) block = Normalize.block(block)
block = block.merge({ nodes: block.nodes.clear() }) block = block.set('nodes', block.nodes.clear())
const { document } = transform.state const { document } = transform.state
const node = document.assertDescendant(key) const node = document.assertDescendant(key)

View File

@ -97,7 +97,7 @@ Transforms.normalizeSelection = (transform) => {
}) })
} }
state = state.merge({ selection }) state = state.set('selection', selection)
transform.state = state transform.state = state
} }

View File

@ -33,8 +33,8 @@ Transforms.redo = (transform) => {
// Update the history. // Update the history.
state = transform.state state = transform.state
history = history.merge({ undos, redos }) history = history.set('undos', undos).set('redos', redos)
state = state.merge({ history }) state = state.set('history', history)
// Update the transform. // Update the transform.
transform.state = state transform.state = state
@ -71,8 +71,8 @@ Transforms.save = (transform, options = {}) => {
redos = redos.clear() redos = redos.clear()
// Update the state. // Update the state.
history = history.merge({ undos, redos }) history = history.set('undos', undos).set('redos', redos)
state = state.merge({ history }) state = state.set('history', history)
// Update the transform. // Update the transform.
transform.state = state transform.state = state
@ -106,8 +106,8 @@ Transforms.undo = (transform) => {
// Update the history. // Update the history.
state = transform.state state = transform.state
history = history.merge({ undos, redos }) history = history.set('undos', undos).set('redos', redos)
state = state.merge({ history }) state = state.set('history', history)
// Update the transform. // Update the transform.
transform.state = state transform.state = state