1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-04-21 13:51:59 +02:00

add toggleMark and toggleMarkAtRange transforms

This commit is contained in:
Ian Storm Taylor 2016-07-21 11:59:21 -07:00
parent a0b45f8074
commit 0ebe5b4b64
83 changed files with 1102 additions and 66 deletions
docs/reference/models
examples
hovering-menu
rich-text
lib/models
test/transforms/fixtures
add-mark-at-range
add-mark/across-blocks
remove-mark-at-range
toggle-mark-at-range
toggle-mark
add-across-blocks
add-across-inlines
add-collapsed-selection-off-again
add-collapsed-selection
add-existing-marks
add-first-character
add-last-character
add-middle-character
add-whole-word
add-with-mark-object
add-with-plain-object
remove-across-blocks

@ -25,6 +25,7 @@ Transform methods can either operate on the [`Document`](./document.md), the [`S
- [`splitBlock`](#splitblock)
- [`splitInline`](#splitinline)
- [`removeMark`](#removemark)
- [`toggleMark`](#togglemark)
- [`unwrapBlock`](#unwrapblock)
- [`unwrapInline`](#unwrapinline)
- [`wrapBlock`](#wrapblock)
@ -53,7 +54,8 @@ Transform methods can either operate on the [`Document`](./document.md), the [`S
- [`setInlineAtRange`](#setinlineatrange)
- [`splitBlockAtRange`](#splitblockatrange)
- [`splitInlineAtRange`](#splitinlineatrange)
- [`removeMarkAtRange`](#removeMarkatrange)
- [`removeMarkAtRange`](#removemarkatrange)
- [`toggleMarkAtRange`](#togglemarkatrange)
- [`unwrapBlockAtRange`](#unwrapblockatrange)
- [`unwrapInlineAtRange`](#unwrapinlineatrange)
- [`wrapBlockAtRange`](#wrapblockatrange)
@ -102,9 +104,10 @@ Insert a string of `text` at the current selection. If the selection is expanded
### `addMark`
`addMark(mark: Mark) => Transform`
`addMark(properties: Object) => Transform`
`addMark(type: String) => Transform`
Add a [`mark`](./mark.md) to the characters in the current selection. For convenience, you can pass a `type` string to implicitly create a [`Mark`](./mark.md) of that type.
Add a [`mark`](./mark.md) to the characters in the current selection. For convenience, you can pass a `type` string or `properties` object to implicitly create a [`Mark`](./mark.md) of that type.
### `setBlock`
`setBlock(properties: Object) => Transform`
@ -130,9 +133,17 @@ Split the [`Inline`](./inline.md) node in the current selection by `depth` level
### `removeMark`
`removeMark(mark: Mark) => Transform`
`removeMark(properties: Object) => Transform`
`removeMark(type: String) => Transform`
Remove a [`mark`](./mark.md) from the characters in the current selection. For convenience, you can pass a `type` string to implicitly create a [`Mark`](./mark.md) of that type.
Remove a [`mark`](./mark.md) from the characters in the current selection. For convenience, you can pass a `type` string or `properties` object to implicitly create a [`Mark`](./mark.md) of that type.
### `toggleMark`
`toggleMark(mark: Mark) => Transform`
`toggleMark(properties: Object) => Transform`
`toggleMark(type: String) => Transform`
Add or remove a [`mark`](./mark.md) from the characters in the current selection, depending on it already exists on any or not. For convenience, you can pass a `type` string or `properties` object to implicitly create a [`Mark`](./mark.md) of that type.
### `unwrapBlock`
`unwrapBlock([type: String], [data: Data]) => Transform`
@ -247,9 +258,10 @@ Insert a string of `text` at a `range`. If the selection is expanded, it will be
### `addMarkAtRange`
`addMarkAtRange(range: Selection, mark: Mark) => Transform`
`addMark(range: Selection, type: String) => Transform`
`addMarkAtRange(range: Selection, properties: Object) => Transform`
`addMarkAtRange(range: Selection, type: String) => Transform`
Add a [`mark`](./mark.md) to the characters in a `range`. For convenience, you can pass a `type` string to implicitly create a [`Mark`](./mark.md) of that type.
Add a [`mark`](./mark.md) to the characters in a `range`. For convenience, you can pass a `type` string or `properties` object to implicitly create a [`Mark`](./mark.md) of that type.
### `setBlockAtRange`
`setBlockAtRange(range: Selection, properties: Object) => Transform`
@ -275,9 +287,17 @@ Split the [`Inline`](./inline.md) node in a `range` by `depth` levels. If the se
### `removeMarkAtRange`
`removeMarkAtRange(range: Selection, mark: Mark) => Transform`
`removeMark(range: Selection, type: String) => Transform`
`removeMarkAtRange(range: Selection, properties: Object) => Transform`
`removeMarkAtRange(range: Selection, type: String) => Transform`
Remove a [`mark`](./mark.md) from the characters in a `range`. For convenience, you can pass a `type` string to implicitly create a [`Mark`](./mark.md) of that type.
Remove a [`mark`](./mark.md) from the characters in a `range`. For convenience, you can pass a `type` string or `properties` object to implicitly create a [`Mark`](./mark.md) of that type.
### `toggleMarkAtRange`
`toggleMarkAtRange(range: Selection, mark: Mark) => Transform`
`toggleMarkAtRange(range: Selection, properties: Object) => Transform`
`toggleMarkAtRange(range: Selection, type: String) => Transform`
Add or remove a [`mark`](./mark.md) from the characters in a `range`, depending on whether any of them already have the mark. For convenience, you can pass a `type` string or `properties` object to implicitly create a [`Mark`](./mark.md) of that type.
### `unwrapBlockAtRange`
`unwrapBlockAtRange(range: Selection, [type: String], [data: Data]) => Transform`

@ -90,12 +90,11 @@ class HoveringMenu extends React.Component {
onClickMark = (e, type) => {
e.preventDefault()
const isActive = this.hasMark(type)
let { state } = this.state
state = state
.transform()
[isActive ? 'removeMark' : 'addMark'](type)
.toggleMark(type)
.apply()
this.setState({ state })

@ -133,7 +133,7 @@ class RichText extends React.Component {
state = state
.transform()
[this.hasMark(mark) ? 'removeMark' : 'addMark'](mark)
.toggleMark(mark)
.apply()
e.preventDefault()
@ -149,12 +149,11 @@ class RichText extends React.Component {
onClickMark = (e, type) => {
e.preventDefault()
const isActive = this.hasMark(type)
let { state } = this.state
state = state
.transform()
[isActive ? 'removeMark' : 'addMark'](type)
.toggleMark(type)
.apply()
this.setState({ state })

@ -499,8 +499,9 @@ const Node = {
// Otherwise, get a set of the marks for each character in the range.
return this
.getCharactersAtRange(range)
.map(char => char.marks)
.toSet()
.reduce((memo, char) => {
return memo.union(char.marks)
}, new Set())
},
/**

@ -349,6 +349,30 @@ class State extends new Record(DEFAULTS) {
return new Transform({ state })
}
/**
* Add a `mark` to the characters in the current selection.
*
* @param {Mark} mark
* @return {State} state
*/
addMark(mark) {
mark = normalizeMark(mark)
let state = this
let { cursorMarks, document, selection } = state
// If the selection is collapsed, add the mark to the cursor instead.
if (selection.isCollapsed) {
const marks = document.getMarksAtRange(selection)
state = state.merge({ cursorMarks: marks.add(mark) })
return state
}
document = document.addMarkAtRange(selection, mark)
state = state.merge({ document })
return state
}
/**
* Move the selection to the start of the previous block.
*
@ -703,30 +727,6 @@ class State extends new Record(DEFAULTS) {
return state
}
/**
* Add a `mark` to the characters in the current selection.
*
* @param {Mark} mark
* @return {State} state
*/
addMark(mark) {
let state = this
let { cursorMarks, document, selection } = state
// If the selection is collapsed, add the mark to the cursor instead.
if (selection.isCollapsed) {
if (typeof mark == 'string') mark = new Mark({ type: mark })
const marks = document.getMarksAtRange(selection)
state = state.merge({ cursorMarks: marks.add(mark) })
return state
}
document = document.addMarkAtRange(selection, mark)
state = state.merge({ document })
return state
}
/**
* Move the selection to a specific anchor and focus point.
*
@ -738,6 +738,17 @@ class State extends new Record(DEFAULTS) {
let state = this
let { document, selection } = state
// Allow for passing a `Selection` object.
if (properties instanceof Selection) {
properties = {
anchorKey: properties.anchorKey,
anchorOffset: properties.anchorOffset,
focusKey: properties.focusKey,
focusOffset: properties.focusOffset,
isFocused: properties.isFocused
}
}
// Pass in properties, and force `isBackward` to be re-resolved.
selection = selection.merge({
...properties,
@ -837,12 +848,12 @@ class State extends new Record(DEFAULTS) {
*/
removeMark(mark) {
mark = normalizeMark(mark)
let state = this
let { cursorMarks, document, selection } = state
// If the selection is collapsed, remove the mark from the cursor instead.
if (selection.isCollapsed) {
if (typeof mark == 'string') mark = new Mark({ type: mark })
const marks = document.getMarksAtRange(selection)
state = state.merge({ cursorMarks: marks.remove(mark) })
return state
@ -853,6 +864,24 @@ class State extends new Record(DEFAULTS) {
return state
}
/**
* Add or remove a `mark` from the characters in the current selection,
* depending on whether it's already there.
*
* @param {Mark} mark
* @return {State} state
*/
toggleMark(mark) {
mark = normalizeMark(mark)
let state = this
let { marks, document, selection } = state
const exists = marks.some(m => m.equals(mark))
return exists
? state.removeMark(mark)
: state.addMark(mark)
}
/**
* Wrap the block nodes in the current selection in new nodes of `type`.
*
@ -937,6 +966,21 @@ class State extends new Record(DEFAULTS) {
}
/**
* Normalize a `mark` argument, which can be a string or plain object too.
*
* @param {Mark or String or Object} mark
* @return {Mark}
*/
function normalizeMark(mark) {
if (typeof mark == 'string') {
return Mark.create({ type: mark })
} else {
return Mark.create(mark)
}
}
/**
* Export.
*/

@ -38,6 +38,7 @@ const DOCUMENT_TRANSFORMS = [
'splitBlockAtRange',
'splitInlineAtRange',
'removeMarkAtRange',
'toggleMarkAtRange',
'unwrapBlockAtRange',
'unwrapInlineAtRange',
'wrapBlockAtRange',
@ -83,6 +84,7 @@ const STATE_DOCUMENT_TRANSFORMS = [
'splitBlock',
'splitInline',
'removeMark',
'toggleMark',
'unwrapBlock',
'unwrapInline',
'wrapBlock',

@ -311,13 +311,9 @@ const Transforms = {
*/
addMarkAtRange(range, mark) {
mark = normalizeMark(mark)
let node = this
// Allow for just passing a type for convenience.
if (typeof mark == 'string') {
mark = new Mark({ type: mark })
}
// When the range is collapsed, do nothing.
if (range.isCollapsed) return node
@ -565,13 +561,9 @@ const Transforms = {
*/
removeMarkAtRange(range, mark) {
mark = normalizeMark(mark)
let node = this
// Allow for just passing a type for convenience.
if (typeof mark == 'string') {
mark = new Mark({ type: mark })
}
// When the range is collapsed, do nothing.
if (range.isCollapsed) return node
@ -600,6 +592,31 @@ const Transforms = {
return node
},
/**
* Add or remove a `mark` from the characters at `range`, depending on whether
* it's already there.
*
* @param {Selection} range
* @param {Mark or String} mark (optional)
* @return {Node} node
*/
toggleMarkAtRange(range, mark) {
mark = normalizeMark(mark)
let node = this
// When the range is collapsed, do nothing.
if (range.isCollapsed) return node
// Check if the mark exists in the range already.
const marks = node.getMarksAtRange(range)
const exists = marks.some(m => m.equals(mark))
return exists
? node.removeMarkAtRange(range, mark)
: node.addMarkAtRange(range, mark)
},
/**
* Unwrap all of the block nodes in a `range` from a block node of `type.`
*
@ -910,6 +927,21 @@ function isInRange(index, text, range) {
}
}
/**
* Normalize a `mark` argument, which can be a string or plain object too.
*
* @param {Mark or String or Object} mark
* @return {Mark}
*/
function normalizeMark(mark) {
if (typeof mark == 'string') {
return Mark.create({ type: mark })
} else {
return Mark.create(mark)
}
}
/**
* Export.
*/

@ -0,0 +1,22 @@
import { Mark } from '../../../../..'
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 0,
focusKey: first.key,
focusOffset: 1
})
return state
.transform()
.addMarkAtRange(range, Mark.create({
type: 'bold',
data: { key: 'value' }
}))
.apply()
}

@ -0,0 +1,13 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: w
marks:
- type: bold
data:
key: value
- text: ord

@ -1,6 +1,4 @@
import { Data } from '../../../../..'
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
@ -14,6 +12,9 @@ export default function (state) {
return state
.transform()
.addMarkAtRange(range, 'bold', Data.create({ key: 'value' }))
.addMarkAtRange(range, {
type: 'bold',
data: { key: 'value' }
})
.apply()
}

@ -0,0 +1,13 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: w
marks:
- type: bold
data:
key: value
- text: ord

@ -1,18 +1,25 @@
import assert from 'assert'
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const second = texts.last()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 2,
focusKey: second.key,
focusOffset: 2
})
return state
const next = state
.transform()
.moveTo({
anchorKey: first.key,
anchorOffset: 2,
focusKey: second.key,
focusOffset: 2
})
.moveTo(range)
.addMark('bold')
.apply()
assert.deepEqual(next.selection.toJS(), range.toJS())
return next
}

@ -0,0 +1,22 @@
import { Mark } from '../../../../..'
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 0,
focusKey: first.key,
focusOffset: 1
})
return state
.transform()
.removeMarkAtRange(range, Mark.create({
type: 'bold',
data: { key: 'value' }
}))
.apply()
}

@ -0,0 +1,13 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: w
marks:
- type: bold
data:
key: value
- text: ord

@ -0,0 +1,20 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 0,
focusKey: first.key,
focusOffset: 1
})
return state
.transform()
.removeMarkAtRange(range, {
type: 'bold',
data: { key: 'value' }
})
.apply()
}

@ -0,0 +1,13 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: w
marks:
- type: bold
data:
key: value
- text: ord

@ -0,0 +1,18 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const second = texts.last()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 2,
focusKey: second.key,
focusOffset: 2
})
return state
.transform()
.toggleMarkAtRange(range, 'bold')
.apply()
}

@ -0,0 +1,14 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: another

@ -0,0 +1,20 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: wo
- text: rd
marks:
- type: bold
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: an
marks:
- type: bold
- text: other

@ -0,0 +1,18 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const second = texts.last()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 2,
focusKey: second.key,
focusOffset: 2
})
return state
.transform()
.toggleMarkAtRange(range, 'bold')
.apply()
}

@ -0,0 +1,20 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: inline
type: link
nodes:
- kind: text
ranges:
- text: word
- kind: block
type: paragraph
nodes:
- kind: inline
type: link
nodes:
- kind: text
ranges:
- text: another

@ -0,0 +1,26 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: inline
type: link
nodes:
- kind: text
ranges:
- text: wo
- text: rd
marks:
- type: bold
- kind: block
type: paragraph
nodes:
- kind: inline
type: link
nodes:
- kind: text
ranges:
- text: an
marks:
- type: bold
- text: other

@ -0,0 +1,17 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 0,
focusKey: first.key,
focusOffset: 2
})
return state
.transform()
.toggleMarkAtRange(range, 'bold')
.apply()
}

@ -0,0 +1,10 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word
marks:
- type: italic

@ -0,0 +1,14 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: wo
marks:
- type: italic
- type: bold
- text: rd
marks:
- type: italic

@ -12,6 +12,6 @@ export default function (state) {
return state
.transform()
.addMarkAtRange(range, 'bold', { key: 'value' })
.toggleMarkAtRange(range, 'bold')
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -0,0 +1,17 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: first.length - 1,
focusKey: first.key,
focusOffset: first.length
})
return state
.transform()
.toggleMarkAtRange(range, 'bold')
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -0,0 +1,11 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: wor
- text: d
marks:
- type: bold

@ -0,0 +1,17 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 1,
focusKey: first.key,
focusOffset: 2
})
return state
.transform()
.toggleMarkAtRange(range, 'bold')
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -6,6 +6,7 @@ nodes:
- kind: text
ranges:
- text: w
- text: o
marks:
- type: bold
- text: ord
- text: rd

