@platejs/code-block
Advanced tools
| import { ElementApi, KEYS, NodeApi, createSlatePlugin, createTSlatePlugin } from "platejs"; | ||
| //#region src/lib/deserializer/htmlDeserializerCodeBlock.ts | ||
| const htmlDeserializerCodeBlock = { | ||
| rules: [{ validNodeName: "PRE" }, { | ||
| validNodeName: "P", | ||
| validStyle: { fontFamily: "Consolas" } | ||
| }], | ||
| parse: ({ element }) => { | ||
| const languageSelectorText = [...element.childNodes].find((node) => node.nodeName === "SELECT")?.textContent || ""; | ||
| const textContent = element.textContent?.replace(languageSelectorText, "") || ""; | ||
| let lines = textContent.split("\n"); | ||
| if (!lines?.length) lines = [textContent]; | ||
| return { | ||
| children: lines.map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: KEYS.codeLine | ||
| })), | ||
| type: KEYS.codeBlock | ||
| }; | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region src/lib/queries/getCodeLineEntry.ts | ||
| /** If at (default = selection) is in ul>li>p, return li and ul node entries. */ | ||
| const getCodeLineEntry = (editor, { at = editor.selection } = {}) => { | ||
| if (at && editor.api.some({ | ||
| at, | ||
| match: { type: editor.getType(KEYS.codeLine) } | ||
| })) { | ||
| const selectionParent = editor.api.parent(at); | ||
| if (!selectionParent) return; | ||
| const [, parentPath] = selectionParent; | ||
| const codeLine = editor.api.above({ | ||
| at, | ||
| match: { type: editor.getType(KEYS.codeLine) } | ||
| }) || editor.api.parent(parentPath); | ||
| if (!codeLine) return; | ||
| const [codeLineNode, codeLinePath] = codeLine; | ||
| if (ElementApi.isElement(codeLineNode) && codeLineNode.type !== editor.getType(KEYS.codeLine)) return; | ||
| const codeBlock = editor.api.parent(codeLinePath); | ||
| if (!codeBlock) return; | ||
| return { | ||
| codeBlock, | ||
| codeLine | ||
| }; | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region src/lib/queries/getIndentDepth.ts | ||
| const nonWhitespaceOrEndRegex = /\S|$/; | ||
| const getIndentDepth = (editor, { codeLine }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| return editor.api.string(codeLinePath).search(nonWhitespaceOrEndRegex); | ||
| }; | ||
| //#endregion | ||
| //#region src/lib/queries/isCodeBlockEmpty.ts | ||
| /** Is the selection inside an empty code block */ | ||
| const isCodeBlockEmpty = (editor) => { | ||
| const { codeBlock } = getCodeLineEntry(editor) ?? {}; | ||
| if (!codeBlock) return false; | ||
| const codeLines = Array.from(NodeApi.children(editor, codeBlock[1])); | ||
| if (codeLines.length === 0) return true; | ||
| if (codeLines.length > 1) return false; | ||
| const firstCodeLineNode = codeLines[0][0]; | ||
| return !NodeApi.string(firstCodeLineNode); | ||
| }; | ||
| //#endregion | ||
| //#region src/lib/setCodeBlockToDecorations.ts | ||
| const CODE_LINE_TO_DECORATIONS = /* @__PURE__ */ new WeakMap(); | ||
| function getHighlightNodes(result) { | ||
| return result.value || result.children || []; | ||
| } | ||
| function parseNodes(nodes, className = []) { | ||
| return nodes.flatMap((node) => { | ||
| const classes = [...className, ...node.properties ? node.properties.className : []]; | ||
| if (node.children) return parseNodes(node.children, classes); | ||
| return { | ||
| classes, | ||
| text: node.value | ||
| }; | ||
| }); | ||
| } | ||
| function normalizeTokens(tokens) { | ||
| const lines = [[]]; | ||
| let currentLine = lines[0]; | ||
| for (const token of tokens) { | ||
| const tokenLines = token.text.split("\n"); | ||
| for (let i = 0; i < tokenLines.length; i++) { | ||
| const content = tokenLines[i]; | ||
| if (content) currentLine.push({ | ||
| classes: token.classes, | ||
| content | ||
| }); | ||
| if (i < tokenLines.length - 1) { | ||
| lines.push([]); | ||
| currentLine = lines.at(-1); | ||
| } | ||
| } | ||
| } | ||
| return lines; | ||
| } | ||
| function codeBlockToDecorations(editor, [block, blockPath]) { | ||
| const { defaultLanguage, ...options } = editor.getOptions(BaseCodeBlockPlugin); | ||
| const lowlight = options.lowlight; | ||
| const text = block.children.map((line) => NodeApi.string(line)).join("\n"); | ||
| const effectiveLanguage = block.lang || defaultLanguage; | ||
| let highlighted; | ||
| try { | ||
| if (!effectiveLanguage || effectiveLanguage === "plaintext") highlighted = { value: [] }; | ||
| else if (effectiveLanguage === "auto") highlighted = lowlight.highlightAuto(text); | ||
| else highlighted = lowlight.highlight(effectiveLanguage, text); | ||
| } catch (error) { | ||
| const availableLanguages = lowlight.listLanguages(); | ||
| if (effectiveLanguage && availableLanguages.includes(effectiveLanguage)) { | ||
| editor.api.debug.error(error, "CODE_HIGHLIGHT"); | ||
| highlighted = { value: [] }; | ||
| } else { | ||
| editor.api.debug.warn(`Language "${effectiveLanguage}" is not registered. Falling back to plaintext`); | ||
| highlighted = { value: [] }; | ||
| } | ||
| } | ||
| const normalizedTokens = normalizeTokens(parseNodes(getHighlightNodes(highlighted))); | ||
| const blockChildren = block.children; | ||
| const nodeToDecorations = /* @__PURE__ */ new Map(); | ||
| const numLines = Math.min(normalizedTokens.length, blockChildren.length); | ||
| for (let index = 0; index < numLines; index++) { | ||
| const lineTokens = normalizedTokens[index]; | ||
| const element = blockChildren[index]; | ||
| if (!nodeToDecorations.has(element)) nodeToDecorations.set(element, []); | ||
| let start = 0; | ||
| for (const token of lineTokens) { | ||
| const length = token.content.length; | ||
| if (!length) continue; | ||
| const end = start + length; | ||
| const decoration = { | ||
| anchor: { | ||
| offset: start, | ||
| path: [ | ||
| ...blockPath, | ||
| index, | ||
| 0 | ||
| ] | ||
| }, | ||
| className: token.classes.join(" "), | ||
| focus: { | ||
| offset: end, | ||
| path: [ | ||
| ...blockPath, | ||
| index, | ||
| 0 | ||
| ] | ||
| }, | ||
| [KEYS.codeSyntax]: true | ||
| }; | ||
| nodeToDecorations.get(element).push(decoration); | ||
| start = end; | ||
| } | ||
| } | ||
| return nodeToDecorations; | ||
| } | ||
| function setCodeBlockToDecorations(editor, [block, blockPath]) { | ||
| const decorations = codeBlockToDecorations(editor, [block, blockPath]); | ||
| for (const [node, decs] of decorations.entries()) CODE_LINE_TO_DECORATIONS.set(node, decs); | ||
| } | ||
| function resetCodeBlockDecorations(codeBlock) { | ||
| codeBlock.children.forEach((line) => { | ||
| CODE_LINE_TO_DECORATIONS.delete(line); | ||
| }); | ||
| } | ||
| //#endregion | ||
| //#region src/lib/transforms/deleteStartSpace.ts | ||
| const whitespaceRegex = /\s/; | ||
| /** If there is a whitespace character at the start of the code line, delete it. */ | ||
| const deleteStartSpace = (editor, { codeLine }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const codeLineStart = editor.api.start(codeLinePath); | ||
| const codeLineEnd = codeLineStart && editor.api.after(codeLineStart); | ||
| const spaceRange = codeLineEnd && editor.api.range(codeLineStart, codeLineEnd); | ||
| const spaceText = editor.api.string(spaceRange); | ||
| if (whitespaceRegex.test(spaceText)) { | ||
| editor.tf.delete({ at: spaceRange }); | ||
| return true; | ||
| } | ||
| return false; | ||
| }; | ||
| //#endregion | ||
| //#region src/lib/transforms/indentCodeLine.ts | ||
| const nonWhitespaceRegex = /\S/; | ||
| /** | ||
| * Indent if: | ||
| * | ||
| * - The selection is expanded OR | ||
| * - There are no non-whitespace characters left of the cursor Indentation = 2 | ||
| * spaces. | ||
| */ | ||
| const indentCodeLine = (editor, { codeLine, indentDepth = 2 }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const codeLineStart = editor.api.start(codeLinePath); | ||
| const indent = " ".repeat(indentDepth); | ||
| if (!editor.api.isExpanded()) { | ||
| const cursor = editor.selection?.anchor; | ||
| const range = editor.api.range(codeLineStart, cursor); | ||
| const text = editor.api.string(range); | ||
| if (nonWhitespaceRegex.test(text)) { | ||
| editor.tf.insertText(indent, { at: editor.selection }); | ||
| return; | ||
| } | ||
| } | ||
| editor.tf.insertText(indent, { at: codeLineStart }); | ||
| }; | ||
| //#endregion | ||
| //#region src/lib/transforms/outdentCodeLine.ts | ||
| /** Outdent the code line. Remove 2 whitespace characters if any. */ | ||
| const outdentCodeLine = (editor, { codeBlock, codeLine }) => { | ||
| if (deleteStartSpace(editor, { | ||
| codeBlock, | ||
| codeLine | ||
| })) deleteStartSpace(editor, { | ||
| codeBlock, | ||
| codeLine | ||
| }); | ||
| }; | ||
| //#endregion | ||
| //#region src/lib/transforms/unwrapCodeBlock.ts | ||
| const unwrapCodeBlock = (editor) => { | ||
| if (!editor.selection) return; | ||
| const codeBlockType = editor.getType(KEYS.codeBlock); | ||
| const defaultType = editor.getType(KEYS.p); | ||
| editor.tf.withoutNormalizing(() => { | ||
| const codeBlockEntries = editor.api.nodes({ | ||
| at: editor.selection, | ||
| match: { type: codeBlockType } | ||
| }); | ||
| const reversedCodeBlockEntries = Array.from(codeBlockEntries).reverse(); | ||
| for (const codeBlockEntry of reversedCodeBlockEntries) { | ||
| const codeLineEntries = NodeApi.children(editor, codeBlockEntry[1]); | ||
| for (const [, path] of codeLineEntries) editor.tf.setNodes({ type: defaultType }, { at: path }); | ||
| editor.tf.unwrapNodes({ | ||
| at: codeBlockEntry[1], | ||
| match: { type: codeBlockType }, | ||
| split: true | ||
| }); | ||
| } | ||
| }); | ||
| }; | ||
| //#endregion | ||
| //#region src/lib/withInsertDataCodeBlock.ts | ||
| const withInsertDataCodeBlock = ({ editor, tf: { insertData }, type: codeBlockType }) => ({ transforms: { insertData(data) { | ||
| const text = data.getData("text/plain"); | ||
| const vscodeDataString = data.getData("vscode-editor-data"); | ||
| const codeLineType = editor.getType(KEYS.codeLine); | ||
| if (vscodeDataString) try { | ||
| const vscodeData = JSON.parse(vscodeDataString); | ||
| const lines = text.split("\n"); | ||
| const [blockAbove$1] = editor.api.block() ?? []; | ||
| if (blockAbove$1 && [codeBlockType, codeLineType].includes(blockAbove$1?.type)) { | ||
| if (lines[0]) editor.tf.insertText(lines[0]); | ||
| if (lines.length > 1) { | ||
| const nodes = lines.slice(1).map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })); | ||
| editor.tf.insertNodes(nodes); | ||
| } | ||
| } else { | ||
| const node = { | ||
| children: lines.map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })), | ||
| lang: vscodeData?.mode, | ||
| type: codeBlockType | ||
| }; | ||
| editor.tf.insertNodes(node, { select: true }); | ||
| } | ||
| return; | ||
| } catch (_error) {} | ||
| const [blockAbove] = editor.api.block() ?? []; | ||
| if (blockAbove && [codeBlockType, codeLineType].includes(blockAbove?.type) && text?.includes("\n")) { | ||
| const lines = text.split("\n"); | ||
| if (lines[0]) editor.tf.insertText(lines[0]); | ||
| if (lines.length > 1) { | ||
| const nodes = lines.slice(1).map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })); | ||
| editor.tf.insertNodes(nodes); | ||
| } | ||
| return; | ||
| } | ||
| insertData(data); | ||
| } } }); | ||
| //#endregion | ||
| //#region src/lib/withInsertFragmentCodeBlock.ts | ||
| function extractCodeLinesFromCodeBlock(node) { | ||
| return node.children; | ||
| } | ||
| const withInsertFragmentCodeBlock = ({ editor, tf: { insertFragment }, type: codeBlockType }) => ({ transforms: { insertFragment(fragment) { | ||
| const [blockAbove] = editor.api.block() ?? []; | ||
| const codeLineType = editor.getType(KEYS.codeLine); | ||
| function convertNodeToCodeLine(node) { | ||
| return { | ||
| children: [{ text: NodeApi.string(node) }], | ||
| type: codeLineType | ||
| }; | ||
| } | ||
| if (blockAbove && [codeBlockType, codeLineType].includes(blockAbove?.type)) return insertFragment(fragment.flatMap((node) => { | ||
| const element = node; | ||
| return element.type === codeBlockType ? extractCodeLinesFromCodeBlock(element) : convertNodeToCodeLine(element); | ||
| })); | ||
| return insertFragment(fragment); | ||
| } } }); | ||
| //#endregion | ||
| //#region src/lib/withNormalizeCodeBlock.tsx | ||
| /** Normalize code block node to force the pre>code>div.codeline structure. */ | ||
| const withNormalizeCodeBlock = ({ editor, getOptions, tf: { normalizeNode }, type }) => ({ transforms: { normalizeNode([node, path]) { | ||
| if (node.type === type && getOptions().lowlight) setCodeBlockToDecorations(editor, [node, path]); | ||
| normalizeNode([node, path]); | ||
| if (!ElementApi.isElement(node)) return; | ||
| const codeBlockType = editor.getType(KEYS.codeBlock); | ||
| const codeLineType = editor.getType(KEYS.codeLine); | ||
| if (node.type === codeBlockType) { | ||
| const nonCodeLine = Array.from(NodeApi.children(editor, path)).find(([child]) => child.type !== codeLineType); | ||
| if (nonCodeLine) editor.tf.setNodes({ type: codeLineType }, { at: nonCodeLine[1] }); | ||
| } | ||
| } } }); | ||
| //#endregion | ||
| //#region src/lib/withCodeBlock.ts | ||
| const withCodeBlock = (ctx) => { | ||
| const { editor, getOptions, tf: { apply, insertBreak, resetBlock, selectAll, tab }, type } = ctx; | ||
| return { transforms: { | ||
| apply(operation) { | ||
| if (getOptions().lowlight && operation.type === "set_node") { | ||
| const entry = editor.api.node(operation.path); | ||
| if (entry?.[0].type === type && operation.newProperties?.lang) resetCodeBlockDecorations(entry[0]); | ||
| } | ||
| apply(operation); | ||
| }, | ||
| insertBreak() { | ||
| const apply$1 = () => { | ||
| if (!editor.selection) return; | ||
| const res = getCodeLineEntry(editor, {}); | ||
| if (!res) return; | ||
| const { codeBlock, codeLine } = res; | ||
| const indentDepth = getIndentDepth(editor, { | ||
| codeBlock, | ||
| codeLine | ||
| }); | ||
| insertBreak(); | ||
| indentCodeLine(editor, { | ||
| codeBlock, | ||
| codeLine, | ||
| indentDepth | ||
| }); | ||
| return true; | ||
| }; | ||
| if (apply$1()) return; | ||
| insertBreak(); | ||
| }, | ||
| resetBlock(options) { | ||
| if (editor.api.block({ | ||
| at: options?.at, | ||
| match: { type } | ||
| })) { | ||
| unwrapCodeBlock(editor); | ||
| return; | ||
| } | ||
| return resetBlock(options); | ||
| }, | ||
| selectAll: () => { | ||
| const apply$1 = () => { | ||
| const codeBlock = editor.api.above({ match: { type } }); | ||
| if (!codeBlock) return; | ||
| if (editor.api.isAt({ end: true }) && editor.api.isAt({ start: true })) return; | ||
| editor.tf.select(codeBlock[1]); | ||
| return true; | ||
| }; | ||
| if (apply$1()) return true; | ||
| return selectAll(); | ||
| }, | ||
| tab: (options) => { | ||
| const apply$1 = () => { | ||
| const _codeLines = editor.api.nodes({ match: { type } }); | ||
| const codeLines = Array.from(_codeLines); | ||
| if (codeLines.length > 0) { | ||
| const [, firstLinePath] = codeLines[0]; | ||
| const codeBlock = editor.api.parent(firstLinePath); | ||
| if (!codeBlock) return; | ||
| editor.tf.withoutNormalizing(() => { | ||
| for (const codeLine of codeLines) if (options.reverse) outdentCodeLine(editor, { | ||
| codeBlock, | ||
| codeLine | ||
| }); | ||
| else indentCodeLine(editor, { | ||
| codeBlock, | ||
| codeLine | ||
| }); | ||
| }); | ||
| return true; | ||
| } | ||
| }; | ||
| if (apply$1()) return true; | ||
| return tab(options); | ||
| }, | ||
| ...withInsertDataCodeBlock(ctx).transforms, | ||
| ...withInsertFragmentCodeBlock(ctx).transforms, | ||
| ...withNormalizeCodeBlock(ctx).transforms | ||
| } }; | ||
| }; | ||
| //#endregion | ||
| //#region src/lib/BaseCodeBlockPlugin.ts | ||
| const BaseCodeLinePlugin = createTSlatePlugin({ | ||
| key: KEYS.codeLine, | ||
| node: { | ||
| isElement: true, | ||
| isStrictSiblings: true | ||
| } | ||
| }); | ||
| const BaseCodeSyntaxPlugin = createSlatePlugin({ | ||
| key: KEYS.codeSyntax, | ||
| node: { isLeaf: true } | ||
| }); | ||
| const BaseCodeBlockPlugin = createTSlatePlugin({ | ||
| key: KEYS.codeBlock, | ||
| inject: { plugins: { [KEYS.html]: { parser: { query: ({ editor }) => !editor.api.some({ match: { type: editor.getType(KEYS.codeLine) } }) } } } }, | ||
| node: { isElement: true }, | ||
| options: { | ||
| defaultLanguage: null, | ||
| lowlight: null | ||
| }, | ||
| parsers: { html: { deserializer: htmlDeserializerCodeBlock } }, | ||
| plugins: [BaseCodeLinePlugin, BaseCodeSyntaxPlugin], | ||
| render: { as: "pre" }, | ||
| rules: { | ||
| delete: { empty: "reset" }, | ||
| match: ({ editor, rule }) => ["break.empty", "delete.empty"].includes(rule) && isCodeBlockEmpty(editor) | ||
| }, | ||
| decorate: ({ editor, entry: [node, path], getOptions, type }) => { | ||
| if (!getOptions().lowlight) return []; | ||
| const codeLineType = editor.getType(KEYS.codeLine); | ||
| if (node.type === type && !CODE_LINE_TO_DECORATIONS.get(node.children[0])) setCodeBlockToDecorations(editor, [node, path]); | ||
| if (node.type === codeLineType) return CODE_LINE_TO_DECORATIONS.get(node) || []; | ||
| return []; | ||
| } | ||
| }).overrideEditor(withCodeBlock).extendTransforms(({ editor }) => ({ toggle: () => { | ||
| editor.tf.toggleBlock(editor.getType(KEYS.codeBlock)); | ||
| } })); | ||
| //#endregion | ||
| export { getIndentDepth as _, withNormalizeCodeBlock as a, unwrapCodeBlock as c, deleteStartSpace as d, CODE_LINE_TO_DECORATIONS as f, isCodeBlockEmpty as g, setCodeBlockToDecorations as h, withCodeBlock as i, outdentCodeLine as l, resetCodeBlockDecorations as m, BaseCodeLinePlugin as n, withInsertFragmentCodeBlock as o, codeBlockToDecorations as p, BaseCodeSyntaxPlugin as r, withInsertDataCodeBlock as s, BaseCodeBlockPlugin as t, indentCodeLine as u, getCodeLineEntry as v, htmlDeserializerCodeBlock as y }; |
+108
-70
@@ -1,72 +0,87 @@ | ||
| import * as platejs from 'platejs'; | ||
| import { PluginConfig, TElement, SlateEditor, NodeEntry, TCodeBlockElement, OverrideEditor, HtmlDeserializer, Editor, ElementOf, TLocation, ElementEntry, InsertNodesOptions } from 'platejs'; | ||
| import { createLowlight } from 'lowlight'; | ||
| import * as slate from 'slate'; | ||
| import * as platejs2 from "platejs"; | ||
| import { Editor, ElementEntry, ElementOf, HtmlDeserializer, InsertNodesOptions, NodeEntry, OverrideEditor, PluginConfig, SlateEditor, TCodeBlockElement, TElement, TLocation } from "platejs"; | ||
| import { createLowlight } from "lowlight"; | ||
| import * as slate0 from "slate"; | ||
| //#region src/lib/BaseCodeBlockPlugin.d.ts | ||
| type CodeBlockConfig = PluginConfig<'code_block', { | ||
| /** | ||
| * Default language to use when no language is specified. Set to null to | ||
| * disable syntax highlighting by default. | ||
| */ | ||
| defaultLanguage?: string | null; | ||
| /** | ||
| * Lowlight instance to use for highlighting. If not provided, syntax | ||
| * highlighting will be disabled. | ||
| */ | ||
| lowlight?: ReturnType<typeof createLowlight> | null; | ||
| /** | ||
| * Default language to use when no language is specified. Set to null to | ||
| * disable syntax highlighting by default. | ||
| */ | ||
| defaultLanguage?: string | null; | ||
| /** | ||
| * Lowlight instance to use for highlighting. If not provided, syntax | ||
| * highlighting will be disabled. | ||
| */ | ||
| lowlight?: ReturnType<typeof createLowlight> | null; | ||
| }>; | ||
| declare const BaseCodeLinePlugin: platejs.SlatePlugin<PluginConfig>; | ||
| declare const BaseCodeSyntaxPlugin: platejs.SlatePlugin<PluginConfig<"code_syntax", {}, {}, {}, {}>>; | ||
| declare const BaseCodeBlockPlugin: platejs.SlatePlugin<PluginConfig<"code_block", { | ||
| /** | ||
| * Default language to use when no language is specified. Set to null to | ||
| * disable syntax highlighting by default. | ||
| */ | ||
| defaultLanguage?: string | null; | ||
| /** | ||
| * Lowlight instance to use for highlighting. If not provided, syntax | ||
| * highlighting will be disabled. | ||
| */ | ||
| lowlight?: ReturnType<typeof createLowlight> | null; | ||
| declare const BaseCodeLinePlugin: platejs2.SlatePlugin<PluginConfig<any, {}, {}, {}, {}>>; | ||
| declare const BaseCodeSyntaxPlugin: platejs2.SlatePlugin<PluginConfig<"code_syntax", {}, {}, {}, {}>>; | ||
| declare const BaseCodeBlockPlugin: platejs2.SlatePlugin<PluginConfig<"code_block", { | ||
| /** | ||
| * Default language to use when no language is specified. Set to null to | ||
| * disable syntax highlighting by default. | ||
| */ | ||
| defaultLanguage?: string | null; | ||
| /** | ||
| * Lowlight instance to use for highlighting. If not provided, syntax | ||
| * highlighting will be disabled. | ||
| */ | ||
| lowlight?: ReturnType<typeof createLowlight> | null; | ||
| }, {}, Record<"code_block", { | ||
| toggle: () => void; | ||
| toggle: () => void; | ||
| }>, {}>>; | ||
| declare const CODE_LINE_TO_DECORATIONS: WeakMap<TElement, slate.DecoratedRange[]>; | ||
| declare function codeBlockToDecorations(editor: SlateEditor, [block, blockPath]: NodeEntry<TCodeBlockElement>): Map<TElement, slate.DecoratedRange[]>; | ||
| //#endregion | ||
| //#region src/lib/setCodeBlockToDecorations.d.ts | ||
| declare const CODE_LINE_TO_DECORATIONS: WeakMap<TElement, slate0.DecoratedRange[]>; | ||
| declare function codeBlockToDecorations(editor: SlateEditor, [block, blockPath]: NodeEntry<TCodeBlockElement>): Map<TElement, slate0.DecoratedRange[]>; | ||
| declare function setCodeBlockToDecorations(editor: SlateEditor, [block, blockPath]: NodeEntry<TCodeBlockElement>): void; | ||
| declare function resetCodeBlockDecorations(codeBlock: TCodeBlockElement): void; | ||
| //#endregion | ||
| //#region src/lib/withCodeBlock.d.ts | ||
| declare const withCodeBlock: OverrideEditor<CodeBlockConfig>; | ||
| //#endregion | ||
| //#region src/lib/withInsertDataCodeBlock.d.ts | ||
| declare const withInsertDataCodeBlock: OverrideEditor; | ||
| //#endregion | ||
| //#region src/lib/withInsertFragmentCodeBlock.d.ts | ||
| declare const withInsertFragmentCodeBlock: OverrideEditor; | ||
| //#endregion | ||
| //#region src/lib/withNormalizeCodeBlock.d.ts | ||
| /** Normalize code block node to force the pre>code>div.codeline structure. */ | ||
| declare const withNormalizeCodeBlock: OverrideEditor<CodeBlockConfig>; | ||
| //#endregion | ||
| //#region src/lib/deserializer/htmlDeserializerCodeBlock.d.ts | ||
| declare const htmlDeserializerCodeBlock: HtmlDeserializer; | ||
| //#endregion | ||
| //#region src/lib/formatter/formatter.d.ts | ||
| declare const isLangSupported: (lang?: string) => boolean; | ||
| declare const isValidSyntax: (code: string, lang?: string) => boolean; | ||
| declare const formatCodeBlock: (editor: Editor, { element, }: { | ||
| element: TCodeBlockElement; | ||
| declare const formatCodeBlock: (editor: Editor, { | ||
| element | ||
| }: { | ||
| element: TCodeBlockElement; | ||
| }) => void; | ||
| //#endregion | ||
| //#region src/lib/formatter/jsonFormatter.d.ts | ||
| declare const formatJson: (code: string) => string; | ||
| declare const isValidJson: (code: string) => boolean; | ||
| //#endregion | ||
| //#region src/lib/queries/getCodeLineEntry.d.ts | ||
| /** If at (default = selection) is in ul>li>p, return li and ul node entries. */ | ||
| declare const getCodeLineEntry: <N extends ElementOf<E>, E extends SlateEditor>(editor: E, { at }?: { | ||
| at?: TLocation | null; | ||
| declare const getCodeLineEntry: <N extends ElementOf<E>, E extends SlateEditor>(editor: E, { | ||
| at | ||
| }?: { | ||
| at?: TLocation | null; | ||
| }) => { | ||
| codeBlock: NodeEntry<N>; | ||
| codeLine: NodeEntry<N>; | ||
| codeBlock: NodeEntry<N>; | ||
| codeLine: NodeEntry<N>; | ||
| } | undefined; | ||
| //#endregion | ||
| //#region src/lib/transforms/indentCodeLine.d.ts | ||
| type IndentCodeLineOptions = { | ||
| codeBlock: ElementEntry; | ||
| codeLine: ElementEntry; | ||
| indentDepth?: number; | ||
| codeBlock: ElementEntry; | ||
| codeLine: ElementEntry; | ||
| indentDepth?: number; | ||
| }; | ||
@@ -80,22 +95,38 @@ /** | ||
| */ | ||
| declare const indentCodeLine: (editor: Editor, { codeLine, indentDepth }: IndentCodeLineOptions) => void; | ||
| declare const getIndentDepth: (editor: Editor, { codeLine }: IndentCodeLineOptions) => number; | ||
| declare const indentCodeLine: (editor: Editor, { | ||
| codeLine, | ||
| indentDepth | ||
| }: IndentCodeLineOptions) => void; | ||
| //#endregion | ||
| //#region src/lib/queries/getIndentDepth.d.ts | ||
| declare const getIndentDepth: (editor: Editor, { | ||
| codeLine | ||
| }: IndentCodeLineOptions) => number; | ||
| //#endregion | ||
| //#region src/lib/queries/isCodeBlockEmpty.d.ts | ||
| /** Is the selection inside an empty code block */ | ||
| declare const isCodeBlockEmpty: (editor: SlateEditor) => boolean; | ||
| //#endregion | ||
| //#region src/lib/queries/isSelectionAtCodeBlockStart.d.ts | ||
| /** Is the selection at the start of the first code line in a code block */ | ||
| declare const isSelectionAtCodeBlockStart: (editor: SlateEditor) => boolean; | ||
| //#endregion | ||
| //#region src/lib/transforms/outdentCodeLine.d.ts | ||
| type OutdentCodeLineOptions = { | ||
| codeBlock: ElementEntry; | ||
| codeLine: ElementEntry; | ||
| codeBlock: ElementEntry; | ||
| codeLine: ElementEntry; | ||
| }; | ||
| /** Outdent the code line. Remove 2 whitespace characters if any. */ | ||
| declare const outdentCodeLine: (editor: Editor, { codeBlock, codeLine }: OutdentCodeLineOptions) => void; | ||
| declare const outdentCodeLine: (editor: Editor, { | ||
| codeBlock, | ||
| codeLine | ||
| }: OutdentCodeLineOptions) => void; | ||
| //#endregion | ||
| //#region src/lib/transforms/deleteStartSpace.d.ts | ||
| /** If there is a whitespace character at the start of the code line, delete it. */ | ||
| declare const deleteStartSpace: (editor: Editor, { codeLine }: OutdentCodeLineOptions) => boolean; | ||
| declare const deleteStartSpace: (editor: Editor, { | ||
| codeLine | ||
| }: OutdentCodeLineOptions) => boolean; | ||
| //#endregion | ||
| //#region src/lib/transforms/insertCodeBlock.d.ts | ||
| /** | ||
@@ -106,9 +137,11 @@ * Insert a code block: set the node to code line and wrap it with a code block. | ||
| declare const insertCodeBlock: (editor: SlateEditor, insertNodesOptions?: Omit<InsertNodesOptions, "match">) => void; | ||
| //#endregion | ||
| //#region src/lib/transforms/insertCodeLine.d.ts | ||
| /** Insert a code line starting with indentation. */ | ||
| declare const insertCodeLine: (editor: SlateEditor, indentDepth?: number) => void; | ||
| //#endregion | ||
| //#region src/lib/transforms/insertEmptyCodeBlock.d.ts | ||
| type CodeBlockInsertOptions = { | ||
| defaultType?: string; | ||
| insertNodesOptions?: Omit<InsertNodesOptions, 'match'>; | ||
| defaultType?: string; | ||
| insertNodesOptions?: Omit<InsertNodesOptions, 'match'>; | ||
| }; | ||
@@ -119,8 +152,13 @@ /** | ||
| */ | ||
| declare const insertEmptyCodeBlock: (editor: SlateEditor, { defaultType, insertNodesOptions, }?: CodeBlockInsertOptions) => void; | ||
| declare const insertEmptyCodeBlock: (editor: SlateEditor, { | ||
| defaultType, | ||
| insertNodesOptions | ||
| }?: CodeBlockInsertOptions) => void; | ||
| //#endregion | ||
| //#region src/lib/transforms/toggleCodeBlock.d.ts | ||
| declare const toggleCodeBlock: (editor: SlateEditor) => void; | ||
| //#endregion | ||
| //#region src/lib/transforms/unwrapCodeBlock.d.ts | ||
| declare const unwrapCodeBlock: (editor: SlateEditor) => void; | ||
| export { BaseCodeBlockPlugin, BaseCodeLinePlugin, BaseCodeSyntaxPlugin, CODE_LINE_TO_DECORATIONS, type CodeBlockConfig, type CodeBlockInsertOptions, type IndentCodeLineOptions, type OutdentCodeLineOptions, codeBlockToDecorations, deleteStartSpace, formatCodeBlock, formatJson, getCodeLineEntry, getIndentDepth, htmlDeserializerCodeBlock, indentCodeLine, insertCodeBlock, insertCodeLine, insertEmptyCodeBlock, isCodeBlockEmpty, isLangSupported, isSelectionAtCodeBlockStart, isValidJson, isValidSyntax, outdentCodeLine, resetCodeBlockDecorations, setCodeBlockToDecorations, toggleCodeBlock, unwrapCodeBlock, withCodeBlock, withInsertDataCodeBlock, withInsertFragmentCodeBlock, withNormalizeCodeBlock }; | ||
| //#endregion | ||
| export { BaseCodeBlockPlugin, BaseCodeLinePlugin, BaseCodeSyntaxPlugin, CODE_LINE_TO_DECORATIONS, CodeBlockConfig, CodeBlockInsertOptions, IndentCodeLineOptions, OutdentCodeLineOptions, codeBlockToDecorations, deleteStartSpace, formatCodeBlock, formatJson, getCodeLineEntry, getIndentDepth, htmlDeserializerCodeBlock, indentCodeLine, insertCodeBlock, insertCodeLine, insertEmptyCodeBlock, isCodeBlockEmpty, isLangSupported, isSelectionAtCodeBlockStart, isValidJson, isValidSyntax, outdentCodeLine, resetCodeBlockDecorations, setCodeBlockToDecorations, toggleCodeBlock, unwrapCodeBlock, withCodeBlock, withInsertDataCodeBlock, withInsertFragmentCodeBlock, withNormalizeCodeBlock }; |
+115
-768
@@ -1,786 +0,133 @@ | ||
| "use strict"; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| import { _ as getIndentDepth, a as withNormalizeCodeBlock, c as unwrapCodeBlock, d as deleteStartSpace, f as CODE_LINE_TO_DECORATIONS, g as isCodeBlockEmpty, h as setCodeBlockToDecorations, i as withCodeBlock, l as outdentCodeLine, m as resetCodeBlockDecorations, n as BaseCodeLinePlugin, o as withInsertFragmentCodeBlock, p as codeBlockToDecorations, r as BaseCodeSyntaxPlugin, s as withInsertDataCodeBlock, t as BaseCodeBlockPlugin, u as indentCodeLine, v as getCodeLineEntry, y as htmlDeserializerCodeBlock } from "./BaseCodeBlockPlugin-BntJ075t.js"; | ||
| import { KEYS } from "platejs"; | ||
| // src/index.ts | ||
| var index_exports = {}; | ||
| __export(index_exports, { | ||
| BaseCodeBlockPlugin: () => BaseCodeBlockPlugin, | ||
| BaseCodeLinePlugin: () => BaseCodeLinePlugin, | ||
| BaseCodeSyntaxPlugin: () => BaseCodeSyntaxPlugin, | ||
| CODE_LINE_TO_DECORATIONS: () => CODE_LINE_TO_DECORATIONS, | ||
| codeBlockToDecorations: () => codeBlockToDecorations, | ||
| deleteStartSpace: () => deleteStartSpace, | ||
| formatCodeBlock: () => formatCodeBlock, | ||
| formatJson: () => formatJson, | ||
| getCodeLineEntry: () => getCodeLineEntry, | ||
| getIndentDepth: () => getIndentDepth, | ||
| htmlDeserializerCodeBlock: () => htmlDeserializerCodeBlock, | ||
| indentCodeLine: () => indentCodeLine, | ||
| insertCodeBlock: () => insertCodeBlock, | ||
| insertCodeLine: () => insertCodeLine, | ||
| insertEmptyCodeBlock: () => insertEmptyCodeBlock, | ||
| isCodeBlockEmpty: () => isCodeBlockEmpty, | ||
| isLangSupported: () => isLangSupported, | ||
| isSelectionAtCodeBlockStart: () => isSelectionAtCodeBlockStart, | ||
| isValidJson: () => isValidJson, | ||
| isValidSyntax: () => isValidSyntax, | ||
| outdentCodeLine: () => outdentCodeLine, | ||
| resetCodeBlockDecorations: () => resetCodeBlockDecorations, | ||
| setCodeBlockToDecorations: () => setCodeBlockToDecorations, | ||
| toggleCodeBlock: () => toggleCodeBlock, | ||
| unwrapCodeBlock: () => unwrapCodeBlock, | ||
| withCodeBlock: () => withCodeBlock, | ||
| withInsertDataCodeBlock: () => withInsertDataCodeBlock, | ||
| withInsertFragmentCodeBlock: () => withInsertFragmentCodeBlock, | ||
| withNormalizeCodeBlock: () => withNormalizeCodeBlock | ||
| }); | ||
| module.exports = __toCommonJS(index_exports); | ||
| // src/lib/BaseCodeBlockPlugin.ts | ||
| var import_platejs13 = require("platejs"); | ||
| // src/lib/deserializer/htmlDeserializerCodeBlock.ts | ||
| var import_platejs = require("platejs"); | ||
| var htmlDeserializerCodeBlock = { | ||
| rules: [ | ||
| { | ||
| validNodeName: "PRE" | ||
| }, | ||
| { | ||
| validNodeName: "P", | ||
| validStyle: { | ||
| fontFamily: "Consolas" | ||
| } | ||
| } | ||
| ], | ||
| parse: ({ element }) => { | ||
| const languageSelectorText = [...element.childNodes].find( | ||
| (node) => node.nodeName === "SELECT" | ||
| )?.textContent || ""; | ||
| const textContent = element.textContent?.replace(languageSelectorText, "") || ""; | ||
| let lines = textContent.split("\n"); | ||
| if (!lines?.length) { | ||
| lines = [textContent]; | ||
| } | ||
| const codeLines = lines.map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: import_platejs.KEYS.codeLine | ||
| })); | ||
| return { | ||
| children: codeLines, | ||
| type: import_platejs.KEYS.codeBlock | ||
| }; | ||
| } | ||
| //#region src/lib/queries/isSelectionAtCodeBlockStart.ts | ||
| /** Is the selection at the start of the first code line in a code block */ | ||
| const isSelectionAtCodeBlockStart = (editor) => { | ||
| const { selection } = editor; | ||
| if (!selection || editor.api.isExpanded()) return false; | ||
| const { codeBlock } = getCodeLineEntry(editor) ?? {}; | ||
| if (!codeBlock) return false; | ||
| return editor.api.isStart(selection.anchor, codeBlock[1]); | ||
| }; | ||
| // src/lib/queries/getCodeLineEntry.ts | ||
| var import_platejs2 = require("platejs"); | ||
| var getCodeLineEntry = (editor, { at = editor.selection } = {}) => { | ||
| if (at && editor.api.some({ | ||
| at, | ||
| match: { type: editor.getType(import_platejs2.KEYS.codeLine) } | ||
| })) { | ||
| const selectionParent = editor.api.parent(at); | ||
| if (!selectionParent) return; | ||
| const [, parentPath] = selectionParent; | ||
| const codeLine = editor.api.above({ | ||
| at, | ||
| match: { type: editor.getType(import_platejs2.KEYS.codeLine) } | ||
| }) || editor.api.parent(parentPath); | ||
| if (!codeLine) return; | ||
| const [codeLineNode, codeLinePath] = codeLine; | ||
| if (import_platejs2.ElementApi.isElement(codeLineNode) && codeLineNode.type !== editor.getType(import_platejs2.KEYS.codeLine)) | ||
| return; | ||
| const codeBlock = editor.api.parent(codeLinePath); | ||
| if (!codeBlock) return; | ||
| return { | ||
| codeBlock, | ||
| codeLine | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/lib/transforms/insertCodeBlock.ts | ||
| /** | ||
| * Insert a code block: set the node to code line and wrap it with a code block. | ||
| * If the cursor is not at the block start, insert break before. | ||
| */ | ||
| const insertCodeBlock = (editor, insertNodesOptions = {}) => { | ||
| if (!editor.selection || editor.api.isExpanded()) return; | ||
| const matchCodeElements = (node) => node.type === KEYS.codeBlock || node.type === KEYS.codeLine; | ||
| if (editor.api.some({ match: matchCodeElements })) return; | ||
| if (!editor.api.isAt({ start: true })) editor.tf.insertBreak(); | ||
| editor.tf.setNodes({ | ||
| children: [{ text: "" }], | ||
| type: KEYS.codeLine | ||
| }, insertNodesOptions); | ||
| editor.tf.wrapNodes({ | ||
| children: [], | ||
| type: KEYS.codeBlock | ||
| }, insertNodesOptions); | ||
| }; | ||
| // src/lib/queries/getIndentDepth.ts | ||
| var nonWhitespaceOrEndRegex = /\S|$/; | ||
| var getIndentDepth = (editor, { codeLine }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const text = editor.api.string(codeLinePath); | ||
| return text.search(nonWhitespaceOrEndRegex); | ||
| //#endregion | ||
| //#region src/lib/transforms/insertCodeLine.ts | ||
| /** Insert a code line starting with indentation. */ | ||
| const insertCodeLine = (editor, indentDepth = 0) => { | ||
| if (editor.selection) { | ||
| const indent = " ".repeat(indentDepth); | ||
| editor.tf.insertNodes({ | ||
| children: [{ text: indent }], | ||
| type: editor.getType(KEYS.codeLine) | ||
| }); | ||
| } | ||
| }; | ||
| // src/lib/queries/isCodeBlockEmpty.ts | ||
| var import_platejs3 = require("platejs"); | ||
| var isCodeBlockEmpty = (editor) => { | ||
| const { codeBlock } = getCodeLineEntry(editor) ?? {}; | ||
| if (!codeBlock) return false; | ||
| const codeLines = Array.from(import_platejs3.NodeApi.children(editor, codeBlock[1])); | ||
| if (codeLines.length === 0) return true; | ||
| if (codeLines.length > 1) return false; | ||
| const firstCodeLineNode = codeLines[0][0]; | ||
| return !import_platejs3.NodeApi.string(firstCodeLineNode); | ||
| //#endregion | ||
| //#region src/lib/transforms/insertEmptyCodeBlock.ts | ||
| /** | ||
| * Called by toolbars to make sure a code-block gets inserted below a paragraph | ||
| * rather than awkwardly splitting the current selection. | ||
| */ | ||
| const insertEmptyCodeBlock = (editor, { defaultType = editor.getType(KEYS.p), insertNodesOptions } = {}) => { | ||
| if (!editor.selection) return; | ||
| if (editor.api.isExpanded() || !editor.api.isEmpty(editor.selection, { block: true })) editor.tf.insertNodes(editor.api.create.block({ | ||
| children: [{ text: "" }], | ||
| type: defaultType | ||
| }), { | ||
| nextBlock: true, | ||
| select: true, | ||
| ...insertNodesOptions | ||
| }); | ||
| insertCodeBlock(editor, insertNodesOptions); | ||
| }; | ||
| // src/lib/queries/isSelectionAtCodeBlockStart.ts | ||
| var isSelectionAtCodeBlockStart = (editor) => { | ||
| const { selection } = editor; | ||
| if (!selection || editor.api.isExpanded()) return false; | ||
| const { codeBlock } = getCodeLineEntry(editor) ?? {}; | ||
| if (!codeBlock) return false; | ||
| return editor.api.isStart(selection.anchor, codeBlock[1]); | ||
| //#endregion | ||
| //#region src/lib/transforms/toggleCodeBlock.ts | ||
| const toggleCodeBlock = (editor) => { | ||
| if (!editor.selection) return; | ||
| const codeBlockType = editor.getType(KEYS.codeBlock); | ||
| const codeLineType = editor.getType(KEYS.codeLine); | ||
| const isActive = editor.api.some({ match: { type: codeBlockType } }); | ||
| editor.tf.withoutNormalizing(() => { | ||
| unwrapCodeBlock(editor); | ||
| if (!isActive) { | ||
| editor.tf.setNodes({ type: codeLineType }); | ||
| const codeBlock = { | ||
| children: [], | ||
| type: codeBlockType | ||
| }; | ||
| editor.tf.wrapNodes(codeBlock); | ||
| } | ||
| }); | ||
| }; | ||
| // src/lib/setCodeBlockToDecorations.ts | ||
| var import_platejs4 = require("platejs"); | ||
| var CODE_LINE_TO_DECORATIONS = /* @__PURE__ */ new WeakMap(); | ||
| function getHighlightNodes(result) { | ||
| return result.value || result.children || []; | ||
| } | ||
| function parseNodes(nodes, className = []) { | ||
| return nodes.flatMap((node) => { | ||
| const classes = [ | ||
| ...className, | ||
| ...node.properties ? node.properties.className : [] | ||
| ]; | ||
| if (node.children) { | ||
| return parseNodes(node.children, classes); | ||
| } | ||
| return { classes, text: node.value }; | ||
| }); | ||
| } | ||
| function normalizeTokens(tokens) { | ||
| const lines = [[]]; | ||
| let currentLine = lines[0]; | ||
| for (const token of tokens) { | ||
| const tokenLines = token.text.split("\n"); | ||
| for (let i = 0; i < tokenLines.length; i++) { | ||
| const content = tokenLines[i]; | ||
| if (content) { | ||
| currentLine.push({ classes: token.classes, content }); | ||
| } | ||
| if (i < tokenLines.length - 1) { | ||
| lines.push([]); | ||
| currentLine = lines.at(-1); | ||
| } | ||
| } | ||
| } | ||
| return lines; | ||
| } | ||
| function codeBlockToDecorations(editor, [block, blockPath]) { | ||
| const { defaultLanguage, ...options } = editor.getOptions(BaseCodeBlockPlugin); | ||
| const lowlight = options.lowlight; | ||
| const text = block.children.map((line) => import_platejs4.NodeApi.string(line)).join("\n"); | ||
| const language = block.lang; | ||
| const effectiveLanguage = language || defaultLanguage; | ||
| let highlighted; | ||
| try { | ||
| if (!effectiveLanguage || effectiveLanguage === "plaintext") { | ||
| highlighted = { value: [] }; | ||
| } else if (effectiveLanguage === "auto") { | ||
| highlighted = lowlight.highlightAuto(text); | ||
| } else { | ||
| highlighted = lowlight.highlight(effectiveLanguage, text); | ||
| } | ||
| } catch (error) { | ||
| const availableLanguages = lowlight.listLanguages(); | ||
| const isLanguageRegistered = effectiveLanguage && availableLanguages.includes(effectiveLanguage); | ||
| if (isLanguageRegistered) { | ||
| editor.api.debug.error(error, "CODE_HIGHLIGHT"); | ||
| highlighted = { value: [] }; | ||
| } else { | ||
| editor.api.debug.warn( | ||
| `Language "${effectiveLanguage}" is not registered. Falling back to plaintext` | ||
| ); | ||
| highlighted = { value: [] }; | ||
| } | ||
| } | ||
| const tokens = parseNodes(getHighlightNodes(highlighted)); | ||
| const normalizedTokens = normalizeTokens(tokens); | ||
| const blockChildren = block.children; | ||
| const nodeToDecorations = /* @__PURE__ */ new Map(); | ||
| const numLines = Math.min(normalizedTokens.length, blockChildren.length); | ||
| for (let index = 0; index < numLines; index++) { | ||
| const lineTokens = normalizedTokens[index]; | ||
| const element = blockChildren[index]; | ||
| if (!nodeToDecorations.has(element)) { | ||
| nodeToDecorations.set(element, []); | ||
| } | ||
| let start = 0; | ||
| for (const token of lineTokens) { | ||
| const length = token.content.length; | ||
| if (!length) continue; | ||
| const end = start + length; | ||
| const decoration = { | ||
| anchor: { | ||
| offset: start, | ||
| path: [...blockPath, index, 0] | ||
| }, | ||
| className: token.classes.join(" "), | ||
| focus: { | ||
| offset: end, | ||
| path: [...blockPath, index, 0] | ||
| }, | ||
| [import_platejs4.KEYS.codeSyntax]: true | ||
| }; | ||
| nodeToDecorations.get(element).push(decoration); | ||
| start = end; | ||
| } | ||
| } | ||
| return nodeToDecorations; | ||
| } | ||
| function setCodeBlockToDecorations(editor, [block, blockPath]) { | ||
| const decorations = codeBlockToDecorations(editor, [block, blockPath]); | ||
| for (const [node, decs] of decorations.entries()) { | ||
| CODE_LINE_TO_DECORATIONS.set(node, decs); | ||
| } | ||
| } | ||
| function resetCodeBlockDecorations(codeBlock) { | ||
| codeBlock.children.forEach((line) => { | ||
| CODE_LINE_TO_DECORATIONS.delete(line); | ||
| }); | ||
| } | ||
| // src/lib/transforms/deleteStartSpace.ts | ||
| var whitespaceRegex = /\s/; | ||
| var deleteStartSpace = (editor, { codeLine }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const codeLineStart = editor.api.start(codeLinePath); | ||
| const codeLineEnd = codeLineStart && editor.api.after(codeLineStart); | ||
| const spaceRange = codeLineEnd && editor.api.range(codeLineStart, codeLineEnd); | ||
| const spaceText = editor.api.string(spaceRange); | ||
| if (whitespaceRegex.test(spaceText)) { | ||
| editor.tf.delete({ at: spaceRange }); | ||
| return true; | ||
| } | ||
| return false; | ||
| //#endregion | ||
| //#region src/lib/formatter/jsonFormatter.ts | ||
| const formatJson = (code) => { | ||
| try { | ||
| return JSON.stringify(JSON.parse(code), null, 2); | ||
| } catch (_error) { | ||
| return code; | ||
| } | ||
| }; | ||
| // src/lib/transforms/indentCodeLine.ts | ||
| var nonWhitespaceRegex = /\S/; | ||
| var indentCodeLine = (editor, { codeLine, indentDepth = 2 }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const codeLineStart = editor.api.start(codeLinePath); | ||
| const indent = " ".repeat(indentDepth); | ||
| if (!editor.api.isExpanded()) { | ||
| const cursor = editor.selection?.anchor; | ||
| const range = editor.api.range(codeLineStart, cursor); | ||
| const text = editor.api.string(range); | ||
| if (nonWhitespaceRegex.test(text)) { | ||
| editor.tf.insertText(indent, { at: editor.selection }); | ||
| return; | ||
| } | ||
| } | ||
| editor.tf.insertText(indent, { at: codeLineStart }); | ||
| const isValidJson = (code) => { | ||
| try { | ||
| JSON.parse(code); | ||
| return true; | ||
| } catch (_error) { | ||
| return false; | ||
| } | ||
| }; | ||
| // src/lib/transforms/insertCodeBlock.ts | ||
| var import_platejs5 = require("platejs"); | ||
| var insertCodeBlock = (editor, insertNodesOptions = {}) => { | ||
| if (!editor.selection || editor.api.isExpanded()) return; | ||
| const matchCodeElements = (node) => node.type === import_platejs5.KEYS.codeBlock || node.type === import_platejs5.KEYS.codeLine; | ||
| if (editor.api.some({ | ||
| match: matchCodeElements | ||
| })) { | ||
| return; | ||
| } | ||
| if (!editor.api.isAt({ start: true })) { | ||
| editor.tf.insertBreak(); | ||
| } | ||
| editor.tf.setNodes( | ||
| { | ||
| children: [{ text: "" }], | ||
| type: import_platejs5.KEYS.codeLine | ||
| }, | ||
| insertNodesOptions | ||
| ); | ||
| editor.tf.wrapNodes( | ||
| { | ||
| children: [], | ||
| type: import_platejs5.KEYS.codeBlock | ||
| }, | ||
| insertNodesOptions | ||
| ); | ||
| //#endregion | ||
| //#region src/lib/formatter/formatter.ts | ||
| const supportedLanguages = new Set(["json"]); | ||
| const isLangSupported = (lang) => Boolean(lang && supportedLanguages.has(lang)); | ||
| const isValidSyntax = (code, lang) => { | ||
| if (!isLangSupported(lang)) return false; | ||
| switch (lang) { | ||
| case "json": return isValidJson(code); | ||
| default: return false; | ||
| } | ||
| }; | ||
| // src/lib/transforms/insertCodeLine.ts | ||
| var import_platejs6 = require("platejs"); | ||
| var insertCodeLine = (editor, indentDepth = 0) => { | ||
| if (editor.selection) { | ||
| const indent = " ".repeat(indentDepth); | ||
| editor.tf.insertNodes({ | ||
| children: [{ text: indent }], | ||
| type: editor.getType(import_platejs6.KEYS.codeLine) | ||
| }); | ||
| } | ||
| const formatCodeBlock = (editor, { element }) => { | ||
| const { lang } = element; | ||
| if (!lang || !isLangSupported(lang)) return; | ||
| const code = editor.api.string(element); | ||
| if (isValidSyntax(code, lang)) { | ||
| const formattedCode = formatCode(code, lang); | ||
| editor.tf.insertText(formattedCode, { at: element }); | ||
| } | ||
| }; | ||
| // src/lib/transforms/insertEmptyCodeBlock.ts | ||
| var import_platejs7 = require("platejs"); | ||
| var insertEmptyCodeBlock = (editor, { | ||
| defaultType = editor.getType(import_platejs7.KEYS.p), | ||
| insertNodesOptions | ||
| } = {}) => { | ||
| if (!editor.selection) return; | ||
| if (editor.api.isExpanded() || !editor.api.isEmpty(editor.selection, { block: true })) { | ||
| editor.tf.insertNodes( | ||
| editor.api.create.block({ children: [{ text: "" }], type: defaultType }), | ||
| { | ||
| nextBlock: true, | ||
| select: true, | ||
| ...insertNodesOptions | ||
| } | ||
| ); | ||
| } | ||
| insertCodeBlock(editor, insertNodesOptions); | ||
| const formatCode = (code, lang) => { | ||
| switch (lang) { | ||
| case "json": return formatJson(code); | ||
| default: return code; | ||
| } | ||
| }; | ||
| // src/lib/transforms/outdentCodeLine.ts | ||
| var outdentCodeLine = (editor, { codeBlock, codeLine }) => { | ||
| const deleted = deleteStartSpace(editor, { codeBlock, codeLine }); | ||
| if (deleted) { | ||
| deleteStartSpace(editor, { codeBlock, codeLine }); | ||
| } | ||
| }; | ||
| // src/lib/transforms/toggleCodeBlock.ts | ||
| var import_platejs9 = require("platejs"); | ||
| // src/lib/transforms/unwrapCodeBlock.ts | ||
| var import_platejs8 = require("platejs"); | ||
| var unwrapCodeBlock = (editor) => { | ||
| if (!editor.selection) return; | ||
| const codeBlockType = editor.getType(import_platejs8.KEYS.codeBlock); | ||
| const defaultType = editor.getType(import_platejs8.KEYS.p); | ||
| editor.tf.withoutNormalizing(() => { | ||
| const codeBlockEntries = editor.api.nodes({ | ||
| at: editor.selection, | ||
| match: { type: codeBlockType } | ||
| }); | ||
| const reversedCodeBlockEntries = Array.from(codeBlockEntries).reverse(); | ||
| for (const codeBlockEntry of reversedCodeBlockEntries) { | ||
| const codeLineEntries = import_platejs8.NodeApi.children(editor, codeBlockEntry[1]); | ||
| for (const [, path] of codeLineEntries) { | ||
| editor.tf.setNodes({ type: defaultType }, { at: path }); | ||
| } | ||
| editor.tf.unwrapNodes({ | ||
| at: codeBlockEntry[1], | ||
| match: { type: codeBlockType }, | ||
| split: true | ||
| }); | ||
| } | ||
| }); | ||
| }; | ||
| // src/lib/transforms/toggleCodeBlock.ts | ||
| var toggleCodeBlock = (editor) => { | ||
| if (!editor.selection) return; | ||
| const codeBlockType = editor.getType(import_platejs9.KEYS.codeBlock); | ||
| const codeLineType = editor.getType(import_platejs9.KEYS.codeLine); | ||
| const isActive = editor.api.some({ | ||
| match: { type: codeBlockType } | ||
| }); | ||
| editor.tf.withoutNormalizing(() => { | ||
| unwrapCodeBlock(editor); | ||
| if (!isActive) { | ||
| editor.tf.setNodes({ | ||
| type: codeLineType | ||
| }); | ||
| const codeBlock = { | ||
| children: [], | ||
| type: codeBlockType | ||
| }; | ||
| editor.tf.wrapNodes(codeBlock); | ||
| } | ||
| }); | ||
| }; | ||
| // src/lib/withInsertDataCodeBlock.ts | ||
| var import_platejs10 = require("platejs"); | ||
| var withInsertDataCodeBlock = ({ | ||
| editor, | ||
| tf: { insertData }, | ||
| type: codeBlockType | ||
| }) => ({ | ||
| transforms: { | ||
| insertData(data) { | ||
| const text = data.getData("text/plain"); | ||
| const vscodeDataString = data.getData("vscode-editor-data"); | ||
| const codeLineType = editor.getType(import_platejs10.KEYS.codeLine); | ||
| if (vscodeDataString) { | ||
| try { | ||
| const vscodeData = JSON.parse(vscodeDataString); | ||
| const lines = text.split("\n"); | ||
| const [blockAbove2] = editor.api.block() ?? []; | ||
| const isInCodeBlock = blockAbove2 && [codeBlockType, codeLineType].includes(blockAbove2?.type); | ||
| if (isInCodeBlock) { | ||
| if (lines[0]) { | ||
| editor.tf.insertText(lines[0]); | ||
| } | ||
| if (lines.length > 1) { | ||
| const nodes = lines.slice(1).map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })); | ||
| editor.tf.insertNodes(nodes); | ||
| } | ||
| } else { | ||
| const node = { | ||
| children: lines.map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })), | ||
| lang: vscodeData?.mode, | ||
| type: codeBlockType | ||
| }; | ||
| editor.tf.insertNodes(node, { | ||
| select: true | ||
| }); | ||
| } | ||
| return; | ||
| } catch (_error) { | ||
| } | ||
| } | ||
| const [blockAbove] = editor.api.block() ?? []; | ||
| if (blockAbove && [codeBlockType, codeLineType].includes(blockAbove?.type) && text?.includes("\n")) { | ||
| const lines = text.split("\n"); | ||
| if (lines[0]) { | ||
| editor.tf.insertText(lines[0]); | ||
| } | ||
| if (lines.length > 1) { | ||
| const nodes = lines.slice(1).map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })); | ||
| editor.tf.insertNodes(nodes); | ||
| } | ||
| return; | ||
| } | ||
| insertData(data); | ||
| } | ||
| } | ||
| }); | ||
| // src/lib/withInsertFragmentCodeBlock.ts | ||
| var import_platejs11 = require("platejs"); | ||
| function extractCodeLinesFromCodeBlock(node) { | ||
| return node.children; | ||
| } | ||
| var withInsertFragmentCodeBlock = ({ | ||
| editor, | ||
| tf: { insertFragment }, | ||
| type: codeBlockType | ||
| }) => ({ | ||
| transforms: { | ||
| insertFragment(fragment) { | ||
| const [blockAbove] = editor.api.block() ?? []; | ||
| const codeLineType = editor.getType(import_platejs11.KEYS.codeLine); | ||
| function convertNodeToCodeLine(node) { | ||
| return { | ||
| children: [{ text: import_platejs11.NodeApi.string(node) }], | ||
| type: codeLineType | ||
| }; | ||
| } | ||
| if (blockAbove && [codeBlockType, codeLineType].includes(blockAbove?.type)) { | ||
| return insertFragment( | ||
| fragment.flatMap((node) => { | ||
| const element = node; | ||
| return element.type === codeBlockType ? extractCodeLinesFromCodeBlock(element) : convertNodeToCodeLine(element); | ||
| }) | ||
| ); | ||
| } | ||
| return insertFragment(fragment); | ||
| } | ||
| } | ||
| }); | ||
| // src/lib/withNormalizeCodeBlock.tsx | ||
| var import_platejs12 = require("platejs"); | ||
| var withNormalizeCodeBlock = ({ | ||
| editor, | ||
| getOptions, | ||
| tf: { normalizeNode }, | ||
| type | ||
| }) => ({ | ||
| transforms: { | ||
| normalizeNode([node, path]) { | ||
| if (node.type === type && getOptions().lowlight) { | ||
| setCodeBlockToDecorations(editor, [ | ||
| node, | ||
| path | ||
| ]); | ||
| } | ||
| normalizeNode([node, path]); | ||
| if (!import_platejs12.ElementApi.isElement(node)) { | ||
| return; | ||
| } | ||
| const codeBlockType = editor.getType(import_platejs12.KEYS.codeBlock); | ||
| const codeLineType = editor.getType(import_platejs12.KEYS.codeLine); | ||
| const isCodeBlockRoot = node.type === codeBlockType; | ||
| if (isCodeBlockRoot) { | ||
| const nonCodeLine = Array.from(import_platejs12.NodeApi.children(editor, path)).find( | ||
| ([child]) => child.type !== codeLineType | ||
| ); | ||
| if (nonCodeLine) { | ||
| editor.tf.setNodes({ type: codeLineType }, { at: nonCodeLine[1] }); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| }); | ||
| // src/lib/withCodeBlock.ts | ||
| var withCodeBlock = (ctx) => { | ||
| const { | ||
| editor, | ||
| getOptions, | ||
| tf: { apply, insertBreak, resetBlock, selectAll, tab }, | ||
| type | ||
| } = ctx; | ||
| return { | ||
| transforms: { | ||
| apply(operation) { | ||
| if (getOptions().lowlight && operation.type === "set_node") { | ||
| const entry = editor.api.node(operation.path); | ||
| if (entry?.[0].type === type && operation.newProperties?.lang) { | ||
| resetCodeBlockDecorations(entry[0]); | ||
| } | ||
| } | ||
| apply(operation); | ||
| }, | ||
| insertBreak() { | ||
| const apply2 = () => { | ||
| if (!editor.selection) return; | ||
| const res = getCodeLineEntry(editor, {}); | ||
| if (!res) return; | ||
| const { codeBlock, codeLine } = res; | ||
| const indentDepth = getIndentDepth(editor, { | ||
| codeBlock, | ||
| codeLine | ||
| }); | ||
| insertBreak(); | ||
| indentCodeLine(editor, { | ||
| codeBlock, | ||
| codeLine, | ||
| indentDepth | ||
| }); | ||
| return true; | ||
| }; | ||
| if (apply2()) return; | ||
| insertBreak(); | ||
| }, | ||
| resetBlock(options) { | ||
| if (editor.api.block({ | ||
| at: options?.at, | ||
| match: { type } | ||
| })) { | ||
| unwrapCodeBlock(editor); | ||
| return; | ||
| } | ||
| return resetBlock(options); | ||
| }, | ||
| selectAll: () => { | ||
| const apply2 = () => { | ||
| const codeBlock = editor.api.above({ | ||
| match: { type } | ||
| }); | ||
| if (!codeBlock) return; | ||
| if (editor.api.isAt({ end: true }) && editor.api.isAt({ start: true })) { | ||
| return; | ||
| } | ||
| editor.tf.select(codeBlock[1]); | ||
| return true; | ||
| }; | ||
| if (apply2()) return true; | ||
| return selectAll(); | ||
| }, | ||
| tab: (options) => { | ||
| const apply2 = () => { | ||
| const _codeLines = editor.api.nodes({ | ||
| match: { type } | ||
| }); | ||
| const codeLines = Array.from(_codeLines); | ||
| if (codeLines.length > 0) { | ||
| const [, firstLinePath] = codeLines[0]; | ||
| const codeBlock = editor.api.parent(firstLinePath); | ||
| if (!codeBlock) return; | ||
| editor.tf.withoutNormalizing(() => { | ||
| for (const codeLine of codeLines) { | ||
| if (options.reverse) { | ||
| outdentCodeLine(editor, { codeBlock, codeLine }); | ||
| } else { | ||
| indentCodeLine(editor, { codeBlock, codeLine }); | ||
| } | ||
| } | ||
| }); | ||
| return true; | ||
| } | ||
| }; | ||
| if (apply2()) return true; | ||
| return tab(options); | ||
| }, | ||
| ...withInsertDataCodeBlock(ctx).transforms, | ||
| ...withInsertFragmentCodeBlock(ctx).transforms, | ||
| ...withNormalizeCodeBlock(ctx).transforms | ||
| } | ||
| }; | ||
| }; | ||
| // src/lib/BaseCodeBlockPlugin.ts | ||
| var BaseCodeLinePlugin = (0, import_platejs13.createTSlatePlugin)({ | ||
| key: import_platejs13.KEYS.codeLine, | ||
| node: { isElement: true, isStrictSiblings: true } | ||
| }); | ||
| var BaseCodeSyntaxPlugin = (0, import_platejs13.createSlatePlugin)({ | ||
| key: import_platejs13.KEYS.codeSyntax, | ||
| node: { isLeaf: true } | ||
| }); | ||
| var BaseCodeBlockPlugin = (0, import_platejs13.createTSlatePlugin)({ | ||
| key: import_platejs13.KEYS.codeBlock, | ||
| inject: { | ||
| plugins: { | ||
| [import_platejs13.KEYS.html]: { | ||
| parser: { | ||
| query: ({ editor }) => !editor.api.some({ | ||
| match: { type: editor.getType(import_platejs13.KEYS.codeLine) } | ||
| }) | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| node: { | ||
| isElement: true | ||
| }, | ||
| options: { | ||
| defaultLanguage: null, | ||
| lowlight: null | ||
| }, | ||
| parsers: { html: { deserializer: htmlDeserializerCodeBlock } }, | ||
| plugins: [BaseCodeLinePlugin, BaseCodeSyntaxPlugin], | ||
| render: { as: "pre" }, | ||
| rules: { | ||
| delete: { | ||
| empty: "reset" | ||
| }, | ||
| match: ({ editor, rule }) => ["break.empty", "delete.empty"].includes(rule) && isCodeBlockEmpty(editor) | ||
| }, | ||
| decorate: ({ editor, entry: [node, path], getOptions, type }) => { | ||
| if (!getOptions().lowlight) return []; | ||
| const codeLineType = editor.getType(import_platejs13.KEYS.codeLine); | ||
| if (node.type === type && !CODE_LINE_TO_DECORATIONS.get(node.children[0])) { | ||
| setCodeBlockToDecorations(editor, [node, path]); | ||
| } | ||
| if (node.type === codeLineType) { | ||
| return CODE_LINE_TO_DECORATIONS.get(node) || []; | ||
| } | ||
| return []; | ||
| } | ||
| }).overrideEditor(withCodeBlock).extendTransforms(({ editor }) => ({ | ||
| toggle: () => { | ||
| editor.tf.toggleBlock(editor.getType(import_platejs13.KEYS.codeBlock)); | ||
| } | ||
| })); | ||
| // src/lib/formatter/jsonFormatter.ts | ||
| var formatJson = (code) => { | ||
| try { | ||
| return JSON.stringify(JSON.parse(code), null, 2); | ||
| } catch (_error) { | ||
| return code; | ||
| } | ||
| }; | ||
| var isValidJson = (code) => { | ||
| try { | ||
| JSON.parse(code); | ||
| return true; | ||
| } catch (_error) { | ||
| return false; | ||
| } | ||
| }; | ||
| // src/lib/formatter/formatter.ts | ||
| var supportedLanguages = /* @__PURE__ */ new Set(["json"]); | ||
| var isLangSupported = (lang) => Boolean(lang && supportedLanguages.has(lang)); | ||
| var isValidSyntax = (code, lang) => { | ||
| if (!isLangSupported(lang)) { | ||
| return false; | ||
| } | ||
| switch (lang) { | ||
| case "json": { | ||
| return isValidJson(code); | ||
| } | ||
| default: { | ||
| return false; | ||
| } | ||
| } | ||
| }; | ||
| var formatCodeBlock = (editor, { | ||
| element | ||
| }) => { | ||
| const { lang } = element; | ||
| if (!lang || !isLangSupported(lang)) { | ||
| return; | ||
| } | ||
| const code = editor.api.string(element); | ||
| if (isValidSyntax(code, lang)) { | ||
| const formattedCode = formatCode(code, lang); | ||
| editor.tf.insertText(formattedCode, { at: element }); | ||
| } | ||
| }; | ||
| var formatCode = (code, lang) => { | ||
| switch (lang) { | ||
| case "json": { | ||
| return formatJson(code); | ||
| } | ||
| default: { | ||
| return code; | ||
| } | ||
| } | ||
| }; | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| BaseCodeBlockPlugin, | ||
| BaseCodeLinePlugin, | ||
| BaseCodeSyntaxPlugin, | ||
| CODE_LINE_TO_DECORATIONS, | ||
| codeBlockToDecorations, | ||
| deleteStartSpace, | ||
| formatCodeBlock, | ||
| formatJson, | ||
| getCodeLineEntry, | ||
| getIndentDepth, | ||
| htmlDeserializerCodeBlock, | ||
| indentCodeLine, | ||
| insertCodeBlock, | ||
| insertCodeLine, | ||
| insertEmptyCodeBlock, | ||
| isCodeBlockEmpty, | ||
| isLangSupported, | ||
| isSelectionAtCodeBlockStart, | ||
| isValidJson, | ||
| isValidSyntax, | ||
| outdentCodeLine, | ||
| resetCodeBlockDecorations, | ||
| setCodeBlockToDecorations, | ||
| toggleCodeBlock, | ||
| unwrapCodeBlock, | ||
| withCodeBlock, | ||
| withInsertDataCodeBlock, | ||
| withInsertFragmentCodeBlock, | ||
| withNormalizeCodeBlock | ||
| }); | ||
| //# sourceMappingURL=index.js.map | ||
| //#endregion | ||
| export { BaseCodeBlockPlugin, BaseCodeLinePlugin, BaseCodeSyntaxPlugin, CODE_LINE_TO_DECORATIONS, codeBlockToDecorations, deleteStartSpace, formatCodeBlock, formatJson, getCodeLineEntry, getIndentDepth, htmlDeserializerCodeBlock, indentCodeLine, insertCodeBlock, insertCodeLine, insertEmptyCodeBlock, isCodeBlockEmpty, isLangSupported, isSelectionAtCodeBlockStart, isValidJson, isValidSyntax, outdentCodeLine, resetCodeBlockDecorations, setCodeBlockToDecorations, toggleCodeBlock, unwrapCodeBlock, withCodeBlock, withInsertDataCodeBlock, withInsertFragmentCodeBlock, withNormalizeCodeBlock }; |
+12
-11
@@ -1,15 +0,16 @@ | ||
| import * as lowlight from 'lowlight'; | ||
| import * as platejs_react from 'platejs/react'; | ||
| import * as platejs from 'platejs'; | ||
| import * as platejs0 from "platejs"; | ||
| import * as platejs_react0 from "platejs/react"; | ||
| import * as lowlight0 from "lowlight"; | ||
| declare const CodeSyntaxPlugin: platejs_react.PlatePlugin<platejs.PluginConfig<"code_syntax", {}, {}, {}, {}>>; | ||
| declare const CodeLinePlugin: platejs_react.PlatePlugin<platejs.PluginConfig<any, {}, {}, {}, {}>>; | ||
| //#region src/react/CodeBlockPlugin.d.ts | ||
| declare const CodeSyntaxPlugin: platejs_react0.PlatePlugin<platejs0.PluginConfig<"code_syntax", {}, {}, {}, {}>>; | ||
| declare const CodeLinePlugin: platejs_react0.PlatePlugin<platejs0.PluginConfig<any, {}, {}, {}, {}>>; | ||
| /** Enables support for pre-formatted code blocks. */ | ||
| declare const CodeBlockPlugin: platejs_react.PlatePlugin<platejs.PluginConfig<"code_block", { | ||
| defaultLanguage?: string | null; | ||
| lowlight?: ReturnType<typeof lowlight.createLowlight> | null; | ||
| declare const CodeBlockPlugin: platejs_react0.PlatePlugin<platejs0.PluginConfig<"code_block", { | ||
| defaultLanguage?: string | null; | ||
| lowlight?: ReturnType<typeof lowlight0.createLowlight> | null; | ||
| }, {}, Record<"code_block", { | ||
| toggle: () => void; | ||
| toggle: () => void; | ||
| }>, {}>>; | ||
| export { CodeBlockPlugin, CodeLinePlugin, CodeSyntaxPlugin }; | ||
| //#endregion | ||
| export { CodeBlockPlugin, CodeLinePlugin, CodeSyntaxPlugin }; |
+9
-589
@@ -1,591 +0,11 @@ | ||
| "use strict"; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| import { n as BaseCodeLinePlugin, r as BaseCodeSyntaxPlugin, t as BaseCodeBlockPlugin } from "../BaseCodeBlockPlugin-BntJ075t.js"; | ||
| import { toPlatePlugin } from "platejs/react"; | ||
| // src/react/index.ts | ||
| var react_exports = {}; | ||
| __export(react_exports, { | ||
| CodeBlockPlugin: () => CodeBlockPlugin, | ||
| CodeLinePlugin: () => CodeLinePlugin, | ||
| CodeSyntaxPlugin: () => CodeSyntaxPlugin | ||
| }); | ||
| module.exports = __toCommonJS(react_exports); | ||
| //#region src/react/CodeBlockPlugin.tsx | ||
| const CodeSyntaxPlugin = toPlatePlugin(BaseCodeSyntaxPlugin); | ||
| const CodeLinePlugin = toPlatePlugin(BaseCodeLinePlugin); | ||
| /** Enables support for pre-formatted code blocks. */ | ||
| const CodeBlockPlugin = toPlatePlugin(BaseCodeBlockPlugin, { plugins: [CodeLinePlugin, CodeSyntaxPlugin] }); | ||
| // src/react/CodeBlockPlugin.tsx | ||
| var import_react = require("platejs/react"); | ||
| // src/lib/BaseCodeBlockPlugin.ts | ||
| var import_platejs9 = require("platejs"); | ||
| // src/lib/deserializer/htmlDeserializerCodeBlock.ts | ||
| var import_platejs = require("platejs"); | ||
| var htmlDeserializerCodeBlock = { | ||
| rules: [ | ||
| { | ||
| validNodeName: "PRE" | ||
| }, | ||
| { | ||
| validNodeName: "P", | ||
| validStyle: { | ||
| fontFamily: "Consolas" | ||
| } | ||
| } | ||
| ], | ||
| parse: ({ element }) => { | ||
| const languageSelectorText = [...element.childNodes].find( | ||
| (node) => node.nodeName === "SELECT" | ||
| )?.textContent || ""; | ||
| const textContent = element.textContent?.replace(languageSelectorText, "") || ""; | ||
| let lines = textContent.split("\n"); | ||
| if (!lines?.length) { | ||
| lines = [textContent]; | ||
| } | ||
| const codeLines = lines.map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: import_platejs.KEYS.codeLine | ||
| })); | ||
| return { | ||
| children: codeLines, | ||
| type: import_platejs.KEYS.codeBlock | ||
| }; | ||
| } | ||
| }; | ||
| // src/lib/queries/getCodeLineEntry.ts | ||
| var import_platejs2 = require("platejs"); | ||
| var getCodeLineEntry = (editor, { at = editor.selection } = {}) => { | ||
| if (at && editor.api.some({ | ||
| at, | ||
| match: { type: editor.getType(import_platejs2.KEYS.codeLine) } | ||
| })) { | ||
| const selectionParent = editor.api.parent(at); | ||
| if (!selectionParent) return; | ||
| const [, parentPath] = selectionParent; | ||
| const codeLine = editor.api.above({ | ||
| at, | ||
| match: { type: editor.getType(import_platejs2.KEYS.codeLine) } | ||
| }) || editor.api.parent(parentPath); | ||
| if (!codeLine) return; | ||
| const [codeLineNode, codeLinePath] = codeLine; | ||
| if (import_platejs2.ElementApi.isElement(codeLineNode) && codeLineNode.type !== editor.getType(import_platejs2.KEYS.codeLine)) | ||
| return; | ||
| const codeBlock = editor.api.parent(codeLinePath); | ||
| if (!codeBlock) return; | ||
| return { | ||
| codeBlock, | ||
| codeLine | ||
| }; | ||
| } | ||
| }; | ||
| // src/lib/queries/getIndentDepth.ts | ||
| var nonWhitespaceOrEndRegex = /\S|$/; | ||
| var getIndentDepth = (editor, { codeLine }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const text = editor.api.string(codeLinePath); | ||
| return text.search(nonWhitespaceOrEndRegex); | ||
| }; | ||
| // src/lib/queries/isCodeBlockEmpty.ts | ||
| var import_platejs3 = require("platejs"); | ||
| var isCodeBlockEmpty = (editor) => { | ||
| const { codeBlock } = getCodeLineEntry(editor) ?? {}; | ||
| if (!codeBlock) return false; | ||
| const codeLines = Array.from(import_platejs3.NodeApi.children(editor, codeBlock[1])); | ||
| if (codeLines.length === 0) return true; | ||
| if (codeLines.length > 1) return false; | ||
| const firstCodeLineNode = codeLines[0][0]; | ||
| return !import_platejs3.NodeApi.string(firstCodeLineNode); | ||
| }; | ||
| // src/lib/setCodeBlockToDecorations.ts | ||
| var import_platejs4 = require("platejs"); | ||
| var CODE_LINE_TO_DECORATIONS = /* @__PURE__ */ new WeakMap(); | ||
| function getHighlightNodes(result) { | ||
| return result.value || result.children || []; | ||
| } | ||
| function parseNodes(nodes, className = []) { | ||
| return nodes.flatMap((node) => { | ||
| const classes = [ | ||
| ...className, | ||
| ...node.properties ? node.properties.className : [] | ||
| ]; | ||
| if (node.children) { | ||
| return parseNodes(node.children, classes); | ||
| } | ||
| return { classes, text: node.value }; | ||
| }); | ||
| } | ||
| function normalizeTokens(tokens) { | ||
| const lines = [[]]; | ||
| let currentLine = lines[0]; | ||
| for (const token of tokens) { | ||
| const tokenLines = token.text.split("\n"); | ||
| for (let i = 0; i < tokenLines.length; i++) { | ||
| const content = tokenLines[i]; | ||
| if (content) { | ||
| currentLine.push({ classes: token.classes, content }); | ||
| } | ||
| if (i < tokenLines.length - 1) { | ||
| lines.push([]); | ||
| currentLine = lines.at(-1); | ||
| } | ||
| } | ||
| } | ||
| return lines; | ||
| } | ||
| function codeBlockToDecorations(editor, [block, blockPath]) { | ||
| const { defaultLanguage, ...options } = editor.getOptions(BaseCodeBlockPlugin); | ||
| const lowlight = options.lowlight; | ||
| const text = block.children.map((line) => import_platejs4.NodeApi.string(line)).join("\n"); | ||
| const language = block.lang; | ||
| const effectiveLanguage = language || defaultLanguage; | ||
| let highlighted; | ||
| try { | ||
| if (!effectiveLanguage || effectiveLanguage === "plaintext") { | ||
| highlighted = { value: [] }; | ||
| } else if (effectiveLanguage === "auto") { | ||
| highlighted = lowlight.highlightAuto(text); | ||
| } else { | ||
| highlighted = lowlight.highlight(effectiveLanguage, text); | ||
| } | ||
| } catch (error) { | ||
| const availableLanguages = lowlight.listLanguages(); | ||
| const isLanguageRegistered = effectiveLanguage && availableLanguages.includes(effectiveLanguage); | ||
| if (isLanguageRegistered) { | ||
| editor.api.debug.error(error, "CODE_HIGHLIGHT"); | ||
| highlighted = { value: [] }; | ||
| } else { | ||
| editor.api.debug.warn( | ||
| `Language "${effectiveLanguage}" is not registered. Falling back to plaintext` | ||
| ); | ||
| highlighted = { value: [] }; | ||
| } | ||
| } | ||
| const tokens = parseNodes(getHighlightNodes(highlighted)); | ||
| const normalizedTokens = normalizeTokens(tokens); | ||
| const blockChildren = block.children; | ||
| const nodeToDecorations = /* @__PURE__ */ new Map(); | ||
| const numLines = Math.min(normalizedTokens.length, blockChildren.length); | ||
| for (let index = 0; index < numLines; index++) { | ||
| const lineTokens = normalizedTokens[index]; | ||
| const element = blockChildren[index]; | ||
| if (!nodeToDecorations.has(element)) { | ||
| nodeToDecorations.set(element, []); | ||
| } | ||
| let start = 0; | ||
| for (const token of lineTokens) { | ||
| const length = token.content.length; | ||
| if (!length) continue; | ||
| const end = start + length; | ||
| const decoration = { | ||
| anchor: { | ||
| offset: start, | ||
| path: [...blockPath, index, 0] | ||
| }, | ||
| className: token.classes.join(" "), | ||
| focus: { | ||
| offset: end, | ||
| path: [...blockPath, index, 0] | ||
| }, | ||
| [import_platejs4.KEYS.codeSyntax]: true | ||
| }; | ||
| nodeToDecorations.get(element).push(decoration); | ||
| start = end; | ||
| } | ||
| } | ||
| return nodeToDecorations; | ||
| } | ||
| function setCodeBlockToDecorations(editor, [block, blockPath]) { | ||
| const decorations = codeBlockToDecorations(editor, [block, blockPath]); | ||
| for (const [node, decs] of decorations.entries()) { | ||
| CODE_LINE_TO_DECORATIONS.set(node, decs); | ||
| } | ||
| } | ||
| function resetCodeBlockDecorations(codeBlock) { | ||
| codeBlock.children.forEach((line) => { | ||
| CODE_LINE_TO_DECORATIONS.delete(line); | ||
| }); | ||
| } | ||
| // src/lib/transforms/deleteStartSpace.ts | ||
| var whitespaceRegex = /\s/; | ||
| var deleteStartSpace = (editor, { codeLine }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const codeLineStart = editor.api.start(codeLinePath); | ||
| const codeLineEnd = codeLineStart && editor.api.after(codeLineStart); | ||
| const spaceRange = codeLineEnd && editor.api.range(codeLineStart, codeLineEnd); | ||
| const spaceText = editor.api.string(spaceRange); | ||
| if (whitespaceRegex.test(spaceText)) { | ||
| editor.tf.delete({ at: spaceRange }); | ||
| return true; | ||
| } | ||
| return false; | ||
| }; | ||
| // src/lib/transforms/indentCodeLine.ts | ||
| var nonWhitespaceRegex = /\S/; | ||
| var indentCodeLine = (editor, { codeLine, indentDepth = 2 }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const codeLineStart = editor.api.start(codeLinePath); | ||
| const indent = " ".repeat(indentDepth); | ||
| if (!editor.api.isExpanded()) { | ||
| const cursor = editor.selection?.anchor; | ||
| const range = editor.api.range(codeLineStart, cursor); | ||
| const text = editor.api.string(range); | ||
| if (nonWhitespaceRegex.test(text)) { | ||
| editor.tf.insertText(indent, { at: editor.selection }); | ||
| return; | ||
| } | ||
| } | ||
| editor.tf.insertText(indent, { at: codeLineStart }); | ||
| }; | ||
| // src/lib/transforms/outdentCodeLine.ts | ||
| var outdentCodeLine = (editor, { codeBlock, codeLine }) => { | ||
| const deleted = deleteStartSpace(editor, { codeBlock, codeLine }); | ||
| if (deleted) { | ||
| deleteStartSpace(editor, { codeBlock, codeLine }); | ||
| } | ||
| }; | ||
| // src/lib/transforms/unwrapCodeBlock.ts | ||
| var import_platejs5 = require("platejs"); | ||
| var unwrapCodeBlock = (editor) => { | ||
| if (!editor.selection) return; | ||
| const codeBlockType = editor.getType(import_platejs5.KEYS.codeBlock); | ||
| const defaultType = editor.getType(import_platejs5.KEYS.p); | ||
| editor.tf.withoutNormalizing(() => { | ||
| const codeBlockEntries = editor.api.nodes({ | ||
| at: editor.selection, | ||
| match: { type: codeBlockType } | ||
| }); | ||
| const reversedCodeBlockEntries = Array.from(codeBlockEntries).reverse(); | ||
| for (const codeBlockEntry of reversedCodeBlockEntries) { | ||
| const codeLineEntries = import_platejs5.NodeApi.children(editor, codeBlockEntry[1]); | ||
| for (const [, path] of codeLineEntries) { | ||
| editor.tf.setNodes({ type: defaultType }, { at: path }); | ||
| } | ||
| editor.tf.unwrapNodes({ | ||
| at: codeBlockEntry[1], | ||
| match: { type: codeBlockType }, | ||
| split: true | ||
| }); | ||
| } | ||
| }); | ||
| }; | ||
| // src/lib/withInsertDataCodeBlock.ts | ||
| var import_platejs6 = require("platejs"); | ||
| var withInsertDataCodeBlock = ({ | ||
| editor, | ||
| tf: { insertData }, | ||
| type: codeBlockType | ||
| }) => ({ | ||
| transforms: { | ||
| insertData(data) { | ||
| const text = data.getData("text/plain"); | ||
| const vscodeDataString = data.getData("vscode-editor-data"); | ||
| const codeLineType = editor.getType(import_platejs6.KEYS.codeLine); | ||
| if (vscodeDataString) { | ||
| try { | ||
| const vscodeData = JSON.parse(vscodeDataString); | ||
| const lines = text.split("\n"); | ||
| const [blockAbove2] = editor.api.block() ?? []; | ||
| const isInCodeBlock = blockAbove2 && [codeBlockType, codeLineType].includes(blockAbove2?.type); | ||
| if (isInCodeBlock) { | ||
| if (lines[0]) { | ||
| editor.tf.insertText(lines[0]); | ||
| } | ||
| if (lines.length > 1) { | ||
| const nodes = lines.slice(1).map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })); | ||
| editor.tf.insertNodes(nodes); | ||
| } | ||
| } else { | ||
| const node = { | ||
| children: lines.map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })), | ||
| lang: vscodeData?.mode, | ||
| type: codeBlockType | ||
| }; | ||
| editor.tf.insertNodes(node, { | ||
| select: true | ||
| }); | ||
| } | ||
| return; | ||
| } catch (_error) { | ||
| } | ||
| } | ||
| const [blockAbove] = editor.api.block() ?? []; | ||
| if (blockAbove && [codeBlockType, codeLineType].includes(blockAbove?.type) && text?.includes("\n")) { | ||
| const lines = text.split("\n"); | ||
| if (lines[0]) { | ||
| editor.tf.insertText(lines[0]); | ||
| } | ||
| if (lines.length > 1) { | ||
| const nodes = lines.slice(1).map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })); | ||
| editor.tf.insertNodes(nodes); | ||
| } | ||
| return; | ||
| } | ||
| insertData(data); | ||
| } | ||
| } | ||
| }); | ||
| // src/lib/withInsertFragmentCodeBlock.ts | ||
| var import_platejs7 = require("platejs"); | ||
| function extractCodeLinesFromCodeBlock(node) { | ||
| return node.children; | ||
| } | ||
| var withInsertFragmentCodeBlock = ({ | ||
| editor, | ||
| tf: { insertFragment }, | ||
| type: codeBlockType | ||
| }) => ({ | ||
| transforms: { | ||
| insertFragment(fragment) { | ||
| const [blockAbove] = editor.api.block() ?? []; | ||
| const codeLineType = editor.getType(import_platejs7.KEYS.codeLine); | ||
| function convertNodeToCodeLine(node) { | ||
| return { | ||
| children: [{ text: import_platejs7.NodeApi.string(node) }], | ||
| type: codeLineType | ||
| }; | ||
| } | ||
| if (blockAbove && [codeBlockType, codeLineType].includes(blockAbove?.type)) { | ||
| return insertFragment( | ||
| fragment.flatMap((node) => { | ||
| const element = node; | ||
| return element.type === codeBlockType ? extractCodeLinesFromCodeBlock(element) : convertNodeToCodeLine(element); | ||
| }) | ||
| ); | ||
| } | ||
| return insertFragment(fragment); | ||
| } | ||
| } | ||
| }); | ||
| // src/lib/withNormalizeCodeBlock.tsx | ||
| var import_platejs8 = require("platejs"); | ||
| var withNormalizeCodeBlock = ({ | ||
| editor, | ||
| getOptions, | ||
| tf: { normalizeNode }, | ||
| type | ||
| }) => ({ | ||
| transforms: { | ||
| normalizeNode([node, path]) { | ||
| if (node.type === type && getOptions().lowlight) { | ||
| setCodeBlockToDecorations(editor, [ | ||
| node, | ||
| path | ||
| ]); | ||
| } | ||
| normalizeNode([node, path]); | ||
| if (!import_platejs8.ElementApi.isElement(node)) { | ||
| return; | ||
| } | ||
| const codeBlockType = editor.getType(import_platejs8.KEYS.codeBlock); | ||
| const codeLineType = editor.getType(import_platejs8.KEYS.codeLine); | ||
| const isCodeBlockRoot = node.type === codeBlockType; | ||
| if (isCodeBlockRoot) { | ||
| const nonCodeLine = Array.from(import_platejs8.NodeApi.children(editor, path)).find( | ||
| ([child]) => child.type !== codeLineType | ||
| ); | ||
| if (nonCodeLine) { | ||
| editor.tf.setNodes({ type: codeLineType }, { at: nonCodeLine[1] }); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| }); | ||
| // src/lib/withCodeBlock.ts | ||
| var withCodeBlock = (ctx) => { | ||
| const { | ||
| editor, | ||
| getOptions, | ||
| tf: { apply, insertBreak, resetBlock, selectAll, tab }, | ||
| type | ||
| } = ctx; | ||
| return { | ||
| transforms: { | ||
| apply(operation) { | ||
| if (getOptions().lowlight && operation.type === "set_node") { | ||
| const entry = editor.api.node(operation.path); | ||
| if (entry?.[0].type === type && operation.newProperties?.lang) { | ||
| resetCodeBlockDecorations(entry[0]); | ||
| } | ||
| } | ||
| apply(operation); | ||
| }, | ||
| insertBreak() { | ||
| const apply2 = () => { | ||
| if (!editor.selection) return; | ||
| const res = getCodeLineEntry(editor, {}); | ||
| if (!res) return; | ||
| const { codeBlock, codeLine } = res; | ||
| const indentDepth = getIndentDepth(editor, { | ||
| codeBlock, | ||
| codeLine | ||
| }); | ||
| insertBreak(); | ||
| indentCodeLine(editor, { | ||
| codeBlock, | ||
| codeLine, | ||
| indentDepth | ||
| }); | ||
| return true; | ||
| }; | ||
| if (apply2()) return; | ||
| insertBreak(); | ||
| }, | ||
| resetBlock(options) { | ||
| if (editor.api.block({ | ||
| at: options?.at, | ||
| match: { type } | ||
| })) { | ||
| unwrapCodeBlock(editor); | ||
| return; | ||
| } | ||
| return resetBlock(options); | ||
| }, | ||
| selectAll: () => { | ||
| const apply2 = () => { | ||
| const codeBlock = editor.api.above({ | ||
| match: { type } | ||
| }); | ||
| if (!codeBlock) return; | ||
| if (editor.api.isAt({ end: true }) && editor.api.isAt({ start: true })) { | ||
| return; | ||
| } | ||
| editor.tf.select(codeBlock[1]); | ||
| return true; | ||
| }; | ||
| if (apply2()) return true; | ||
| return selectAll(); | ||
| }, | ||
| tab: (options) => { | ||
| const apply2 = () => { | ||
| const _codeLines = editor.api.nodes({ | ||
| match: { type } | ||
| }); | ||
| const codeLines = Array.from(_codeLines); | ||
| if (codeLines.length > 0) { | ||
| const [, firstLinePath] = codeLines[0]; | ||
| const codeBlock = editor.api.parent(firstLinePath); | ||
| if (!codeBlock) return; | ||
| editor.tf.withoutNormalizing(() => { | ||
| for (const codeLine of codeLines) { | ||
| if (options.reverse) { | ||
| outdentCodeLine(editor, { codeBlock, codeLine }); | ||
| } else { | ||
| indentCodeLine(editor, { codeBlock, codeLine }); | ||
| } | ||
| } | ||
| }); | ||
| return true; | ||
| } | ||
| }; | ||
| if (apply2()) return true; | ||
| return tab(options); | ||
| }, | ||
| ...withInsertDataCodeBlock(ctx).transforms, | ||
| ...withInsertFragmentCodeBlock(ctx).transforms, | ||
| ...withNormalizeCodeBlock(ctx).transforms | ||
| } | ||
| }; | ||
| }; | ||
| // src/lib/BaseCodeBlockPlugin.ts | ||
| var BaseCodeLinePlugin = (0, import_platejs9.createTSlatePlugin)({ | ||
| key: import_platejs9.KEYS.codeLine, | ||
| node: { isElement: true, isStrictSiblings: true } | ||
| }); | ||
| var BaseCodeSyntaxPlugin = (0, import_platejs9.createSlatePlugin)({ | ||
| key: import_platejs9.KEYS.codeSyntax, | ||
| node: { isLeaf: true } | ||
| }); | ||
| var BaseCodeBlockPlugin = (0, import_platejs9.createTSlatePlugin)({ | ||
| key: import_platejs9.KEYS.codeBlock, | ||
| inject: { | ||
| plugins: { | ||
| [import_platejs9.KEYS.html]: { | ||
| parser: { | ||
| query: ({ editor }) => !editor.api.some({ | ||
| match: { type: editor.getType(import_platejs9.KEYS.codeLine) } | ||
| }) | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| node: { | ||
| isElement: true | ||
| }, | ||
| options: { | ||
| defaultLanguage: null, | ||
| lowlight: null | ||
| }, | ||
| parsers: { html: { deserializer: htmlDeserializerCodeBlock } }, | ||
| plugins: [BaseCodeLinePlugin, BaseCodeSyntaxPlugin], | ||
| render: { as: "pre" }, | ||
| rules: { | ||
| delete: { | ||
| empty: "reset" | ||
| }, | ||
| match: ({ editor, rule }) => ["break.empty", "delete.empty"].includes(rule) && isCodeBlockEmpty(editor) | ||
| }, | ||
| decorate: ({ editor, entry: [node, path], getOptions, type }) => { | ||
| if (!getOptions().lowlight) return []; | ||
| const codeLineType = editor.getType(import_platejs9.KEYS.codeLine); | ||
| if (node.type === type && !CODE_LINE_TO_DECORATIONS.get(node.children[0])) { | ||
| setCodeBlockToDecorations(editor, [node, path]); | ||
| } | ||
| if (node.type === codeLineType) { | ||
| return CODE_LINE_TO_DECORATIONS.get(node) || []; | ||
| } | ||
| return []; | ||
| } | ||
| }).overrideEditor(withCodeBlock).extendTransforms(({ editor }) => ({ | ||
| toggle: () => { | ||
| editor.tf.toggleBlock(editor.getType(import_platejs9.KEYS.codeBlock)); | ||
| } | ||
| })); | ||
| // src/react/CodeBlockPlugin.tsx | ||
| var CodeSyntaxPlugin = (0, import_react.toPlatePlugin)(BaseCodeSyntaxPlugin); | ||
| var CodeLinePlugin = (0, import_react.toPlatePlugin)(BaseCodeLinePlugin); | ||
| var CodeBlockPlugin = (0, import_react.toPlatePlugin)(BaseCodeBlockPlugin, { | ||
| plugins: [CodeLinePlugin, CodeSyntaxPlugin] | ||
| }); | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| CodeBlockPlugin, | ||
| CodeLinePlugin, | ||
| CodeSyntaxPlugin | ||
| }); | ||
| //# sourceMappingURL=index.js.map | ||
| //#endregion | ||
| export { CodeBlockPlugin, CodeLinePlugin, CodeSyntaxPlugin }; |
+10
-18
| { | ||
| "name": "@platejs/code-block", | ||
| "version": "51.1.2", | ||
| "version": "52.0.0", | ||
| "description": "Code block plugin for Plate", | ||
@@ -22,18 +22,8 @@ "keywords": [ | ||
| "exports": { | ||
| ".": { | ||
| "types": "./dist/index.d.ts", | ||
| "import": "./dist/index.mjs", | ||
| "module": "./dist/index.mjs", | ||
| "require": "./dist/index.js" | ||
| }, | ||
| "./react": { | ||
| "types": "./dist/react/index.d.ts", | ||
| "import": "./dist/react/index.mjs", | ||
| "module": "./dist/react/index.mjs", | ||
| "require": "./dist/react/index.js" | ||
| } | ||
| ".": "./dist/index.js", | ||
| "./react": "./dist/react/index.js", | ||
| "./package.json": "./package.json" | ||
| }, | ||
| "main": "dist/index.js", | ||
| "module": "dist/index.mjs", | ||
| "types": "dist/index.d.ts", | ||
| "main": "./dist/index.js", | ||
| "types": "./dist/index.d.ts", | ||
| "files": [ | ||
@@ -58,3 +48,3 @@ "dist/**/*" | ||
| "peerDependencies": { | ||
| "platejs": ">=51.1.2", | ||
| "platejs": ">=52.0.0", | ||
| "react": ">=18.0.0", | ||
@@ -65,3 +55,5 @@ "react-dom": ">=18.0.0" | ||
| "access": "public" | ||
| } | ||
| }, | ||
| "type": "module", | ||
| "module": "./dist/index.js" | ||
| } |
-123
| import * as platejs from 'platejs'; | ||
| import { PluginConfig, TElement, SlateEditor, NodeEntry, TCodeBlockElement, OverrideEditor, HtmlDeserializer, Editor, ElementOf, TLocation, ElementEntry, InsertNodesOptions } from 'platejs'; | ||
| import { createLowlight } from 'lowlight'; | ||
| import * as slate from 'slate'; | ||
| type CodeBlockConfig = PluginConfig<'code_block', { | ||
| /** | ||
| * Default language to use when no language is specified. Set to null to | ||
| * disable syntax highlighting by default. | ||
| */ | ||
| defaultLanguage?: string | null; | ||
| /** | ||
| * Lowlight instance to use for highlighting. If not provided, syntax | ||
| * highlighting will be disabled. | ||
| */ | ||
| lowlight?: ReturnType<typeof createLowlight> | null; | ||
| }>; | ||
| declare const BaseCodeLinePlugin: platejs.SlatePlugin<PluginConfig>; | ||
| declare const BaseCodeSyntaxPlugin: platejs.SlatePlugin<PluginConfig<"code_syntax", {}, {}, {}, {}>>; | ||
| declare const BaseCodeBlockPlugin: platejs.SlatePlugin<PluginConfig<"code_block", { | ||
| /** | ||
| * Default language to use when no language is specified. Set to null to | ||
| * disable syntax highlighting by default. | ||
| */ | ||
| defaultLanguage?: string | null; | ||
| /** | ||
| * Lowlight instance to use for highlighting. If not provided, syntax | ||
| * highlighting will be disabled. | ||
| */ | ||
| lowlight?: ReturnType<typeof createLowlight> | null; | ||
| }, {}, Record<"code_block", { | ||
| toggle: () => void; | ||
| }>, {}>>; | ||
| declare const CODE_LINE_TO_DECORATIONS: WeakMap<TElement, slate.DecoratedRange[]>; | ||
| declare function codeBlockToDecorations(editor: SlateEditor, [block, blockPath]: NodeEntry<TCodeBlockElement>): Map<TElement, slate.DecoratedRange[]>; | ||
| declare function setCodeBlockToDecorations(editor: SlateEditor, [block, blockPath]: NodeEntry<TCodeBlockElement>): void; | ||
| declare function resetCodeBlockDecorations(codeBlock: TCodeBlockElement): void; | ||
| declare const withCodeBlock: OverrideEditor<CodeBlockConfig>; | ||
| declare const withInsertDataCodeBlock: OverrideEditor; | ||
| declare const withInsertFragmentCodeBlock: OverrideEditor; | ||
| /** Normalize code block node to force the pre>code>div.codeline structure. */ | ||
| declare const withNormalizeCodeBlock: OverrideEditor<CodeBlockConfig>; | ||
| declare const htmlDeserializerCodeBlock: HtmlDeserializer; | ||
| declare const isLangSupported: (lang?: string) => boolean; | ||
| declare const isValidSyntax: (code: string, lang?: string) => boolean; | ||
| declare const formatCodeBlock: (editor: Editor, { element, }: { | ||
| element: TCodeBlockElement; | ||
| }) => void; | ||
| declare const formatJson: (code: string) => string; | ||
| declare const isValidJson: (code: string) => boolean; | ||
| /** If at (default = selection) is in ul>li>p, return li and ul node entries. */ | ||
| declare const getCodeLineEntry: <N extends ElementOf<E>, E extends SlateEditor>(editor: E, { at }?: { | ||
| at?: TLocation | null; | ||
| }) => { | ||
| codeBlock: NodeEntry<N>; | ||
| codeLine: NodeEntry<N>; | ||
| } | undefined; | ||
| type IndentCodeLineOptions = { | ||
| codeBlock: ElementEntry; | ||
| codeLine: ElementEntry; | ||
| indentDepth?: number; | ||
| }; | ||
| /** | ||
| * Indent if: | ||
| * | ||
| * - The selection is expanded OR | ||
| * - There are no non-whitespace characters left of the cursor Indentation = 2 | ||
| * spaces. | ||
| */ | ||
| declare const indentCodeLine: (editor: Editor, { codeLine, indentDepth }: IndentCodeLineOptions) => void; | ||
| declare const getIndentDepth: (editor: Editor, { codeLine }: IndentCodeLineOptions) => number; | ||
| /** Is the selection inside an empty code block */ | ||
| declare const isCodeBlockEmpty: (editor: SlateEditor) => boolean; | ||
| /** Is the selection at the start of the first code line in a code block */ | ||
| declare const isSelectionAtCodeBlockStart: (editor: SlateEditor) => boolean; | ||
| type OutdentCodeLineOptions = { | ||
| codeBlock: ElementEntry; | ||
| codeLine: ElementEntry; | ||
| }; | ||
| /** Outdent the code line. Remove 2 whitespace characters if any. */ | ||
| declare const outdentCodeLine: (editor: Editor, { codeBlock, codeLine }: OutdentCodeLineOptions) => void; | ||
| /** If there is a whitespace character at the start of the code line, delete it. */ | ||
| declare const deleteStartSpace: (editor: Editor, { codeLine }: OutdentCodeLineOptions) => boolean; | ||
| /** | ||
| * Insert a code block: set the node to code line and wrap it with a code block. | ||
| * If the cursor is not at the block start, insert break before. | ||
| */ | ||
| declare const insertCodeBlock: (editor: SlateEditor, insertNodesOptions?: Omit<InsertNodesOptions, "match">) => void; | ||
| /** Insert a code line starting with indentation. */ | ||
| declare const insertCodeLine: (editor: SlateEditor, indentDepth?: number) => void; | ||
| type CodeBlockInsertOptions = { | ||
| defaultType?: string; | ||
| insertNodesOptions?: Omit<InsertNodesOptions, 'match'>; | ||
| }; | ||
| /** | ||
| * Called by toolbars to make sure a code-block gets inserted below a paragraph | ||
| * rather than awkwardly splitting the current selection. | ||
| */ | ||
| declare const insertEmptyCodeBlock: (editor: SlateEditor, { defaultType, insertNodesOptions, }?: CodeBlockInsertOptions) => void; | ||
| declare const toggleCodeBlock: (editor: SlateEditor) => void; | ||
| declare const unwrapCodeBlock: (editor: SlateEditor) => void; | ||
| export { BaseCodeBlockPlugin, BaseCodeLinePlugin, BaseCodeSyntaxPlugin, CODE_LINE_TO_DECORATIONS, type CodeBlockConfig, type CodeBlockInsertOptions, type IndentCodeLineOptions, type OutdentCodeLineOptions, codeBlockToDecorations, deleteStartSpace, formatCodeBlock, formatJson, getCodeLineEntry, getIndentDepth, htmlDeserializerCodeBlock, indentCodeLine, insertCodeBlock, insertCodeLine, insertEmptyCodeBlock, isCodeBlockEmpty, isLangSupported, isSelectionAtCodeBlockStart, isValidJson, isValidSyntax, outdentCodeLine, resetCodeBlockDecorations, setCodeBlockToDecorations, toggleCodeBlock, unwrapCodeBlock, withCodeBlock, withInsertDataCodeBlock, withInsertFragmentCodeBlock, withNormalizeCodeBlock }; |
| {"version":3,"sources":["../src/index.ts","../src/lib/BaseCodeBlockPlugin.ts","../src/lib/deserializer/htmlDeserializerCodeBlock.ts","../src/lib/queries/getCodeLineEntry.ts","../src/lib/queries/getIndentDepth.ts","../src/lib/queries/isCodeBlockEmpty.ts","../src/lib/queries/isSelectionAtCodeBlockStart.ts","../src/lib/setCodeBlockToDecorations.ts","../src/lib/transforms/deleteStartSpace.ts","../src/lib/transforms/indentCodeLine.ts","../src/lib/transforms/insertCodeBlock.ts","../src/lib/transforms/insertCodeLine.ts","../src/lib/transforms/insertEmptyCodeBlock.ts","../src/lib/transforms/outdentCodeLine.ts","../src/lib/transforms/toggleCodeBlock.ts","../src/lib/transforms/unwrapCodeBlock.ts","../src/lib/withInsertDataCodeBlock.ts","../src/lib/withInsertFragmentCodeBlock.ts","../src/lib/withNormalizeCodeBlock.tsx","../src/lib/withCodeBlock.ts","../src/lib/formatter/jsonFormatter.ts","../src/lib/formatter/formatter.ts"],"sourcesContent":["/**\n * @file Automatically generated by barrelsby.\n */\n\nexport * from './lib/index';\n","import type { createLowlight } from 'lowlight';\n\nimport {\n type PluginConfig,\n type TCodeBlockElement,\n type TElement,\n createSlatePlugin,\n createTSlatePlugin,\n KEYS,\n} from 'platejs';\n\nimport { htmlDeserializerCodeBlock } from './deserializer/htmlDeserializerCodeBlock';\nimport { isCodeBlockEmpty } from './queries';\nimport {\n CODE_LINE_TO_DECORATIONS,\n setCodeBlockToDecorations,\n} from './setCodeBlockToDecorations';\nimport { withCodeBlock } from './withCodeBlock';\n\nexport type CodeBlockConfig = PluginConfig<\n 'code_block',\n {\n /**\n * Default language to use when no language is specified. Set to null to\n * disable syntax highlighting by default.\n */\n defaultLanguage?: string | null;\n /**\n * Lowlight instance to use for highlighting. If not provided, syntax\n * highlighting will be disabled.\n */\n lowlight?: ReturnType<typeof createLowlight> | null;\n }\n>;\n\nexport const BaseCodeLinePlugin = createTSlatePlugin({\n key: KEYS.codeLine,\n node: { isElement: true, isStrictSiblings: true },\n});\n\nexport const BaseCodeSyntaxPlugin = createSlatePlugin({\n key: KEYS.codeSyntax,\n node: { isLeaf: true },\n});\n\nexport const BaseCodeBlockPlugin = createTSlatePlugin<CodeBlockConfig>({\n key: KEYS.codeBlock,\n inject: {\n plugins: {\n [KEYS.html]: {\n parser: {\n query: ({ editor }) =>\n !editor.api.some({\n match: { type: editor.getType(KEYS.codeLine) },\n }),\n },\n },\n },\n },\n node: {\n isElement: true,\n },\n options: {\n defaultLanguage: null,\n lowlight: null,\n },\n parsers: { html: { deserializer: htmlDeserializerCodeBlock } },\n plugins: [BaseCodeLinePlugin, BaseCodeSyntaxPlugin],\n render: { as: 'pre' },\n rules: {\n delete: {\n empty: 'reset',\n },\n match: ({ editor, rule }) =>\n ['break.empty', 'delete.empty'].includes(rule) &&\n isCodeBlockEmpty(editor),\n },\n decorate: ({ editor, entry: [node, path], getOptions, type }) => {\n if (!getOptions().lowlight) return [];\n\n const codeLineType = editor.getType(KEYS.codeLine);\n\n // Initialize decorations for the code block, we assume code line decorate will be called next.\n if (\n node.type === type &&\n !CODE_LINE_TO_DECORATIONS.get((node.children as TElement[])[0])\n ) {\n setCodeBlockToDecorations(editor, [node as TCodeBlockElement, path]);\n }\n\n if (node.type === codeLineType) {\n return CODE_LINE_TO_DECORATIONS.get(node as TElement) || [];\n }\n\n return [];\n },\n})\n .overrideEditor(withCodeBlock)\n .extendTransforms(({ editor }) => ({\n toggle: () => {\n editor.tf.toggleBlock(editor.getType(KEYS.codeBlock));\n },\n }));\n","import type { HtmlDeserializer } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\nexport const htmlDeserializerCodeBlock: HtmlDeserializer = {\n rules: [\n {\n validNodeName: 'PRE',\n },\n {\n validNodeName: 'P',\n validStyle: {\n fontFamily: 'Consolas',\n },\n },\n ],\n parse: ({ element }) => {\n const languageSelectorText =\n [...element.childNodes].find(\n (node: ChildNode) => node.nodeName === 'SELECT'\n )?.textContent || '';\n\n const textContent =\n element.textContent?.replace(languageSelectorText, '') || '';\n\n let lines = textContent.split('\\n');\n\n if (!lines?.length) {\n lines = [textContent];\n }\n\n const codeLines = lines.map((line) => ({\n children: [{ text: line }],\n type: KEYS.codeLine,\n }));\n\n return {\n children: codeLines,\n type: KEYS.codeBlock,\n };\n },\n};\n","import {\n type ElementOf,\n type NodeEntry,\n type SlateEditor,\n type TElement,\n type TLocation,\n ElementApi,\n KEYS,\n} from 'platejs';\n\n/** If at (default = selection) is in ul>li>p, return li and ul node entries. */\nexport const getCodeLineEntry = <N extends ElementOf<E>, E extends SlateEditor>(\n editor: E,\n { at = editor.selection }: { at?: TLocation | null } = {}\n) => {\n if (\n at &&\n editor.api.some({\n at,\n match: { type: editor.getType(KEYS.codeLine) },\n })\n ) {\n const selectionParent = editor.api.parent(at);\n\n if (!selectionParent) return;\n\n const [, parentPath] = selectionParent;\n\n const codeLine =\n editor.api.above<TElement>({\n at,\n match: { type: editor.getType(KEYS.codeLine) },\n }) || editor.api.parent<N>(parentPath);\n\n if (!codeLine) return;\n\n const [codeLineNode, codeLinePath] = codeLine;\n\n if (\n ElementApi.isElement(codeLineNode) &&\n codeLineNode.type !== editor.getType(KEYS.codeLine)\n )\n return;\n\n const codeBlock = editor.api.parent<N>(codeLinePath);\n\n if (!codeBlock) return;\n\n return {\n codeBlock,\n codeLine: codeLine as NodeEntry<N>,\n };\n }\n};\n","import type { Editor } from 'platejs';\n\nimport type { IndentCodeLineOptions } from '../transforms/indentCodeLine';\n\nconst nonWhitespaceOrEndRegex = /\\S|$/;\n\nexport const getIndentDepth = (\n editor: Editor,\n { codeLine }: IndentCodeLineOptions\n) => {\n const [, codeLinePath] = codeLine;\n const text = editor.api.string(codeLinePath);\n\n return text.search(nonWhitespaceOrEndRegex);\n};\n","import { type SlateEditor, NodeApi } from 'platejs';\n\nimport { getCodeLineEntry } from './getCodeLineEntry';\n\n/** Is the selection inside an empty code block */\nexport const isCodeBlockEmpty = (editor: SlateEditor) => {\n const { codeBlock } = getCodeLineEntry(editor) ?? {};\n\n if (!codeBlock) return false;\n\n const codeLines = Array.from(NodeApi.children(editor, codeBlock[1]));\n\n if (codeLines.length === 0) return true;\n if (codeLines.length > 1) return false;\n\n const firstCodeLineNode = codeLines[0][0];\n\n return !NodeApi.string(firstCodeLineNode);\n};\n","import type { SlateEditor } from 'platejs';\n\nimport { getCodeLineEntry } from './getCodeLineEntry';\n\n/** Is the selection at the start of the first code line in a code block */\nexport const isSelectionAtCodeBlockStart = (editor: SlateEditor) => {\n const { selection } = editor;\n\n if (!selection || editor.api.isExpanded()) return false;\n\n const { codeBlock } = getCodeLineEntry(editor) ?? {};\n\n if (!codeBlock) return false;\n\n return editor.api.isStart(selection.anchor, codeBlock[1]);\n};\n","import {\n type DecoratedRange,\n type NodeEntry,\n type SlateEditor,\n type TCodeBlockElement,\n type TElement,\n KEYS,\n NodeApi,\n} from 'platejs';\n\nimport { BaseCodeBlockPlugin } from './BaseCodeBlockPlugin';\n\n// Cache for storing decorations per code line element\nexport const CODE_LINE_TO_DECORATIONS = new WeakMap<\n TElement,\n DecoratedRange[]\n>();\n\n// Helper function to get highlight nodes from Lowlight result\nfunction getHighlightNodes(result: any) {\n return result.value || result.children || [];\n}\n\n// Helper function to parse nodes from Lowlight's hast tree\nfunction parseNodes(\n nodes: any[],\n className: string[] = []\n): { classes: string[]; text: string }[] {\n return nodes.flatMap((node) => {\n const classes = [\n ...className,\n ...(node.properties ? node.properties.className : []),\n ];\n if (node.children) {\n return parseNodes(node.children, classes);\n }\n return { classes, text: node.value };\n });\n}\n\n// Helper function to normalize tokens by line\nfunction normalizeTokens(tokens: { classes: string[]; text: string }[]) {\n const lines: { classes: string[]; content: string }[][] = [[]];\n let currentLine = lines[0];\n\n for (const token of tokens) {\n const tokenLines = token.text.split('\\n');\n\n for (let i = 0; i < tokenLines.length; i++) {\n const content = tokenLines[i];\n\n if (content) {\n currentLine.push({ classes: token.classes, content });\n }\n\n // Create a new line unless we're on the last line\n if (i < tokenLines.length - 1) {\n lines.push([]);\n currentLine = lines.at(-1) as any;\n }\n }\n }\n\n return lines;\n}\n\n// Helper function to compute decorations for a code block\nexport function codeBlockToDecorations(\n editor: SlateEditor,\n [block, blockPath]: NodeEntry<TCodeBlockElement>\n) {\n const { defaultLanguage, ...options } =\n editor.getOptions(BaseCodeBlockPlugin);\n const lowlight = options.lowlight!;\n\n // Get all code lines and combine their text\n const text = block.children.map((line) => NodeApi.string(line)).join('\\n');\n const language = block.lang;\n const effectiveLanguage = language || defaultLanguage;\n\n let highlighted: any;\n try {\n // Skip highlighting for plaintext or when no language is specified\n if (!effectiveLanguage || effectiveLanguage === 'plaintext') {\n highlighted = { value: [] }; // Empty result for plaintext\n } else if (effectiveLanguage === 'auto') {\n highlighted = lowlight.highlightAuto(text);\n } else {\n highlighted = lowlight.highlight(effectiveLanguage, text);\n }\n } catch (error) {\n // Verify if language is registered, fallback to plaintext if not\n const availableLanguages = lowlight.listLanguages();\n const isLanguageRegistered =\n effectiveLanguage && availableLanguages.includes(effectiveLanguage);\n if (isLanguageRegistered) {\n editor.api.debug.error(error, 'CODE_HIGHLIGHT');\n highlighted = { value: [] }; // Empty result on error\n } else {\n editor.api.debug.warn(\n `Language \"${effectiveLanguage}\" is not registered. Falling back to plaintext`\n );\n highlighted = { value: [] };\n }\n }\n\n // Parse and normalize tokens\n const tokens = parseNodes(getHighlightNodes(highlighted));\n const normalizedTokens = normalizeTokens(tokens);\n const blockChildren = block.children as TElement[];\n\n // Create decorations map\n const nodeToDecorations = new Map<TElement, DecoratedRange[]>();\n\n // Safety check: don't process more lines than we have children\n const numLines = Math.min(normalizedTokens.length, blockChildren.length);\n\n // Process each line's tokens\n for (let index = 0; index < numLines; index++) {\n const lineTokens = normalizedTokens[index];\n const element = blockChildren[index];\n\n if (!nodeToDecorations.has(element)) {\n nodeToDecorations.set(element, []);\n }\n\n let start = 0;\n for (const token of lineTokens) {\n const length = token.content.length;\n if (!length) continue;\n\n const end = start + length;\n\n const decoration: DecoratedRange = {\n anchor: {\n offset: start,\n path: [...blockPath, index, 0],\n },\n className: token.classes.join(' '),\n focus: {\n offset: end,\n path: [...blockPath, index, 0],\n },\n [KEYS.codeSyntax]: true,\n } as any;\n\n nodeToDecorations.get(element)!.push(decoration);\n start = end;\n }\n }\n\n return nodeToDecorations;\n}\n\nexport function setCodeBlockToDecorations(\n editor: SlateEditor,\n [block, blockPath]: NodeEntry<TCodeBlockElement>\n) {\n const decorations = codeBlockToDecorations(editor, [block, blockPath]);\n\n // Update the global cache with the new decorations\n for (const [node, decs] of decorations.entries()) {\n CODE_LINE_TO_DECORATIONS.set(node, decs);\n }\n}\n\nexport function resetCodeBlockDecorations(codeBlock: TCodeBlockElement) {\n codeBlock.children.forEach((line) => {\n CODE_LINE_TO_DECORATIONS.delete(line as TElement);\n });\n}\n","import type { Editor } from 'platejs';\n\nimport type { OutdentCodeLineOptions } from './outdentCodeLine';\n\nconst whitespaceRegex = /\\s/;\n\n/** If there is a whitespace character at the start of the code line, delete it. */\nexport const deleteStartSpace = (\n editor: Editor,\n { codeLine }: OutdentCodeLineOptions\n) => {\n const [, codeLinePath] = codeLine;\n const codeLineStart = editor.api.start(codeLinePath);\n const codeLineEnd = codeLineStart && editor.api.after(codeLineStart);\n const spaceRange =\n codeLineEnd && editor.api.range(codeLineStart, codeLineEnd);\n const spaceText = editor.api.string(spaceRange);\n\n if (whitespaceRegex.test(spaceText)) {\n editor.tf.delete({ at: spaceRange });\n\n return true;\n }\n\n return false;\n};\n","import type { Editor, ElementEntry } from 'platejs';\n\nconst nonWhitespaceRegex = /\\S/;\n\nexport type IndentCodeLineOptions = {\n codeBlock: ElementEntry;\n codeLine: ElementEntry;\n indentDepth?: number;\n};\n\n/**\n * Indent if:\n *\n * - The selection is expanded OR\n * - There are no non-whitespace characters left of the cursor Indentation = 2\n * spaces.\n */\nexport const indentCodeLine = (\n editor: Editor,\n { codeLine, indentDepth = 2 }: IndentCodeLineOptions\n) => {\n const [, codeLinePath] = codeLine;\n const codeLineStart = editor.api.start(codeLinePath)!;\n const indent = ' '.repeat(indentDepth);\n\n if (!editor.api.isExpanded()) {\n const cursor = editor.selection?.anchor;\n const range = editor.api.range(codeLineStart, cursor);\n const text = editor.api.string(range);\n\n if (nonWhitespaceRegex.test(text)) {\n editor.tf.insertText(indent, { at: editor.selection! });\n\n return;\n }\n }\n\n editor.tf.insertText(indent, { at: codeLineStart });\n};\n","import type { InsertNodesOptions, SlateEditor, TElement } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\n/**\n * Insert a code block: set the node to code line and wrap it with a code block.\n * If the cursor is not at the block start, insert break before.\n */\nexport const insertCodeBlock = (\n editor: SlateEditor,\n insertNodesOptions: Omit<InsertNodesOptions, 'match'> = {}\n) => {\n if (!editor.selection || editor.api.isExpanded()) return;\n\n const matchCodeElements = (node: TElement) =>\n node.type === KEYS.codeBlock || node.type === KEYS.codeLine;\n\n if (\n editor.api.some({\n match: matchCodeElements,\n })\n ) {\n return;\n }\n if (!editor.api.isAt({ start: true })) {\n editor.tf.insertBreak();\n }\n\n editor.tf.setNodes(\n {\n children: [{ text: '' }],\n type: KEYS.codeLine,\n },\n insertNodesOptions\n );\n\n editor.tf.wrapNodes<TElement>(\n {\n children: [],\n type: KEYS.codeBlock,\n },\n insertNodesOptions\n );\n};\n","import type { SlateEditor } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\n/** Insert a code line starting with indentation. */\nexport const insertCodeLine = (editor: SlateEditor, indentDepth = 0) => {\n if (editor.selection) {\n const indent = ' '.repeat(indentDepth);\n\n editor.tf.insertNodes({\n children: [{ text: indent }],\n type: editor.getType(KEYS.codeLine),\n });\n }\n};\n","import { type InsertNodesOptions, type SlateEditor, KEYS } from 'platejs';\n\nimport { insertCodeBlock } from './insertCodeBlock';\n\nexport type CodeBlockInsertOptions = {\n defaultType?: string;\n insertNodesOptions?: Omit<InsertNodesOptions, 'match'>;\n};\n\n/**\n * Called by toolbars to make sure a code-block gets inserted below a paragraph\n * rather than awkwardly splitting the current selection.\n */\nexport const insertEmptyCodeBlock = (\n editor: SlateEditor,\n {\n defaultType = editor.getType(KEYS.p),\n insertNodesOptions,\n }: CodeBlockInsertOptions = {}\n) => {\n if (!editor.selection) return;\n if (\n editor.api.isExpanded() ||\n !editor.api.isEmpty(editor.selection, { block: true })\n ) {\n editor.tf.insertNodes(\n editor.api.create.block({ children: [{ text: '' }], type: defaultType }),\n {\n nextBlock: true,\n select: true,\n ...insertNodesOptions,\n }\n );\n }\n\n insertCodeBlock(editor, insertNodesOptions);\n};\n","import type { Editor, ElementEntry } from 'platejs';\n\nimport { deleteStartSpace } from './deleteStartSpace';\n\nexport type OutdentCodeLineOptions = {\n codeBlock: ElementEntry;\n codeLine: ElementEntry;\n};\n\n/** Outdent the code line. Remove 2 whitespace characters if any. */\nexport const outdentCodeLine = (\n editor: Editor,\n { codeBlock, codeLine }: OutdentCodeLineOptions\n) => {\n const deleted = deleteStartSpace(editor, { codeBlock, codeLine });\n if (deleted) {\n deleteStartSpace(editor, { codeBlock, codeLine });\n }\n};\n","import type { SlateEditor, TElement } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\nimport { unwrapCodeBlock } from './unwrapCodeBlock';\n\nexport const toggleCodeBlock = (editor: SlateEditor) => {\n if (!editor.selection) return;\n\n const codeBlockType = editor.getType(KEYS.codeBlock);\n const codeLineType = editor.getType(KEYS.codeLine);\n\n const isActive = editor.api.some({\n match: { type: codeBlockType },\n });\n\n editor.tf.withoutNormalizing(() => {\n unwrapCodeBlock(editor);\n\n if (!isActive) {\n editor.tf.setNodes({\n type: codeLineType,\n });\n\n const codeBlock = {\n children: [],\n type: codeBlockType,\n };\n\n editor.tf.wrapNodes<TElement>(codeBlock);\n }\n });\n};\n","import { type SlateEditor, type TLocation, KEYS, NodeApi } from 'platejs';\n\nexport const unwrapCodeBlock = (editor: SlateEditor) => {\n if (!editor.selection) return;\n\n const codeBlockType = editor.getType(KEYS.codeBlock);\n const defaultType = editor.getType(KEYS.p);\n\n editor.tf.withoutNormalizing(() => {\n const codeBlockEntries = editor.api.nodes({\n at: editor.selection as TLocation,\n match: { type: codeBlockType },\n });\n\n const reversedCodeBlockEntries = Array.from(codeBlockEntries).reverse();\n\n for (const codeBlockEntry of reversedCodeBlockEntries) {\n const codeLineEntries = NodeApi.children(editor, codeBlockEntry[1]);\n\n for (const [, path] of codeLineEntries) {\n editor.tf.setNodes({ type: defaultType }, { at: path });\n }\n\n editor.tf.unwrapNodes({\n at: codeBlockEntry[1],\n match: { type: codeBlockType },\n split: true,\n });\n }\n });\n};\n","import type { OverrideEditor, TElement } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\nexport const withInsertDataCodeBlock: OverrideEditor = ({\n editor,\n tf: { insertData },\n type: codeBlockType,\n}) => ({\n transforms: {\n insertData(data) {\n const text = data.getData('text/plain');\n const vscodeDataString = data.getData('vscode-editor-data');\n const codeLineType = editor.getType(KEYS.codeLine);\n\n // Handle VSCode paste with language\n if (vscodeDataString) {\n try {\n const vscodeData = JSON.parse(vscodeDataString);\n const lines = text.split('\\n');\n\n // Check if we're in a code block\n const [blockAbove] = editor.api.block<TElement>() ?? [];\n const isInCodeBlock =\n blockAbove &&\n [codeBlockType, codeLineType].includes(blockAbove?.type);\n\n if (isInCodeBlock) {\n // If in code block, insert first line as text at cursor\n if (lines[0]) {\n editor.tf.insertText(lines[0]);\n }\n\n // Insert remaining lines as new code lines\n if (lines.length > 1) {\n const nodes = lines.slice(1).map((line) => ({\n children: [{ text: line }],\n type: codeLineType,\n }));\n editor.tf.insertNodes(nodes);\n }\n } else {\n // Create new code block\n const node = {\n children: lines.map((line) => ({\n children: [{ text: line }],\n type: codeLineType,\n })),\n lang: vscodeData?.mode,\n type: codeBlockType,\n };\n\n editor.tf.insertNodes(node, {\n select: true,\n });\n }\n\n return;\n } catch (_error) {}\n }\n\n // Handle plain text paste into code block only if there are line breaks\n const [blockAbove] = editor.api.block<TElement>() ?? [];\n if (\n blockAbove &&\n [codeBlockType, codeLineType].includes(blockAbove?.type) &&\n text?.includes('\\n')\n ) {\n const lines = text.split('\\n');\n\n // Insert first line as text at cursor\n if (lines[0]) {\n editor.tf.insertText(lines[0]);\n }\n\n // Insert remaining lines as new code lines\n if (lines.length > 1) {\n const nodes = lines.slice(1).map((line) => ({\n children: [{ text: line }],\n type: codeLineType,\n }));\n editor.tf.insertNodes(nodes);\n }\n return;\n }\n\n insertData(data);\n },\n },\n});\n","import { type OverrideEditor, type TElement, KEYS, NodeApi } from 'platejs';\n\nfunction extractCodeLinesFromCodeBlock(node: TElement) {\n return node.children as TElement[];\n}\n\nexport const withInsertFragmentCodeBlock: OverrideEditor = ({\n editor,\n tf: { insertFragment },\n type: codeBlockType,\n}) => ({\n transforms: {\n insertFragment(fragment) {\n const [blockAbove] = editor.api.block<TElement>() ?? [];\n const codeLineType = editor.getType(KEYS.codeLine);\n\n function convertNodeToCodeLine(node: TElement): TElement {\n return {\n children: [{ text: NodeApi.string(node) }],\n type: codeLineType,\n };\n }\n\n if (\n blockAbove &&\n [codeBlockType, codeLineType].includes(blockAbove?.type)\n ) {\n return insertFragment(\n fragment.flatMap((node) => {\n const element = node as TElement;\n\n return element.type === codeBlockType\n ? extractCodeLinesFromCodeBlock(element)\n : convertNodeToCodeLine(element);\n })\n );\n }\n\n return insertFragment(fragment);\n },\n },\n});\n","import {\n type NodeEntry,\n type OverrideEditor,\n type TCodeBlockElement,\n ElementApi,\n KEYS,\n NodeApi,\n} from 'platejs';\n\nimport type { CodeBlockConfig } from './BaseCodeBlockPlugin';\n\nimport { setCodeBlockToDecorations } from './setCodeBlockToDecorations';\n\n/** Normalize code block node to force the pre>code>div.codeline structure. */\nexport const withNormalizeCodeBlock: OverrideEditor<CodeBlockConfig> = ({\n editor,\n getOptions,\n tf: { normalizeNode },\n type,\n}) => ({\n transforms: {\n normalizeNode([node, path]) {\n // Decorate is called on selection change as well, so we prefer to only run this on code block changes.\n if (node.type === type && getOptions().lowlight) {\n setCodeBlockToDecorations(editor, [\n node,\n path,\n ] as NodeEntry<TCodeBlockElement>);\n }\n\n normalizeNode([node, path]);\n\n if (!ElementApi.isElement(node)) {\n return;\n }\n\n const codeBlockType = editor.getType(KEYS.codeBlock);\n const codeLineType = editor.getType(KEYS.codeLine);\n const isCodeBlockRoot = node.type === codeBlockType;\n\n if (isCodeBlockRoot) {\n // Children should all be code lines\n const nonCodeLine = Array.from(NodeApi.children(editor, path)).find(\n ([child]) => child.type !== codeLineType\n );\n\n if (nonCodeLine) {\n editor.tf.setNodes({ type: codeLineType }, { at: nonCodeLine[1] });\n }\n }\n },\n },\n});\n","import type { OverrideEditor, TCodeBlockElement, TElement } from 'platejs';\n\nimport type { CodeBlockConfig } from './BaseCodeBlockPlugin';\n\nimport { getCodeLineEntry, getIndentDepth } from './queries';\nimport { resetCodeBlockDecorations } from './setCodeBlockToDecorations';\nimport { indentCodeLine, outdentCodeLine, unwrapCodeBlock } from './transforms';\nimport { withInsertDataCodeBlock } from './withInsertDataCodeBlock';\nimport { withInsertFragmentCodeBlock } from './withInsertFragmentCodeBlock';\nimport { withNormalizeCodeBlock } from './withNormalizeCodeBlock';\n\nexport const withCodeBlock: OverrideEditor<CodeBlockConfig> = (ctx) => {\n const {\n editor,\n getOptions,\n tf: { apply, insertBreak, resetBlock, selectAll, tab },\n type,\n } = ctx;\n\n return {\n transforms: {\n apply(operation) {\n if (getOptions().lowlight && operation.type === 'set_node') {\n const entry = editor.api.node(operation.path);\n\n if (entry?.[0].type === type && operation.newProperties?.lang) {\n // Clear decorations for all code lines in this block\n resetCodeBlockDecorations(entry[0] as TCodeBlockElement);\n }\n }\n\n apply(operation);\n },\n insertBreak() {\n const apply = () => {\n if (!editor.selection) return;\n\n const res = getCodeLineEntry(editor, {});\n\n if (!res) return;\n\n const { codeBlock, codeLine } = res;\n const indentDepth = getIndentDepth(editor, {\n codeBlock,\n codeLine,\n });\n\n insertBreak();\n\n indentCodeLine(editor, {\n codeBlock,\n codeLine,\n indentDepth,\n });\n\n return true;\n };\n\n if (apply()) return;\n\n insertBreak();\n },\n resetBlock(options) {\n if (\n editor.api.block({\n at: options?.at,\n match: { type },\n })\n ) {\n unwrapCodeBlock(editor);\n return;\n }\n\n return resetBlock(options);\n },\n selectAll: () => {\n const apply = () => {\n const codeBlock = editor.api.above({\n match: { type },\n });\n\n if (!codeBlock) return;\n\n if (\n editor.api.isAt({ end: true }) &&\n editor.api.isAt({ start: true })\n ) {\n return;\n }\n\n // Select the whole code block\n editor.tf.select(codeBlock[1]);\n return true;\n };\n\n if (apply()) return true;\n\n return selectAll();\n },\n tab: (options) => {\n const apply = () => {\n const _codeLines = editor.api.nodes<TElement>({\n match: { type },\n });\n const codeLines = Array.from(_codeLines);\n\n if (codeLines.length > 0) {\n const [, firstLinePath] = codeLines[0];\n const codeBlock = editor.api.parent<TElement>(firstLinePath);\n\n if (!codeBlock) return;\n\n editor.tf.withoutNormalizing(() => {\n for (const codeLine of codeLines) {\n if (options.reverse) {\n outdentCodeLine(editor, { codeBlock, codeLine });\n } else {\n indentCodeLine(editor, { codeBlock, codeLine });\n }\n }\n });\n\n return true; // Prevent default\n }\n };\n\n if (apply()) return true;\n\n return tab(options);\n },\n ...withInsertDataCodeBlock(ctx).transforms,\n ...withInsertFragmentCodeBlock(ctx).transforms,\n ...withNormalizeCodeBlock(ctx).transforms,\n },\n };\n};\n","export const formatJson = (code: string): string => {\n try {\n return JSON.stringify(JSON.parse(code), null, 2);\n } catch (_error) {\n return code;\n }\n};\n\nexport const isValidJson = (code: string): boolean => {\n try {\n JSON.parse(code);\n\n return true;\n } catch (_error) {\n return false;\n }\n};\n","import type { Editor, TCodeBlockElement } from 'platejs';\n\nimport { formatJson, isValidJson } from './jsonFormatter';\n\nconst supportedLanguages = new Set(['json']);\n\nexport const isLangSupported = (lang?: string): boolean =>\n Boolean(lang && supportedLanguages.has(lang));\n\nexport const isValidSyntax = (code: string, lang?: string): boolean => {\n if (!isLangSupported(lang)) {\n return false;\n }\n\n switch (lang) {\n case 'json': {\n return isValidJson(code);\n }\n default: {\n return false;\n }\n }\n};\n\nexport const formatCodeBlock = (\n editor: Editor,\n {\n element,\n }: {\n element: TCodeBlockElement;\n }\n) => {\n const { lang } = element;\n\n if (!lang || !isLangSupported(lang)) {\n return;\n }\n\n const code = editor.api.string(element);\n\n if (isValidSyntax(code, lang)) {\n const formattedCode = formatCode(code, lang);\n editor.tf.insertText(formattedCode, { at: element });\n }\n};\n\nconst formatCode = (code: string, lang?: string): string => {\n switch (lang) {\n case 'json': {\n return formatJson(code);\n }\n default: {\n return code;\n }\n }\n};\n"],"mappings":"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","names":["import_platejs","import_platejs","import_platejs","import_platejs","import_platejs","import_platejs","import_platejs","import_platejs","import_platejs","import_platejs","blockAbove","import_platejs","import_platejs","apply"]} |
-745
| // src/lib/BaseCodeBlockPlugin.ts | ||
| import { | ||
| createSlatePlugin, | ||
| createTSlatePlugin, | ||
| KEYS as KEYS12 | ||
| } from "platejs"; | ||
| // src/lib/deserializer/htmlDeserializerCodeBlock.ts | ||
| import { KEYS } from "platejs"; | ||
| var htmlDeserializerCodeBlock = { | ||
| rules: [ | ||
| { | ||
| validNodeName: "PRE" | ||
| }, | ||
| { | ||
| validNodeName: "P", | ||
| validStyle: { | ||
| fontFamily: "Consolas" | ||
| } | ||
| } | ||
| ], | ||
| parse: ({ element }) => { | ||
| const languageSelectorText = [...element.childNodes].find( | ||
| (node) => node.nodeName === "SELECT" | ||
| )?.textContent || ""; | ||
| const textContent = element.textContent?.replace(languageSelectorText, "") || ""; | ||
| let lines = textContent.split("\n"); | ||
| if (!lines?.length) { | ||
| lines = [textContent]; | ||
| } | ||
| const codeLines = lines.map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: KEYS.codeLine | ||
| })); | ||
| return { | ||
| children: codeLines, | ||
| type: KEYS.codeBlock | ||
| }; | ||
| } | ||
| }; | ||
| // src/lib/queries/getCodeLineEntry.ts | ||
| import { | ||
| ElementApi, | ||
| KEYS as KEYS2 | ||
| } from "platejs"; | ||
| var getCodeLineEntry = (editor, { at = editor.selection } = {}) => { | ||
| if (at && editor.api.some({ | ||
| at, | ||
| match: { type: editor.getType(KEYS2.codeLine) } | ||
| })) { | ||
| const selectionParent = editor.api.parent(at); | ||
| if (!selectionParent) return; | ||
| const [, parentPath] = selectionParent; | ||
| const codeLine = editor.api.above({ | ||
| at, | ||
| match: { type: editor.getType(KEYS2.codeLine) } | ||
| }) || editor.api.parent(parentPath); | ||
| if (!codeLine) return; | ||
| const [codeLineNode, codeLinePath] = codeLine; | ||
| if (ElementApi.isElement(codeLineNode) && codeLineNode.type !== editor.getType(KEYS2.codeLine)) | ||
| return; | ||
| const codeBlock = editor.api.parent(codeLinePath); | ||
| if (!codeBlock) return; | ||
| return { | ||
| codeBlock, | ||
| codeLine | ||
| }; | ||
| } | ||
| }; | ||
| // src/lib/queries/getIndentDepth.ts | ||
| var nonWhitespaceOrEndRegex = /\S|$/; | ||
| var getIndentDepth = (editor, { codeLine }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const text = editor.api.string(codeLinePath); | ||
| return text.search(nonWhitespaceOrEndRegex); | ||
| }; | ||
| // src/lib/queries/isCodeBlockEmpty.ts | ||
| import { NodeApi } from "platejs"; | ||
| var isCodeBlockEmpty = (editor) => { | ||
| const { codeBlock } = getCodeLineEntry(editor) ?? {}; | ||
| if (!codeBlock) return false; | ||
| const codeLines = Array.from(NodeApi.children(editor, codeBlock[1])); | ||
| if (codeLines.length === 0) return true; | ||
| if (codeLines.length > 1) return false; | ||
| const firstCodeLineNode = codeLines[0][0]; | ||
| return !NodeApi.string(firstCodeLineNode); | ||
| }; | ||
| // src/lib/queries/isSelectionAtCodeBlockStart.ts | ||
| var isSelectionAtCodeBlockStart = (editor) => { | ||
| const { selection } = editor; | ||
| if (!selection || editor.api.isExpanded()) return false; | ||
| const { codeBlock } = getCodeLineEntry(editor) ?? {}; | ||
| if (!codeBlock) return false; | ||
| return editor.api.isStart(selection.anchor, codeBlock[1]); | ||
| }; | ||
| // src/lib/setCodeBlockToDecorations.ts | ||
| import { | ||
| KEYS as KEYS3, | ||
| NodeApi as NodeApi2 | ||
| } from "platejs"; | ||
| var CODE_LINE_TO_DECORATIONS = /* @__PURE__ */ new WeakMap(); | ||
| function getHighlightNodes(result) { | ||
| return result.value || result.children || []; | ||
| } | ||
| function parseNodes(nodes, className = []) { | ||
| return nodes.flatMap((node) => { | ||
| const classes = [ | ||
| ...className, | ||
| ...node.properties ? node.properties.className : [] | ||
| ]; | ||
| if (node.children) { | ||
| return parseNodes(node.children, classes); | ||
| } | ||
| return { classes, text: node.value }; | ||
| }); | ||
| } | ||
| function normalizeTokens(tokens) { | ||
| const lines = [[]]; | ||
| let currentLine = lines[0]; | ||
| for (const token of tokens) { | ||
| const tokenLines = token.text.split("\n"); | ||
| for (let i = 0; i < tokenLines.length; i++) { | ||
| const content = tokenLines[i]; | ||
| if (content) { | ||
| currentLine.push({ classes: token.classes, content }); | ||
| } | ||
| if (i < tokenLines.length - 1) { | ||
| lines.push([]); | ||
| currentLine = lines.at(-1); | ||
| } | ||
| } | ||
| } | ||
| return lines; | ||
| } | ||
| function codeBlockToDecorations(editor, [block, blockPath]) { | ||
| const { defaultLanguage, ...options } = editor.getOptions(BaseCodeBlockPlugin); | ||
| const lowlight = options.lowlight; | ||
| const text = block.children.map((line) => NodeApi2.string(line)).join("\n"); | ||
| const language = block.lang; | ||
| const effectiveLanguage = language || defaultLanguage; | ||
| let highlighted; | ||
| try { | ||
| if (!effectiveLanguage || effectiveLanguage === "plaintext") { | ||
| highlighted = { value: [] }; | ||
| } else if (effectiveLanguage === "auto") { | ||
| highlighted = lowlight.highlightAuto(text); | ||
| } else { | ||
| highlighted = lowlight.highlight(effectiveLanguage, text); | ||
| } | ||
| } catch (error) { | ||
| const availableLanguages = lowlight.listLanguages(); | ||
| const isLanguageRegistered = effectiveLanguage && availableLanguages.includes(effectiveLanguage); | ||
| if (isLanguageRegistered) { | ||
| editor.api.debug.error(error, "CODE_HIGHLIGHT"); | ||
| highlighted = { value: [] }; | ||
| } else { | ||
| editor.api.debug.warn( | ||
| `Language "${effectiveLanguage}" is not registered. Falling back to plaintext` | ||
| ); | ||
| highlighted = { value: [] }; | ||
| } | ||
| } | ||
| const tokens = parseNodes(getHighlightNodes(highlighted)); | ||
| const normalizedTokens = normalizeTokens(tokens); | ||
| const blockChildren = block.children; | ||
| const nodeToDecorations = /* @__PURE__ */ new Map(); | ||
| const numLines = Math.min(normalizedTokens.length, blockChildren.length); | ||
| for (let index = 0; index < numLines; index++) { | ||
| const lineTokens = normalizedTokens[index]; | ||
| const element = blockChildren[index]; | ||
| if (!nodeToDecorations.has(element)) { | ||
| nodeToDecorations.set(element, []); | ||
| } | ||
| let start = 0; | ||
| for (const token of lineTokens) { | ||
| const length = token.content.length; | ||
| if (!length) continue; | ||
| const end = start + length; | ||
| const decoration = { | ||
| anchor: { | ||
| offset: start, | ||
| path: [...blockPath, index, 0] | ||
| }, | ||
| className: token.classes.join(" "), | ||
| focus: { | ||
| offset: end, | ||
| path: [...blockPath, index, 0] | ||
| }, | ||
| [KEYS3.codeSyntax]: true | ||
| }; | ||
| nodeToDecorations.get(element).push(decoration); | ||
| start = end; | ||
| } | ||
| } | ||
| return nodeToDecorations; | ||
| } | ||
| function setCodeBlockToDecorations(editor, [block, blockPath]) { | ||
| const decorations = codeBlockToDecorations(editor, [block, blockPath]); | ||
| for (const [node, decs] of decorations.entries()) { | ||
| CODE_LINE_TO_DECORATIONS.set(node, decs); | ||
| } | ||
| } | ||
| function resetCodeBlockDecorations(codeBlock) { | ||
| codeBlock.children.forEach((line) => { | ||
| CODE_LINE_TO_DECORATIONS.delete(line); | ||
| }); | ||
| } | ||
| // src/lib/transforms/deleteStartSpace.ts | ||
| var whitespaceRegex = /\s/; | ||
| var deleteStartSpace = (editor, { codeLine }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const codeLineStart = editor.api.start(codeLinePath); | ||
| const codeLineEnd = codeLineStart && editor.api.after(codeLineStart); | ||
| const spaceRange = codeLineEnd && editor.api.range(codeLineStart, codeLineEnd); | ||
| const spaceText = editor.api.string(spaceRange); | ||
| if (whitespaceRegex.test(spaceText)) { | ||
| editor.tf.delete({ at: spaceRange }); | ||
| return true; | ||
| } | ||
| return false; | ||
| }; | ||
| // src/lib/transforms/indentCodeLine.ts | ||
| var nonWhitespaceRegex = /\S/; | ||
| var indentCodeLine = (editor, { codeLine, indentDepth = 2 }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const codeLineStart = editor.api.start(codeLinePath); | ||
| const indent = " ".repeat(indentDepth); | ||
| if (!editor.api.isExpanded()) { | ||
| const cursor = editor.selection?.anchor; | ||
| const range = editor.api.range(codeLineStart, cursor); | ||
| const text = editor.api.string(range); | ||
| if (nonWhitespaceRegex.test(text)) { | ||
| editor.tf.insertText(indent, { at: editor.selection }); | ||
| return; | ||
| } | ||
| } | ||
| editor.tf.insertText(indent, { at: codeLineStart }); | ||
| }; | ||
| // src/lib/transforms/insertCodeBlock.ts | ||
| import { KEYS as KEYS4 } from "platejs"; | ||
| var insertCodeBlock = (editor, insertNodesOptions = {}) => { | ||
| if (!editor.selection || editor.api.isExpanded()) return; | ||
| const matchCodeElements = (node) => node.type === KEYS4.codeBlock || node.type === KEYS4.codeLine; | ||
| if (editor.api.some({ | ||
| match: matchCodeElements | ||
| })) { | ||
| return; | ||
| } | ||
| if (!editor.api.isAt({ start: true })) { | ||
| editor.tf.insertBreak(); | ||
| } | ||
| editor.tf.setNodes( | ||
| { | ||
| children: [{ text: "" }], | ||
| type: KEYS4.codeLine | ||
| }, | ||
| insertNodesOptions | ||
| ); | ||
| editor.tf.wrapNodes( | ||
| { | ||
| children: [], | ||
| type: KEYS4.codeBlock | ||
| }, | ||
| insertNodesOptions | ||
| ); | ||
| }; | ||
| // src/lib/transforms/insertCodeLine.ts | ||
| import { KEYS as KEYS5 } from "platejs"; | ||
| var insertCodeLine = (editor, indentDepth = 0) => { | ||
| if (editor.selection) { | ||
| const indent = " ".repeat(indentDepth); | ||
| editor.tf.insertNodes({ | ||
| children: [{ text: indent }], | ||
| type: editor.getType(KEYS5.codeLine) | ||
| }); | ||
| } | ||
| }; | ||
| // src/lib/transforms/insertEmptyCodeBlock.ts | ||
| import { KEYS as KEYS6 } from "platejs"; | ||
| var insertEmptyCodeBlock = (editor, { | ||
| defaultType = editor.getType(KEYS6.p), | ||
| insertNodesOptions | ||
| } = {}) => { | ||
| if (!editor.selection) return; | ||
| if (editor.api.isExpanded() || !editor.api.isEmpty(editor.selection, { block: true })) { | ||
| editor.tf.insertNodes( | ||
| editor.api.create.block({ children: [{ text: "" }], type: defaultType }), | ||
| { | ||
| nextBlock: true, | ||
| select: true, | ||
| ...insertNodesOptions | ||
| } | ||
| ); | ||
| } | ||
| insertCodeBlock(editor, insertNodesOptions); | ||
| }; | ||
| // src/lib/transforms/outdentCodeLine.ts | ||
| var outdentCodeLine = (editor, { codeBlock, codeLine }) => { | ||
| const deleted = deleteStartSpace(editor, { codeBlock, codeLine }); | ||
| if (deleted) { | ||
| deleteStartSpace(editor, { codeBlock, codeLine }); | ||
| } | ||
| }; | ||
| // src/lib/transforms/toggleCodeBlock.ts | ||
| import { KEYS as KEYS8 } from "platejs"; | ||
| // src/lib/transforms/unwrapCodeBlock.ts | ||
| import { KEYS as KEYS7, NodeApi as NodeApi3 } from "platejs"; | ||
| var unwrapCodeBlock = (editor) => { | ||
| if (!editor.selection) return; | ||
| const codeBlockType = editor.getType(KEYS7.codeBlock); | ||
| const defaultType = editor.getType(KEYS7.p); | ||
| editor.tf.withoutNormalizing(() => { | ||
| const codeBlockEntries = editor.api.nodes({ | ||
| at: editor.selection, | ||
| match: { type: codeBlockType } | ||
| }); | ||
| const reversedCodeBlockEntries = Array.from(codeBlockEntries).reverse(); | ||
| for (const codeBlockEntry of reversedCodeBlockEntries) { | ||
| const codeLineEntries = NodeApi3.children(editor, codeBlockEntry[1]); | ||
| for (const [, path] of codeLineEntries) { | ||
| editor.tf.setNodes({ type: defaultType }, { at: path }); | ||
| } | ||
| editor.tf.unwrapNodes({ | ||
| at: codeBlockEntry[1], | ||
| match: { type: codeBlockType }, | ||
| split: true | ||
| }); | ||
| } | ||
| }); | ||
| }; | ||
| // src/lib/transforms/toggleCodeBlock.ts | ||
| var toggleCodeBlock = (editor) => { | ||
| if (!editor.selection) return; | ||
| const codeBlockType = editor.getType(KEYS8.codeBlock); | ||
| const codeLineType = editor.getType(KEYS8.codeLine); | ||
| const isActive = editor.api.some({ | ||
| match: { type: codeBlockType } | ||
| }); | ||
| editor.tf.withoutNormalizing(() => { | ||
| unwrapCodeBlock(editor); | ||
| if (!isActive) { | ||
| editor.tf.setNodes({ | ||
| type: codeLineType | ||
| }); | ||
| const codeBlock = { | ||
| children: [], | ||
| type: codeBlockType | ||
| }; | ||
| editor.tf.wrapNodes(codeBlock); | ||
| } | ||
| }); | ||
| }; | ||
| // src/lib/withInsertDataCodeBlock.ts | ||
| import { KEYS as KEYS9 } from "platejs"; | ||
| var withInsertDataCodeBlock = ({ | ||
| editor, | ||
| tf: { insertData }, | ||
| type: codeBlockType | ||
| }) => ({ | ||
| transforms: { | ||
| insertData(data) { | ||
| const text = data.getData("text/plain"); | ||
| const vscodeDataString = data.getData("vscode-editor-data"); | ||
| const codeLineType = editor.getType(KEYS9.codeLine); | ||
| if (vscodeDataString) { | ||
| try { | ||
| const vscodeData = JSON.parse(vscodeDataString); | ||
| const lines = text.split("\n"); | ||
| const [blockAbove2] = editor.api.block() ?? []; | ||
| const isInCodeBlock = blockAbove2 && [codeBlockType, codeLineType].includes(blockAbove2?.type); | ||
| if (isInCodeBlock) { | ||
| if (lines[0]) { | ||
| editor.tf.insertText(lines[0]); | ||
| } | ||
| if (lines.length > 1) { | ||
| const nodes = lines.slice(1).map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })); | ||
| editor.tf.insertNodes(nodes); | ||
| } | ||
| } else { | ||
| const node = { | ||
| children: lines.map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })), | ||
| lang: vscodeData?.mode, | ||
| type: codeBlockType | ||
| }; | ||
| editor.tf.insertNodes(node, { | ||
| select: true | ||
| }); | ||
| } | ||
| return; | ||
| } catch (_error) { | ||
| } | ||
| } | ||
| const [blockAbove] = editor.api.block() ?? []; | ||
| if (blockAbove && [codeBlockType, codeLineType].includes(blockAbove?.type) && text?.includes("\n")) { | ||
| const lines = text.split("\n"); | ||
| if (lines[0]) { | ||
| editor.tf.insertText(lines[0]); | ||
| } | ||
| if (lines.length > 1) { | ||
| const nodes = lines.slice(1).map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })); | ||
| editor.tf.insertNodes(nodes); | ||
| } | ||
| return; | ||
| } | ||
| insertData(data); | ||
| } | ||
| } | ||
| }); | ||
| // src/lib/withInsertFragmentCodeBlock.ts | ||
| import { KEYS as KEYS10, NodeApi as NodeApi4 } from "platejs"; | ||
| function extractCodeLinesFromCodeBlock(node) { | ||
| return node.children; | ||
| } | ||
| var withInsertFragmentCodeBlock = ({ | ||
| editor, | ||
| tf: { insertFragment }, | ||
| type: codeBlockType | ||
| }) => ({ | ||
| transforms: { | ||
| insertFragment(fragment) { | ||
| const [blockAbove] = editor.api.block() ?? []; | ||
| const codeLineType = editor.getType(KEYS10.codeLine); | ||
| function convertNodeToCodeLine(node) { | ||
| return { | ||
| children: [{ text: NodeApi4.string(node) }], | ||
| type: codeLineType | ||
| }; | ||
| } | ||
| if (blockAbove && [codeBlockType, codeLineType].includes(blockAbove?.type)) { | ||
| return insertFragment( | ||
| fragment.flatMap((node) => { | ||
| const element = node; | ||
| return element.type === codeBlockType ? extractCodeLinesFromCodeBlock(element) : convertNodeToCodeLine(element); | ||
| }) | ||
| ); | ||
| } | ||
| return insertFragment(fragment); | ||
| } | ||
| } | ||
| }); | ||
| // src/lib/withNormalizeCodeBlock.tsx | ||
| import { | ||
| ElementApi as ElementApi2, | ||
| KEYS as KEYS11, | ||
| NodeApi as NodeApi5 | ||
| } from "platejs"; | ||
| var withNormalizeCodeBlock = ({ | ||
| editor, | ||
| getOptions, | ||
| tf: { normalizeNode }, | ||
| type | ||
| }) => ({ | ||
| transforms: { | ||
| normalizeNode([node, path]) { | ||
| if (node.type === type && getOptions().lowlight) { | ||
| setCodeBlockToDecorations(editor, [ | ||
| node, | ||
| path | ||
| ]); | ||
| } | ||
| normalizeNode([node, path]); | ||
| if (!ElementApi2.isElement(node)) { | ||
| return; | ||
| } | ||
| const codeBlockType = editor.getType(KEYS11.codeBlock); | ||
| const codeLineType = editor.getType(KEYS11.codeLine); | ||
| const isCodeBlockRoot = node.type === codeBlockType; | ||
| if (isCodeBlockRoot) { | ||
| const nonCodeLine = Array.from(NodeApi5.children(editor, path)).find( | ||
| ([child]) => child.type !== codeLineType | ||
| ); | ||
| if (nonCodeLine) { | ||
| editor.tf.setNodes({ type: codeLineType }, { at: nonCodeLine[1] }); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| }); | ||
| // src/lib/withCodeBlock.ts | ||
| var withCodeBlock = (ctx) => { | ||
| const { | ||
| editor, | ||
| getOptions, | ||
| tf: { apply, insertBreak, resetBlock, selectAll, tab }, | ||
| type | ||
| } = ctx; | ||
| return { | ||
| transforms: { | ||
| apply(operation) { | ||
| if (getOptions().lowlight && operation.type === "set_node") { | ||
| const entry = editor.api.node(operation.path); | ||
| if (entry?.[0].type === type && operation.newProperties?.lang) { | ||
| resetCodeBlockDecorations(entry[0]); | ||
| } | ||
| } | ||
| apply(operation); | ||
| }, | ||
| insertBreak() { | ||
| const apply2 = () => { | ||
| if (!editor.selection) return; | ||
| const res = getCodeLineEntry(editor, {}); | ||
| if (!res) return; | ||
| const { codeBlock, codeLine } = res; | ||
| const indentDepth = getIndentDepth(editor, { | ||
| codeBlock, | ||
| codeLine | ||
| }); | ||
| insertBreak(); | ||
| indentCodeLine(editor, { | ||
| codeBlock, | ||
| codeLine, | ||
| indentDepth | ||
| }); | ||
| return true; | ||
| }; | ||
| if (apply2()) return; | ||
| insertBreak(); | ||
| }, | ||
| resetBlock(options) { | ||
| if (editor.api.block({ | ||
| at: options?.at, | ||
| match: { type } | ||
| })) { | ||
| unwrapCodeBlock(editor); | ||
| return; | ||
| } | ||
| return resetBlock(options); | ||
| }, | ||
| selectAll: () => { | ||
| const apply2 = () => { | ||
| const codeBlock = editor.api.above({ | ||
| match: { type } | ||
| }); | ||
| if (!codeBlock) return; | ||
| if (editor.api.isAt({ end: true }) && editor.api.isAt({ start: true })) { | ||
| return; | ||
| } | ||
| editor.tf.select(codeBlock[1]); | ||
| return true; | ||
| }; | ||
| if (apply2()) return true; | ||
| return selectAll(); | ||
| }, | ||
| tab: (options) => { | ||
| const apply2 = () => { | ||
| const _codeLines = editor.api.nodes({ | ||
| match: { type } | ||
| }); | ||
| const codeLines = Array.from(_codeLines); | ||
| if (codeLines.length > 0) { | ||
| const [, firstLinePath] = codeLines[0]; | ||
| const codeBlock = editor.api.parent(firstLinePath); | ||
| if (!codeBlock) return; | ||
| editor.tf.withoutNormalizing(() => { | ||
| for (const codeLine of codeLines) { | ||
| if (options.reverse) { | ||
| outdentCodeLine(editor, { codeBlock, codeLine }); | ||
| } else { | ||
| indentCodeLine(editor, { codeBlock, codeLine }); | ||
| } | ||
| } | ||
| }); | ||
| return true; | ||
| } | ||
| }; | ||
| if (apply2()) return true; | ||
| return tab(options); | ||
| }, | ||
| ...withInsertDataCodeBlock(ctx).transforms, | ||
| ...withInsertFragmentCodeBlock(ctx).transforms, | ||
| ...withNormalizeCodeBlock(ctx).transforms | ||
| } | ||
| }; | ||
| }; | ||
| // src/lib/BaseCodeBlockPlugin.ts | ||
| var BaseCodeLinePlugin = createTSlatePlugin({ | ||
| key: KEYS12.codeLine, | ||
| node: { isElement: true, isStrictSiblings: true } | ||
| }); | ||
| var BaseCodeSyntaxPlugin = createSlatePlugin({ | ||
| key: KEYS12.codeSyntax, | ||
| node: { isLeaf: true } | ||
| }); | ||
| var BaseCodeBlockPlugin = createTSlatePlugin({ | ||
| key: KEYS12.codeBlock, | ||
| inject: { | ||
| plugins: { | ||
| [KEYS12.html]: { | ||
| parser: { | ||
| query: ({ editor }) => !editor.api.some({ | ||
| match: { type: editor.getType(KEYS12.codeLine) } | ||
| }) | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| node: { | ||
| isElement: true | ||
| }, | ||
| options: { | ||
| defaultLanguage: null, | ||
| lowlight: null | ||
| }, | ||
| parsers: { html: { deserializer: htmlDeserializerCodeBlock } }, | ||
| plugins: [BaseCodeLinePlugin, BaseCodeSyntaxPlugin], | ||
| render: { as: "pre" }, | ||
| rules: { | ||
| delete: { | ||
| empty: "reset" | ||
| }, | ||
| match: ({ editor, rule }) => ["break.empty", "delete.empty"].includes(rule) && isCodeBlockEmpty(editor) | ||
| }, | ||
| decorate: ({ editor, entry: [node, path], getOptions, type }) => { | ||
| if (!getOptions().lowlight) return []; | ||
| const codeLineType = editor.getType(KEYS12.codeLine); | ||
| if (node.type === type && !CODE_LINE_TO_DECORATIONS.get(node.children[0])) { | ||
| setCodeBlockToDecorations(editor, [node, path]); | ||
| } | ||
| if (node.type === codeLineType) { | ||
| return CODE_LINE_TO_DECORATIONS.get(node) || []; | ||
| } | ||
| return []; | ||
| } | ||
| }).overrideEditor(withCodeBlock).extendTransforms(({ editor }) => ({ | ||
| toggle: () => { | ||
| editor.tf.toggleBlock(editor.getType(KEYS12.codeBlock)); | ||
| } | ||
| })); | ||
| // src/lib/formatter/jsonFormatter.ts | ||
| var formatJson = (code) => { | ||
| try { | ||
| return JSON.stringify(JSON.parse(code), null, 2); | ||
| } catch (_error) { | ||
| return code; | ||
| } | ||
| }; | ||
| var isValidJson = (code) => { | ||
| try { | ||
| JSON.parse(code); | ||
| return true; | ||
| } catch (_error) { | ||
| return false; | ||
| } | ||
| }; | ||
| // src/lib/formatter/formatter.ts | ||
| var supportedLanguages = /* @__PURE__ */ new Set(["json"]); | ||
| var isLangSupported = (lang) => Boolean(lang && supportedLanguages.has(lang)); | ||
| var isValidSyntax = (code, lang) => { | ||
| if (!isLangSupported(lang)) { | ||
| return false; | ||
| } | ||
| switch (lang) { | ||
| case "json": { | ||
| return isValidJson(code); | ||
| } | ||
| default: { | ||
| return false; | ||
| } | ||
| } | ||
| }; | ||
| var formatCodeBlock = (editor, { | ||
| element | ||
| }) => { | ||
| const { lang } = element; | ||
| if (!lang || !isLangSupported(lang)) { | ||
| return; | ||
| } | ||
| const code = editor.api.string(element); | ||
| if (isValidSyntax(code, lang)) { | ||
| const formattedCode = formatCode(code, lang); | ||
| editor.tf.insertText(formattedCode, { at: element }); | ||
| } | ||
| }; | ||
| var formatCode = (code, lang) => { | ||
| switch (lang) { | ||
| case "json": { | ||
| return formatJson(code); | ||
| } | ||
| default: { | ||
| return code; | ||
| } | ||
| } | ||
| }; | ||
| export { | ||
| BaseCodeBlockPlugin, | ||
| BaseCodeLinePlugin, | ||
| BaseCodeSyntaxPlugin, | ||
| CODE_LINE_TO_DECORATIONS, | ||
| codeBlockToDecorations, | ||
| deleteStartSpace, | ||
| formatCodeBlock, | ||
| formatJson, | ||
| getCodeLineEntry, | ||
| getIndentDepth, | ||
| htmlDeserializerCodeBlock, | ||
| indentCodeLine, | ||
| insertCodeBlock, | ||
| insertCodeLine, | ||
| insertEmptyCodeBlock, | ||
| isCodeBlockEmpty, | ||
| isLangSupported, | ||
| isSelectionAtCodeBlockStart, | ||
| isValidJson, | ||
| isValidSyntax, | ||
| outdentCodeLine, | ||
| resetCodeBlockDecorations, | ||
| setCodeBlockToDecorations, | ||
| toggleCodeBlock, | ||
| unwrapCodeBlock, | ||
| withCodeBlock, | ||
| withInsertDataCodeBlock, | ||
| withInsertFragmentCodeBlock, | ||
| withNormalizeCodeBlock | ||
| }; | ||
| //# sourceMappingURL=index.mjs.map |
| {"version":3,"sources":["../src/lib/BaseCodeBlockPlugin.ts","../src/lib/deserializer/htmlDeserializerCodeBlock.ts","../src/lib/queries/getCodeLineEntry.ts","../src/lib/queries/getIndentDepth.ts","../src/lib/queries/isCodeBlockEmpty.ts","../src/lib/queries/isSelectionAtCodeBlockStart.ts","../src/lib/setCodeBlockToDecorations.ts","../src/lib/transforms/deleteStartSpace.ts","../src/lib/transforms/indentCodeLine.ts","../src/lib/transforms/insertCodeBlock.ts","../src/lib/transforms/insertCodeLine.ts","../src/lib/transforms/insertEmptyCodeBlock.ts","../src/lib/transforms/outdentCodeLine.ts","../src/lib/transforms/toggleCodeBlock.ts","../src/lib/transforms/unwrapCodeBlock.ts","../src/lib/withInsertDataCodeBlock.ts","../src/lib/withInsertFragmentCodeBlock.ts","../src/lib/withNormalizeCodeBlock.tsx","../src/lib/withCodeBlock.ts","../src/lib/formatter/jsonFormatter.ts","../src/lib/formatter/formatter.ts"],"sourcesContent":["import type { createLowlight } from 'lowlight';\n\nimport {\n type PluginConfig,\n type TCodeBlockElement,\n type TElement,\n createSlatePlugin,\n createTSlatePlugin,\n KEYS,\n} from 'platejs';\n\nimport { htmlDeserializerCodeBlock } from './deserializer/htmlDeserializerCodeBlock';\nimport { isCodeBlockEmpty } from './queries';\nimport {\n CODE_LINE_TO_DECORATIONS,\n setCodeBlockToDecorations,\n} from './setCodeBlockToDecorations';\nimport { withCodeBlock } from './withCodeBlock';\n\nexport type CodeBlockConfig = PluginConfig<\n 'code_block',\n {\n /**\n * Default language to use when no language is specified. Set to null to\n * disable syntax highlighting by default.\n */\n defaultLanguage?: string | null;\n /**\n * Lowlight instance to use for highlighting. If not provided, syntax\n * highlighting will be disabled.\n */\n lowlight?: ReturnType<typeof createLowlight> | null;\n }\n>;\n\nexport const BaseCodeLinePlugin = createTSlatePlugin({\n key: KEYS.codeLine,\n node: { isElement: true, isStrictSiblings: true },\n});\n\nexport const BaseCodeSyntaxPlugin = createSlatePlugin({\n key: KEYS.codeSyntax,\n node: { isLeaf: true },\n});\n\nexport const BaseCodeBlockPlugin = createTSlatePlugin<CodeBlockConfig>({\n key: KEYS.codeBlock,\n inject: {\n plugins: {\n [KEYS.html]: {\n parser: {\n query: ({ editor }) =>\n !editor.api.some({\n match: { type: editor.getType(KEYS.codeLine) },\n }),\n },\n },\n },\n },\n node: {\n isElement: true,\n },\n options: {\n defaultLanguage: null,\n lowlight: null,\n },\n parsers: { html: { deserializer: htmlDeserializerCodeBlock } },\n plugins: [BaseCodeLinePlugin, BaseCodeSyntaxPlugin],\n render: { as: 'pre' },\n rules: {\n delete: {\n empty: 'reset',\n },\n match: ({ editor, rule }) =>\n ['break.empty', 'delete.empty'].includes(rule) &&\n isCodeBlockEmpty(editor),\n },\n decorate: ({ editor, entry: [node, path], getOptions, type }) => {\n if (!getOptions().lowlight) return [];\n\n const codeLineType = editor.getType(KEYS.codeLine);\n\n // Initialize decorations for the code block, we assume code line decorate will be called next.\n if (\n node.type === type &&\n !CODE_LINE_TO_DECORATIONS.get((node.children as TElement[])[0])\n ) {\n setCodeBlockToDecorations(editor, [node as TCodeBlockElement, path]);\n }\n\n if (node.type === codeLineType) {\n return CODE_LINE_TO_DECORATIONS.get(node as TElement) || [];\n }\n\n return [];\n },\n})\n .overrideEditor(withCodeBlock)\n .extendTransforms(({ editor }) => ({\n toggle: () => {\n editor.tf.toggleBlock(editor.getType(KEYS.codeBlock));\n },\n }));\n","import type { HtmlDeserializer } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\nexport const htmlDeserializerCodeBlock: HtmlDeserializer = {\n rules: [\n {\n validNodeName: 'PRE',\n },\n {\n validNodeName: 'P',\n validStyle: {\n fontFamily: 'Consolas',\n },\n },\n ],\n parse: ({ element }) => {\n const languageSelectorText =\n [...element.childNodes].find(\n (node: ChildNode) => node.nodeName === 'SELECT'\n )?.textContent || '';\n\n const textContent =\n element.textContent?.replace(languageSelectorText, '') || '';\n\n let lines = textContent.split('\\n');\n\n if (!lines?.length) {\n lines = [textContent];\n }\n\n const codeLines = lines.map((line) => ({\n children: [{ text: line }],\n type: KEYS.codeLine,\n }));\n\n return {\n children: codeLines,\n type: KEYS.codeBlock,\n };\n },\n};\n","import {\n type ElementOf,\n type NodeEntry,\n type SlateEditor,\n type TElement,\n type TLocation,\n ElementApi,\n KEYS,\n} from 'platejs';\n\n/** If at (default = selection) is in ul>li>p, return li and ul node entries. */\nexport const getCodeLineEntry = <N extends ElementOf<E>, E extends SlateEditor>(\n editor: E,\n { at = editor.selection }: { at?: TLocation | null } = {}\n) => {\n if (\n at &&\n editor.api.some({\n at,\n match: { type: editor.getType(KEYS.codeLine) },\n })\n ) {\n const selectionParent = editor.api.parent(at);\n\n if (!selectionParent) return;\n\n const [, parentPath] = selectionParent;\n\n const codeLine =\n editor.api.above<TElement>({\n at,\n match: { type: editor.getType(KEYS.codeLine) },\n }) || editor.api.parent<N>(parentPath);\n\n if (!codeLine) return;\n\n const [codeLineNode, codeLinePath] = codeLine;\n\n if (\n ElementApi.isElement(codeLineNode) &&\n codeLineNode.type !== editor.getType(KEYS.codeLine)\n )\n return;\n\n const codeBlock = editor.api.parent<N>(codeLinePath);\n\n if (!codeBlock) return;\n\n return {\n codeBlock,\n codeLine: codeLine as NodeEntry<N>,\n };\n }\n};\n","import type { Editor } from 'platejs';\n\nimport type { IndentCodeLineOptions } from '../transforms/indentCodeLine';\n\nconst nonWhitespaceOrEndRegex = /\\S|$/;\n\nexport const getIndentDepth = (\n editor: Editor,\n { codeLine }: IndentCodeLineOptions\n) => {\n const [, codeLinePath] = codeLine;\n const text = editor.api.string(codeLinePath);\n\n return text.search(nonWhitespaceOrEndRegex);\n};\n","import { type SlateEditor, NodeApi } from 'platejs';\n\nimport { getCodeLineEntry } from './getCodeLineEntry';\n\n/** Is the selection inside an empty code block */\nexport const isCodeBlockEmpty = (editor: SlateEditor) => {\n const { codeBlock } = getCodeLineEntry(editor) ?? {};\n\n if (!codeBlock) return false;\n\n const codeLines = Array.from(NodeApi.children(editor, codeBlock[1]));\n\n if (codeLines.length === 0) return true;\n if (codeLines.length > 1) return false;\n\n const firstCodeLineNode = codeLines[0][0];\n\n return !NodeApi.string(firstCodeLineNode);\n};\n","import type { SlateEditor } from 'platejs';\n\nimport { getCodeLineEntry } from './getCodeLineEntry';\n\n/** Is the selection at the start of the first code line in a code block */\nexport const isSelectionAtCodeBlockStart = (editor: SlateEditor) => {\n const { selection } = editor;\n\n if (!selection || editor.api.isExpanded()) return false;\n\n const { codeBlock } = getCodeLineEntry(editor) ?? {};\n\n if (!codeBlock) return false;\n\n return editor.api.isStart(selection.anchor, codeBlock[1]);\n};\n","import {\n type DecoratedRange,\n type NodeEntry,\n type SlateEditor,\n type TCodeBlockElement,\n type TElement,\n KEYS,\n NodeApi,\n} from 'platejs';\n\nimport { BaseCodeBlockPlugin } from './BaseCodeBlockPlugin';\n\n// Cache for storing decorations per code line element\nexport const CODE_LINE_TO_DECORATIONS = new WeakMap<\n TElement,\n DecoratedRange[]\n>();\n\n// Helper function to get highlight nodes from Lowlight result\nfunction getHighlightNodes(result: any) {\n return result.value || result.children || [];\n}\n\n// Helper function to parse nodes from Lowlight's hast tree\nfunction parseNodes(\n nodes: any[],\n className: string[] = []\n): { classes: string[]; text: string }[] {\n return nodes.flatMap((node) => {\n const classes = [\n ...className,\n ...(node.properties ? node.properties.className : []),\n ];\n if (node.children) {\n return parseNodes(node.children, classes);\n }\n return { classes, text: node.value };\n });\n}\n\n// Helper function to normalize tokens by line\nfunction normalizeTokens(tokens: { classes: string[]; text: string }[]) {\n const lines: { classes: string[]; content: string }[][] = [[]];\n let currentLine = lines[0];\n\n for (const token of tokens) {\n const tokenLines = token.text.split('\\n');\n\n for (let i = 0; i < tokenLines.length; i++) {\n const content = tokenLines[i];\n\n if (content) {\n currentLine.push({ classes: token.classes, content });\n }\n\n // Create a new line unless we're on the last line\n if (i < tokenLines.length - 1) {\n lines.push([]);\n currentLine = lines.at(-1) as any;\n }\n }\n }\n\n return lines;\n}\n\n// Helper function to compute decorations for a code block\nexport function codeBlockToDecorations(\n editor: SlateEditor,\n [block, blockPath]: NodeEntry<TCodeBlockElement>\n) {\n const { defaultLanguage, ...options } =\n editor.getOptions(BaseCodeBlockPlugin);\n const lowlight = options.lowlight!;\n\n // Get all code lines and combine their text\n const text = block.children.map((line) => NodeApi.string(line)).join('\\n');\n const language = block.lang;\n const effectiveLanguage = language || defaultLanguage;\n\n let highlighted: any;\n try {\n // Skip highlighting for plaintext or when no language is specified\n if (!effectiveLanguage || effectiveLanguage === 'plaintext') {\n highlighted = { value: [] }; // Empty result for plaintext\n } else if (effectiveLanguage === 'auto') {\n highlighted = lowlight.highlightAuto(text);\n } else {\n highlighted = lowlight.highlight(effectiveLanguage, text);\n }\n } catch (error) {\n // Verify if language is registered, fallback to plaintext if not\n const availableLanguages = lowlight.listLanguages();\n const isLanguageRegistered =\n effectiveLanguage && availableLanguages.includes(effectiveLanguage);\n if (isLanguageRegistered) {\n editor.api.debug.error(error, 'CODE_HIGHLIGHT');\n highlighted = { value: [] }; // Empty result on error\n } else {\n editor.api.debug.warn(\n `Language \"${effectiveLanguage}\" is not registered. Falling back to plaintext`\n );\n highlighted = { value: [] };\n }\n }\n\n // Parse and normalize tokens\n const tokens = parseNodes(getHighlightNodes(highlighted));\n const normalizedTokens = normalizeTokens(tokens);\n const blockChildren = block.children as TElement[];\n\n // Create decorations map\n const nodeToDecorations = new Map<TElement, DecoratedRange[]>();\n\n // Safety check: don't process more lines than we have children\n const numLines = Math.min(normalizedTokens.length, blockChildren.length);\n\n // Process each line's tokens\n for (let index = 0; index < numLines; index++) {\n const lineTokens = normalizedTokens[index];\n const element = blockChildren[index];\n\n if (!nodeToDecorations.has(element)) {\n nodeToDecorations.set(element, []);\n }\n\n let start = 0;\n for (const token of lineTokens) {\n const length = token.content.length;\n if (!length) continue;\n\n const end = start + length;\n\n const decoration: DecoratedRange = {\n anchor: {\n offset: start,\n path: [...blockPath, index, 0],\n },\n className: token.classes.join(' '),\n focus: {\n offset: end,\n path: [...blockPath, index, 0],\n },\n [KEYS.codeSyntax]: true,\n } as any;\n\n nodeToDecorations.get(element)!.push(decoration);\n start = end;\n }\n }\n\n return nodeToDecorations;\n}\n\nexport function setCodeBlockToDecorations(\n editor: SlateEditor,\n [block, blockPath]: NodeEntry<TCodeBlockElement>\n) {\n const decorations = codeBlockToDecorations(editor, [block, blockPath]);\n\n // Update the global cache with the new decorations\n for (const [node, decs] of decorations.entries()) {\n CODE_LINE_TO_DECORATIONS.set(node, decs);\n }\n}\n\nexport function resetCodeBlockDecorations(codeBlock: TCodeBlockElement) {\n codeBlock.children.forEach((line) => {\n CODE_LINE_TO_DECORATIONS.delete(line as TElement);\n });\n}\n","import type { Editor } from 'platejs';\n\nimport type { OutdentCodeLineOptions } from './outdentCodeLine';\n\nconst whitespaceRegex = /\\s/;\n\n/** If there is a whitespace character at the start of the code line, delete it. */\nexport const deleteStartSpace = (\n editor: Editor,\n { codeLine }: OutdentCodeLineOptions\n) => {\n const [, codeLinePath] = codeLine;\n const codeLineStart = editor.api.start(codeLinePath);\n const codeLineEnd = codeLineStart && editor.api.after(codeLineStart);\n const spaceRange =\n codeLineEnd && editor.api.range(codeLineStart, codeLineEnd);\n const spaceText = editor.api.string(spaceRange);\n\n if (whitespaceRegex.test(spaceText)) {\n editor.tf.delete({ at: spaceRange });\n\n return true;\n }\n\n return false;\n};\n","import type { Editor, ElementEntry } from 'platejs';\n\nconst nonWhitespaceRegex = /\\S/;\n\nexport type IndentCodeLineOptions = {\n codeBlock: ElementEntry;\n codeLine: ElementEntry;\n indentDepth?: number;\n};\n\n/**\n * Indent if:\n *\n * - The selection is expanded OR\n * - There are no non-whitespace characters left of the cursor Indentation = 2\n * spaces.\n */\nexport const indentCodeLine = (\n editor: Editor,\n { codeLine, indentDepth = 2 }: IndentCodeLineOptions\n) => {\n const [, codeLinePath] = codeLine;\n const codeLineStart = editor.api.start(codeLinePath)!;\n const indent = ' '.repeat(indentDepth);\n\n if (!editor.api.isExpanded()) {\n const cursor = editor.selection?.anchor;\n const range = editor.api.range(codeLineStart, cursor);\n const text = editor.api.string(range);\n\n if (nonWhitespaceRegex.test(text)) {\n editor.tf.insertText(indent, { at: editor.selection! });\n\n return;\n }\n }\n\n editor.tf.insertText(indent, { at: codeLineStart });\n};\n","import type { InsertNodesOptions, SlateEditor, TElement } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\n/**\n * Insert a code block: set the node to code line and wrap it with a code block.\n * If the cursor is not at the block start, insert break before.\n */\nexport const insertCodeBlock = (\n editor: SlateEditor,\n insertNodesOptions: Omit<InsertNodesOptions, 'match'> = {}\n) => {\n if (!editor.selection || editor.api.isExpanded()) return;\n\n const matchCodeElements = (node: TElement) =>\n node.type === KEYS.codeBlock || node.type === KEYS.codeLine;\n\n if (\n editor.api.some({\n match: matchCodeElements,\n })\n ) {\n return;\n }\n if (!editor.api.isAt({ start: true })) {\n editor.tf.insertBreak();\n }\n\n editor.tf.setNodes(\n {\n children: [{ text: '' }],\n type: KEYS.codeLine,\n },\n insertNodesOptions\n );\n\n editor.tf.wrapNodes<TElement>(\n {\n children: [],\n type: KEYS.codeBlock,\n },\n insertNodesOptions\n );\n};\n","import type { SlateEditor } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\n/** Insert a code line starting with indentation. */\nexport const insertCodeLine = (editor: SlateEditor, indentDepth = 0) => {\n if (editor.selection) {\n const indent = ' '.repeat(indentDepth);\n\n editor.tf.insertNodes({\n children: [{ text: indent }],\n type: editor.getType(KEYS.codeLine),\n });\n }\n};\n","import { type InsertNodesOptions, type SlateEditor, KEYS } from 'platejs';\n\nimport { insertCodeBlock } from './insertCodeBlock';\n\nexport type CodeBlockInsertOptions = {\n defaultType?: string;\n insertNodesOptions?: Omit<InsertNodesOptions, 'match'>;\n};\n\n/**\n * Called by toolbars to make sure a code-block gets inserted below a paragraph\n * rather than awkwardly splitting the current selection.\n */\nexport const insertEmptyCodeBlock = (\n editor: SlateEditor,\n {\n defaultType = editor.getType(KEYS.p),\n insertNodesOptions,\n }: CodeBlockInsertOptions = {}\n) => {\n if (!editor.selection) return;\n if (\n editor.api.isExpanded() ||\n !editor.api.isEmpty(editor.selection, { block: true })\n ) {\n editor.tf.insertNodes(\n editor.api.create.block({ children: [{ text: '' }], type: defaultType }),\n {\n nextBlock: true,\n select: true,\n ...insertNodesOptions,\n }\n );\n }\n\n insertCodeBlock(editor, insertNodesOptions);\n};\n","import type { Editor, ElementEntry } from 'platejs';\n\nimport { deleteStartSpace } from './deleteStartSpace';\n\nexport type OutdentCodeLineOptions = {\n codeBlock: ElementEntry;\n codeLine: ElementEntry;\n};\n\n/** Outdent the code line. Remove 2 whitespace characters if any. */\nexport const outdentCodeLine = (\n editor: Editor,\n { codeBlock, codeLine }: OutdentCodeLineOptions\n) => {\n const deleted = deleteStartSpace(editor, { codeBlock, codeLine });\n if (deleted) {\n deleteStartSpace(editor, { codeBlock, codeLine });\n }\n};\n","import type { SlateEditor, TElement } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\nimport { unwrapCodeBlock } from './unwrapCodeBlock';\n\nexport const toggleCodeBlock = (editor: SlateEditor) => {\n if (!editor.selection) return;\n\n const codeBlockType = editor.getType(KEYS.codeBlock);\n const codeLineType = editor.getType(KEYS.codeLine);\n\n const isActive = editor.api.some({\n match: { type: codeBlockType },\n });\n\n editor.tf.withoutNormalizing(() => {\n unwrapCodeBlock(editor);\n\n if (!isActive) {\n editor.tf.setNodes({\n type: codeLineType,\n });\n\n const codeBlock = {\n children: [],\n type: codeBlockType,\n };\n\n editor.tf.wrapNodes<TElement>(codeBlock);\n }\n });\n};\n","import { type SlateEditor, type TLocation, KEYS, NodeApi } from 'platejs';\n\nexport const unwrapCodeBlock = (editor: SlateEditor) => {\n if (!editor.selection) return;\n\n const codeBlockType = editor.getType(KEYS.codeBlock);\n const defaultType = editor.getType(KEYS.p);\n\n editor.tf.withoutNormalizing(() => {\n const codeBlockEntries = editor.api.nodes({\n at: editor.selection as TLocation,\n match: { type: codeBlockType },\n });\n\n const reversedCodeBlockEntries = Array.from(codeBlockEntries).reverse();\n\n for (const codeBlockEntry of reversedCodeBlockEntries) {\n const codeLineEntries = NodeApi.children(editor, codeBlockEntry[1]);\n\n for (const [, path] of codeLineEntries) {\n editor.tf.setNodes({ type: defaultType }, { at: path });\n }\n\n editor.tf.unwrapNodes({\n at: codeBlockEntry[1],\n match: { type: codeBlockType },\n split: true,\n });\n }\n });\n};\n","import type { OverrideEditor, TElement } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\nexport const withInsertDataCodeBlock: OverrideEditor = ({\n editor,\n tf: { insertData },\n type: codeBlockType,\n}) => ({\n transforms: {\n insertData(data) {\n const text = data.getData('text/plain');\n const vscodeDataString = data.getData('vscode-editor-data');\n const codeLineType = editor.getType(KEYS.codeLine);\n\n // Handle VSCode paste with language\n if (vscodeDataString) {\n try {\n const vscodeData = JSON.parse(vscodeDataString);\n const lines = text.split('\\n');\n\n // Check if we're in a code block\n const [blockAbove] = editor.api.block<TElement>() ?? [];\n const isInCodeBlock =\n blockAbove &&\n [codeBlockType, codeLineType].includes(blockAbove?.type);\n\n if (isInCodeBlock) {\n // If in code block, insert first line as text at cursor\n if (lines[0]) {\n editor.tf.insertText(lines[0]);\n }\n\n // Insert remaining lines as new code lines\n if (lines.length > 1) {\n const nodes = lines.slice(1).map((line) => ({\n children: [{ text: line }],\n type: codeLineType,\n }));\n editor.tf.insertNodes(nodes);\n }\n } else {\n // Create new code block\n const node = {\n children: lines.map((line) => ({\n children: [{ text: line }],\n type: codeLineType,\n })),\n lang: vscodeData?.mode,\n type: codeBlockType,\n };\n\n editor.tf.insertNodes(node, {\n select: true,\n });\n }\n\n return;\n } catch (_error) {}\n }\n\n // Handle plain text paste into code block only if there are line breaks\n const [blockAbove] = editor.api.block<TElement>() ?? [];\n if (\n blockAbove &&\n [codeBlockType, codeLineType].includes(blockAbove?.type) &&\n text?.includes('\\n')\n ) {\n const lines = text.split('\\n');\n\n // Insert first line as text at cursor\n if (lines[0]) {\n editor.tf.insertText(lines[0]);\n }\n\n // Insert remaining lines as new code lines\n if (lines.length > 1) {\n const nodes = lines.slice(1).map((line) => ({\n children: [{ text: line }],\n type: codeLineType,\n }));\n editor.tf.insertNodes(nodes);\n }\n return;\n }\n\n insertData(data);\n },\n },\n});\n","import { type OverrideEditor, type TElement, KEYS, NodeApi } from 'platejs';\n\nfunction extractCodeLinesFromCodeBlock(node: TElement) {\n return node.children as TElement[];\n}\n\nexport const withInsertFragmentCodeBlock: OverrideEditor = ({\n editor,\n tf: { insertFragment },\n type: codeBlockType,\n}) => ({\n transforms: {\n insertFragment(fragment) {\n const [blockAbove] = editor.api.block<TElement>() ?? [];\n const codeLineType = editor.getType(KEYS.codeLine);\n\n function convertNodeToCodeLine(node: TElement): TElement {\n return {\n children: [{ text: NodeApi.string(node) }],\n type: codeLineType,\n };\n }\n\n if (\n blockAbove &&\n [codeBlockType, codeLineType].includes(blockAbove?.type)\n ) {\n return insertFragment(\n fragment.flatMap((node) => {\n const element = node as TElement;\n\n return element.type === codeBlockType\n ? extractCodeLinesFromCodeBlock(element)\n : convertNodeToCodeLine(element);\n })\n );\n }\n\n return insertFragment(fragment);\n },\n },\n});\n","import {\n type NodeEntry,\n type OverrideEditor,\n type TCodeBlockElement,\n ElementApi,\n KEYS,\n NodeApi,\n} from 'platejs';\n\nimport type { CodeBlockConfig } from './BaseCodeBlockPlugin';\n\nimport { setCodeBlockToDecorations } from './setCodeBlockToDecorations';\n\n/** Normalize code block node to force the pre>code>div.codeline structure. */\nexport const withNormalizeCodeBlock: OverrideEditor<CodeBlockConfig> = ({\n editor,\n getOptions,\n tf: { normalizeNode },\n type,\n}) => ({\n transforms: {\n normalizeNode([node, path]) {\n // Decorate is called on selection change as well, so we prefer to only run this on code block changes.\n if (node.type === type && getOptions().lowlight) {\n setCodeBlockToDecorations(editor, [\n node,\n path,\n ] as NodeEntry<TCodeBlockElement>);\n }\n\n normalizeNode([node, path]);\n\n if (!ElementApi.isElement(node)) {\n return;\n }\n\n const codeBlockType = editor.getType(KEYS.codeBlock);\n const codeLineType = editor.getType(KEYS.codeLine);\n const isCodeBlockRoot = node.type === codeBlockType;\n\n if (isCodeBlockRoot) {\n // Children should all be code lines\n const nonCodeLine = Array.from(NodeApi.children(editor, path)).find(\n ([child]) => child.type !== codeLineType\n );\n\n if (nonCodeLine) {\n editor.tf.setNodes({ type: codeLineType }, { at: nonCodeLine[1] });\n }\n }\n },\n },\n});\n","import type { OverrideEditor, TCodeBlockElement, TElement } from 'platejs';\n\nimport type { CodeBlockConfig } from './BaseCodeBlockPlugin';\n\nimport { getCodeLineEntry, getIndentDepth } from './queries';\nimport { resetCodeBlockDecorations } from './setCodeBlockToDecorations';\nimport { indentCodeLine, outdentCodeLine, unwrapCodeBlock } from './transforms';\nimport { withInsertDataCodeBlock } from './withInsertDataCodeBlock';\nimport { withInsertFragmentCodeBlock } from './withInsertFragmentCodeBlock';\nimport { withNormalizeCodeBlock } from './withNormalizeCodeBlock';\n\nexport const withCodeBlock: OverrideEditor<CodeBlockConfig> = (ctx) => {\n const {\n editor,\n getOptions,\n tf: { apply, insertBreak, resetBlock, selectAll, tab },\n type,\n } = ctx;\n\n return {\n transforms: {\n apply(operation) {\n if (getOptions().lowlight && operation.type === 'set_node') {\n const entry = editor.api.node(operation.path);\n\n if (entry?.[0].type === type && operation.newProperties?.lang) {\n // Clear decorations for all code lines in this block\n resetCodeBlockDecorations(entry[0] as TCodeBlockElement);\n }\n }\n\n apply(operation);\n },\n insertBreak() {\n const apply = () => {\n if (!editor.selection) return;\n\n const res = getCodeLineEntry(editor, {});\n\n if (!res) return;\n\n const { codeBlock, codeLine } = res;\n const indentDepth = getIndentDepth(editor, {\n codeBlock,\n codeLine,\n });\n\n insertBreak();\n\n indentCodeLine(editor, {\n codeBlock,\n codeLine,\n indentDepth,\n });\n\n return true;\n };\n\n if (apply()) return;\n\n insertBreak();\n },\n resetBlock(options) {\n if (\n editor.api.block({\n at: options?.at,\n match: { type },\n })\n ) {\n unwrapCodeBlock(editor);\n return;\n }\n\n return resetBlock(options);\n },\n selectAll: () => {\n const apply = () => {\n const codeBlock = editor.api.above({\n match: { type },\n });\n\n if (!codeBlock) return;\n\n if (\n editor.api.isAt({ end: true }) &&\n editor.api.isAt({ start: true })\n ) {\n return;\n }\n\n // Select the whole code block\n editor.tf.select(codeBlock[1]);\n return true;\n };\n\n if (apply()) return true;\n\n return selectAll();\n },\n tab: (options) => {\n const apply = () => {\n const _codeLines = editor.api.nodes<TElement>({\n match: { type },\n });\n const codeLines = Array.from(_codeLines);\n\n if (codeLines.length > 0) {\n const [, firstLinePath] = codeLines[0];\n const codeBlock = editor.api.parent<TElement>(firstLinePath);\n\n if (!codeBlock) return;\n\n editor.tf.withoutNormalizing(() => {\n for (const codeLine of codeLines) {\n if (options.reverse) {\n outdentCodeLine(editor, { codeBlock, codeLine });\n } else {\n indentCodeLine(editor, { codeBlock, codeLine });\n }\n }\n });\n\n return true; // Prevent default\n }\n };\n\n if (apply()) return true;\n\n return tab(options);\n },\n ...withInsertDataCodeBlock(ctx).transforms,\n ...withInsertFragmentCodeBlock(ctx).transforms,\n ...withNormalizeCodeBlock(ctx).transforms,\n },\n };\n};\n","export const formatJson = (code: string): string => {\n try {\n return JSON.stringify(JSON.parse(code), null, 2);\n } catch (_error) {\n return code;\n }\n};\n\nexport const isValidJson = (code: string): boolean => {\n try {\n JSON.parse(code);\n\n return true;\n } catch (_error) {\n return false;\n }\n};\n","import type { Editor, TCodeBlockElement } from 'platejs';\n\nimport { formatJson, isValidJson } from './jsonFormatter';\n\nconst supportedLanguages = new Set(['json']);\n\nexport const isLangSupported = (lang?: string): boolean =>\n Boolean(lang && supportedLanguages.has(lang));\n\nexport const isValidSyntax = (code: string, lang?: string): boolean => {\n if (!isLangSupported(lang)) {\n return false;\n }\n\n switch (lang) {\n case 'json': {\n return isValidJson(code);\n }\n default: {\n return false;\n }\n }\n};\n\nexport const formatCodeBlock = (\n editor: Editor,\n {\n element,\n }: {\n element: TCodeBlockElement;\n }\n) => {\n const { lang } = element;\n\n if (!lang || !isLangSupported(lang)) {\n return;\n }\n\n const code = editor.api.string(element);\n\n if (isValidSyntax(code, lang)) {\n const formattedCode = formatCode(code, lang);\n editor.tf.insertText(formattedCode, { at: element });\n }\n};\n\nconst formatCode = (code: string, lang?: string): string => {\n switch (lang) {\n case 'json': {\n return formatJson(code);\n }\n default: {\n return code;\n }\n }\n};\n"],"mappings":"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","names":["KEYS","KEYS","KEYS","NodeApi","NodeApi","KEYS","KEYS","KEYS","KEYS","KEYS","KEYS","KEYS","NodeApi","KEYS","KEYS","blockAbove","KEYS","NodeApi","ElementApi","KEYS","NodeApi","ElementApi","KEYS","NodeApi","apply","KEYS"]} |
| import * as lowlight from 'lowlight'; | ||
| import * as platejs_react from 'platejs/react'; | ||
| import * as platejs from 'platejs'; | ||
| declare const CodeSyntaxPlugin: platejs_react.PlatePlugin<platejs.PluginConfig<"code_syntax", {}, {}, {}, {}>>; | ||
| declare const CodeLinePlugin: platejs_react.PlatePlugin<platejs.PluginConfig<any, {}, {}, {}, {}>>; | ||
| /** Enables support for pre-formatted code blocks. */ | ||
| declare const CodeBlockPlugin: platejs_react.PlatePlugin<platejs.PluginConfig<"code_block", { | ||
| defaultLanguage?: string | null; | ||
| lowlight?: ReturnType<typeof lowlight.createLowlight> | null; | ||
| }, {}, Record<"code_block", { | ||
| toggle: () => void; | ||
| }>, {}>>; | ||
| export { CodeBlockPlugin, CodeLinePlugin, CodeSyntaxPlugin }; |
| {"version":3,"sources":["../../src/react/index.ts","../../src/react/CodeBlockPlugin.tsx","../../src/lib/BaseCodeBlockPlugin.ts","../../src/lib/deserializer/htmlDeserializerCodeBlock.ts","../../src/lib/queries/getCodeLineEntry.ts","../../src/lib/queries/getIndentDepth.ts","../../src/lib/queries/isCodeBlockEmpty.ts","../../src/lib/setCodeBlockToDecorations.ts","../../src/lib/transforms/deleteStartSpace.ts","../../src/lib/transforms/indentCodeLine.ts","../../src/lib/transforms/outdentCodeLine.ts","../../src/lib/transforms/unwrapCodeBlock.ts","../../src/lib/withInsertDataCodeBlock.ts","../../src/lib/withInsertFragmentCodeBlock.ts","../../src/lib/withNormalizeCodeBlock.tsx","../../src/lib/withCodeBlock.ts"],"sourcesContent":["/**\n * @file Automatically generated by barrelsby.\n */\n\nexport * from './CodeBlockPlugin';\n","import { toPlatePlugin } from 'platejs/react';\n\nimport {\n BaseCodeBlockPlugin,\n BaseCodeLinePlugin,\n BaseCodeSyntaxPlugin,\n} from '../lib/BaseCodeBlockPlugin';\n\nexport const CodeSyntaxPlugin = toPlatePlugin(BaseCodeSyntaxPlugin);\n\nexport const CodeLinePlugin = toPlatePlugin(BaseCodeLinePlugin);\n\n/** Enables support for pre-formatted code blocks. */\nexport const CodeBlockPlugin = toPlatePlugin(BaseCodeBlockPlugin, {\n plugins: [CodeLinePlugin, CodeSyntaxPlugin],\n});\n","import type { createLowlight } from 'lowlight';\n\nimport {\n type PluginConfig,\n type TCodeBlockElement,\n type TElement,\n createSlatePlugin,\n createTSlatePlugin,\n KEYS,\n} from 'platejs';\n\nimport { htmlDeserializerCodeBlock } from './deserializer/htmlDeserializerCodeBlock';\nimport { isCodeBlockEmpty } from './queries';\nimport {\n CODE_LINE_TO_DECORATIONS,\n setCodeBlockToDecorations,\n} from './setCodeBlockToDecorations';\nimport { withCodeBlock } from './withCodeBlock';\n\nexport type CodeBlockConfig = PluginConfig<\n 'code_block',\n {\n /**\n * Default language to use when no language is specified. Set to null to\n * disable syntax highlighting by default.\n */\n defaultLanguage?: string | null;\n /**\n * Lowlight instance to use for highlighting. If not provided, syntax\n * highlighting will be disabled.\n */\n lowlight?: ReturnType<typeof createLowlight> | null;\n }\n>;\n\nexport const BaseCodeLinePlugin = createTSlatePlugin({\n key: KEYS.codeLine,\n node: { isElement: true, isStrictSiblings: true },\n});\n\nexport const BaseCodeSyntaxPlugin = createSlatePlugin({\n key: KEYS.codeSyntax,\n node: { isLeaf: true },\n});\n\nexport const BaseCodeBlockPlugin = createTSlatePlugin<CodeBlockConfig>({\n key: KEYS.codeBlock,\n inject: {\n plugins: {\n [KEYS.html]: {\n parser: {\n query: ({ editor }) =>\n !editor.api.some({\n match: { type: editor.getType(KEYS.codeLine) },\n }),\n },\n },\n },\n },\n node: {\n isElement: true,\n },\n options: {\n defaultLanguage: null,\n lowlight: null,\n },\n parsers: { html: { deserializer: htmlDeserializerCodeBlock } },\n plugins: [BaseCodeLinePlugin, BaseCodeSyntaxPlugin],\n render: { as: 'pre' },\n rules: {\n delete: {\n empty: 'reset',\n },\n match: ({ editor, rule }) =>\n ['break.empty', 'delete.empty'].includes(rule) &&\n isCodeBlockEmpty(editor),\n },\n decorate: ({ editor, entry: [node, path], getOptions, type }) => {\n if (!getOptions().lowlight) return [];\n\n const codeLineType = editor.getType(KEYS.codeLine);\n\n // Initialize decorations for the code block, we assume code line decorate will be called next.\n if (\n node.type === type &&\n !CODE_LINE_TO_DECORATIONS.get((node.children as TElement[])[0])\n ) {\n setCodeBlockToDecorations(editor, [node as TCodeBlockElement, path]);\n }\n\n if (node.type === codeLineType) {\n return CODE_LINE_TO_DECORATIONS.get(node as TElement) || [];\n }\n\n return [];\n },\n})\n .overrideEditor(withCodeBlock)\n .extendTransforms(({ editor }) => ({\n toggle: () => {\n editor.tf.toggleBlock(editor.getType(KEYS.codeBlock));\n },\n }));\n","import type { HtmlDeserializer } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\nexport const htmlDeserializerCodeBlock: HtmlDeserializer = {\n rules: [\n {\n validNodeName: 'PRE',\n },\n {\n validNodeName: 'P',\n validStyle: {\n fontFamily: 'Consolas',\n },\n },\n ],\n parse: ({ element }) => {\n const languageSelectorText =\n [...element.childNodes].find(\n (node: ChildNode) => node.nodeName === 'SELECT'\n )?.textContent || '';\n\n const textContent =\n element.textContent?.replace(languageSelectorText, '') || '';\n\n let lines = textContent.split('\\n');\n\n if (!lines?.length) {\n lines = [textContent];\n }\n\n const codeLines = lines.map((line) => ({\n children: [{ text: line }],\n type: KEYS.codeLine,\n }));\n\n return {\n children: codeLines,\n type: KEYS.codeBlock,\n };\n },\n};\n","import {\n type ElementOf,\n type NodeEntry,\n type SlateEditor,\n type TElement,\n type TLocation,\n ElementApi,\n KEYS,\n} from 'platejs';\n\n/** If at (default = selection) is in ul>li>p, return li and ul node entries. */\nexport const getCodeLineEntry = <N extends ElementOf<E>, E extends SlateEditor>(\n editor: E,\n { at = editor.selection }: { at?: TLocation | null } = {}\n) => {\n if (\n at &&\n editor.api.some({\n at,\n match: { type: editor.getType(KEYS.codeLine) },\n })\n ) {\n const selectionParent = editor.api.parent(at);\n\n if (!selectionParent) return;\n\n const [, parentPath] = selectionParent;\n\n const codeLine =\n editor.api.above<TElement>({\n at,\n match: { type: editor.getType(KEYS.codeLine) },\n }) || editor.api.parent<N>(parentPath);\n\n if (!codeLine) return;\n\n const [codeLineNode, codeLinePath] = codeLine;\n\n if (\n ElementApi.isElement(codeLineNode) &&\n codeLineNode.type !== editor.getType(KEYS.codeLine)\n )\n return;\n\n const codeBlock = editor.api.parent<N>(codeLinePath);\n\n if (!codeBlock) return;\n\n return {\n codeBlock,\n codeLine: codeLine as NodeEntry<N>,\n };\n }\n};\n","import type { Editor } from 'platejs';\n\nimport type { IndentCodeLineOptions } from '../transforms/indentCodeLine';\n\nconst nonWhitespaceOrEndRegex = /\\S|$/;\n\nexport const getIndentDepth = (\n editor: Editor,\n { codeLine }: IndentCodeLineOptions\n) => {\n const [, codeLinePath] = codeLine;\n const text = editor.api.string(codeLinePath);\n\n return text.search(nonWhitespaceOrEndRegex);\n};\n","import { type SlateEditor, NodeApi } from 'platejs';\n\nimport { getCodeLineEntry } from './getCodeLineEntry';\n\n/** Is the selection inside an empty code block */\nexport const isCodeBlockEmpty = (editor: SlateEditor) => {\n const { codeBlock } = getCodeLineEntry(editor) ?? {};\n\n if (!codeBlock) return false;\n\n const codeLines = Array.from(NodeApi.children(editor, codeBlock[1]));\n\n if (codeLines.length === 0) return true;\n if (codeLines.length > 1) return false;\n\n const firstCodeLineNode = codeLines[0][0];\n\n return !NodeApi.string(firstCodeLineNode);\n};\n","import {\n type DecoratedRange,\n type NodeEntry,\n type SlateEditor,\n type TCodeBlockElement,\n type TElement,\n KEYS,\n NodeApi,\n} from 'platejs';\n\nimport { BaseCodeBlockPlugin } from './BaseCodeBlockPlugin';\n\n// Cache for storing decorations per code line element\nexport const CODE_LINE_TO_DECORATIONS = new WeakMap<\n TElement,\n DecoratedRange[]\n>();\n\n// Helper function to get highlight nodes from Lowlight result\nfunction getHighlightNodes(result: any) {\n return result.value || result.children || [];\n}\n\n// Helper function to parse nodes from Lowlight's hast tree\nfunction parseNodes(\n nodes: any[],\n className: string[] = []\n): { classes: string[]; text: string }[] {\n return nodes.flatMap((node) => {\n const classes = [\n ...className,\n ...(node.properties ? node.properties.className : []),\n ];\n if (node.children) {\n return parseNodes(node.children, classes);\n }\n return { classes, text: node.value };\n });\n}\n\n// Helper function to normalize tokens by line\nfunction normalizeTokens(tokens: { classes: string[]; text: string }[]) {\n const lines: { classes: string[]; content: string }[][] = [[]];\n let currentLine = lines[0];\n\n for (const token of tokens) {\n const tokenLines = token.text.split('\\n');\n\n for (let i = 0; i < tokenLines.length; i++) {\n const content = tokenLines[i];\n\n if (content) {\n currentLine.push({ classes: token.classes, content });\n }\n\n // Create a new line unless we're on the last line\n if (i < tokenLines.length - 1) {\n lines.push([]);\n currentLine = lines.at(-1) as any;\n }\n }\n }\n\n return lines;\n}\n\n// Helper function to compute decorations for a code block\nexport function codeBlockToDecorations(\n editor: SlateEditor,\n [block, blockPath]: NodeEntry<TCodeBlockElement>\n) {\n const { defaultLanguage, ...options } =\n editor.getOptions(BaseCodeBlockPlugin);\n const lowlight = options.lowlight!;\n\n // Get all code lines and combine their text\n const text = block.children.map((line) => NodeApi.string(line)).join('\\n');\n const language = block.lang;\n const effectiveLanguage = language || defaultLanguage;\n\n let highlighted: any;\n try {\n // Skip highlighting for plaintext or when no language is specified\n if (!effectiveLanguage || effectiveLanguage === 'plaintext') {\n highlighted = { value: [] }; // Empty result for plaintext\n } else if (effectiveLanguage === 'auto') {\n highlighted = lowlight.highlightAuto(text);\n } else {\n highlighted = lowlight.highlight(effectiveLanguage, text);\n }\n } catch (error) {\n // Verify if language is registered, fallback to plaintext if not\n const availableLanguages = lowlight.listLanguages();\n const isLanguageRegistered =\n effectiveLanguage && availableLanguages.includes(effectiveLanguage);\n if (isLanguageRegistered) {\n editor.api.debug.error(error, 'CODE_HIGHLIGHT');\n highlighted = { value: [] }; // Empty result on error\n } else {\n editor.api.debug.warn(\n `Language \"${effectiveLanguage}\" is not registered. Falling back to plaintext`\n );\n highlighted = { value: [] };\n }\n }\n\n // Parse and normalize tokens\n const tokens = parseNodes(getHighlightNodes(highlighted));\n const normalizedTokens = normalizeTokens(tokens);\n const blockChildren = block.children as TElement[];\n\n // Create decorations map\n const nodeToDecorations = new Map<TElement, DecoratedRange[]>();\n\n // Safety check: don't process more lines than we have children\n const numLines = Math.min(normalizedTokens.length, blockChildren.length);\n\n // Process each line's tokens\n for (let index = 0; index < numLines; index++) {\n const lineTokens = normalizedTokens[index];\n const element = blockChildren[index];\n\n if (!nodeToDecorations.has(element)) {\n nodeToDecorations.set(element, []);\n }\n\n let start = 0;\n for (const token of lineTokens) {\n const length = token.content.length;\n if (!length) continue;\n\n const end = start + length;\n\n const decoration: DecoratedRange = {\n anchor: {\n offset: start,\n path: [...blockPath, index, 0],\n },\n className: token.classes.join(' '),\n focus: {\n offset: end,\n path: [...blockPath, index, 0],\n },\n [KEYS.codeSyntax]: true,\n } as any;\n\n nodeToDecorations.get(element)!.push(decoration);\n start = end;\n }\n }\n\n return nodeToDecorations;\n}\n\nexport function setCodeBlockToDecorations(\n editor: SlateEditor,\n [block, blockPath]: NodeEntry<TCodeBlockElement>\n) {\n const decorations = codeBlockToDecorations(editor, [block, blockPath]);\n\n // Update the global cache with the new decorations\n for (const [node, decs] of decorations.entries()) {\n CODE_LINE_TO_DECORATIONS.set(node, decs);\n }\n}\n\nexport function resetCodeBlockDecorations(codeBlock: TCodeBlockElement) {\n codeBlock.children.forEach((line) => {\n CODE_LINE_TO_DECORATIONS.delete(line as TElement);\n });\n}\n","import type { Editor } from 'platejs';\n\nimport type { OutdentCodeLineOptions } from './outdentCodeLine';\n\nconst whitespaceRegex = /\\s/;\n\n/** If there is a whitespace character at the start of the code line, delete it. */\nexport const deleteStartSpace = (\n editor: Editor,\n { codeLine }: OutdentCodeLineOptions\n) => {\n const [, codeLinePath] = codeLine;\n const codeLineStart = editor.api.start(codeLinePath);\n const codeLineEnd = codeLineStart && editor.api.after(codeLineStart);\n const spaceRange =\n codeLineEnd && editor.api.range(codeLineStart, codeLineEnd);\n const spaceText = editor.api.string(spaceRange);\n\n if (whitespaceRegex.test(spaceText)) {\n editor.tf.delete({ at: spaceRange });\n\n return true;\n }\n\n return false;\n};\n","import type { Editor, ElementEntry } from 'platejs';\n\nconst nonWhitespaceRegex = /\\S/;\n\nexport type IndentCodeLineOptions = {\n codeBlock: ElementEntry;\n codeLine: ElementEntry;\n indentDepth?: number;\n};\n\n/**\n * Indent if:\n *\n * - The selection is expanded OR\n * - There are no non-whitespace characters left of the cursor Indentation = 2\n * spaces.\n */\nexport const indentCodeLine = (\n editor: Editor,\n { codeLine, indentDepth = 2 }: IndentCodeLineOptions\n) => {\n const [, codeLinePath] = codeLine;\n const codeLineStart = editor.api.start(codeLinePath)!;\n const indent = ' '.repeat(indentDepth);\n\n if (!editor.api.isExpanded()) {\n const cursor = editor.selection?.anchor;\n const range = editor.api.range(codeLineStart, cursor);\n const text = editor.api.string(range);\n\n if (nonWhitespaceRegex.test(text)) {\n editor.tf.insertText(indent, { at: editor.selection! });\n\n return;\n }\n }\n\n editor.tf.insertText(indent, { at: codeLineStart });\n};\n","import type { Editor, ElementEntry } from 'platejs';\n\nimport { deleteStartSpace } from './deleteStartSpace';\n\nexport type OutdentCodeLineOptions = {\n codeBlock: ElementEntry;\n codeLine: ElementEntry;\n};\n\n/** Outdent the code line. Remove 2 whitespace characters if any. */\nexport const outdentCodeLine = (\n editor: Editor,\n { codeBlock, codeLine }: OutdentCodeLineOptions\n) => {\n const deleted = deleteStartSpace(editor, { codeBlock, codeLine });\n if (deleted) {\n deleteStartSpace(editor, { codeBlock, codeLine });\n }\n};\n","import { type SlateEditor, type TLocation, KEYS, NodeApi } from 'platejs';\n\nexport const unwrapCodeBlock = (editor: SlateEditor) => {\n if (!editor.selection) return;\n\n const codeBlockType = editor.getType(KEYS.codeBlock);\n const defaultType = editor.getType(KEYS.p);\n\n editor.tf.withoutNormalizing(() => {\n const codeBlockEntries = editor.api.nodes({\n at: editor.selection as TLocation,\n match: { type: codeBlockType },\n });\n\n const reversedCodeBlockEntries = Array.from(codeBlockEntries).reverse();\n\n for (const codeBlockEntry of reversedCodeBlockEntries) {\n const codeLineEntries = NodeApi.children(editor, codeBlockEntry[1]);\n\n for (const [, path] of codeLineEntries) {\n editor.tf.setNodes({ type: defaultType }, { at: path });\n }\n\n editor.tf.unwrapNodes({\n at: codeBlockEntry[1],\n match: { type: codeBlockType },\n split: true,\n });\n }\n });\n};\n","import type { OverrideEditor, TElement } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\nexport const withInsertDataCodeBlock: OverrideEditor = ({\n editor,\n tf: { insertData },\n type: codeBlockType,\n}) => ({\n transforms: {\n insertData(data) {\n const text = data.getData('text/plain');\n const vscodeDataString = data.getData('vscode-editor-data');\n const codeLineType = editor.getType(KEYS.codeLine);\n\n // Handle VSCode paste with language\n if (vscodeDataString) {\n try {\n const vscodeData = JSON.parse(vscodeDataString);\n const lines = text.split('\\n');\n\n // Check if we're in a code block\n const [blockAbove] = editor.api.block<TElement>() ?? [];\n const isInCodeBlock =\n blockAbove &&\n [codeBlockType, codeLineType].includes(blockAbove?.type);\n\n if (isInCodeBlock) {\n // If in code block, insert first line as text at cursor\n if (lines[0]) {\n editor.tf.insertText(lines[0]);\n }\n\n // Insert remaining lines as new code lines\n if (lines.length > 1) {\n const nodes = lines.slice(1).map((line) => ({\n children: [{ text: line }],\n type: codeLineType,\n }));\n editor.tf.insertNodes(nodes);\n }\n } else {\n // Create new code block\n const node = {\n children: lines.map((line) => ({\n children: [{ text: line }],\n type: codeLineType,\n })),\n lang: vscodeData?.mode,\n type: codeBlockType,\n };\n\n editor.tf.insertNodes(node, {\n select: true,\n });\n }\n\n return;\n } catch (_error) {}\n }\n\n // Handle plain text paste into code block only if there are line breaks\n const [blockAbove] = editor.api.block<TElement>() ?? [];\n if (\n blockAbove &&\n [codeBlockType, codeLineType].includes(blockAbove?.type) &&\n text?.includes('\\n')\n ) {\n const lines = text.split('\\n');\n\n // Insert first line as text at cursor\n if (lines[0]) {\n editor.tf.insertText(lines[0]);\n }\n\n // Insert remaining lines as new code lines\n if (lines.length > 1) {\n const nodes = lines.slice(1).map((line) => ({\n children: [{ text: line }],\n type: codeLineType,\n }));\n editor.tf.insertNodes(nodes);\n }\n return;\n }\n\n insertData(data);\n },\n },\n});\n","import { type OverrideEditor, type TElement, KEYS, NodeApi } from 'platejs';\n\nfunction extractCodeLinesFromCodeBlock(node: TElement) {\n return node.children as TElement[];\n}\n\nexport const withInsertFragmentCodeBlock: OverrideEditor = ({\n editor,\n tf: { insertFragment },\n type: codeBlockType,\n}) => ({\n transforms: {\n insertFragment(fragment) {\n const [blockAbove] = editor.api.block<TElement>() ?? [];\n const codeLineType = editor.getType(KEYS.codeLine);\n\n function convertNodeToCodeLine(node: TElement): TElement {\n return {\n children: [{ text: NodeApi.string(node) }],\n type: codeLineType,\n };\n }\n\n if (\n blockAbove &&\n [codeBlockType, codeLineType].includes(blockAbove?.type)\n ) {\n return insertFragment(\n fragment.flatMap((node) => {\n const element = node as TElement;\n\n return element.type === codeBlockType\n ? extractCodeLinesFromCodeBlock(element)\n : convertNodeToCodeLine(element);\n })\n );\n }\n\n return insertFragment(fragment);\n },\n },\n});\n","import {\n type NodeEntry,\n type OverrideEditor,\n type TCodeBlockElement,\n ElementApi,\n KEYS,\n NodeApi,\n} from 'platejs';\n\nimport type { CodeBlockConfig } from './BaseCodeBlockPlugin';\n\nimport { setCodeBlockToDecorations } from './setCodeBlockToDecorations';\n\n/** Normalize code block node to force the pre>code>div.codeline structure. */\nexport const withNormalizeCodeBlock: OverrideEditor<CodeBlockConfig> = ({\n editor,\n getOptions,\n tf: { normalizeNode },\n type,\n}) => ({\n transforms: {\n normalizeNode([node, path]) {\n // Decorate is called on selection change as well, so we prefer to only run this on code block changes.\n if (node.type === type && getOptions().lowlight) {\n setCodeBlockToDecorations(editor, [\n node,\n path,\n ] as NodeEntry<TCodeBlockElement>);\n }\n\n normalizeNode([node, path]);\n\n if (!ElementApi.isElement(node)) {\n return;\n }\n\n const codeBlockType = editor.getType(KEYS.codeBlock);\n const codeLineType = editor.getType(KEYS.codeLine);\n const isCodeBlockRoot = node.type === codeBlockType;\n\n if (isCodeBlockRoot) {\n // Children should all be code lines\n const nonCodeLine = Array.from(NodeApi.children(editor, path)).find(\n ([child]) => child.type !== codeLineType\n );\n\n if (nonCodeLine) {\n editor.tf.setNodes({ type: codeLineType }, { at: nonCodeLine[1] });\n }\n }\n },\n },\n});\n","import type { OverrideEditor, TCodeBlockElement, TElement } from 'platejs';\n\nimport type { CodeBlockConfig } from './BaseCodeBlockPlugin';\n\nimport { getCodeLineEntry, getIndentDepth } from './queries';\nimport { resetCodeBlockDecorations } from './setCodeBlockToDecorations';\nimport { indentCodeLine, outdentCodeLine, unwrapCodeBlock } from './transforms';\nimport { withInsertDataCodeBlock } from './withInsertDataCodeBlock';\nimport { withInsertFragmentCodeBlock } from './withInsertFragmentCodeBlock';\nimport { withNormalizeCodeBlock } from './withNormalizeCodeBlock';\n\nexport const withCodeBlock: OverrideEditor<CodeBlockConfig> = (ctx) => {\n const {\n editor,\n getOptions,\n tf: { apply, insertBreak, resetBlock, selectAll, tab },\n type,\n } = ctx;\n\n return {\n transforms: {\n apply(operation) {\n if (getOptions().lowlight && operation.type === 'set_node') {\n const entry = editor.api.node(operation.path);\n\n if (entry?.[0].type === type && operation.newProperties?.lang) {\n // Clear decorations for all code lines in this block\n resetCodeBlockDecorations(entry[0] as TCodeBlockElement);\n }\n }\n\n apply(operation);\n },\n insertBreak() {\n const apply = () => {\n if (!editor.selection) return;\n\n const res = getCodeLineEntry(editor, {});\n\n if (!res) return;\n\n const { codeBlock, codeLine } = res;\n const indentDepth = getIndentDepth(editor, {\n codeBlock,\n codeLine,\n });\n\n insertBreak();\n\n indentCodeLine(editor, {\n codeBlock,\n codeLine,\n indentDepth,\n });\n\n return true;\n };\n\n if (apply()) return;\n\n insertBreak();\n },\n resetBlock(options) {\n if (\n editor.api.block({\n at: options?.at,\n match: { type },\n })\n ) {\n unwrapCodeBlock(editor);\n return;\n }\n\n return resetBlock(options);\n },\n selectAll: () => {\n const apply = () => {\n const codeBlock = editor.api.above({\n match: { type },\n });\n\n if (!codeBlock) return;\n\n if (\n editor.api.isAt({ end: true }) &&\n editor.api.isAt({ start: true })\n ) {\n return;\n }\n\n // Select the whole code block\n editor.tf.select(codeBlock[1]);\n return true;\n };\n\n if (apply()) return true;\n\n return selectAll();\n },\n tab: (options) => {\n const apply = () => {\n const _codeLines = editor.api.nodes<TElement>({\n match: { type },\n });\n const codeLines = Array.from(_codeLines);\n\n if (codeLines.length > 0) {\n const [, firstLinePath] = codeLines[0];\n const codeBlock = editor.api.parent<TElement>(firstLinePath);\n\n if (!codeBlock) return;\n\n editor.tf.withoutNormalizing(() => {\n for (const codeLine of codeLines) {\n if (options.reverse) {\n outdentCodeLine(editor, { codeBlock, codeLine });\n } else {\n indentCodeLine(editor, { codeBlock, codeLine });\n }\n }\n });\n\n return true; // Prevent default\n }\n };\n\n if (apply()) return true;\n\n return tab(options);\n },\n ...withInsertDataCodeBlock(ctx).transforms,\n ...withInsertFragmentCodeBlock(ctx).transforms,\n ...withNormalizeCodeBlock(ctx).transforms,\n },\n };\n};\n"],"mappings":"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","names":["import_platejs","import_platejs","import_platejs","import_platejs","import_platejs","import_platejs","blockAbove","import_platejs","import_platejs","apply"]} |
| // src/react/CodeBlockPlugin.tsx | ||
| import { toPlatePlugin } from "platejs/react"; | ||
| // src/lib/BaseCodeBlockPlugin.ts | ||
| import { | ||
| createSlatePlugin, | ||
| createTSlatePlugin, | ||
| KEYS as KEYS8 | ||
| } from "platejs"; | ||
| // src/lib/deserializer/htmlDeserializerCodeBlock.ts | ||
| import { KEYS } from "platejs"; | ||
| var htmlDeserializerCodeBlock = { | ||
| rules: [ | ||
| { | ||
| validNodeName: "PRE" | ||
| }, | ||
| { | ||
| validNodeName: "P", | ||
| validStyle: { | ||
| fontFamily: "Consolas" | ||
| } | ||
| } | ||
| ], | ||
| parse: ({ element }) => { | ||
| const languageSelectorText = [...element.childNodes].find( | ||
| (node) => node.nodeName === "SELECT" | ||
| )?.textContent || ""; | ||
| const textContent = element.textContent?.replace(languageSelectorText, "") || ""; | ||
| let lines = textContent.split("\n"); | ||
| if (!lines?.length) { | ||
| lines = [textContent]; | ||
| } | ||
| const codeLines = lines.map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: KEYS.codeLine | ||
| })); | ||
| return { | ||
| children: codeLines, | ||
| type: KEYS.codeBlock | ||
| }; | ||
| } | ||
| }; | ||
| // src/lib/queries/getCodeLineEntry.ts | ||
| import { | ||
| ElementApi, | ||
| KEYS as KEYS2 | ||
| } from "platejs"; | ||
| var getCodeLineEntry = (editor, { at = editor.selection } = {}) => { | ||
| if (at && editor.api.some({ | ||
| at, | ||
| match: { type: editor.getType(KEYS2.codeLine) } | ||
| })) { | ||
| const selectionParent = editor.api.parent(at); | ||
| if (!selectionParent) return; | ||
| const [, parentPath] = selectionParent; | ||
| const codeLine = editor.api.above({ | ||
| at, | ||
| match: { type: editor.getType(KEYS2.codeLine) } | ||
| }) || editor.api.parent(parentPath); | ||
| if (!codeLine) return; | ||
| const [codeLineNode, codeLinePath] = codeLine; | ||
| if (ElementApi.isElement(codeLineNode) && codeLineNode.type !== editor.getType(KEYS2.codeLine)) | ||
| return; | ||
| const codeBlock = editor.api.parent(codeLinePath); | ||
| if (!codeBlock) return; | ||
| return { | ||
| codeBlock, | ||
| codeLine | ||
| }; | ||
| } | ||
| }; | ||
| // src/lib/queries/getIndentDepth.ts | ||
| var nonWhitespaceOrEndRegex = /\S|$/; | ||
| var getIndentDepth = (editor, { codeLine }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const text = editor.api.string(codeLinePath); | ||
| return text.search(nonWhitespaceOrEndRegex); | ||
| }; | ||
| // src/lib/queries/isCodeBlockEmpty.ts | ||
| import { NodeApi } from "platejs"; | ||
| var isCodeBlockEmpty = (editor) => { | ||
| const { codeBlock } = getCodeLineEntry(editor) ?? {}; | ||
| if (!codeBlock) return false; | ||
| const codeLines = Array.from(NodeApi.children(editor, codeBlock[1])); | ||
| if (codeLines.length === 0) return true; | ||
| if (codeLines.length > 1) return false; | ||
| const firstCodeLineNode = codeLines[0][0]; | ||
| return !NodeApi.string(firstCodeLineNode); | ||
| }; | ||
| // src/lib/setCodeBlockToDecorations.ts | ||
| import { | ||
| KEYS as KEYS3, | ||
| NodeApi as NodeApi2 | ||
| } from "platejs"; | ||
| var CODE_LINE_TO_DECORATIONS = /* @__PURE__ */ new WeakMap(); | ||
| function getHighlightNodes(result) { | ||
| return result.value || result.children || []; | ||
| } | ||
| function parseNodes(nodes, className = []) { | ||
| return nodes.flatMap((node) => { | ||
| const classes = [ | ||
| ...className, | ||
| ...node.properties ? node.properties.className : [] | ||
| ]; | ||
| if (node.children) { | ||
| return parseNodes(node.children, classes); | ||
| } | ||
| return { classes, text: node.value }; | ||
| }); | ||
| } | ||
| function normalizeTokens(tokens) { | ||
| const lines = [[]]; | ||
| let currentLine = lines[0]; | ||
| for (const token of tokens) { | ||
| const tokenLines = token.text.split("\n"); | ||
| for (let i = 0; i < tokenLines.length; i++) { | ||
| const content = tokenLines[i]; | ||
| if (content) { | ||
| currentLine.push({ classes: token.classes, content }); | ||
| } | ||
| if (i < tokenLines.length - 1) { | ||
| lines.push([]); | ||
| currentLine = lines.at(-1); | ||
| } | ||
| } | ||
| } | ||
| return lines; | ||
| } | ||
| function codeBlockToDecorations(editor, [block, blockPath]) { | ||
| const { defaultLanguage, ...options } = editor.getOptions(BaseCodeBlockPlugin); | ||
| const lowlight = options.lowlight; | ||
| const text = block.children.map((line) => NodeApi2.string(line)).join("\n"); | ||
| const language = block.lang; | ||
| const effectiveLanguage = language || defaultLanguage; | ||
| let highlighted; | ||
| try { | ||
| if (!effectiveLanguage || effectiveLanguage === "plaintext") { | ||
| highlighted = { value: [] }; | ||
| } else if (effectiveLanguage === "auto") { | ||
| highlighted = lowlight.highlightAuto(text); | ||
| } else { | ||
| highlighted = lowlight.highlight(effectiveLanguage, text); | ||
| } | ||
| } catch (error) { | ||
| const availableLanguages = lowlight.listLanguages(); | ||
| const isLanguageRegistered = effectiveLanguage && availableLanguages.includes(effectiveLanguage); | ||
| if (isLanguageRegistered) { | ||
| editor.api.debug.error(error, "CODE_HIGHLIGHT"); | ||
| highlighted = { value: [] }; | ||
| } else { | ||
| editor.api.debug.warn( | ||
| `Language "${effectiveLanguage}" is not registered. Falling back to plaintext` | ||
| ); | ||
| highlighted = { value: [] }; | ||
| } | ||
| } | ||
| const tokens = parseNodes(getHighlightNodes(highlighted)); | ||
| const normalizedTokens = normalizeTokens(tokens); | ||
| const blockChildren = block.children; | ||
| const nodeToDecorations = /* @__PURE__ */ new Map(); | ||
| const numLines = Math.min(normalizedTokens.length, blockChildren.length); | ||
| for (let index = 0; index < numLines; index++) { | ||
| const lineTokens = normalizedTokens[index]; | ||
| const element = blockChildren[index]; | ||
| if (!nodeToDecorations.has(element)) { | ||
| nodeToDecorations.set(element, []); | ||
| } | ||
| let start = 0; | ||
| for (const token of lineTokens) { | ||
| const length = token.content.length; | ||
| if (!length) continue; | ||
| const end = start + length; | ||
| const decoration = { | ||
| anchor: { | ||
| offset: start, | ||
| path: [...blockPath, index, 0] | ||
| }, | ||
| className: token.classes.join(" "), | ||
| focus: { | ||
| offset: end, | ||
| path: [...blockPath, index, 0] | ||
| }, | ||
| [KEYS3.codeSyntax]: true | ||
| }; | ||
| nodeToDecorations.get(element).push(decoration); | ||
| start = end; | ||
| } | ||
| } | ||
| return nodeToDecorations; | ||
| } | ||
| function setCodeBlockToDecorations(editor, [block, blockPath]) { | ||
| const decorations = codeBlockToDecorations(editor, [block, blockPath]); | ||
| for (const [node, decs] of decorations.entries()) { | ||
| CODE_LINE_TO_DECORATIONS.set(node, decs); | ||
| } | ||
| } | ||
| function resetCodeBlockDecorations(codeBlock) { | ||
| codeBlock.children.forEach((line) => { | ||
| CODE_LINE_TO_DECORATIONS.delete(line); | ||
| }); | ||
| } | ||
| // src/lib/transforms/deleteStartSpace.ts | ||
| var whitespaceRegex = /\s/; | ||
| var deleteStartSpace = (editor, { codeLine }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const codeLineStart = editor.api.start(codeLinePath); | ||
| const codeLineEnd = codeLineStart && editor.api.after(codeLineStart); | ||
| const spaceRange = codeLineEnd && editor.api.range(codeLineStart, codeLineEnd); | ||
| const spaceText = editor.api.string(spaceRange); | ||
| if (whitespaceRegex.test(spaceText)) { | ||
| editor.tf.delete({ at: spaceRange }); | ||
| return true; | ||
| } | ||
| return false; | ||
| }; | ||
| // src/lib/transforms/indentCodeLine.ts | ||
| var nonWhitespaceRegex = /\S/; | ||
| var indentCodeLine = (editor, { codeLine, indentDepth = 2 }) => { | ||
| const [, codeLinePath] = codeLine; | ||
| const codeLineStart = editor.api.start(codeLinePath); | ||
| const indent = " ".repeat(indentDepth); | ||
| if (!editor.api.isExpanded()) { | ||
| const cursor = editor.selection?.anchor; | ||
| const range = editor.api.range(codeLineStart, cursor); | ||
| const text = editor.api.string(range); | ||
| if (nonWhitespaceRegex.test(text)) { | ||
| editor.tf.insertText(indent, { at: editor.selection }); | ||
| return; | ||
| } | ||
| } | ||
| editor.tf.insertText(indent, { at: codeLineStart }); | ||
| }; | ||
| // src/lib/transforms/outdentCodeLine.ts | ||
| var outdentCodeLine = (editor, { codeBlock, codeLine }) => { | ||
| const deleted = deleteStartSpace(editor, { codeBlock, codeLine }); | ||
| if (deleted) { | ||
| deleteStartSpace(editor, { codeBlock, codeLine }); | ||
| } | ||
| }; | ||
| // src/lib/transforms/unwrapCodeBlock.ts | ||
| import { KEYS as KEYS4, NodeApi as NodeApi3 } from "platejs"; | ||
| var unwrapCodeBlock = (editor) => { | ||
| if (!editor.selection) return; | ||
| const codeBlockType = editor.getType(KEYS4.codeBlock); | ||
| const defaultType = editor.getType(KEYS4.p); | ||
| editor.tf.withoutNormalizing(() => { | ||
| const codeBlockEntries = editor.api.nodes({ | ||
| at: editor.selection, | ||
| match: { type: codeBlockType } | ||
| }); | ||
| const reversedCodeBlockEntries = Array.from(codeBlockEntries).reverse(); | ||
| for (const codeBlockEntry of reversedCodeBlockEntries) { | ||
| const codeLineEntries = NodeApi3.children(editor, codeBlockEntry[1]); | ||
| for (const [, path] of codeLineEntries) { | ||
| editor.tf.setNodes({ type: defaultType }, { at: path }); | ||
| } | ||
| editor.tf.unwrapNodes({ | ||
| at: codeBlockEntry[1], | ||
| match: { type: codeBlockType }, | ||
| split: true | ||
| }); | ||
| } | ||
| }); | ||
| }; | ||
| // src/lib/withInsertDataCodeBlock.ts | ||
| import { KEYS as KEYS5 } from "platejs"; | ||
| var withInsertDataCodeBlock = ({ | ||
| editor, | ||
| tf: { insertData }, | ||
| type: codeBlockType | ||
| }) => ({ | ||
| transforms: { | ||
| insertData(data) { | ||
| const text = data.getData("text/plain"); | ||
| const vscodeDataString = data.getData("vscode-editor-data"); | ||
| const codeLineType = editor.getType(KEYS5.codeLine); | ||
| if (vscodeDataString) { | ||
| try { | ||
| const vscodeData = JSON.parse(vscodeDataString); | ||
| const lines = text.split("\n"); | ||
| const [blockAbove2] = editor.api.block() ?? []; | ||
| const isInCodeBlock = blockAbove2 && [codeBlockType, codeLineType].includes(blockAbove2?.type); | ||
| if (isInCodeBlock) { | ||
| if (lines[0]) { | ||
| editor.tf.insertText(lines[0]); | ||
| } | ||
| if (lines.length > 1) { | ||
| const nodes = lines.slice(1).map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })); | ||
| editor.tf.insertNodes(nodes); | ||
| } | ||
| } else { | ||
| const node = { | ||
| children: lines.map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })), | ||
| lang: vscodeData?.mode, | ||
| type: codeBlockType | ||
| }; | ||
| editor.tf.insertNodes(node, { | ||
| select: true | ||
| }); | ||
| } | ||
| return; | ||
| } catch (_error) { | ||
| } | ||
| } | ||
| const [blockAbove] = editor.api.block() ?? []; | ||
| if (blockAbove && [codeBlockType, codeLineType].includes(blockAbove?.type) && text?.includes("\n")) { | ||
| const lines = text.split("\n"); | ||
| if (lines[0]) { | ||
| editor.tf.insertText(lines[0]); | ||
| } | ||
| if (lines.length > 1) { | ||
| const nodes = lines.slice(1).map((line) => ({ | ||
| children: [{ text: line }], | ||
| type: codeLineType | ||
| })); | ||
| editor.tf.insertNodes(nodes); | ||
| } | ||
| return; | ||
| } | ||
| insertData(data); | ||
| } | ||
| } | ||
| }); | ||
| // src/lib/withInsertFragmentCodeBlock.ts | ||
| import { KEYS as KEYS6, NodeApi as NodeApi4 } from "platejs"; | ||
| function extractCodeLinesFromCodeBlock(node) { | ||
| return node.children; | ||
| } | ||
| var withInsertFragmentCodeBlock = ({ | ||
| editor, | ||
| tf: { insertFragment }, | ||
| type: codeBlockType | ||
| }) => ({ | ||
| transforms: { | ||
| insertFragment(fragment) { | ||
| const [blockAbove] = editor.api.block() ?? []; | ||
| const codeLineType = editor.getType(KEYS6.codeLine); | ||
| function convertNodeToCodeLine(node) { | ||
| return { | ||
| children: [{ text: NodeApi4.string(node) }], | ||
| type: codeLineType | ||
| }; | ||
| } | ||
| if (blockAbove && [codeBlockType, codeLineType].includes(blockAbove?.type)) { | ||
| return insertFragment( | ||
| fragment.flatMap((node) => { | ||
| const element = node; | ||
| return element.type === codeBlockType ? extractCodeLinesFromCodeBlock(element) : convertNodeToCodeLine(element); | ||
| }) | ||
| ); | ||
| } | ||
| return insertFragment(fragment); | ||
| } | ||
| } | ||
| }); | ||
| // src/lib/withNormalizeCodeBlock.tsx | ||
| import { | ||
| ElementApi as ElementApi2, | ||
| KEYS as KEYS7, | ||
| NodeApi as NodeApi5 | ||
| } from "platejs"; | ||
| var withNormalizeCodeBlock = ({ | ||
| editor, | ||
| getOptions, | ||
| tf: { normalizeNode }, | ||
| type | ||
| }) => ({ | ||
| transforms: { | ||
| normalizeNode([node, path]) { | ||
| if (node.type === type && getOptions().lowlight) { | ||
| setCodeBlockToDecorations(editor, [ | ||
| node, | ||
| path | ||
| ]); | ||
| } | ||
| normalizeNode([node, path]); | ||
| if (!ElementApi2.isElement(node)) { | ||
| return; | ||
| } | ||
| const codeBlockType = editor.getType(KEYS7.codeBlock); | ||
| const codeLineType = editor.getType(KEYS7.codeLine); | ||
| const isCodeBlockRoot = node.type === codeBlockType; | ||
| if (isCodeBlockRoot) { | ||
| const nonCodeLine = Array.from(NodeApi5.children(editor, path)).find( | ||
| ([child]) => child.type !== codeLineType | ||
| ); | ||
| if (nonCodeLine) { | ||
| editor.tf.setNodes({ type: codeLineType }, { at: nonCodeLine[1] }); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| }); | ||
| // src/lib/withCodeBlock.ts | ||
| var withCodeBlock = (ctx) => { | ||
| const { | ||
| editor, | ||
| getOptions, | ||
| tf: { apply, insertBreak, resetBlock, selectAll, tab }, | ||
| type | ||
| } = ctx; | ||
| return { | ||
| transforms: { | ||
| apply(operation) { | ||
| if (getOptions().lowlight && operation.type === "set_node") { | ||
| const entry = editor.api.node(operation.path); | ||
| if (entry?.[0].type === type && operation.newProperties?.lang) { | ||
| resetCodeBlockDecorations(entry[0]); | ||
| } | ||
| } | ||
| apply(operation); | ||
| }, | ||
| insertBreak() { | ||
| const apply2 = () => { | ||
| if (!editor.selection) return; | ||
| const res = getCodeLineEntry(editor, {}); | ||
| if (!res) return; | ||
| const { codeBlock, codeLine } = res; | ||
| const indentDepth = getIndentDepth(editor, { | ||
| codeBlock, | ||
| codeLine | ||
| }); | ||
| insertBreak(); | ||
| indentCodeLine(editor, { | ||
| codeBlock, | ||
| codeLine, | ||
| indentDepth | ||
| }); | ||
| return true; | ||
| }; | ||
| if (apply2()) return; | ||
| insertBreak(); | ||
| }, | ||
| resetBlock(options) { | ||
| if (editor.api.block({ | ||
| at: options?.at, | ||
| match: { type } | ||
| })) { | ||
| unwrapCodeBlock(editor); | ||
| return; | ||
| } | ||
| return resetBlock(options); | ||
| }, | ||
| selectAll: () => { | ||
| const apply2 = () => { | ||
| const codeBlock = editor.api.above({ | ||
| match: { type } | ||
| }); | ||
| if (!codeBlock) return; | ||
| if (editor.api.isAt({ end: true }) && editor.api.isAt({ start: true })) { | ||
| return; | ||
| } | ||
| editor.tf.select(codeBlock[1]); | ||
| return true; | ||
| }; | ||
| if (apply2()) return true; | ||
| return selectAll(); | ||
| }, | ||
| tab: (options) => { | ||
| const apply2 = () => { | ||
| const _codeLines = editor.api.nodes({ | ||
| match: { type } | ||
| }); | ||
| const codeLines = Array.from(_codeLines); | ||
| if (codeLines.length > 0) { | ||
| const [, firstLinePath] = codeLines[0]; | ||
| const codeBlock = editor.api.parent(firstLinePath); | ||
| if (!codeBlock) return; | ||
| editor.tf.withoutNormalizing(() => { | ||
| for (const codeLine of codeLines) { | ||
| if (options.reverse) { | ||
| outdentCodeLine(editor, { codeBlock, codeLine }); | ||
| } else { | ||
| indentCodeLine(editor, { codeBlock, codeLine }); | ||
| } | ||
| } | ||
| }); | ||
| return true; | ||
| } | ||
| }; | ||
| if (apply2()) return true; | ||
| return tab(options); | ||
| }, | ||
| ...withInsertDataCodeBlock(ctx).transforms, | ||
| ...withInsertFragmentCodeBlock(ctx).transforms, | ||
| ...withNormalizeCodeBlock(ctx).transforms | ||
| } | ||
| }; | ||
| }; | ||
| // src/lib/BaseCodeBlockPlugin.ts | ||
| var BaseCodeLinePlugin = createTSlatePlugin({ | ||
| key: KEYS8.codeLine, | ||
| node: { isElement: true, isStrictSiblings: true } | ||
| }); | ||
| var BaseCodeSyntaxPlugin = createSlatePlugin({ | ||
| key: KEYS8.codeSyntax, | ||
| node: { isLeaf: true } | ||
| }); | ||
| var BaseCodeBlockPlugin = createTSlatePlugin({ | ||
| key: KEYS8.codeBlock, | ||
| inject: { | ||
| plugins: { | ||
| [KEYS8.html]: { | ||
| parser: { | ||
| query: ({ editor }) => !editor.api.some({ | ||
| match: { type: editor.getType(KEYS8.codeLine) } | ||
| }) | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| node: { | ||
| isElement: true | ||
| }, | ||
| options: { | ||
| defaultLanguage: null, | ||
| lowlight: null | ||
| }, | ||
| parsers: { html: { deserializer: htmlDeserializerCodeBlock } }, | ||
| plugins: [BaseCodeLinePlugin, BaseCodeSyntaxPlugin], | ||
| render: { as: "pre" }, | ||
| rules: { | ||
| delete: { | ||
| empty: "reset" | ||
| }, | ||
| match: ({ editor, rule }) => ["break.empty", "delete.empty"].includes(rule) && isCodeBlockEmpty(editor) | ||
| }, | ||
| decorate: ({ editor, entry: [node, path], getOptions, type }) => { | ||
| if (!getOptions().lowlight) return []; | ||
| const codeLineType = editor.getType(KEYS8.codeLine); | ||
| if (node.type === type && !CODE_LINE_TO_DECORATIONS.get(node.children[0])) { | ||
| setCodeBlockToDecorations(editor, [node, path]); | ||
| } | ||
| if (node.type === codeLineType) { | ||
| return CODE_LINE_TO_DECORATIONS.get(node) || []; | ||
| } | ||
| return []; | ||
| } | ||
| }).overrideEditor(withCodeBlock).extendTransforms(({ editor }) => ({ | ||
| toggle: () => { | ||
| editor.tf.toggleBlock(editor.getType(KEYS8.codeBlock)); | ||
| } | ||
| })); | ||
| // src/react/CodeBlockPlugin.tsx | ||
| var CodeSyntaxPlugin = toPlatePlugin(BaseCodeSyntaxPlugin); | ||
| var CodeLinePlugin = toPlatePlugin(BaseCodeLinePlugin); | ||
| var CodeBlockPlugin = toPlatePlugin(BaseCodeBlockPlugin, { | ||
| plugins: [CodeLinePlugin, CodeSyntaxPlugin] | ||
| }); | ||
| export { | ||
| CodeBlockPlugin, | ||
| CodeLinePlugin, | ||
| CodeSyntaxPlugin | ||
| }; | ||
| //# sourceMappingURL=index.mjs.map |
| {"version":3,"sources":["../../src/react/CodeBlockPlugin.tsx","../../src/lib/BaseCodeBlockPlugin.ts","../../src/lib/deserializer/htmlDeserializerCodeBlock.ts","../../src/lib/queries/getCodeLineEntry.ts","../../src/lib/queries/getIndentDepth.ts","../../src/lib/queries/isCodeBlockEmpty.ts","../../src/lib/setCodeBlockToDecorations.ts","../../src/lib/transforms/deleteStartSpace.ts","../../src/lib/transforms/indentCodeLine.ts","../../src/lib/transforms/outdentCodeLine.ts","../../src/lib/transforms/unwrapCodeBlock.ts","../../src/lib/withInsertDataCodeBlock.ts","../../src/lib/withInsertFragmentCodeBlock.ts","../../src/lib/withNormalizeCodeBlock.tsx","../../src/lib/withCodeBlock.ts"],"sourcesContent":["import { toPlatePlugin } from 'platejs/react';\n\nimport {\n BaseCodeBlockPlugin,\n BaseCodeLinePlugin,\n BaseCodeSyntaxPlugin,\n} from '../lib/BaseCodeBlockPlugin';\n\nexport const CodeSyntaxPlugin = toPlatePlugin(BaseCodeSyntaxPlugin);\n\nexport const CodeLinePlugin = toPlatePlugin(BaseCodeLinePlugin);\n\n/** Enables support for pre-formatted code blocks. */\nexport const CodeBlockPlugin = toPlatePlugin(BaseCodeBlockPlugin, {\n plugins: [CodeLinePlugin, CodeSyntaxPlugin],\n});\n","import type { createLowlight } from 'lowlight';\n\nimport {\n type PluginConfig,\n type TCodeBlockElement,\n type TElement,\n createSlatePlugin,\n createTSlatePlugin,\n KEYS,\n} from 'platejs';\n\nimport { htmlDeserializerCodeBlock } from './deserializer/htmlDeserializerCodeBlock';\nimport { isCodeBlockEmpty } from './queries';\nimport {\n CODE_LINE_TO_DECORATIONS,\n setCodeBlockToDecorations,\n} from './setCodeBlockToDecorations';\nimport { withCodeBlock } from './withCodeBlock';\n\nexport type CodeBlockConfig = PluginConfig<\n 'code_block',\n {\n /**\n * Default language to use when no language is specified. Set to null to\n * disable syntax highlighting by default.\n */\n defaultLanguage?: string | null;\n /**\n * Lowlight instance to use for highlighting. If not provided, syntax\n * highlighting will be disabled.\n */\n lowlight?: ReturnType<typeof createLowlight> | null;\n }\n>;\n\nexport const BaseCodeLinePlugin = createTSlatePlugin({\n key: KEYS.codeLine,\n node: { isElement: true, isStrictSiblings: true },\n});\n\nexport const BaseCodeSyntaxPlugin = createSlatePlugin({\n key: KEYS.codeSyntax,\n node: { isLeaf: true },\n});\n\nexport const BaseCodeBlockPlugin = createTSlatePlugin<CodeBlockConfig>({\n key: KEYS.codeBlock,\n inject: {\n plugins: {\n [KEYS.html]: {\n parser: {\n query: ({ editor }) =>\n !editor.api.some({\n match: { type: editor.getType(KEYS.codeLine) },\n }),\n },\n },\n },\n },\n node: {\n isElement: true,\n },\n options: {\n defaultLanguage: null,\n lowlight: null,\n },\n parsers: { html: { deserializer: htmlDeserializerCodeBlock } },\n plugins: [BaseCodeLinePlugin, BaseCodeSyntaxPlugin],\n render: { as: 'pre' },\n rules: {\n delete: {\n empty: 'reset',\n },\n match: ({ editor, rule }) =>\n ['break.empty', 'delete.empty'].includes(rule) &&\n isCodeBlockEmpty(editor),\n },\n decorate: ({ editor, entry: [node, path], getOptions, type }) => {\n if (!getOptions().lowlight) return [];\n\n const codeLineType = editor.getType(KEYS.codeLine);\n\n // Initialize decorations for the code block, we assume code line decorate will be called next.\n if (\n node.type === type &&\n !CODE_LINE_TO_DECORATIONS.get((node.children as TElement[])[0])\n ) {\n setCodeBlockToDecorations(editor, [node as TCodeBlockElement, path]);\n }\n\n if (node.type === codeLineType) {\n return CODE_LINE_TO_DECORATIONS.get(node as TElement) || [];\n }\n\n return [];\n },\n})\n .overrideEditor(withCodeBlock)\n .extendTransforms(({ editor }) => ({\n toggle: () => {\n editor.tf.toggleBlock(editor.getType(KEYS.codeBlock));\n },\n }));\n","import type { HtmlDeserializer } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\nexport const htmlDeserializerCodeBlock: HtmlDeserializer = {\n rules: [\n {\n validNodeName: 'PRE',\n },\n {\n validNodeName: 'P',\n validStyle: {\n fontFamily: 'Consolas',\n },\n },\n ],\n parse: ({ element }) => {\n const languageSelectorText =\n [...element.childNodes].find(\n (node: ChildNode) => node.nodeName === 'SELECT'\n )?.textContent || '';\n\n const textContent =\n element.textContent?.replace(languageSelectorText, '') || '';\n\n let lines = textContent.split('\\n');\n\n if (!lines?.length) {\n lines = [textContent];\n }\n\n const codeLines = lines.map((line) => ({\n children: [{ text: line }],\n type: KEYS.codeLine,\n }));\n\n return {\n children: codeLines,\n type: KEYS.codeBlock,\n };\n },\n};\n","import {\n type ElementOf,\n type NodeEntry,\n type SlateEditor,\n type TElement,\n type TLocation,\n ElementApi,\n KEYS,\n} from 'platejs';\n\n/** If at (default = selection) is in ul>li>p, return li and ul node entries. */\nexport const getCodeLineEntry = <N extends ElementOf<E>, E extends SlateEditor>(\n editor: E,\n { at = editor.selection }: { at?: TLocation | null } = {}\n) => {\n if (\n at &&\n editor.api.some({\n at,\n match: { type: editor.getType(KEYS.codeLine) },\n })\n ) {\n const selectionParent = editor.api.parent(at);\n\n if (!selectionParent) return;\n\n const [, parentPath] = selectionParent;\n\n const codeLine =\n editor.api.above<TElement>({\n at,\n match: { type: editor.getType(KEYS.codeLine) },\n }) || editor.api.parent<N>(parentPath);\n\n if (!codeLine) return;\n\n const [codeLineNode, codeLinePath] = codeLine;\n\n if (\n ElementApi.isElement(codeLineNode) &&\n codeLineNode.type !== editor.getType(KEYS.codeLine)\n )\n return;\n\n const codeBlock = editor.api.parent<N>(codeLinePath);\n\n if (!codeBlock) return;\n\n return {\n codeBlock,\n codeLine: codeLine as NodeEntry<N>,\n };\n }\n};\n","import type { Editor } from 'platejs';\n\nimport type { IndentCodeLineOptions } from '../transforms/indentCodeLine';\n\nconst nonWhitespaceOrEndRegex = /\\S|$/;\n\nexport const getIndentDepth = (\n editor: Editor,\n { codeLine }: IndentCodeLineOptions\n) => {\n const [, codeLinePath] = codeLine;\n const text = editor.api.string(codeLinePath);\n\n return text.search(nonWhitespaceOrEndRegex);\n};\n","import { type SlateEditor, NodeApi } from 'platejs';\n\nimport { getCodeLineEntry } from './getCodeLineEntry';\n\n/** Is the selection inside an empty code block */\nexport const isCodeBlockEmpty = (editor: SlateEditor) => {\n const { codeBlock } = getCodeLineEntry(editor) ?? {};\n\n if (!codeBlock) return false;\n\n const codeLines = Array.from(NodeApi.children(editor, codeBlock[1]));\n\n if (codeLines.length === 0) return true;\n if (codeLines.length > 1) return false;\n\n const firstCodeLineNode = codeLines[0][0];\n\n return !NodeApi.string(firstCodeLineNode);\n};\n","import {\n type DecoratedRange,\n type NodeEntry,\n type SlateEditor,\n type TCodeBlockElement,\n type TElement,\n KEYS,\n NodeApi,\n} from 'platejs';\n\nimport { BaseCodeBlockPlugin } from './BaseCodeBlockPlugin';\n\n// Cache for storing decorations per code line element\nexport const CODE_LINE_TO_DECORATIONS = new WeakMap<\n TElement,\n DecoratedRange[]\n>();\n\n// Helper function to get highlight nodes from Lowlight result\nfunction getHighlightNodes(result: any) {\n return result.value || result.children || [];\n}\n\n// Helper function to parse nodes from Lowlight's hast tree\nfunction parseNodes(\n nodes: any[],\n className: string[] = []\n): { classes: string[]; text: string }[] {\n return nodes.flatMap((node) => {\n const classes = [\n ...className,\n ...(node.properties ? node.properties.className : []),\n ];\n if (node.children) {\n return parseNodes(node.children, classes);\n }\n return { classes, text: node.value };\n });\n}\n\n// Helper function to normalize tokens by line\nfunction normalizeTokens(tokens: { classes: string[]; text: string }[]) {\n const lines: { classes: string[]; content: string }[][] = [[]];\n let currentLine = lines[0];\n\n for (const token of tokens) {\n const tokenLines = token.text.split('\\n');\n\n for (let i = 0; i < tokenLines.length; i++) {\n const content = tokenLines[i];\n\n if (content) {\n currentLine.push({ classes: token.classes, content });\n }\n\n // Create a new line unless we're on the last line\n if (i < tokenLines.length - 1) {\n lines.push([]);\n currentLine = lines.at(-1) as any;\n }\n }\n }\n\n return lines;\n}\n\n// Helper function to compute decorations for a code block\nexport function codeBlockToDecorations(\n editor: SlateEditor,\n [block, blockPath]: NodeEntry<TCodeBlockElement>\n) {\n const { defaultLanguage, ...options } =\n editor.getOptions(BaseCodeBlockPlugin);\n const lowlight = options.lowlight!;\n\n // Get all code lines and combine their text\n const text = block.children.map((line) => NodeApi.string(line)).join('\\n');\n const language = block.lang;\n const effectiveLanguage = language || defaultLanguage;\n\n let highlighted: any;\n try {\n // Skip highlighting for plaintext or when no language is specified\n if (!effectiveLanguage || effectiveLanguage === 'plaintext') {\n highlighted = { value: [] }; // Empty result for plaintext\n } else if (effectiveLanguage === 'auto') {\n highlighted = lowlight.highlightAuto(text);\n } else {\n highlighted = lowlight.highlight(effectiveLanguage, text);\n }\n } catch (error) {\n // Verify if language is registered, fallback to plaintext if not\n const availableLanguages = lowlight.listLanguages();\n const isLanguageRegistered =\n effectiveLanguage && availableLanguages.includes(effectiveLanguage);\n if (isLanguageRegistered) {\n editor.api.debug.error(error, 'CODE_HIGHLIGHT');\n highlighted = { value: [] }; // Empty result on error\n } else {\n editor.api.debug.warn(\n `Language \"${effectiveLanguage}\" is not registered. Falling back to plaintext`\n );\n highlighted = { value: [] };\n }\n }\n\n // Parse and normalize tokens\n const tokens = parseNodes(getHighlightNodes(highlighted));\n const normalizedTokens = normalizeTokens(tokens);\n const blockChildren = block.children as TElement[];\n\n // Create decorations map\n const nodeToDecorations = new Map<TElement, DecoratedRange[]>();\n\n // Safety check: don't process more lines than we have children\n const numLines = Math.min(normalizedTokens.length, blockChildren.length);\n\n // Process each line's tokens\n for (let index = 0; index < numLines; index++) {\n const lineTokens = normalizedTokens[index];\n const element = blockChildren[index];\n\n if (!nodeToDecorations.has(element)) {\n nodeToDecorations.set(element, []);\n }\n\n let start = 0;\n for (const token of lineTokens) {\n const length = token.content.length;\n if (!length) continue;\n\n const end = start + length;\n\n const decoration: DecoratedRange = {\n anchor: {\n offset: start,\n path: [...blockPath, index, 0],\n },\n className: token.classes.join(' '),\n focus: {\n offset: end,\n path: [...blockPath, index, 0],\n },\n [KEYS.codeSyntax]: true,\n } as any;\n\n nodeToDecorations.get(element)!.push(decoration);\n start = end;\n }\n }\n\n return nodeToDecorations;\n}\n\nexport function setCodeBlockToDecorations(\n editor: SlateEditor,\n [block, blockPath]: NodeEntry<TCodeBlockElement>\n) {\n const decorations = codeBlockToDecorations(editor, [block, blockPath]);\n\n // Update the global cache with the new decorations\n for (const [node, decs] of decorations.entries()) {\n CODE_LINE_TO_DECORATIONS.set(node, decs);\n }\n}\n\nexport function resetCodeBlockDecorations(codeBlock: TCodeBlockElement) {\n codeBlock.children.forEach((line) => {\n CODE_LINE_TO_DECORATIONS.delete(line as TElement);\n });\n}\n","import type { Editor } from 'platejs';\n\nimport type { OutdentCodeLineOptions } from './outdentCodeLine';\n\nconst whitespaceRegex = /\\s/;\n\n/** If there is a whitespace character at the start of the code line, delete it. */\nexport const deleteStartSpace = (\n editor: Editor,\n { codeLine }: OutdentCodeLineOptions\n) => {\n const [, codeLinePath] = codeLine;\n const codeLineStart = editor.api.start(codeLinePath);\n const codeLineEnd = codeLineStart && editor.api.after(codeLineStart);\n const spaceRange =\n codeLineEnd && editor.api.range(codeLineStart, codeLineEnd);\n const spaceText = editor.api.string(spaceRange);\n\n if (whitespaceRegex.test(spaceText)) {\n editor.tf.delete({ at: spaceRange });\n\n return true;\n }\n\n return false;\n};\n","import type { Editor, ElementEntry } from 'platejs';\n\nconst nonWhitespaceRegex = /\\S/;\n\nexport type IndentCodeLineOptions = {\n codeBlock: ElementEntry;\n codeLine: ElementEntry;\n indentDepth?: number;\n};\n\n/**\n * Indent if:\n *\n * - The selection is expanded OR\n * - There are no non-whitespace characters left of the cursor Indentation = 2\n * spaces.\n */\nexport const indentCodeLine = (\n editor: Editor,\n { codeLine, indentDepth = 2 }: IndentCodeLineOptions\n) => {\n const [, codeLinePath] = codeLine;\n const codeLineStart = editor.api.start(codeLinePath)!;\n const indent = ' '.repeat(indentDepth);\n\n if (!editor.api.isExpanded()) {\n const cursor = editor.selection?.anchor;\n const range = editor.api.range(codeLineStart, cursor);\n const text = editor.api.string(range);\n\n if (nonWhitespaceRegex.test(text)) {\n editor.tf.insertText(indent, { at: editor.selection! });\n\n return;\n }\n }\n\n editor.tf.insertText(indent, { at: codeLineStart });\n};\n","import type { Editor, ElementEntry } from 'platejs';\n\nimport { deleteStartSpace } from './deleteStartSpace';\n\nexport type OutdentCodeLineOptions = {\n codeBlock: ElementEntry;\n codeLine: ElementEntry;\n};\n\n/** Outdent the code line. Remove 2 whitespace characters if any. */\nexport const outdentCodeLine = (\n editor: Editor,\n { codeBlock, codeLine }: OutdentCodeLineOptions\n) => {\n const deleted = deleteStartSpace(editor, { codeBlock, codeLine });\n if (deleted) {\n deleteStartSpace(editor, { codeBlock, codeLine });\n }\n};\n","import { type SlateEditor, type TLocation, KEYS, NodeApi } from 'platejs';\n\nexport const unwrapCodeBlock = (editor: SlateEditor) => {\n if (!editor.selection) return;\n\n const codeBlockType = editor.getType(KEYS.codeBlock);\n const defaultType = editor.getType(KEYS.p);\n\n editor.tf.withoutNormalizing(() => {\n const codeBlockEntries = editor.api.nodes({\n at: editor.selection as TLocation,\n match: { type: codeBlockType },\n });\n\n const reversedCodeBlockEntries = Array.from(codeBlockEntries).reverse();\n\n for (const codeBlockEntry of reversedCodeBlockEntries) {\n const codeLineEntries = NodeApi.children(editor, codeBlockEntry[1]);\n\n for (const [, path] of codeLineEntries) {\n editor.tf.setNodes({ type: defaultType }, { at: path });\n }\n\n editor.tf.unwrapNodes({\n at: codeBlockEntry[1],\n match: { type: codeBlockType },\n split: true,\n });\n }\n });\n};\n","import type { OverrideEditor, TElement } from 'platejs';\n\nimport { KEYS } from 'platejs';\n\nexport const withInsertDataCodeBlock: OverrideEditor = ({\n editor,\n tf: { insertData },\n type: codeBlockType,\n}) => ({\n transforms: {\n insertData(data) {\n const text = data.getData('text/plain');\n const vscodeDataString = data.getData('vscode-editor-data');\n const codeLineType = editor.getType(KEYS.codeLine);\n\n // Handle VSCode paste with language\n if (vscodeDataString) {\n try {\n const vscodeData = JSON.parse(vscodeDataString);\n const lines = text.split('\\n');\n\n // Check if we're in a code block\n const [blockAbove] = editor.api.block<TElement>() ?? [];\n const isInCodeBlock =\n blockAbove &&\n [codeBlockType, codeLineType].includes(blockAbove?.type);\n\n if (isInCodeBlock) {\n // If in code block, insert first line as text at cursor\n if (lines[0]) {\n editor.tf.insertText(lines[0]);\n }\n\n // Insert remaining lines as new code lines\n if (lines.length > 1) {\n const nodes = lines.slice(1).map((line) => ({\n children: [{ text: line }],\n type: codeLineType,\n }));\n editor.tf.insertNodes(nodes);\n }\n } else {\n // Create new code block\n const node = {\n children: lines.map((line) => ({\n children: [{ text: line }],\n type: codeLineType,\n })),\n lang: vscodeData?.mode,\n type: codeBlockType,\n };\n\n editor.tf.insertNodes(node, {\n select: true,\n });\n }\n\n return;\n } catch (_error) {}\n }\n\n // Handle plain text paste into code block only if there are line breaks\n const [blockAbove] = editor.api.block<TElement>() ?? [];\n if (\n blockAbove &&\n [codeBlockType, codeLineType].includes(blockAbove?.type) &&\n text?.includes('\\n')\n ) {\n const lines = text.split('\\n');\n\n // Insert first line as text at cursor\n if (lines[0]) {\n editor.tf.insertText(lines[0]);\n }\n\n // Insert remaining lines as new code lines\n if (lines.length > 1) {\n const nodes = lines.slice(1).map((line) => ({\n children: [{ text: line }],\n type: codeLineType,\n }));\n editor.tf.insertNodes(nodes);\n }\n return;\n }\n\n insertData(data);\n },\n },\n});\n","import { type OverrideEditor, type TElement, KEYS, NodeApi } from 'platejs';\n\nfunction extractCodeLinesFromCodeBlock(node: TElement) {\n return node.children as TElement[];\n}\n\nexport const withInsertFragmentCodeBlock: OverrideEditor = ({\n editor,\n tf: { insertFragment },\n type: codeBlockType,\n}) => ({\n transforms: {\n insertFragment(fragment) {\n const [blockAbove] = editor.api.block<TElement>() ?? [];\n const codeLineType = editor.getType(KEYS.codeLine);\n\n function convertNodeToCodeLine(node: TElement): TElement {\n return {\n children: [{ text: NodeApi.string(node) }],\n type: codeLineType,\n };\n }\n\n if (\n blockAbove &&\n [codeBlockType, codeLineType].includes(blockAbove?.type)\n ) {\n return insertFragment(\n fragment.flatMap((node) => {\n const element = node as TElement;\n\n return element.type === codeBlockType\n ? extractCodeLinesFromCodeBlock(element)\n : convertNodeToCodeLine(element);\n })\n );\n }\n\n return insertFragment(fragment);\n },\n },\n});\n","import {\n type NodeEntry,\n type OverrideEditor,\n type TCodeBlockElement,\n ElementApi,\n KEYS,\n NodeApi,\n} from 'platejs';\n\nimport type { CodeBlockConfig } from './BaseCodeBlockPlugin';\n\nimport { setCodeBlockToDecorations } from './setCodeBlockToDecorations';\n\n/** Normalize code block node to force the pre>code>div.codeline structure. */\nexport const withNormalizeCodeBlock: OverrideEditor<CodeBlockConfig> = ({\n editor,\n getOptions,\n tf: { normalizeNode },\n type,\n}) => ({\n transforms: {\n normalizeNode([node, path]) {\n // Decorate is called on selection change as well, so we prefer to only run this on code block changes.\n if (node.type === type && getOptions().lowlight) {\n setCodeBlockToDecorations(editor, [\n node,\n path,\n ] as NodeEntry<TCodeBlockElement>);\n }\n\n normalizeNode([node, path]);\n\n if (!ElementApi.isElement(node)) {\n return;\n }\n\n const codeBlockType = editor.getType(KEYS.codeBlock);\n const codeLineType = editor.getType(KEYS.codeLine);\n const isCodeBlockRoot = node.type === codeBlockType;\n\n if (isCodeBlockRoot) {\n // Children should all be code lines\n const nonCodeLine = Array.from(NodeApi.children(editor, path)).find(\n ([child]) => child.type !== codeLineType\n );\n\n if (nonCodeLine) {\n editor.tf.setNodes({ type: codeLineType }, { at: nonCodeLine[1] });\n }\n }\n },\n },\n});\n","import type { OverrideEditor, TCodeBlockElement, TElement } from 'platejs';\n\nimport type { CodeBlockConfig } from './BaseCodeBlockPlugin';\n\nimport { getCodeLineEntry, getIndentDepth } from './queries';\nimport { resetCodeBlockDecorations } from './setCodeBlockToDecorations';\nimport { indentCodeLine, outdentCodeLine, unwrapCodeBlock } from './transforms';\nimport { withInsertDataCodeBlock } from './withInsertDataCodeBlock';\nimport { withInsertFragmentCodeBlock } from './withInsertFragmentCodeBlock';\nimport { withNormalizeCodeBlock } from './withNormalizeCodeBlock';\n\nexport const withCodeBlock: OverrideEditor<CodeBlockConfig> = (ctx) => {\n const {\n editor,\n getOptions,\n tf: { apply, insertBreak, resetBlock, selectAll, tab },\n type,\n } = ctx;\n\n return {\n transforms: {\n apply(operation) {\n if (getOptions().lowlight && operation.type === 'set_node') {\n const entry = editor.api.node(operation.path);\n\n if (entry?.[0].type === type && operation.newProperties?.lang) {\n // Clear decorations for all code lines in this block\n resetCodeBlockDecorations(entry[0] as TCodeBlockElement);\n }\n }\n\n apply(operation);\n },\n insertBreak() {\n const apply = () => {\n if (!editor.selection) return;\n\n const res = getCodeLineEntry(editor, {});\n\n if (!res) return;\n\n const { codeBlock, codeLine } = res;\n const indentDepth = getIndentDepth(editor, {\n codeBlock,\n codeLine,\n });\n\n insertBreak();\n\n indentCodeLine(editor, {\n codeBlock,\n codeLine,\n indentDepth,\n });\n\n return true;\n };\n\n if (apply()) return;\n\n insertBreak();\n },\n resetBlock(options) {\n if (\n editor.api.block({\n at: options?.at,\n match: { type },\n })\n ) {\n unwrapCodeBlock(editor);\n return;\n }\n\n return resetBlock(options);\n },\n selectAll: () => {\n const apply = () => {\n const codeBlock = editor.api.above({\n match: { type },\n });\n\n if (!codeBlock) return;\n\n if (\n editor.api.isAt({ end: true }) &&\n editor.api.isAt({ start: true })\n ) {\n return;\n }\n\n // Select the whole code block\n editor.tf.select(codeBlock[1]);\n return true;\n };\n\n if (apply()) return true;\n\n return selectAll();\n },\n tab: (options) => {\n const apply = () => {\n const _codeLines = editor.api.nodes<TElement>({\n match: { type },\n });\n const codeLines = Array.from(_codeLines);\n\n if (codeLines.length > 0) {\n const [, firstLinePath] = codeLines[0];\n const codeBlock = editor.api.parent<TElement>(firstLinePath);\n\n if (!codeBlock) return;\n\n editor.tf.withoutNormalizing(() => {\n for (const codeLine of codeLines) {\n if (options.reverse) {\n outdentCodeLine(editor, { codeBlock, codeLine });\n } else {\n indentCodeLine(editor, { codeBlock, codeLine });\n }\n }\n });\n\n return true; // Prevent default\n }\n };\n\n if (apply()) return true;\n\n return tab(options);\n },\n ...withInsertDataCodeBlock(ctx).transforms,\n ...withInsertFragmentCodeBlock(ctx).transforms,\n ...withNormalizeCodeBlock(ctx).transforms,\n },\n };\n};\n"],"mappings":"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","names":["KEYS","KEYS","KEYS","NodeApi","NodeApi","KEYS","KEYS","NodeApi","KEYS","blockAbove","KEYS","NodeApi","ElementApi","KEYS","NodeApi","ElementApi","KEYS","NodeApi","apply","KEYS"]} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Yes
NaN30364
-88.44%7
-50%754
-72.38%1
Infinity%