mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-20 06:01:24 +02:00
Documents use of Editor.withoutNormalizing in conjunction with normalization (#4737)
This commit is contained in:
@@ -365,6 +365,7 @@ Options: `{force?: boolean}`
|
|||||||
#### `Editor.withoutNormalizing(editor: Editor, fn: () => void) => void`
|
#### `Editor.withoutNormalizing(editor: Editor, fn: () => void) => void`
|
||||||
|
|
||||||
Call a function, deferring normalization until after it completes.
|
Call a function, deferring normalization until after it completes.
|
||||||
|
See [Normalization - Implications for Other Code](./11-normalizing.md#implications-for-other-code);
|
||||||
|
|
||||||
## Instance Methods
|
## Instance Methods
|
||||||
|
|
||||||
|
@@ -230,3 +230,8 @@ Transform.setNodes(
|
|||||||
|
|
||||||
When performing transforms, if you're ever looping over nodes and transforming them one at a time, consider seeing if `match` can solve your use case, and offload the complexity of managing loops to Slate instead.
|
When performing transforms, if you're ever looping over nodes and transforming them one at a time, consider seeing if `match` can solve your use case, and offload the complexity of managing loops to Slate instead.
|
||||||
The `match` function can examine the children of a node, in `node.children`, or use `Node.parent` to examine its parent.
|
The `match` function can examine the children of a node, in `node.children`, or use `Node.parent` to examine its parent.
|
||||||
|
|
||||||
|
## Transforms and Normalization
|
||||||
|
|
||||||
|
Sequences of Transforms may need to be wrapped in [`Editor.withoutNormalizing`](../api/nodes/editor.md#editorwithoutnormalizingeditor-editor-fn---void--void) if the node tree should _not_ be normalized between Transforms.
|
||||||
|
See [Normalization - Implications for Other Code](./11-normalizing.md#implications-for-other-code);
|
||||||
|
@@ -8,7 +8,7 @@ Slate editors can edit complex, nested data structures. And for the most part th
|
|||||||
|
|
||||||
Slate editors come with a few built-in constraints out of the box. These constraints are there to make working with content _much_ more predictable than standard `contenteditable`. All of the built-in logic in Slate depends on these constraints, so unfortunately you cannot omit them. They are...
|
Slate editors come with a few built-in constraints out of the box. These constraints are there to make working with content _much_ more predictable than standard `contenteditable`. All of the built-in logic in Slate depends on these constraints, so unfortunately you cannot omit them. They are...
|
||||||
|
|
||||||
1. **All `Element` nodes must contain at least one `Text` descendant.** If an element node does not contain any children, an empty text node will be added as its only child. This constraint exists to ensure that the selection's anchor and focus points \(which rely on referencing text nodes\) can always be placed inside any node. With this, empty elements \(or void elements\) wouldn't be selectable.
|
1. **All `Element` nodes must contain at least one `Text` descendant** — even [Void Elements](./02-nodes.md#voids). If an element node does not contain any children, an empty text node will be added as its only child. This constraint exists to ensure that the selection's anchor and focus points \(which rely on referencing text nodes\) can always be placed inside any node. With this, empty elements \(or void elements\) wouldn't be selectable.
|
||||||
2. **Two adjacent texts with the same custom properties will be merged.** If two adjacent text nodes have the same formatting, they're merged into a single text node with a combined text string of the two. This exists to prevent the text nodes from only ever expanding in count in the document, since both adding and removing formatting results in splitting text nodes.
|
2. **Two adjacent texts with the same custom properties will be merged.** If two adjacent text nodes have the same formatting, they're merged into a single text node with a combined text string of the two. This exists to prevent the text nodes from only ever expanding in count in the document, since both adding and removing formatting results in splitting text nodes.
|
||||||
3. **Block nodes can only contain other blocks, or inline and text nodes.** For example, a `paragraph` block cannot have another `paragraph` block element _and_ a `link` inline element as children at the same time. The type of children allowed is determined by the first child, and any other non-conforming children are removed. This ensures that common richtext behaviors like "splitting a block in two" function consistently.
|
3. **Block nodes can only contain other blocks, or inline and text nodes.** For example, a `paragraph` block cannot have another `paragraph` block element _and_ a `link` inline element as children at the same time. The type of children allowed is determined by the first child, and any other non-conforming children are removed. This ensures that common richtext behaviors like "splitting a block in two" function consistently.
|
||||||
4. **Inline nodes cannot be the first or last child of a parent block, nor can it be next to another inline node in the children array.** If this is the case, an empty text node will be added to correct this to be in compliance with the constraint.
|
4. **Inline nodes cannot be the first or last child of a parent block, nor can it be next to another inline node in the children array.** If this is the case, an empty text node will be added to correct this to be in compliance with the constraint.
|
||||||
@@ -156,3 +156,37 @@ const withLinks = editor => {
|
|||||||
This fix is incorrectly written. It wants to ensure that all `link` elements have a `url` property string. But to fix invalid links it sets the `url` to `null`, which is still not a string!
|
This fix is incorrectly written. It wants to ensure that all `link` elements have a `url` property string. But to fix invalid links it sets the `url` to `null`, which is still not a string!
|
||||||
|
|
||||||
In this case you'd either want to unwrap the link, removing it entirely. _Or_ expand your validation to accept an "empty" `url == null` as well.
|
In this case you'd either want to unwrap the link, removing it entirely. _Or_ expand your validation to accept an "empty" `url == null` as well.
|
||||||
|
|
||||||
|
## Implications for Other Code
|
||||||
|
|
||||||
|
Sequences of Transforms may need to be wrapped in [`Editor.withoutNormalizing`](../api/nodes/editor.md#editorwithoutnormalizingeditor-editor-fn---void--void) if the node tree should _not_ be normalized between Transforms.
|
||||||
|
This is frequently the case when you `unwrapNodes` followed by `wrapNodes`.
|
||||||
|
For example, you might write a function to change the type of a block as follows:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const LIST_TYPES = ['numbered-list', 'bulleted-list']
|
||||||
|
|
||||||
|
function changeBlockType(editor, type) {
|
||||||
|
Editor.withoutNormalizing(editor, () => {
|
||||||
|
const isActive = isBlockActive(editor, type)
|
||||||
|
const isList = LIST_TYPES.includes(type)
|
||||||
|
|
||||||
|
Transforms.unwrapNodes(editor, {
|
||||||
|
match: n =>
|
||||||
|
LIST_TYPES.includes(
|
||||||
|
!Editor.isEditor(n) && SlateElement.isElement(n) && n.type
|
||||||
|
),
|
||||||
|
split: true,
|
||||||
|
})
|
||||||
|
const newProperties = {
|
||||||
|
type: isActive ? 'paragraph' : isList ? 'list-item' : type,
|
||||||
|
}
|
||||||
|
Transforms.setNodes(editor, newProperties)
|
||||||
|
|
||||||
|
if (!isActive && isList) {
|
||||||
|
const block = { type: type, children: [] }
|
||||||
|
Transforms.wrapNodes(editor, block)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Reference in New Issue
Block a user