@ -0,0 +1,17 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 0,
focusKey: first.key,
focusOffset: first.length
})
return state
.transform()
.toggleMarkAtRange(range, 'bold')
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -0,0 +1,10 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word
marks:
- type: bold

@ -0,0 +1,22 @@
import { Mark } from '../../../../..'
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 0,
focusKey: first.key,
focusOffset: 1
})
return state
.transform()
.toggleMarkAtRange(range, Mark.create({
type: 'bold',
data: { key: 'value' }
}))
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -0,0 +1,13 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: w
marks:
- type: bold
data:
key: value
- text: ord

@ -0,0 +1,20 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 0,
focusKey: first.key,
focusOffset: 1
})
return state
.transform()
.toggleMarkAtRange(range, {
type: 'bold',
data: { key: 'value' }
})
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -0,0 +1,13 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: w
marks:
- type: bold
data:
key: value
- text: ord

@ -0,0 +1,25 @@
import assert from 'assert'
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const second = texts.last()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 2,
focusKey: second.key,
focusOffset: 2
})
const next = state
.transform()
.moveTo(range)
.toggleMark('bold')
.apply()
assert.deepEqual(next.selection.toJS(), range.toJS())
return next
}

@ -0,0 +1,14 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: another

@ -0,0 +1,20 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: wo
- text: rd
marks:
- type: bold
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: an
marks:
- type: bold
- text: other

