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:
parent
a0b45f8074
commit
0ebe5b4b64
docs/reference/models
examples
lib/models
test/transforms/fixtures
add-mark-at-range
add-mark/across-blocks
remove-mark-at-range
toggle-mark-at-range
add-across-blocks
add-across-inlines
add-existing-marks
add-first-character
add-last-character
add-middle-character
add-whole-word
add-with-mark-object
add-with-plain-object
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
|
17
test/transforms/fixtures/toggle-mark/add-whole-word/index.js
Normal file
17
test/transforms/fixtures/toggle-mark/add-whole-word/index.js
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user