slate
slate copied to clipboard
Hardcoded text node inside normalizeNode method
Description
There is following blocks of code inside editor's normalizeNode
method:
// Ensure that block and inline nodes have at least one text child.
if (Element.isElement(node) && node.children.length === 0) {
const child = { text: '' }; // <-- Problem here
Transforms.insertNodes(editor, child, {
at: path.concat(0),
voids: true,
});
return;
}
and
// Ensure that inline nodes are surrounded by text nodes.
if (editor.isInline(child)) {
if (prev == null || !Text.isText(prev)) {
const newChild = { text: '' }; // <-- Problem here
Transforms.insertNodes(editor, newChild, {
at: path.concat(n),
voids: true,
});
n++;
} else if (isLast) {
const newChild = { text: '' }; // <-- Problem here
Transforms.insertNodes(editor, newChild, {
at: path.concat(n + 1),
voids: true,
});
n++;
}
}
Text node structure is hardcoded with only one text
field, but i want to add some properties and declare interface like this:
interface Text {
text: string;
bold: boolean;
}
This is correct according to docs (https://docs.slatejs.org/concepts/02-nodes#text).
Here i expect bold
property to contain true
or false
, but sometimes i receive undefined
. It's okay for boolean, but i might want to create non-boolean property:
interface Text {
text: string;
bold: boolean;
fontFamily: string; // <- single source of truth for default font family
}
This is not feature request but bug, because of logical conflict between example in docs and real implementation.
Expectation I expect ability to override text nodes creation inside Slate, for example:
function createCustomTextNode(text: string): Text {
return { text, bold: false, fontFamily: "Helvetica" }
}
function withCustomTextNode(editor: Editor): Editor {
editor.createTextNode = createCustomTextNode;
return editor;
}
And Slate methods should use this method instead of hardcoded values.
Environment
- Slate Version: 0.65.3
- Operating System: all
- Browser: all
- TypeScript Version: all
Workaround
I've found current workaround for this problem with overriding editor's apply
method:
import { Editor, Text } from 'slate';
function createCustomTextNode(text: string): Text {
return { text, bold: false, fontFamily: "Helvetica" }
}
export function withCustomTextNode(editor: Editor): Editor {
const { apply } = editor;
editor.apply = (operation) => {
if (
operation.type === 'insert_node' &&
Text.isText(operation.node) &&
operation.node.text.length === 0
) {
apply({
...operation,
node: createCustomTextNode("")
});
} else {
apply(operation);
}
};
return editor;
}
emm.. that's right,You should override the editor's apply method. I think can close the bug.