@ -0,0 +1,18 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const second = texts.last()
return state
.transform()
.moveTo({
anchorKey: first.key,
anchorOffset: 2,
focusKey: second.key,
focusOffset: 2
})
.toggleMark('bold')
.apply()
}

@ -0,0 +1,20 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: inline
type: link
nodes:
- kind: text
ranges:
- text: word
- kind: block
type: paragraph
nodes:
- kind: inline
type: link
nodes:
- kind: text
ranges:
- text: another

@ -0,0 +1,26 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: inline
type: link
nodes:
- kind: text
ranges:
- text: wo
- text: rd
marks:
- type: bold
- kind: block
type: paragraph
nodes:
- kind: inline
type: link
nodes:
- kind: text
ranges:
- text: an
marks:
- type: bold
- text: other

@ -0,0 +1,20 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
return state
.transform()
.moveTo({
anchorKey: first.key,
anchorOffset: 0,
focusKey: first.key,
focusOffset: 0
})
.toggleMark('bold')
.insertText('a')
.toggleMark('bold')
.insertText('b')
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -0,0 +1,11 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: a
marks:
- type: bold
- text: bword

@ -0,0 +1,18 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
return state
.transform()
.moveTo({
anchorKey: first.key,
anchorOffset: 0,
focusKey: first.key,
focusOffset: 0
})
.toggleMark('bold')
.insertText('a')
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -0,0 +1,11 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: a
marks:
- type: bold
- text: word

