slate#Node TypeScript Examples
The following examples show how to use
slate#Node.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts From slate-ot with MIT License | 7 votes |
checkOp = (snapshot: Editor, op: Operation) => {
switch (op.type) {
case 'remove_text': {
const leaf = Node.leaf(snapshot, op.path);
const textToRemove = leaf.text.slice(
op.offset,
op.offset + op.text.length
);
expect(textToRemove).toBe(op.text);
break;
}
case 'merge_node': {
const prev = Node.get(snapshot, Path.previous(op.path));
const prevLen = Text.isText(prev)
? prev.text.length
: prev.children.length;
expect(prevLen).toBe(op.position);
break;
}
case 'remove_node': {
// op.node needs to be checked
break;
}
default:
return;
}
}
Example #2
Source File: playground-current.stories.tsx From remark-slate-transformer with MIT License | 6 votes |
SlateToMarkdown = () => {
const [value, setValue] = useState(toSlate(text));
const [md, setMd] = useState(toMd(value));
const ref = useRef<Node[]>(null);
return (
<Wrapper>
<SlateEditor ref={ref} initialValue={value} />
<div style={{ padding: 10 }}>
<button
style={{ height: "100%" }}
onClick={() => {
if (!ref.current) return;
setMd(toMd(ref.current));
}}
>
{"slate -> md"}
</button>
</div>
<Text>{md}</Text>
</Wrapper>
);
}
Example #3
Source File: code-block-decorate.ts From fantasy-editor with MIT License | 6 votes |
codeBlockDecorate = (entry: NodeEntry, editor: Editor) => {
const ranges: any = [];
const [node, path] = entry;
if (node.type === BLOCK_CODE) {
const text = Node.string(node);
const langName: any = node.lang || 'markup';
const lang = languages[langName];
if (lang) {
const tokens = tokenize(text, lang);
let offset = 0;
const {ranges: r} = buildRange(tokens, path, offset);
ranges.push(...r);
}
}
return ranges;
}
Example #4
Source File: runtime-util.ts From slate-vue with MIT License | 6 votes |
getChildren = (node: Node): any => {
return Editor.isEditor(node) ? (node as any)._state: (node as any).children
}
Example #5
Source File: Editor.tsx From react-editor-kit with MIT License | 6 votes |
isAtEndOfNode = (editor: ReactEditor) => {
if (editor.selection) {
const { anchor, focus } = editor.selection;
const node = getActiveNode(editor);
if (node) {
const length = Node.string(node).length;
return anchor.offset === length && focus.offset === length;
}
}
return false;
}
Example #6
Source File: op-generator.ts From slate-ot with MIT License | 6 votes |
getRandomLeafWithPath = (snapshot: Node): TextWithPath | null => {
const paths = getAllTextPaths(snapshot);
const path = paths[fuzzer.randomInt(paths.length)];
if (!path || !path.length) {
return null;
}
const t = Node.leaf(snapshot, path);
return { ...t, path };
}
Example #7
Source File: LokiQueryFieldForm.tsx From grafana-chinese with Apache License 2.0 | 6 votes |
constructor(props: LokiQueryFieldFormProps, context: React.Context<any>) {
super(props, context);
this.plugins = [
BracesPlugin(),
SlatePrism({
onlyIn: (node: Node) => node.object === 'block' && node.type === 'code_block',
getSyntax: (node: Node) => 'promql',
}),
];
}
Example #8
Source File: placeholder.component.ts From slate-angular with MIT License | 6 votes |
placeholderDecorate: (editor: Editor) => SlatePlaceholder[] = (editor) => {
const cursorAnchor = editor.selection?.anchor
if(cursorAnchor) {
const parent = Node.parent(editor,cursorAnchor.path)
if(parent.children.length === 1 &&
Array.from(Node.texts(parent)).length === 1 &&
Node.string(parent) === '' ) {
const start = Editor.start(editor, cursorAnchor)
return [{
placeholder: 'advance placeholder use with placeholderDecoration',
anchor: start,
focus: start
}];
} else {
return [];
}
}
return [];
};
Example #9
Source File: RichEditor.tsx From Full-Stack-React-TypeScript-and-Node with MIT License | 5 votes |
RichEditor: FC<RichEditorProps> = ({ existingBody }) => {
const [value, setValue] = useState<Node[]>(initialValue);
const renderElement = useCallback((props) => <Element {...props} />, []);
const renderLeaf = useCallback((props) => <Leaf {...props} />, []);
const editor = useMemo(() => withHistory(withReact(createEditor())), []);
useEffect(() => {
if (existingBody) {
setValue([
{
type: "paragraph",
text: existingBody,
},
]);
}
}, []);
const onChangeEditorValue = (val: Node[]) => {
setValue(val);
};
return (
<Slate editor={editor} value={value} onChange={onChangeEditorValue}>
<Toolbar>
<MarkButton format="bold" icon="bold" />
<MarkButton format="italic" icon="italic" />
<MarkButton format="underline" icon="underlined" />
<MarkButton format="code" icon="code" />
<BlockButton format="heading-one" icon="header1" />
<BlockButton format="block-quote" icon="in_quotes" />
<BlockButton format="numbered-list" icon="list_numbered" />
<BlockButton format="bulleted-list" icon="list_bulleted" />
</Toolbar>
<Editable
className="editor"
renderElement={renderElement}
renderLeaf={renderLeaf}
placeholder="Enter some rich text…"
spellCheck
autoFocus
onKeyDown={(event) => {
for (const hotkey in HOTKEYS) {
if (isHotkey(hotkey, event as any)) {
event.preventDefault();
const mark = HOTKEYS[hotkey];
toggleMark(editor, mark);
}
}
}}
/>
</Slate>
);
}
Example #10
Source File: playground-current.stories.tsx From remark-slate-transformer with MIT License | 5 votes |
toSlate = (s: string) => toSlateProcessor.processSync(s).result as Node[]
Example #11
Source File: serialize-html.ts From fantasy-editor with MIT License | 5 votes |
serializeHtml = (nodes:Node[], formatCodeBlock:boolean = false) => {
const editor = {
children: nodes
}
return serialize(editor, formatCodeBlock);
}
Example #12
Source File: string.tsx From slate-vue with MIT License | 5 votes |
string = tsx.component({
props: {
leaf: {
type: Object as PropType<Text>
},
editor: Object
},
inject: ['isLast', 'parent', 'text'],
components: {
TextString
},
data(): providedByText {
return {}
},
render() {
const { leaf, editor, isLast, parent, text } = this
const path = VueEditor.findPath(editor, text as Node)
const parentPath = Path.parent(path)
// COMPAT: Render text inside void nodes with a zero-width space.
// So the node can contain selection but the text is not visible.
if (editor.isVoid(parent)) {
return <ZeroWidthString length={Node.string(parent as Node).length} />
}
// COMPAT: If this is the last text node in an empty block, render a zero-
// width space that will convert into a line break when copying and pasting
// to support expected plain text.
if (
leaf.text === '' &&
(parent as Element & Editor).children[(parent as Element & Editor).children.length - 1] === text &&
!editor.isInline(parent) &&
Editor.string(editor, parentPath) === ''
) {
return <ZeroWidthString isLineBreak={true} />
}
// COMPAT: If the text is empty, it's because it's on the edge of an inline
// node, so we render a zero-width space so that the selection can be
// inserted next to it still.
if (leaf.text === '') {
return <ZeroWidthString />
}
// 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.
if (isLast && leaf.text.slice(-1) === '\n') {
return <TextString isTrailing={true} text={leaf.text} />
}
return <TextString text={leaf.text} />
}
})
Example #13
Source File: Editor.d.ts From react-editor-kit with MIT License | 5 votes |
getSelectionRootNodes: (selection: Range, editor: ReactEditor) => Node[]
Example #14
Source File: op-generator.ts From slate-ot with MIT License | 5 votes |
getAllTextPaths = (node: Node): Path[] => {
let array: Path[] = [];
for (let [, p] of Node.texts(node)) {
array.push(p);
}
return array;
}
Example #15
Source File: options.tsx From grafana-chinese with Apache License 2.0 | 5 votes |
readonly onlyIn!: (node: Node) => boolean;
Example #16
Source File: editable.component.ts From slate-angular with MIT License | 5 votes |
forceFlush() {
timeDebug('start data sync');
this.detectContext();
this.cdr.detectChanges();
// repair collaborative editing when Chinese input is interrupted by other users' cursors
// when the DOMElement where the selection is located is removed
// the compositionupdate and compositionend events will no longer be fired
// so isComposing needs to be corrected
// need exec after this.cdr.detectChanges() to render HTML
// need exec before this.toNativeSelection() to correct native selection
if (this.isComposing) {
// Composition input text be not rendered when user composition input with selection is expanded
// At this time, the following matching conditions are met, assign isComposing to false, and the status is wrong
// this time condition is true and isComposiing is assigned false
// Therefore, need to wait for the composition input text to be rendered before performing condition matching
setTimeout(() => {
const textNode = Node.get(this.editor, this.editor.selection.anchor.path);
const textDOMNode = AngularEditor.toDOMNode(this.editor, textNode);
let textContent = '';
// skip decorate text
textDOMNode.querySelectorAll('[editable-text]').forEach((stringDOMNode) => {
let text = stringDOMNode.textContent;
const zeroChar = '\uFEFF';
// remove zero with char
if (text.startsWith(zeroChar)) {
text = text.slice(1);
}
if (text.endsWith(zeroChar)) {
text = text.slice(0, text.length - 1);
}
textContent += text;
});
if (Node.string(textNode).endsWith(textContent)) {
this.isComposing = false;
}
}, 0);
}
this.toNativeSelection();
timeDebug('end data sync');
}
Example #17
Source File: Client.tsx From slate-yjs-example with MIT License | 4 votes |
Client: React.FC<ClientProps> = ({ id, name, slug, removeUser }) => {
const [value, setValue] = useState<Node[]>([]);
const [isOnline, setOnlineState] = useState<boolean>(false);
const color = useMemo(
() =>
randomColor({
luminosity: "dark",
format: "rgba",
alpha: 1,
}),
[]
);
const [sharedType, provider] = useMemo(() => {
const doc = new Y.Doc();
const sharedType = doc.getArray<SyncElement>("content");
const provider = new WebsocketProvider(WEBSOCKET_ENDPOINT, slug, doc, {
connect: false,
});
return [sharedType, provider];
}, [id]);
const editor = useMemo(() => {
const editor = withCursor(
withYjs(withLinks(withReact(withHistory(createEditor()))), sharedType),
provider.awareness
);
return editor;
}, [sharedType, provider]);
useEffect(() => {
provider.on("status", ({ status }: { status: string }) => {
setOnlineState(status === "connected");
});
provider.awareness.setLocalState({
alphaColor: color.slice(0, -2) + "0.2)",
color,
name,
});
// Super hacky way to provide a initial value from the client, if
// you plan to use y-websocket in prod you probably should provide the
// initial state from the server.
provider.on("sync", (isSynced: boolean) => {
if (isSynced && sharedType.length === 0) {
toSharedType(sharedType, [
{ type: "paragraph", children: [{ text: "Hello world!" }] },
]);
}
});
provider.connect();
return () => {
provider.disconnect();
};
}, [provider]);
const { decorate } = useCursors(editor);
const toggleOnline = () => {
isOnline ? provider.disconnect() : provider.connect();
};
return (
<Instance online={isOnline}>
<Title>
<Head>Editor: {name}</Head>
<div style={{ display: "flex", marginTop: 10, marginBottom: 10 }}>
<Button type="button" onClick={toggleOnline}>
Go {isOnline ? "offline" : "online"}
</Button>
<Button type="button" onClick={() => removeUser(id)}>
Remove
</Button>
</div>
</Title>
<EditorFrame
editor={editor}
value={value}
decorate={decorate}
onChange={(value: Node[]) => setValue(value)}
/>
</Instance>
);
}