@ -0,0 +1,17 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
return state
.transform()
.moveTo({
anchorKey: first.key,
anchorOffset: 0,
focusKey: first.key,
focusOffset: 2
})
.toggleMark('bold')
.apply()
}

@ -0,0 +1,10 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word
marks:
- type: italic

@ -0,0 +1,14 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: wo
marks:
- type: italic
- type: bold
- text: rd
marks:
- type: italic

@ -12,6 +12,6 @@ export default function (state) {
focusKey: first.key,
focusOffset: 1
})
.addMark('bold', { key: 'value' })
.toggleMark('bold')
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -0,0 +1,17 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
return state
.transform()
.moveTo({
anchorKey: first.key,
anchorOffset: first.length - 1,
focusKey: first.key,
focusOffset: first.length
})
.toggleMark('bold')
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -0,0 +1,11 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: wor
- text: d
marks:
- type: bold

@ -0,0 +1,17 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
return state
.transform()
.moveTo({
anchorKey: first.key,
anchorOffset: 1,
focusKey: first.key,
focusOffset: 2
})
.toggleMark('bold')
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -6,6 +6,7 @@ nodes:
- kind: text
ranges:
- text: w
- text: o
marks:
- type: bold
- text: ord
- text: rd

@ -0,0 +1,17 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
return state
.transform()
.moveTo({
anchorKey: first.key,
anchorOffset: 0,
focusKey: first.key,
focusOffset: first.length
})
.toggleMark('bold')
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -0,0 +1,10 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word
marks:
- type: bold

@ -0,0 +1,22 @@
import { Mark } from '../../../../..'
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
return state
.transform()
.moveTo({
anchorKey: first.key,
anchorOffset: 0,
focusKey: first.key,
focusOffset: 1
})
.toggleMark(Mark.create({
type: 'bold',
data: { key: 'value' }
}))
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -0,0 +1,13 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: w
marks:
- type: bold
data:
key: value
- text: ord

@ -1,6 +1,4 @@
import { Data } from '../../../../..'
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
@ -14,6 +12,9 @@ export default function (state) {
focusKey: first.key,
focusOffset: 1
})
.addMark('bold', Data.create({ key: 'value' }))
.toggleMark({
type: 'bold',
data: { key: 'value' }
})
.apply()
}

@ -0,0 +1,8 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word

@ -0,0 +1,13 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: w
marks:
- type: bold
data:
key: value
- text: ord

@ -0,0 +1,25 @@
import assert from 'assert'
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.first()
const second = texts.last()
const range = selection.merge({
anchorKey: first.key,
anchorOffset: 2,
focusKey: second.key,
focusOffset: 2
})
const next = state
.transform()
.moveTo(range)
.toggleMark('bold')
.apply()
assert.deepEqual(next.selection.toJS(), range.toJS())
return next
}

@ -0,0 +1,20 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: wo
- text: rd
marks:
- type: bold
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: an
marks:
- type: bold
- text: other

@ -0,0 +1,14 @@
nodes:
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: word
- kind: block
type: paragraph
nodes:
- kind: text
ranges:
- text: another