editate 0.0.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/src/utils.ts","../src/src/doc/utils.ts","../src/src/doc/edit.ts","../src/src/doc/position.ts","../src/src/commands.ts","../src/src/dom/parser.ts","../src/src/dom/default.ts","../src/src/dom/index.ts","../src/src/hooks/copy/plain.ts","../src/src/hooks/utils.ts","../src/src/hooks/keyboard.ts","../src/src/plugins/history.ts","../src/src/editor.ts","../src/src/hooks/paste/plain.ts","../src/src/dom/mutation.ts","../src/src/plugins/singleline.ts","../src/src/presets/plain.ts","../src/src/plugins/debug.ts","../src/src/hooks/paste/file.ts","../src/src/hooks/copy/html.ts","../src/src/hooks/paste/html.ts","../src/src/hooks/copy/internal.ts","../src/src/hooks/paste/internal.ts"],"sourcesContent":["/**\n * @internal\n */\nexport const min = Math.min;\n\n/**\n * @internal\n */\nexport const { keys, is } = Object;\n\n/**\n * @internal\n */\nexport const isString = (n: unknown) => typeof n === \"string\";\n\n/**\n * @internal\n */\nexport const isFunction = (n: unknown) => typeof n === \"function\";\n\n/**\n * @internal\n */\nexport const microtask: (fn: () => void) => void = isFunction(queueMicrotask)\n ? queueMicrotask\n : (fn) => {\n Promise.resolve().then(fn);\n };\n","import { isBlockNode, isTextNode } from \"./edit.js\";\nimport {\n type BlockNode,\n type DocNode,\n type InlineNode,\n type TextNode,\n} from \"./types.js\";\n\n/**\n * @internal\n */\nexport const docToString = <T extends DocNode>(\n doc: T,\n serializer: (node: InlineNode) => string = (n) =>\n isTextNode(n) ? n.text : \"\",\n): string => {\n return doc.children.reduce((acc: string, r, i) => {\n const isBlock = isBlockNode(r);\n if (i !== 0 && isBlock) {\n acc += \"\\n\";\n }\n return (\n acc +\n (isBlock\n ? r.children.reduce((acc: string, n) => acc + serializer(n), \"\")\n : \"\")\n );\n }, \"\");\n};\n\n/**\n * @internal\n */\nexport const stringToFragment = <T extends TextNode, B extends BlockNode>(\n text: string,\n node?: T,\n block?: B,\n) => {\n return text\n .split(\"\\n\")\n .map((l) => ({ ...block, children: [{ ...node, text: l } as T] }));\n};\n","import { is, keys } from \"../utils.js\";\nimport type {\n DocNode,\n Fragment,\n InlineNode,\n Selection,\n TextNode,\n Path,\n BlockNode,\n Node,\n DomPosition,\n SelectionSnapshot,\n} from \"./types.js\";\nimport { stringToFragment } from \"./utils.js\";\n\nconst OP_DELETE = \"delete\";\ntype DeleteOperation = Readonly<{\n type: typeof OP_DELETE;\n start: number;\n end: number;\n}>;\n\nconst OP_INSERT_TEXT = \"insert_text\";\ntype InsertTextOperation = Readonly<{\n type: typeof OP_INSERT_TEXT;\n at: number;\n text: string;\n}>;\n\nconst OP_INSERT_NODE = \"insert_node\";\ntype InsertNodeOperation = Readonly<{\n type: typeof OP_INSERT_NODE;\n at: number;\n fragment: Fragment;\n}>;\n\nconst OP_SET_ATTR = \"set_attr\";\ntype SetAttrOperation = Readonly<{\n type: typeof OP_SET_ATTR;\n start: number;\n end: number;\n key: string;\n value: unknown;\n}>;\n\nconst OP_SET_NODE_ATTR = \"set_node_attr\";\ntype SetNodeAttrOperation = Readonly<{\n type: typeof OP_SET_NODE_ATTR;\n path: Path;\n key: string;\n value: unknown;\n}>;\n\nexport type Operation =\n | DeleteOperation\n | InsertTextOperation\n | InsertNodeOperation\n | SetAttrOperation\n | SetNodeAttrOperation;\n\n/**\n * @internal\n */\nexport const isUnsafeOperation = ({ type }: Operation): boolean =>\n type === OP_INSERT_NODE || type === OP_SET_ATTR || type === OP_SET_NODE_ATTR;\n\nexport class Transaction {\n private readonly _ops: Operation[];\n\n constructor(ops?: readonly Operation[]) {\n this._ops = ops ? ops.slice() : [];\n }\n\n get ops(): readonly Operation[] {\n return this._ops;\n }\n\n insertText(at: number, text: string): this {\n this._ops.push({\n type: OP_INSERT_TEXT,\n at: at,\n text: text,\n });\n return this;\n }\n\n insertFragment(at: number, fragment: Fragment): this {\n this._ops.push({\n type: OP_INSERT_NODE,\n at: at,\n fragment: fragment,\n });\n return this;\n }\n\n delete(start: number, end: number): this {\n this._ops.push({\n type: OP_DELETE,\n start: start,\n end: end,\n });\n return this;\n }\n\n format(start: number, end: number, key: string, value: unknown): this {\n this._ops.push({\n type: OP_SET_ATTR,\n start: start,\n end: end,\n key: key,\n value: value,\n });\n return this;\n }\n\n attr(at: Path, key: string, value: unknown): this {\n this._ops.push({\n type: OP_SET_NODE_ATTR,\n path: at,\n key: key,\n value: value,\n });\n return this;\n }\n\n transform(position: number): number {\n return this._ops.reduce((acc, op) => rebasePosition(acc, op), position);\n }\n}\n\n/**\n * @internal\n */\nexport const isTextNode = (node: Node): node is TextNode => \"text\" in node;\n\n/**\n * @internal\n */\nexport const isBlockNode = (node: Node): node is BlockNode =>\n \"children\" in node;\n\nconst isSameNode = (a: InlineNode, b: InlineNode): boolean => {\n const aKeys = keys(a);\n if (aKeys.length !== keys(b).length) {\n return false;\n }\n return aKeys.every((k) => {\n if (!(k in b)) {\n return false;\n }\n return k === \"text\" || is((a as any)[k], (b as any)[k]);\n });\n};\n\nconst sizeCache = new WeakMap<BlockNode, number>();\n\nconst calcBlockSize = (\n { children }: BlockNode,\n start: number = 0,\n end: number = children.length,\n): number => {\n let size = 0;\n let count = 0;\n for (let i = start; i < end; i++) {\n const n = children[i]!;\n size += getNodeSize(n);\n if (count !== 0 && isBlockNode(n)) {\n size++;\n }\n count++;\n }\n return size;\n};\n\nexport const getNodeSize = (node: Node): number => {\n if (isBlockNode(node)) {\n let size = sizeCache.get(node);\n if (size == null) {\n sizeCache.set(node, (size = calcBlockSize(node)));\n }\n return size;\n }\n return isTextNode(node) ? node.text.length : 1;\n};\n\n/**\n * @internal\n */\nexport const positionToOffset = (\n node: DocNode | BlockNode,\n [path, offset]: DomPosition,\n): number => {\n let size = 0;\n for (const p of path) {\n size += calcBlockSize(node, 0, p);\n if (p !== 0) {\n size++;\n }\n node = node.children[p]! as BlockNode;\n }\n return size + offset;\n};\n\nexport const offsetToPosition = (\n node: DocNode | BlockNode,\n offset: number,\n): DomPosition => {\n const path: number[] = [];\n while (node) {\n const found = getChildAt(node, offset);\n if (!found) {\n break;\n }\n const index = found._index;\n const nextNode = found._node;\n if (!isBlockNode(nextNode)) {\n break;\n }\n offset = found._offset;\n path.push(index);\n node = nextNode;\n }\n return [path, offset];\n};\n\n/**\n * @internal\n */\nexport const domSelectionToSelection = (\n doc: DocNode,\n [anchor, focus]: SelectionSnapshot,\n): Selection => {\n return [positionToOffset(doc, anchor), positionToOffset(doc, focus)];\n};\n\n/**\n * @internal\n */\nexport const selectionToDomSelection = (\n doc: DocNode,\n [anchor, focus]: Selection,\n): SelectionSnapshot => {\n return [offsetToPosition(doc, anchor), offsetToPosition(doc, focus)];\n};\n\nconst normalizeInline = (\n array: InlineNode[],\n start: number = 0,\n end: number = array.length - 1,\n): void => {\n let i = start + 1;\n while (i <= end) {\n const prev = array[i - 1]!;\n const curr = array[i]!;\n // merge text nodes with same attrs\n if (isTextNode(prev) && isTextNode(curr) && isSameNode(prev, curr)) {\n array[i - 1] = { ...prev, text: prev.text + curr.text };\n array.splice(i, 1);\n end--;\n } else {\n i++;\n }\n }\n\n // remove empty text nodes, leaving at least one node per block\n i = start;\n while (i <= end) {\n const node = array[i]!;\n if (isTextNode(node) && !node.text && array.length > 1) {\n array.splice(i, 1);\n end--;\n } else {\n i++;\n }\n }\n};\n\nconst normalizeBlock = (\n array: BlockNode[],\n start: number = 0,\n end: number = array.length - 1,\n): void => {\n let i = start + 1;\n while (i <= end) {\n const prev = array[i - 1]!;\n const curr = array[i]!;\n // merge block nodes\n array[i - 1] = joinBlocks(prev, curr);\n array.splice(i, 1);\n end--;\n }\n};\n\nconst concat = <T extends Node>(\n a: T[],\n b: readonly T[],\n normalize: (array: T[], start: number, end: number) => void,\n): void => {\n if (b.length) {\n const prevLength = a.length;\n a.push(...b);\n if (prevLength) {\n normalize(a, prevLength - 1, prevLength);\n }\n }\n};\n\n/**\n * @internal\n */\nexport const joinBlocks = <T extends BlockNode>(...blocks: T[]): T => {\n return {\n ...blocks[0]!,\n children: blocks.reduce((acc, b) => {\n concat(acc, b.children, normalizeInline);\n return acc;\n }, []),\n };\n};\n\nconst getChildAt = <T extends BlockNode>(\n { children }: T,\n offset: number,\n): { _node: T[\"children\"][number]; _index: number; _offset: number } | null => {\n for (let i = 0; i < children.length; i++) {\n const node = children[i]!;\n let size = getNodeSize(node);\n if (isBlockNode(node)) {\n size++;\n }\n if (size > offset) {\n return { _node: node, _index: i, _offset: offset };\n }\n offset -= size;\n }\n return null;\n};\n\nconst splitBlock = <T extends DocNode | BlockNode>(\n block: T,\n pos: number,\n): [T, T] => {\n const children = block.children;\n const target = getChildAt(block, pos);\n if (target) {\n const { _node: node, _offset: offsetAtNode, _index: i } = target;\n if (isBlockNode(node)) {\n const [childBefore, childAfter] = splitBlock(node, offsetAtNode);\n const before = children.slice(0, i);\n const after = children.slice(i + 1);\n before.push(childBefore);\n after.unshift(childAfter);\n return [\n { ...block, children: before },\n { ...block, children: after },\n ];\n } else {\n const before = children.slice(0, i);\n const after = children.slice(i + 1);\n if (isTextNode(node)) {\n const beforeText = node.text.slice(0, offsetAtNode);\n const afterText = node.text.slice(offsetAtNode);\n if (beforeText || !before.length) {\n before.push({ ...node, text: beforeText });\n }\n if (afterText || !after.length) {\n after.unshift({ ...node, text: afterText });\n }\n } else {\n // node size must be 1\n after.unshift(node);\n }\n return [\n { ...block, children: before },\n { ...block, children: after },\n ];\n }\n }\n return [block, { ...block, children: [] }];\n};\n\n/**\n * @internal\n */\nexport const getNodeAt = (\n node: DocNode | BlockNode,\n path: Path,\n): BlockNode | DocNode => {\n for (let i = 0; i < path.length; i++) {\n node = node.children[path[i]!]! as BlockNode; // TODO improve\n }\n return node;\n};\n\nconst replace = <\n T extends { readonly children: readonly BlockNode[] | readonly InlineNode[] },\n>(\n node: T,\n start: number,\n end: number,\n lines: Fragment,\n): T => {\n const sliced = node.children.slice();\n sliced.splice(start, end - start + 1, ...lines);\n return { ...node, children: sliced };\n};\n\nconst replaceNodeAt = <\n T extends { readonly children: readonly BlockNode[] | readonly InlineNode[] },\n>(\n node: T,\n path: Path,\n afterNode: Node,\n i: number = 0,\n): T => {\n if (i < path.length) {\n const index = path[i]!;\n return replace(node, index, index, [\n replaceNodeAt(node.children[index]! as T, path, afterNode, i + 1),\n ]);\n }\n // TODO improve type\n return afterNode as T;\n};\n\nconst replaceRange = <T extends DocNode>(\n doc: T,\n start: number,\n end: number,\n inserted: Fragment,\n): T => {\n const [before, maybeAfter] = splitBlock(doc, start);\n const after = start < end ? splitBlock(doc, end)[1] : maybeAfter;\n\n const array = before.children.slice();\n concat(array, inserted, normalizeBlock);\n concat(array, after.children, normalizeBlock);\n\n return { ...doc, children: array };\n};\n\n/**\n * @internal\n */\nexport const sliceFragment = <T extends DocNode>(\n doc: T,\n start: number,\n end: number,\n): T[\"children\"] => {\n if (start >= end) {\n return [];\n }\n\n return splitBlock(splitBlock(doc, end)[0], start)[1].children;\n};\n\nconst isValidPosition = (doc: DocNode, offset: number): boolean => {\n return offset >= 0 && offset <= getNodeSize(doc);\n};\n\nconst rebasePosition = (position: number, op: Operation): number => {\n switch (op.type) {\n case OP_DELETE: {\n const { start, end } = op;\n\n if (position >= start) {\n // start <= position\n if (end >= position) {\n // start <= position <= end\n return start;\n }\n // start <= end < position\n return position + start - end;\n }\n break;\n }\n case OP_INSERT_TEXT: {\n const { at, text } = op;\n\n if (position >= at) {\n // at <= position\n return position + text.length;\n }\n break;\n }\n case OP_INSERT_NODE: {\n const { at, fragment } = op;\n\n if (position >= at) {\n // at <= position\n return position + getNodeSize({ children: fragment });\n }\n break;\n }\n }\n return position;\n};\n\n/**\n * @internal\n */\nexport const rebaseSelection = (\n [anchor, focus]: Selection,\n op: Operation,\n): Selection => {\n return [rebasePosition(anchor, op), rebasePosition(focus, op)];\n};\n\n/**\n * @internal\n */\nexport const isValidSelection = (\n doc: DocNode,\n [anchor, focus]: Selection,\n): boolean => {\n return isValidPosition(doc, anchor) && isValidPosition(doc, focus);\n};\n\n/**\n * @internal\n */\nexport const applyOperation = <T extends DocNode>(\n doc: T,\n selection: Selection,\n op: Operation,\n): [T, Selection] => {\n switch (op.type) {\n case OP_DELETE: {\n const { start, end } = op;\n if (\n isValidPosition(doc, start) &&\n isValidPosition(doc, end) &&\n start < end\n ) {\n doc = replaceRange(doc, start, end, []);\n selection = rebaseSelection(selection, op);\n }\n break;\n }\n case OP_INSERT_TEXT: {\n const { at, text } = op;\n if (isValidPosition(doc, at) && text) {\n // inherit style from previous block/text node\n const [path, offset] = offsetToPosition(doc, at);\n const block = getNodeAt(doc, path);\n const res = getChildAt(block, offset - 1);\n let anchorNode: TextNode | undefined;\n if (res) {\n const node = res._node;\n if (isTextNode(node)) {\n anchorNode = node;\n }\n }\n\n doc = replaceRange(\n doc,\n at,\n at,\n stringToFragment(text, anchorNode, block),\n );\n selection = rebaseSelection(selection, op);\n }\n break;\n }\n case OP_INSERT_NODE: {\n const { at, fragment } = op;\n if (isValidPosition(doc, at) && fragment.length) {\n doc = replaceRange(doc, at, at, fragment);\n selection = rebaseSelection(selection, op);\n }\n break;\n }\n case OP_SET_ATTR: {\n const { start, end, key, value } = op;\n if (\n isValidPosition(doc, start) &&\n isValidPosition(doc, end) &&\n start < end\n ) {\n doc = replaceRange(\n doc,\n start,\n end,\n sliceFragment(doc, start, end).map((block) => ({\n ...block,\n children: block.children.map((node) =>\n isTextNode(node) ? { ...node, [key]: value } : node,\n ),\n })),\n );\n }\n break;\n }\n case OP_SET_NODE_ATTR: {\n const { path, key, value } = op;\n const node = getNodeAt(doc, path);\n if (node) {\n doc = replaceNodeAt(doc, path, { ...node, [key]: value });\n }\n break;\n }\n default: {\n op satisfies never;\n }\n }\n\n return [doc, selection];\n};\n","import type { Range, Selection } from \"./types.js\";\n\n/**\n * @internal\n */\nexport const toRange = ([a, b]: Selection | Range): Range => {\n return a > b ? [b, a] : [a, b];\n};\n\n/**\n * @internal\n */\nexport const isCollapsed = ([a, b]: Selection | Range): boolean => {\n return a === b;\n};\n","import { toRange } from \"./doc/position.js\";\nimport {\n getNodeAt,\n getNodeSize,\n isTextNode,\n offsetToPosition,\n sliceFragment,\n Transaction,\n} from \"./doc/edit.js\";\nimport type { Editor } from \"./editor.js\";\nimport type {\n DocNode,\n InferBlockNode,\n InferInlineNode,\n Path,\n Range,\n TextNode,\n} from \"./doc/types.js\";\n\n/**\n * Delete content in the selection or specified range.\n */\nexport function Delete(\n editor: Editor,\n range: Range = toRange(editor.selection),\n) {\n editor.apply(new Transaction().delete(...range));\n}\n\n/**\n * Insert text at the caret or specified position.\n */\nexport function InsertText(\n editor: Editor,\n text: string,\n position: number = editor.selection[0],\n) {\n editor.apply(new Transaction().insertText(position, text));\n}\n\n/**\n * Insert node at the caret or specified position.\n */\nexport function InsertNode<T extends DocNode>(\n editor: Editor<T>,\n node: Exclude<InferInlineNode<T>, TextNode>,\n position: number = editor.selection[0],\n) {\n editor.apply(\n new Transaction().insertFragment(position, [{ children: [node] }]),\n );\n}\n\n/**\n * Replace text in the selection or specified range.\n */\nexport function ReplaceText(editor: Editor, text: string) {\n const [start, end] = toRange(editor.selection);\n editor.apply(new Transaction().delete(start, end).insertText(start, text));\n}\n\n/**\n * Replace document in the editor.\n */\nexport function ReplaceDoc<T extends DocNode>(\n editor: Editor<T>,\n fragment: T[\"children\"],\n) {\n // TODO revisit\n editor.apply(\n new Transaction()\n .delete(0, getNodeSize(editor.doc))\n .insertFragment(0, fragment),\n );\n}\n\ntype ToggleableKey<T> = {\n [K in keyof T]-?: T[K] extends boolean | undefined ? K : never;\n}[keyof T];\n\n/**\n * Format content in the selection or specified range.\n */\nexport function Format<\n T extends DocNode,\n N extends Omit<InferInlineNode<T>, \"text\">,\n K extends Extract<keyof N, string>,\n>(\n editor: Editor<T>,\n key: K,\n value: N[K],\n range: Range = toRange(editor.selection),\n) {\n editor.apply(new Transaction().format(...range, key, value));\n}\n\n/**\n * Toggle formatting in the selection or specified range.\n */\nexport function ToggleFormat<T extends DocNode>(\n editor: Editor<T>,\n key: Extract<ToggleableKey<Omit<InferInlineNode<T>, \"text\">>, string>,\n range: Range = toRange(editor.selection),\n) {\n const texts = sliceFragment(editor.doc, ...range).flatMap((n) =>\n n.children.filter(isTextNode),\n );\n if (texts.length) {\n editor.apply(\n new Transaction().format(\n ...range,\n key,\n texts.some((n) => !n[key as keyof typeof n]) ? true : false,\n ),\n );\n }\n}\n\n/**\n * Set attr to a block node at the caret or specified position.\n */\nexport function SetBlockAttr<\n T extends DocNode,\n N extends InferBlockNode<T>,\n K extends Extract<keyof N, string>,\n>(\n editor: Editor<T>,\n key: K,\n value: N[K],\n path: Path = offsetToPosition(editor.doc, editor.selection[0])[0],\n) {\n editor.apply(new Transaction().attr(path, key, value));\n}\n\n/**\n * Toggle attr of block node at the caret or specified position.\n */\nexport function ToggleBlockAttr<\n T extends DocNode,\n N extends InferBlockNode<T>,\n K extends Extract<keyof N, string>,\n>(\n editor: Editor<T>,\n key: K,\n onValue: N[K],\n offValue: N[K],\n path: Path = offsetToPosition(editor.doc, editor.selection[0])[0],\n) {\n const block = getNodeAt(editor.doc, path) as N;\n editor.apply(\n new Transaction().attr(\n path,\n key,\n block[key] === onValue ? offValue : onValue,\n ),\n );\n}\n","let walker: TreeWalker | null = null;\nlet node: Node | null = null;\nlet _token: TokenType | null = null;\nlet config: ParserConfig | null = null;\nlet parse: Parser | null = null;\n\ninterface ParserConfig {\n readonly _document: Document;\n readonly _isBlock: (node: Element) => boolean;\n readonly _isVoid: (node: Element) => boolean;\n}\n\nconst SHOW_ELEMENT = 0x1;\nconst SHOW_TEXT = 0x4;\n\nconst TOKEN_NULL = 0;\n/** @internal */\nexport const TOKEN_TEXT = 1;\n/** @internal */\nexport const TOKEN_VOID = 2;\n/** @internal */\nexport const TOKEN_SOFT_BREAK = 3;\n/** @internal */\nexport const TOKEN_BLOCK = 4;\nconst TOKEN_EMPTY_BLOCK_ANCHOR = 5;\nconst TOKEN_INVALID_SOFT_BREAK = 6;\n\n/**\n * @internal\n */\nexport type TokenType =\n | typeof TOKEN_NULL\n | typeof TOKEN_TEXT\n | typeof TOKEN_VOID\n | typeof TOKEN_SOFT_BREAK\n | typeof TOKEN_BLOCK\n | typeof TOKEN_EMPTY_BLOCK_ANCHOR\n | typeof TOKEN_INVALID_SOFT_BREAK;\n\nconst ELEMENT_NODE = 1;\nconst TEXT_NODE = 3;\nconst COMMENT_NODE = 8;\n\n/**\n * @internal\n */\nexport const isTextNode = (node: Node): node is Text => {\n return node.nodeType === TEXT_NODE;\n};\n\n/**\n * @internal\n */\nexport const isElementNode = (node: Node): node is Element => {\n return node.nodeType === ELEMENT_NODE;\n};\n\n/**\n * @internal\n */\nexport const isCommentNode = (node: Node): node is Comment => {\n return node.nodeType === COMMENT_NODE;\n};\n\n/**\n * @internal\n */\nexport const getDomNode = <\n T extends TokenType | void,\n>(): T extends typeof TOKEN_TEXT\n ? Text\n : T extends TokenType\n ? Element\n : Text | Element => {\n return node as any;\n};\n\n/**\n * @internal\n */\nexport const getNodeSize = (): number => {\n const token = readToken();\n return token === TOKEN_TEXT\n ? (node as Text).data.length\n : token === TOKEN_VOID\n ? 1\n : 0;\n};\n\n/**\n * @internal\n */\nexport const readToken = (): TokenType => {\n if (_token != null) {\n return _token;\n }\n\n if (node) {\n if (isTextNode(node)) {\n const text = node.data;\n // Ignore empty text nodes some frameworks may generate\n if (text) {\n return (_token =\n // Especially Shift+Enter in Chrome\n text === \"\\n\"\n ? isValidSoftBreak()\n ? TOKEN_SOFT_BREAK\n : TOKEN_INVALID_SOFT_BREAK\n : TOKEN_TEXT);\n }\n } else if (isElementNode(node)) {\n if (node.tagName === \"BR\") {\n return (_token = isValidSoftBreak()\n ? // Especially Shift+Enter in Firefox\n TOKEN_SOFT_BREAK\n : // Returning <div><br/></div> is necessary to anchor selection\n TOKEN_EMPTY_BLOCK_ANCHOR);\n } else if (config!._isVoid(node)) {\n return (_token = TOKEN_VOID);\n } else if (config!._isBlock(node)) {\n return (_token = TOKEN_BLOCK);\n }\n }\n }\n return (_token = TOKEN_NULL);\n};\n\nconst nextNode = (): Node | null => {\n _token = null;\n return (node = walker!.nextNode());\n};\n\n/**\n * @internal\n */\nexport const nextBlock = () => {\n while ((_token = null) || (node = walker!.nextSibling())) {\n if (readToken() === TOKEN_BLOCK) {\n return;\n }\n }\n};\n\n/**\n * @internal\n */\nexport const parentBlock = () => {\n while ((_token = null) || (node = walker!.parentNode())) {\n if (readToken() === TOKEN_BLOCK) {\n return;\n }\n }\n};\n\nconst isValidSoftBreak = (): boolean => {\n // This function will return false if there are no nodes after soft break.\n //\n // In contenteditable, Shift+Enter will insert soft break. \\n in Chrome, <br/> in Firefox. Safari doesn't insert soft break.\n // And \\n or <br/> has a special role that represents empty block in contenteditable.\n // We have to distinguish real soft breaks from empty blocks.\n //\n // There are many possible markups for soft break ([] means text node):\n // <div>[\\n][abc]</div> Shift+Enter at start of line in Chrome\n // <div><br/>[abc]</div> Shift+Enter at start of line in Firefox\n // <div>[ab][\\n][c]</div> Shift+Enter at mid of line in Chrome\n // <div>[ab]<br/>[c]</div> Shift+Enter at mid of line in Firefox\n // <div>[abc][\\n][\\n]</div> Shift+Enter at end of line in Chrome\n // <div>[abc]<br/><br/></div> Shift+Enter at end of line in Firefox\n // <div>[\\n]<br/></div> Shift+Enter at empty line in Chrome\n // <div><br/><br/></div> Shift+Enter at empty line in Firefox\n //\n // And these do not include soft breaks:\n // <div><br/></div> empty line\n // <div>[a]<br/></div> type on empty line in Firefox\n const parent = node!.parentNode!;\n return parse!(() => {\n while (nextNode()) {\n if (readToken()) {\n return true;\n }\n if (!parent.contains(node)) {\n break;\n }\n }\n return false;\n });\n};\n\n/**\n * @internal\n */\nexport const readNext = (): Exclude<TokenType, typeof TOKEN_NULL> | void => {\n while (true) {\n if (readToken() === TOKEN_VOID) {\n const current = node!;\n // don't use TreeWalker.nextSibling() to support case like <body><p><a><img /></a></p><p>hello</p></body>\n while (nextNode()) {\n if (!current.contains(node)) {\n break;\n }\n }\n } else {\n nextNode();\n }\n\n if (!node) {\n break;\n }\n\n const t = readToken();\n if (t) {\n return t;\n }\n }\n};\n\n/**\n * @internal\n */\nexport const createParser = (initConfig: ParserConfig): Parser => {\n const parser: Parser = (scopeFn, root, startNode) => {\n const prevConfig = config;\n const prevParse = parse;\n const prevWalker = walker;\n const prevNode = node;\n const prevToken = _token;\n try {\n if (!walker) {\n config = initConfig;\n parse = parser;\n walker = config._document.createTreeWalker(\n root!,\n SHOW_TEXT | SHOW_ELEMENT,\n );\n }\n if (startNode) {\n walker!.currentNode = node = startNode;\n }\n return scopeFn();\n } finally {\n config = prevConfig;\n parse = prevParse;\n walker = prevWalker;\n node = prevNode;\n _token = prevToken;\n if (walker && prevNode) {\n walker.currentNode = prevNode;\n }\n }\n };\n return parser;\n};\n\nexport type Parser = <T>(scopeFn: () => T, root?: Node, startNode?: Node) => T;\n","const SINGLE_LINE_CONTAINER_NAMES = new Set([\n // https://w3c.github.io/editing/docs/execCommand/#single-line-container\n // non-list single-line container\n \"DIV\",\n \"H1\",\n \"H2\",\n \"H3\",\n \"H4\",\n \"H5\",\n \"H6\",\n \"P\",\n \"PRE\",\n // list single-line container\n \"LI\",\n \"DT\",\n \"DD\",\n\n // other elements for HTML paste\n \"TR\",\n]);\n\n/**\n * @internal\n */\nexport const defaultIsBlockNode = (node: Element): boolean => {\n return SINGLE_LINE_CONTAINER_NAMES.has(node.tagName);\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/HTML/Content_categories\n// https://html.spec.whatwg.org/multipage/dom.html#embedded-content-category\nconst EMBEDDED_CONTENT_TAG_NAMES = new Set([\n \"EMBED\",\n \"IMG\",\n \"PICTURE\",\n \"AUDIO\",\n \"VIDEO\",\n \"SVG\",\n \"CANVAS\",\n \"MATH\",\n \"IFRAME\",\n \"OBJECT\",\n]);\n\n/**\n * @internal\n */\nexport const defaultIsVoidNode = (node: Element): boolean => {\n return (\n (node as HTMLElement).contentEditable === \"false\" ||\n EMBEDDED_CONTENT_TAG_NAMES.has(node.tagName)\n );\n};\n","import {\n type TokenType,\n type Parser,\n getNodeSize,\n getDomNode,\n isElementNode,\n TOKEN_TEXT,\n TOKEN_VOID,\n TOKEN_SOFT_BREAK,\n TOKEN_BLOCK,\n nextBlock,\n readNext as next,\n parentBlock,\n readToken,\n} from \"./parser.js\";\nimport type {\n DomPosition,\n InlineNode,\n SelectionSnapshot,\n Fragment,\n TextNode,\n Path,\n BlockNode,\n} from \"../doc/types.js\";\nimport { min } from \"../utils.js\";\n\nexport { createParser } from \"./parser.js\";\nexport { defaultIsBlockNode, defaultIsVoidNode } from \"./default.js\";\n\n// const DOCUMENT_POSITION_DISCONNECTED = 0x01;\nconst DOCUMENT_POSITION_PRECEDING = 0x02;\nconst DOCUMENT_POSITION_FOLLOWING = 0x04;\n// const DOCUMENT_POSITION_CONTAINS = 0x08;\nconst DOCUMENT_POSITION_CONTAINED_BY = 0x10;\n// const DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;\n\nconst compareDomPosition = (a: Node, b: Node) => a.compareDocumentPosition(b);\n\n/**\n * @internal\n */\nexport const getCurrentDocument = (node: Element): Document =>\n node.ownerDocument;\n\n/**\n * @internal\n */\nexport const getDOMSelection = (element: Element): Selection => {\n // TODO support ShadowRoot\n return getCurrentDocument(element).getSelection()!;\n};\n\n/**\n * @internal\n */\nexport const getSelectionRangeInEditor = (\n selection: Selection,\n root: Element,\n): Range | void => {\n if (selection.rangeCount) {\n const range = selection.getRangeAt(0);\n if (root.contains(range.commonAncestorContainer)) {\n return range;\n }\n }\n};\n\nconst setRangeToSelection = (\n root: Element,\n range: Range,\n force: boolean | undefined,\n backward?: boolean,\n): void => {\n const selection = getDOMSelection(root);\n if (force || getSelectionRangeInEditor(selection, root)) {\n selection.removeAllRanges();\n selection.addRange(range);\n if (backward) {\n selection.collapseToEnd();\n selection.extend(range.startContainer, range.startOffset);\n }\n }\n};\n\n/**\n * @internal\n */\nexport const setSelectionToDOM = (\n document: Document,\n root: Element,\n [anchor, focus]: SelectionSnapshot,\n posDiff: number, // TODO remove\n parse: Parser,\n force?: boolean,\n): void => {\n const isCollapsed = posDiff === 0;\n const backward = posDiff > 0;\n const start = backward ? focus : anchor;\n const end = backward ? anchor : focus;\n // special path for empty content with empty selection, necessary for placeholder\n if (\n start[0].length === 0 &&\n start[1] === 0 &&\n isCollapsed &&\n !root.hasChildNodes()\n ) {\n const range = document.createRange();\n range.setStart(root, 0);\n range.setEnd(root, 0);\n\n return setRangeToSelection(root, range, force);\n }\n\n const domStart = findPosition(root, start, parse);\n if (!domStart) {\n return;\n }\n\n const domEnd = isCollapsed ? domStart : findPosition(root, end, parse);\n if (!domEnd) {\n return;\n }\n\n // https://w3c.github.io/contentEditable/#dfn-legal-caret-positions\n const range = document.createRange();\n\n const [startNode, startOffset] = domStart;\n const [endNode, endOffset] = domEnd;\n\n // embed or br\n if (isElementNode(startNode)) {\n if (startOffset < 1) {\n range.setStartBefore(startNode);\n } else {\n range.setStartAfter(startNode);\n }\n } else {\n range.setStart(startNode, startOffset);\n }\n\n // embed or br\n if (isElementNode(endNode)) {\n if (endOffset < 1) {\n range.setEndBefore(endNode);\n } else {\n range.setEndAfter(endNode);\n }\n } else {\n range.setEnd(endNode, endOffset);\n }\n\n setRangeToSelection(root, range, force, backward);\n};\n\ntype DOMPosition = [node: Text | Element, offsetAtNode: number];\n\nconst findPosition = (\n root: Element,\n [path, offset]: DomPosition,\n parse: Parser,\n): DOMPosition | undefined => {\n return parse((): DOMPosition | undefined => {\n let pathIndex = 0;\n let type: TokenType | void;\n while ((type = next())) {\n if (type === TOKEN_BLOCK) {\n if (pathIndex < path.length) {\n for (\n let blockIndex = path[pathIndex++]!;\n blockIndex > 0;\n blockIndex--\n ) {\n nextBlock();\n }\n }\n } else {\n const size = getNodeSize();\n if (offset <= size) {\n return [getDomNode<typeof type>(), offset];\n }\n offset -= size;\n }\n }\n return;\n }, root);\n};\n\nconst serializePosition = (\n root: Element,\n node: Node,\n offsetAtNode: number,\n parse: Parser,\n): DomPosition => {\n let excludeEnd = true;\n if (root === node && !node.hasChildNodes()) {\n // for placeholder\n return [[0], 0];\n }\n\n if (isElementNode(node) && node.hasChildNodes()) {\n // If start/end of Range is not selectable node, it will have offset relative to its parent\n // 0 1 2 3\n // <div>aaaa<img /><span>bbbb</span></div>\n //\n // And there are other possible cases:\n // - Selection with Ctrl+A in Firefox\n // - getTargetRanges() when deleting contenteditable:false in Firefox\n // - Selection.setBaseAndExtent(element, 0, element, 0)\n const index = min(offsetAtNode, node.childNodes.length - 1);\n node = node.childNodes[index]!;\n excludeEnd = index === offsetAtNode;\n offsetAtNode = 0;\n }\n\n return parse(\n () => {\n if (readToken() !== TOKEN_BLOCK) {\n parentBlock();\n }\n\n const path = parse((): Path => {\n const blocks: Element[] = [];\n // TODO improve type\n let block: Element | null;\n while ((block = getDomNode<typeof TOKEN_BLOCK>()) && block !== root) {\n blocks.unshift(block);\n parentBlock();\n }\n\n if (!blocks.length) {\n return [0];\n }\n\n let i = 0;\n let sib: Element = blocks[blocks.length - 1]!;\n while ((sib = sib.previousElementSibling!)) {\n i++;\n }\n return [i];\n });\n\n let offset = 0;\n while (next()) {\n const comp = compareDomPosition(node, getDomNode());\n if (\n comp === 0 || // same object\n comp & DOCUMENT_POSITION_CONTAINED_BY\n ) {\n if (excludeEnd) {\n break;\n }\n } else if (comp & DOCUMENT_POSITION_FOLLOWING) {\n break;\n }\n offset += getNodeSize();\n }\n return [path, offset + offsetAtNode];\n },\n root,\n node,\n );\n};\n\n/**\n * @internal\n */\nexport const serializeRange = (\n root: Element,\n parse: Parser,\n { startOffset, startContainer, endOffset, endContainer }: AbstractRange,\n): [DomPosition, DomPosition] => {\n const start = serializePosition(root, startContainer, startOffset, parse);\n return [\n start,\n startContainer === endContainer && startOffset === endOffset\n ? start\n : serializePosition(root, endContainer, endOffset, parse),\n ];\n};\n\n/**\n * @internal\n */\nexport const takeSelectionSnapshot = (\n root: Element,\n parse: Parser,\n): SelectionSnapshot => {\n const selection = getDOMSelection(root);\n const domRange = getSelectionRangeInEditor(selection, root);\n if (!domRange) {\n return [\n [[0], 0],\n [[0], 0],\n ];\n }\n\n const range = serializeRange(root, parse, domRange);\n const comp = compareDomPosition(selection.anchorNode!, selection.focusNode!);\n\n // https://stackoverflow.com/questions/9180405/detect-direction-of-user-selection-with-javascript\n return (\n comp === 0 // same object\n ? selection.anchorOffset > selection.focusOffset\n : comp & DOCUMENT_POSITION_PRECEDING\n )\n ? [range[1], range[0]]\n : range;\n};\n\n/**\n * @internal\n */\nexport const domToFragment = (\n root: Node,\n parse: Parser,\n serializeText: (text: string) => TextNode,\n serializeVoid: (node: Element) => InlineNode | void,\n): Fragment => {\n return parse(() => {\n let type: TokenType | void;\n let row: InlineNode[] | null = null;\n let text = \"\";\n let hasContent = false;\n\n const rows: BlockNode[] = [];\n\n const completeText = () => {\n if (text) {\n if (!row) {\n row = [];\n }\n row.push(serializeText(text));\n text = \"\";\n }\n };\n const completeRow = () => {\n completeText();\n if (!row && hasContent) {\n row = [];\n }\n if (row) {\n rows.push({ children: row });\n }\n row = null;\n hasContent = false;\n };\n\n while ((type = next())) {\n if (type === TOKEN_BLOCK) {\n completeRow();\n } else {\n hasContent = true;\n\n if (type === TOKEN_TEXT) {\n text += getDomNode<typeof type>().data;\n } else if (type === TOKEN_VOID) {\n completeText();\n const docNode = serializeVoid(getDomNode<typeof type>());\n if (docNode) {\n row!.push(docNode);\n }\n } else if (type === TOKEN_SOFT_BREAK) {\n completeRow();\n }\n }\n }\n completeRow();\n\n if (!rows.length) {\n rows.push({ children: [] });\n }\n\n return rows;\n }, root);\n};\n\n/**\n * @internal\n */\nexport const getPointedCaretPosition = (\n document: Document,\n root: Element,\n { clientX, clientY }: MouseEvent,\n parse: Parser,\n): DomPosition | void => {\n // https://developer.mozilla.org/en-US/docs/Web/API/Document/caretPositionFromPoint\n // https://developer.mozilla.org/en-US/docs/Web/API/Document/caretRangeFromPoint\n // caretPositionFromPoint caretRangeFromPoint\n // Chrome: 128 4\n // Firefox: 20 -\n // Safari: 26.2 5\n if (document.caretPositionFromPoint) {\n const position = document.caretPositionFromPoint(clientX, clientY);\n if (position) {\n return serializePosition(\n root,\n position.offsetNode,\n position.offset,\n parse,\n );\n }\n } else if (document.caretRangeFromPoint) {\n const range = document.caretRangeFromPoint(clientX, clientY);\n if (range) {\n return serializePosition(\n root,\n range.startContainer,\n range.startOffset,\n parse,\n );\n }\n }\n};\n","import type { DocNode, InlineNode, InferInlineNode } from \"../../doc/types.js\";\nimport { docToString } from \"../../doc/utils.js\";\nimport type { CopyHook } from \"./types.js\";\n\n/**\n * An extension to handle copying to plain text.\n */\nexport const plainCopy = <T extends DocNode>(\n serializer?: (node: InferInlineNode<T>) => string,\n): CopyHook => {\n return (dataTransfer, data) => {\n dataTransfer.setData(\n \"text/plain\",\n docToString(\n { children: data },\n serializer as ((node: InlineNode) => string) | undefined,\n ),\n );\n };\n};\n","/**\n * @internal\n */\nexport const INTERNAL_COPY_KEY = \"application/x-editate-editor\";\n","/**\n * Functions to handle keyboard events.\n *\n * Return `true` if you want to stop propagation.\n */\nexport type KeyboardHook = (keyboard: KeyboardEvent) => boolean | void;\n\n/**\n * TODO\n */\nexport const hotkey = (\n key: string,\n cb: (e: KeyboardEvent) => void,\n {\n mod,\n shift = false,\n alt = false,\n }: {\n mod?: boolean;\n // ctrl?: boolean;\n // meta?: boolean;\n shift?: boolean;\n alt?: boolean;\n // phase?: 'down' | 'up';\n } = {},\n): KeyboardHook => {\n key = key.toLowerCase();\n\n return (e): boolean | void => {\n // TODO should we handle it e.code?\n if (e.key.toLowerCase() === key) {\n if (\n // TODO detect OS\n (!mod || e.ctrlKey || e.metaKey) &&\n shift === e.shiftKey &&\n alt === e.altKey\n ) {\n cb(e);\n return true;\n }\n }\n };\n};\n","import { ReplaceDoc } from \"../commands.js\";\nimport { rebaseSelection, type Operation } from \"../doc/edit.js\";\nimport type { DocNode, Selection } from \"../doc/types.js\";\nimport type { Editor } from \"../editor.js\";\nimport { hotkey } from \"../hooks/keyboard.js\";\nimport { is } from \"../utils.js\";\n\nconst MAX_HISTORY_LENGTH = 500;\nconst BATCH_HISTORY_TIME = 500;\n\n/**\n * @internal\n */\nexport function historyPlugin<T extends DocNode>(editor: Editor<T>) {\n type History = [T, Selection, Operation[]];\n let index = 0;\n let prevTime = 0;\n let undoOrRedoing = false;\n const now = Date.now;\n const histories: History[] = [[editor.doc, editor.selection, []]];\n\n const get = () => histories[index]!;\n\n const isUndoable = (): boolean => {\n return index > 0;\n };\n\n const isRedoable = (): boolean => {\n return index < histories.length - 1;\n };\n\n const undo = () => {\n if (isUndoable()) {\n const sel = get()[1];\n index--;\n const currentDoc = editor.doc;\n undoOrRedoing = true;\n editor.exec(ReplaceDoc, get()[0].children);\n undoOrRedoing = false;\n if (!is(currentDoc, editor.doc)) {\n editor.selection = sel;\n }\n }\n };\n const redo = () => {\n if (isRedoable()) {\n index++;\n const [doc, sel, ops] = get();\n const currentDoc = editor.doc;\n undoOrRedoing = true;\n editor.exec(ReplaceDoc, doc.children);\n undoOrRedoing = false;\n if (!is(currentDoc, editor.doc)) {\n editor.selection = ops.reduce(\n (acc, op) => rebaseSelection(acc, op),\n sel,\n );\n }\n }\n };\n\n editor.hook(\"apply\", (op, next) => {\n if (undoOrRedoing) return;\n const doc = editor.doc;\n const selection = editor.selection;\n next(op);\n const newDoc = editor.doc;\n\n if (!is(doc, newDoc)) {\n const time = now();\n if (index === 0 || time - prevTime >= BATCH_HISTORY_TIME) {\n index++;\n const history: History = [doc, selection, []];\n if (index >= histories.length) {\n histories.push(history);\n } else {\n histories[index] = history;\n }\n }\n prevTime = time;\n histories[index]![0] = newDoc;\n histories[index]![2].push(op);\n histories.splice(index + 1);\n if (index > MAX_HISTORY_LENGTH) {\n index--;\n histories.shift();\n }\n }\n });\n\n editor.hook(\"keyboard\", hotkey(\"z\", undo, { mod: true }));\n editor.hook(\"keyboard\", hotkey(\"z\", redo, { mod: true, shift: true }));\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport {\n getCurrentDocument,\n takeSelectionSnapshot,\n setSelectionToDOM,\n getPointedCaretPosition,\n defaultIsBlockNode,\n defaultIsVoidNode,\n serializeRange,\n} from \"./dom/index.js\";\nimport { createMutationObserver } from \"./dom/mutation.js\";\nimport type { DocNode, Fragment, Selection } from \"./doc/types.js\";\nimport { is, isFunction, isString, microtask } from \"./utils.js\";\nimport {\n applyOperation,\n Transaction,\n sliceFragment,\n type Operation,\n isUnsafeOperation,\n isValidSelection,\n domSelectionToSelection,\n selectionToDomSelection,\n positionToOffset,\n} from \"./doc/edit.js\";\nimport { createParser } from \"./dom/index.js\";\nimport { isCollapsed, toRange } from \"./doc/position.js\";\nimport {\n type CopyHook,\n type PasteHook,\n plainCopy,\n plainPaste,\n type KeyboardHook,\n} from \"./hooks/index.js\";\nimport { historyPlugin } from \"./plugins/history.js\";\n\nconst empty: unknown[] = [];\n\nconst noop = () => {};\n\n/**\n * https://www.w3.org/TR/input-events-1/#interface-InputEvent-Attributes\n */\ntype InputType =\n | \"insertText\" // insert typed plain text\n | \"insertReplacementText\" // replace existing text by means of a spell checker, auto-correct or similar\n | \"insertLineBreak\" // insert a line break\n | \"insertParagraph\" // insert a paragraph break\n | \"insertOrderedList\" // insert a numbered list\n | \"insertUnorderedList\" // insert a bulleted list\n | \"insertHorizontalRule\" // insert a horizontal rule\n | \"insertFromYank\" // replace the current selection with content stored in a kill buffer\n | \"insertFromDrop\" // insert content into the DOM by means of drop\n | \"insertFromPaste\" // paste\n | \"insertFromPasteAsQuotation\" // paste content as a quotation\n | \"insertTranspose\" // transpose the last two characters that were entered\n | \"insertCompositionText\" // replace the current composition string\n | \"insertLink\" // insert a link\n | \"deleteWordBackward\" // delete a word directly before the caret position\n | \"deleteWordForward\" // delete a word directly after the caret position\n | \"deleteSoftLineBackward\" // delete from the caret to the nearest visual line break before the caret position\n | \"deleteSoftLineForward\" // delete from the caret to the nearest visual line break after the caret position\n | \"deleteEntireSoftLine\" // delete from to the nearest visual line break before the caret position to the nearest visual line break after the caret position\n | \"deleteHardLineBackward\" // delete from the caret to the nearest beginning of a block element or br element before the caret position\n | \"deleteHardLineForward\" // delete from the caret to the nearest end of a block element or br element after the caret position\n | \"deleteByDrag\" // remove content from the DOM by means of drag\n | \"deleteByCut\" // remove the current selection as part of a cut\n | \"deleteContent\" // delete the selection without specifying the direction of the deletion and this intention is not covered by another inputType\n | \"deleteContentBackward\" // delete the content directly before the caret position and this intention is not covered by another inputType or delete the selection with the selection collapsing to its start after the deletion\n | \"deleteContentForward\" // delete the content directly after the caret position and this intention is not covered by another inputType or delete the selection with the selection collapsing to its end after the deletion\n | \"historyUndo\" // undo the last editing action\n | \"historyRedo\" // to redo the last undone editing action\n | \"formatBold\" // initiate bold text\n | \"formatItalic\" // initiate italic text\n | \"formatUnderline\" // initiate underline text\n | \"formatStrikeThrough\" // initiate stricken through text\n | \"formatSuperscript\" // initiate superscript text\n | \"formatSubscript\" // initiate subscript text\n | \"formatJustifyFull\" // make the current selection fully justified\n | \"formatJustifyCenter\" // center align the current selection\n | \"formatJustifyRight\" // right align the current selection\n | \"formatJustifyLeft\" // left align the current selection\n | \"formatIndent\" // indent the current selection\n | \"formatOutdent\" // outdent the current selection\n | \"formatRemove\" // remove all formatting from the current selection\n | \"formatSetBlockTextDirection\" // set the text block direction\n | \"formatSetInlineTextDirection\" // set the text inline direction\n | \"formatBackColor\" // change the background color\n | \"formatFontColor\" // change the font color\n | \"formatFontName\" // change the font-family\n // Legacy events older Chrome/Safari may dispatch\n // https://github.com/w3c/input-events/pull/122\n | \"deleteCompositionText\"\n | \"deleteByComposition\"\n | \"insertFromComposition\";\n\ntype EditorCommand<A extends unknown[], T extends DocNode = DocNode> = (\n editor: Editor<T>,\n ...args: A\n) => void | undefined;\n\ntype EditorQuery<A extends unknown[], V, T extends DocNode = DocNode> = (\n editor: Editor<T>,\n ...args: A\n) => V;\n\n/**\n * Options of {@link createEditor}.\n */\nexport interface EditorOptions<\n T extends DocNode,\n S extends StandardSchemaV1<T, T> | void = void,\n> {\n /**\n * Optional [Standard Schema](https://github.com/standard-schema/standard-schema) to validate unsafe edits.\n */\n schema?: S;\n /**\n * Initial document.\n */\n doc: T;\n /**\n * The state editable or not.\n */\n readonly?: boolean;\n /**\n * Functions to handle keyboard events.\n *\n * Return `true` if you want to stop propagation.\n */\n keyboard?: KeyboardHook[];\n /**\n * Functions to handle copy events\n * @default [plainCopy()]\n */\n copy?: [CopyHook, ...rest: CopyHook[]];\n /**\n * Functions to handle paste / drop events\n * @default [plainPaste()]\n */\n paste?: [PasteHook, ...rest: PasteHook[]];\n /**\n * TODO\n */\n isBlock?: (node: HTMLElement) => boolean;\n /**\n * Callback invoked when document changes.\n */\n onChange: (doc: T) => void;\n /**\n * Callback invoked when errors happen.\n *\n * @default console.error\n */\n onError?: (message: string) => void;\n}\n\ntype EditorEventMap = {\n change: () => void;\n selectionchange: () => void;\n readonly: () => void;\n};\n\ntype EditorHookMap = {\n apply: (op: Operation, next: (op?: Operation) => void) => void;\n mount: (element: HTMLElement) => void | (() => void);\n keyboard: KeyboardHook;\n};\n\n/**\n * The editor instance.\n */\nexport interface Editor<T extends DocNode = DocNode> {\n readonly doc: T;\n selection: Selection;\n /**\n * The getter/setter for the editor's read-only state.\n * `true` to read-only. `false` to editable.\n */\n readonly: boolean;\n /**\n * Dispatches editing operations.\n * @param tr {@link Transaction}\n */\n apply(tr: Transaction): this;\n /**\n * Executes a function with editor bound as context.\n * @param fn {@link EditorCommand} or {@link EditorQuery}\n * @param args arguments of the function\n */\n exec<A extends unknown[]>(fn: EditorCommand<A, T>, ...args: A): this;\n exec<A extends unknown[], V>(fn: EditorQuery<A, V, T>, ...args: A): V;\n /**\n * A function to subscribe editor events.\n * @returns cleanup function\n */\n on<K extends keyof EditorEventMap>(\n key: K,\n callback: EditorEventMap[K],\n ): () => void;\n /**\n * A function to register editor hooks.\n * @returns cleanup function\n */\n hook<K extends keyof EditorHookMap>(\n key: K,\n callback: EditorHookMap[K],\n ): () => void;\n /**\n * A function to make DOM editable.\n * @returns A function to stop subscribing DOM changes and restores previous DOM state.\n */\n input: (element: HTMLElement) => () => void;\n}\n\n/**\n * A function to initialize {@link Editor}.\n */\nexport const createEditor = <\n T extends DocNode,\n S extends StandardSchemaV1<T, T> | void = void,\n>({\n doc,\n readonly = false,\n schema,\n keyboard,\n copy: copyHooks = [plainCopy()],\n paste: pasteHooks = [plainPaste()],\n isBlock = defaultIsBlockNode,\n onChange,\n onError = console.error,\n}: EditorOptions<T, S>): Editor<T> => {\n let selection: Selection = [0, 0];\n\n const validate = (value: T, onError: (m: string) => void): boolean => {\n if (!schema) {\n onError(\n \"An unsafe operation was detected. We recommend using schema option.\",\n );\n return true;\n }\n const result = schema[\"~standard\"].validate(value);\n if (result instanceof Promise) {\n onError(\"async validate is not supported.\");\n } else if (result.issues) {\n onError(result.issues.map((i) => i.message).join(\"\\n\"));\n } else {\n return true;\n }\n return false;\n };\n\n let initialError: string | undefined;\n if (\n !validate(doc, (m) => {\n initialError = m;\n }) &&\n initialError\n ) {\n throw new Error(initialError);\n }\n\n const hooks = new Map<\n keyof EditorHookMap,\n EditorHookMap[keyof EditorHookMap][]\n >();\n\n const getHook = <T extends keyof EditorHookMap>(\n key: T,\n ): readonly EditorHookMap[T][] => {\n return (hooks.get(key) || empty) as unknown as EditorHookMap[T][];\n };\n\n const subs = new Map<\n keyof EditorEventMap,\n [cbs: Set<EditorEventMap[keyof EditorEventMap]>, queued: boolean]\n >();\n\n const publish = <K extends keyof EditorEventMap>(key: K) => {\n const sub = subs.get(key);\n if (sub && !sub[1]) {\n sub[1] = true;\n microtask(() => {\n sub[1] = false;\n sub[0].forEach((cb) => {\n cb();\n });\n });\n }\n };\n\n const apply = (tr: Transaction) => {\n if (!readonly) {\n const currentDoc = doc;\n const applyHooks = getHook(\"apply\");\n const length = applyHooks.length;\n\n for (let op of tr.ops) {\n let index = 0;\n\n const dispatch = () => {\n if (index < length) {\n const i = index;\n applyHooks[index]!(op, next);\n if (i === index) {\n next();\n }\n } else if (index === length) {\n index++;\n\n try {\n const [nextDoc, nextSelection] = applyOperation(\n doc,\n selection,\n op,\n );\n if (!isUnsafeOperation(op) || validate(nextDoc, onError)) {\n doc = nextDoc;\n selection = nextSelection;\n }\n } catch (e) {\n // rollback\n onError(\"rollback operation: \" + e);\n }\n }\n };\n\n const next = (o?: Operation): void => {\n if (o) {\n op = o;\n }\n index++;\n dispatch();\n };\n\n dispatch();\n }\n\n if (!is(currentDoc, doc)) {\n publish(\"change\");\n }\n }\n };\n\n const updateSelection = (s: Selection) => {\n if (\n isValidSelection(doc, s) &&\n (selection[0] !== s[0] || selection[1] !== s[1])\n ) {\n selection = s;\n publish(\"selectionchange\");\n }\n };\n\n const editor: Editor<T> = {\n get doc() {\n return doc;\n },\n get selection() {\n return selection;\n },\n set selection(value) {\n updateSelection(value);\n },\n get readonly() {\n return readonly;\n },\n set readonly(value) {\n readonly = value;\n publish(\"readonly\");\n },\n apply: (tr: Transaction) => {\n apply(tr);\n return editor;\n },\n on: (type, callback) => {\n let sub = subs.get(type);\n if (!sub) {\n subs.set(type, (sub = [new Set(), false]));\n }\n const cbs = sub[0];\n cbs.add(callback);\n return () => {\n cbs.delete(callback);\n };\n },\n hook: (type, callback) => {\n let sub = hooks.get(type);\n if (!sub) {\n hooks.set(type, (sub = []));\n }\n sub.push(callback);\n return () => {\n const i = sub.indexOf(callback);\n if (i !== -1) {\n sub.splice(i, 1);\n }\n };\n },\n exec: (\n fn: EditorCommand<any, T> | EditorQuery<any, unknown, T>,\n ...args: unknown[]\n ): any => {\n const result = fn(editor, ...args);\n if (typeof result === \"undefined\") {\n return editor;\n }\n return result;\n },\n input: (element) => {\n if (\n !(window.InputEvent && isFunction(InputEvent.prototype.getTargetRanges))\n ) {\n onError(\"beforeinput event is not supported.\");\n return noop;\n }\n\n // https://w3c.github.io/contentEditable/\n // https://w3c.github.io/editing/docs/execCommand/\n // https://w3c.github.io/selection-api/\n const {\n contentEditable: prevContentEditable,\n role: prevRole,\n ariaMultiLine: prevAriaMultiLine,\n ariaReadOnly: prevAriaReadOnly,\n } = element;\n const prevWhiteSpace = element.style.whiteSpace;\n\n element.role = \"textbox\";\n // https://html.spec.whatwg.org/multipage/interaction.html#best-practices-for-in-page-editors\n element.style.whiteSpace = \"pre-wrap\";\n element.ariaMultiLine = \"true\";\n\n let disposed = false;\n let inputTransaction: [Transaction, Selection] | null = null;\n let isComposing = false;\n let hasFocus = false;\n let isDragging = false;\n\n const document = getCurrentDocument(element);\n\n const parser = createParser({\n _document: document,\n _isBlock: isBlock as (node: Element) => boolean,\n _isVoid: defaultIsVoidNode,\n });\n\n const setEditableState = () => {\n element.contentEditable = readonly ? \"false\" : \"true\";\n element.ariaReadOnly = readonly ? \"true\" : null;\n };\n\n setEditableState();\n\n const cleanupOnChange = editor.on(\"change\", () => {\n if (!hasFocus) {\n requestAnimationFrame(() => {\n if (!hasFocus) {\n // Set focus imperatively to return focus to the editor after a command execution via click.\n // It must be queued after the MO callback because that may cause an additional selectionchange event.\n element.focus({ preventScroll: true });\n }\n });\n }\n });\n const cleanupOnReadonly = editor.on(\"readonly\", setEditableState);\n\n const paste = (dataTransfer: DataTransfer): string | Fragment | void => {\n for (const ex of pasteHooks) {\n const pasted = ex(dataTransfer, parser);\n if (pasted) {\n return pasted;\n }\n }\n onError(\"failed to serialize pasted data\");\n };\n\n const observer = createMutationObserver(element, () => {\n // TODO optimize\n // Mutation to selected DOM may change selection, so restore it.\n setSelectionToDOM(\n document,\n element,\n selectionToDomSelection(doc, selection),\n selection[0] - selection[1],\n parser,\n );\n });\n\n const syncSelection = () => {\n updateSelection(\n domSelectionToSelection(doc, takeSelectionSnapshot(element, parser)),\n );\n };\n\n const flushInput = () => {\n const queue = observer._flush();\n\n observer._record(false);\n\n if (queue.length) {\n observer._revert(queue);\n\n // Restore previous selection\n // Updating selection may schedule the next selectionchange event\n // It should be ignored especially in firefox not to confuse editor state\n document.removeEventListener(\"selectionchange\", onSelectionChange);\n setSelectionToDOM(\n document,\n element,\n selectionToDomSelection(doc, selection),\n selection[0] - selection[1],\n parser,\n true,\n );\n document.addEventListener(\"selectionchange\", onSelectionChange);\n }\n\n if (inputTransaction) {\n updateSelection(inputTransaction[1]);\n apply(inputTransaction[0]);\n inputTransaction = null;\n }\n isComposing = false;\n };\n\n // spec compliant: keydown -> beforeinput -> input (-> keyup)\n // Safari (IME) : beforeinput -> input -> keydown (-> keyup)\n // https://w3c.github.io/uievents/#events-keyboard-event-order\n // https://bugs.webkit.org/show_bug.cgi?id=165004\n const onKeyDown = (e: KeyboardEvent) => {\n if (isComposing) return;\n\n for (const handler of getHook(\"keyboard\")) {\n if (handler(e)) {\n e.preventDefault();\n observer._record(false);\n return;\n }\n }\n };\n\n const onInput = () => {\n if (!isComposing) {\n flushInput();\n }\n };\n const onBeforeInput = (e: InputEvent) => {\n e.preventDefault();\n\n const inputType = e.inputType as InputType;\n\n if (inputType.startsWith(\"format\")) {\n // Ignore format inputs from document.execCommand() or shortcuts like mod+b.\n return;\n }\n if (inputType === \"historyUndo\" || inputType === \"historyRedo\") {\n // Cancel for now.\n return;\n }\n\n if (isComposing) {\n // Unfortunately, input events related to composition are not cancellable.\n // So we record mutations to DOM and revert them after composition ended.\n observer._record(true);\n } else {\n syncSelection();\n }\n\n const domRange = e.getTargetRanges()[0];\n if (domRange) {\n // Read input\n const range = domSelectionToSelection(\n doc,\n serializeRange(element, parser, domRange),\n );\n let data =\n inputType === \"insertParagraph\" || inputType === \"insertLineBreak\"\n ? \"\\n\"\n : e.data;\n if (data == null) {\n const dataTransfer = e.dataTransfer;\n if (dataTransfer) {\n // In some cases (e.g. insertReplacementText), dataTransfer contains text.\n data = dataTransfer.getData(\"text/plain\");\n }\n }\n\n let tr: Transaction;\n if (!inputTransaction) {\n inputTransaction = [new Transaction(), selection];\n }\n tr = inputTransaction[0];\n if (!isCollapsed(range)) {\n // replace or delete\n tr.delete(...range);\n }\n if (data) {\n // replace or insert\n tr.insertText(range[0], data);\n }\n }\n\n if (!isComposing) {\n flushInput();\n }\n };\n const onCompositionStart = () => {\n if (!isComposing) {\n syncSelection();\n }\n isComposing = true;\n };\n const onCompositionEnd = () => {\n flushInput();\n };\n\n const onFocus = () => {\n hasFocus = true;\n syncSelection();\n };\n const onBlur = () => {\n hasFocus = false;\n };\n\n const onSelectionChange = () => {\n // Safari may dispatch selectionchange event after dragstart\n if (hasFocus && !isComposing && !isDragging) {\n syncSelection();\n }\n };\n\n const copy = (dataTransfer: DataTransfer) => {\n syncSelection();\n if (!isCollapsed(selection)) {\n const fragment = sliceFragment(doc, ...toRange(selection));\n for (const ex of copyHooks) {\n ex(dataTransfer, fragment, element);\n }\n }\n };\n\n const onCopy = (e: ClipboardEvent) => {\n e.preventDefault();\n copy(e.clipboardData!);\n };\n const onCut = (e: ClipboardEvent) => {\n e.preventDefault();\n if (!readonly) {\n copy(e.clipboardData!);\n apply(new Transaction().delete(...toRange(selection)));\n }\n };\n const onPaste = (e: ClipboardEvent) => {\n e.preventDefault();\n const pasted = paste(e.clipboardData!);\n if (pasted) {\n const [start, end] = toRange(selection);\n const tr = new Transaction().delete(start, end);\n if (isString(pasted)) {\n tr.insertText(start, pasted);\n } else {\n tr.insertFragment(start, pasted);\n }\n apply(tr);\n }\n };\n\n const onDrop = (e: DragEvent) => {\n e.preventDefault();\n\n const dataTransfer = e.dataTransfer;\n const droppedPosition = getPointedCaretPosition(\n document,\n element,\n e,\n parser,\n );\n if (dataTransfer && droppedPosition) {\n let afterSelection: Selection | undefined;\n const tr = new Transaction();\n if (isDragging) {\n tr.delete(...toRange(selection));\n }\n const pasted = paste(dataTransfer);\n if (pasted) {\n const offset = positionToOffset(doc, droppedPosition);\n const pos = tr.transform(offset);\n if (isString(pasted)) {\n tr.insertText(pos, pasted);\n } else {\n tr.insertFragment(pos, pasted);\n }\n afterSelection = [pos, tr.transform(offset)];\n }\n apply(tr);\n if (afterSelection) {\n updateSelection(afterSelection);\n }\n }\n };\n const onDragStart = (e: DragEvent) => {\n isDragging = true;\n copy(e.dataTransfer!);\n };\n const onDragEnd = () => {\n isDragging = false;\n };\n\n document.addEventListener(\"selectionchange\", onSelectionChange);\n element.addEventListener(\"keydown\", onKeyDown);\n element.addEventListener(\"input\", onInput);\n element.addEventListener(\"beforeinput\", onBeforeInput);\n element.addEventListener(\"compositionstart\", onCompositionStart);\n element.addEventListener(\"compositionend\", onCompositionEnd);\n element.addEventListener(\"focus\", onFocus);\n element.addEventListener(\"blur\", onBlur);\n element.addEventListener(\"copy\", onCopy);\n element.addEventListener(\"cut\", onCut);\n element.addEventListener(\"paste\", onPaste);\n element.addEventListener(\"drop\", onDrop);\n element.addEventListener(\"dragstart\", onDragStart);\n element.addEventListener(\"dragend\", onDragEnd);\n\n const mountHooks = getHook(\"mount\");\n const unmountHooks: (() => void)[] = [];\n mountHooks.forEach((mount) => {\n const cb = mount(element);\n if (cb) {\n unmountHooks.push(cb);\n }\n });\n\n return () => {\n if (disposed) return;\n disposed = true;\n\n cleanupOnChange();\n cleanupOnReadonly();\n\n element.contentEditable = prevContentEditable;\n element.role = prevRole;\n element.ariaMultiLine = prevAriaMultiLine;\n element.ariaReadOnly = prevAriaReadOnly;\n element.style.whiteSpace = prevWhiteSpace;\n\n observer._dispose();\n\n document.removeEventListener(\"selectionchange\", onSelectionChange);\n element.removeEventListener(\"keydown\", onKeyDown);\n element.removeEventListener(\"input\", onInput);\n element.removeEventListener(\"beforeinput\", onBeforeInput);\n element.removeEventListener(\"compositionstart\", onCompositionStart);\n element.removeEventListener(\"compositionend\", onCompositionEnd);\n element.removeEventListener(\"focus\", onFocus);\n element.removeEventListener(\"blur\", onBlur);\n element.removeEventListener(\"copy\", onCopy);\n element.removeEventListener(\"cut\", onCut);\n element.removeEventListener(\"paste\", onPaste);\n element.removeEventListener(\"drop\", onDrop);\n element.removeEventListener(\"dragstart\", onDragStart);\n element.removeEventListener(\"dragend\", onDragEnd);\n\n unmountHooks.forEach((cb) => {\n cb();\n });\n };\n },\n };\n\n editor.exec(historyPlugin);\n\n editor.on(\"change\", () => {\n onChange(doc);\n });\n\n if (keyboard) {\n keyboard.forEach((h) => {\n editor.hook(\"keyboard\", h);\n });\n }\n\n return editor;\n};\n","import type { PasteHook } from \"./types.js\";\n\n/**\n * An extension to handle pasting / dropping from plain text.\n */\nexport const plainPaste = (): PasteHook => {\n return (dataTransfer) => {\n return dataTransfer.getData(\"text/plain\");\n };\n};\n","/**\n * @internal\n */\nexport const createMutationObserver = (\n element: Element,\n onMutationIgnored: () => void,\n) => {\n let isInputing = false;\n\n const queue: MutationRecord[] = [];\n const process = (records: MutationRecord[]) => {\n if (isInputing) {\n queue.push(...records);\n }\n };\n // https://dom.spec.whatwg.org/#interface-mutationobserver\n const mo = new MutationObserver((records) => {\n process(records);\n if (!isInputing) {\n onMutationIgnored();\n }\n });\n\n const sync = () => {\n process(mo.takeRecords());\n };\n\n const flush = (): MutationRecord[] => {\n sync();\n return queue.splice(0);\n };\n\n mo.observe(element, {\n characterData: true,\n characterDataOldValue: true,\n childList: true,\n subtree: true,\n });\n\n return {\n _revert: (records: MutationRecord[]) => {\n let m: MutationRecord | undefined;\n while ((m = records.pop())) {\n if (m.type === \"childList\") {\n const { target, removedNodes, addedNodes, nextSibling } = m;\n for (let i = removedNodes.length - 1; i >= 0; i--) {\n target.insertBefore(removedNodes[i]!, nextSibling);\n }\n for (let i = addedNodes.length - 1; i >= 0; i--) {\n target.removeChild(addedNodes[i]!);\n }\n } else {\n (m.target as CharacterData).data = m.oldValue!;\n }\n }\n flush();\n },\n _record: (enable: boolean) => {\n if (!isInputing && enable) {\n sync();\n }\n isInputing = enable;\n },\n _flush: flush,\n _dispose: () => {\n queue.splice(0);\n mo.disconnect();\n },\n };\n};\n","import { joinBlocks } from \"../doc/edit.js\";\nimport type { Editor } from \"../editor.js\";\n\nexport function singlelinePlugin(editor: Editor) {\n editor.hook(\"mount\", (element) => {\n element.ariaMultiLine = null;\n });\n editor.hook(\"apply\", (op, next) => {\n if (op.type === \"insert_text\") {\n op = {\n ...op,\n text: op.text.replaceAll(\"\\n\", \"\"),\n };\n } else if (op.type === \"insert_node\") {\n op = {\n ...op,\n fragment: [joinBlocks(...op.fragment)],\n };\n }\n next(op);\n });\n}\n","import { docToString, stringToFragment } from \"../doc/utils.js\";\nimport { createEditor, type Editor, type EditorOptions } from \"../editor.js\";\nimport { singlelinePlugin } from \"../plugins/index.js\";\n\ntype PlainDoc = { children: { children: { text: string }[] }[] };\n\nexport interface PlainEditorOptions extends Omit<\n EditorOptions<PlainDoc>,\n \"doc\" | \"schema\" | \"onChange\"\n> {\n /**\n * Initial document text.\n */\n text: string;\n /**\n * TODO\n */\n singleline?: boolean;\n /**\n * Callback invoked when document changes.\n */\n onChange: (text: string) => void;\n}\n\n/**\n * A function to initialize editor with plaintext.\n */\nexport const createPlainEditor = ({\n text,\n singleline,\n onChange,\n ...opts\n}: PlainEditorOptions): Editor<PlainDoc> => {\n const editor = createEditor({\n ...opts,\n doc: { children: stringToFragment(text) },\n onChange: (doc) => {\n onChange(docToString(doc));\n },\n });\n if (singleline) {\n editor.exec(singlelinePlugin);\n }\n return editor;\n};\n","import type { Editor } from \"../editor.js\";\n\nexport function debugPlugin(editor: Editor) {\n editor.hook(\"apply\", (op) => {\n console.log(\"apply\", op);\n });\n editor.on(\"change\", () => {\n console.log(\"change\", editor.doc);\n });\n editor.on(\"selectionchange\", () => {\n console.log(\"selectionchange\", editor.selection);\n });\n}\n","import type { InlineNode } from \"../../doc/types.js\";\nimport type { PasteHook } from \"./types.js\";\n\n/**\n * An extension to handle pasting / dropping from File.\n */\nexport const filePaste = (\n handlerByMime: Record<string, (file: File) => InlineNode>,\n): PasteHook => {\n return (dataTransfer) => {\n for (const item of dataTransfer.items) {\n if (item.kind === \"file\") {\n const mapper = handlerByMime[item.type];\n if (mapper) {\n const file = item.getAsFile();\n if (file) {\n return [{ children: [mapper(file)] }];\n }\n }\n }\n }\n return null;\n };\n};\n","import { getDOMSelection, getSelectionRangeInEditor } from \"../../dom/index.js\";\nimport type { CopyHook } from \"./types.js\";\n\n/**\n * An extension to handle copying to HTML.\n */\nexport const htmlCopy = (): CopyHook => {\n return (dataTransfer, _, element) => {\n const wrapper = document.createElement(\"div\");\n wrapper.appendChild(\n // DOM range must exist here\n getSelectionRangeInEditor(\n getDOMSelection(element),\n element,\n )!.cloneContents(),\n );\n dataTransfer.setData(\"text/html\", wrapper.innerHTML);\n };\n};\n","import type { DocNode, InferInlineNode, TextNode } from \"../../doc/types.js\";\nimport { domToFragment } from \"../../dom/index.js\";\nimport { isCommentNode } from \"../../dom/parser.js\";\nimport type { PasteHook } from \"./types.js\";\n\n/**\n * An extension to handle pasting / dropping from HTML.\n */\nexport const htmlPaste = <T extends DocNode>(\n serializeText: (t: string) => Extract<InferInlineNode<T>, TextNode>,\n serializers: ((\n node: HTMLElement,\n ) => Exclude<InferInlineNode<T>, TextNode> | void)[] = [],\n): PasteHook => {\n return (dataTransfer, parse) => {\n const html = dataTransfer.getData(\"text/html\");\n if (html) {\n let dom: Node = new DOMParser().parseFromString(html, \"text/html\").body;\n let isWindowsCopy = false;\n // https://github.com/w3c/clipboard-apis/issues/193\n for (const n of [...dom.childNodes]) {\n if (isCommentNode(n)) {\n if (n.data === \"StartFragment\") {\n isWindowsCopy = true;\n dom = new DocumentFragment();\n } else if (n.data === \"EndFragment\") {\n isWindowsCopy = false;\n }\n } else if (isWindowsCopy) {\n dom.appendChild(n);\n }\n }\n\n // TODO customizable dom to standard schema and validate\n return domToFragment(dom, parse, serializeText, (n) => {\n for (const s of serializers) {\n const node = s(n as HTMLElement);\n if (node) {\n return node;\n }\n }\n return;\n });\n }\n return null;\n };\n};\n","import { INTERNAL_COPY_KEY } from \"../utils.js\";\nimport type { CopyHook } from \"./types.js\";\n\n/**\n * An extension to handle copying to editor instance.\n */\nexport const internalCopy = ({\n key = INTERNAL_COPY_KEY,\n}: {\n key?: string;\n} = {}): CopyHook => {\n return (dataTransfer, data) => {\n dataTransfer.setData(key, JSON.stringify(data));\n };\n};\n","import { INTERNAL_COPY_KEY } from \"../utils.js\";\nimport type { PasteHook } from \"./types.js\";\n\n/**\n * An extension to handle pasting / dropping from editor instance.\n */\nexport const internalPaste = ({\n key = INTERNAL_COPY_KEY,\n}: { key?: string } = {}): PasteHook => {\n return (dataTransfer) => {\n try {\n return JSON.parse(dataTransfer.getData(key));\n } catch (e) {\n return null;\n }\n };\n};\n"],"names":["min","Math","keys","is","Object","isString","n","isFunction","microtask","queueMicrotask","fn","Promise","resolve","then","docToString","doc","serializer","isTextNode","text","children","reduce","acc","r","i","isBlock","isBlockNode","stringToFragment","node","block","split","map","l","OP_DELETE","OP_INSERT_TEXT","OP_INSERT_NODE","OP_SET_ATTR","OP_SET_NODE_ATTR","isUnsafeOperation","type","Transaction","_ops","constructor","ops","this","slice","insertText","at","push","insertFragment","fragment","start","end","format","key","value","attr","path","transform","position","op","rebasePosition","isSameNode","a","b","aKeys","length","every","k","sizeCache","WeakMap","calcBlockSize","size","count","getNodeSize","get","set","positionToOffset","offset","p","offsetToPosition","found","getChildAt","index","_index","nextNode","_node","_offset","domSelectionToSelection","anchor","focus","selectionToDomSelection","normalizeInline","array","prev","curr","splice","normalizeBlock","joinBlocks","concat","normalize","prevLength","blocks","splitBlock","pos","target","offsetAtNode","childBefore","childAfter","before","after","unshift","beforeText","afterText","getNodeAt","replaceNodeAt","afterNode","lines","sliced","replace","replaceRange","inserted","maybeAfter","sliceFragment","isValidPosition","rebaseSelection","applyOperation","selection","res","anchorNode","toRange","isCollapsed","ReplaceDoc","editor","apply","delete","walker","_token","config","parse","isElementNode","nodeType","isCommentNode","getDomNode","token","readToken","data","isValidSoftBreak","tagName","_isVoid","_isBlock","nextBlock","nextSibling","parentBlock","parentNode","parent","contains","readNext","current","t","SINGLE_LINE_CONTAINER_NAMES","Set","defaultIsBlockNode","has","EMBEDDED_CONTENT_TAG_NAMES","defaultIsVoidNode","contentEditable","compareDomPosition","compareDocumentPosition","getCurrentDocument","ownerDocument","getDOMSelection","element","getSelection","getSelectionRangeInEditor","root","rangeCount","range","getRangeAt","commonAncestorContainer","setRangeToSelection","force","backward","removeAllRanges","addRange","collapseToEnd","extend","startContainer","startOffset","setSelectionToDOM","document","posDiff","hasChildNodes","createRange","setStart","setEnd","domStart","findPosition","domEnd","startNode","endNode","endOffset","setStartBefore","setStartAfter","setEndBefore","setEndAfter","pathIndex","next","blockIndex","serializePosition","excludeEnd","childNodes","sib","previousElementSibling","comp","serializeRange","endContainer","plainCopy","dataTransfer","setData","INTERNAL_COPY_KEY","hotkey","cb","mod","shift","alt","toLowerCase","e","ctrlKey","metaKey","shiftKey","altKey","historyPlugin","prevTime","undoOrRedoing","now","Date","histories","hook","newDoc","time","history","sel","currentDoc","exec","empty","noop","createEditor","readonly","schema","keyboard","copy","copyHooks","paste","pasteHooks","getData","onChange","onError","console","error","validate","result","issues","message","join","initialError","m","Error","hooks","Map","getHook","subs","publish","sub","forEach","tr","applyHooks","dispatch","nextDoc","nextSelection","o","updateSelection","s","isValidSelection","on","callback","cbs","add","indexOf","args","input","window","InputEvent","prototype","getTargetRanges","prevContentEditable","role","prevRole","ariaMultiLine","prevAriaMultiLine","ariaReadOnly","prevAriaReadOnly","prevWhiteSpace","style","whiteSpace","disposed","inputTransaction","isComposing","hasFocus","isDragging","parser","initConfig","scopeFn","prevConfig","prevParse","prevWalker","prevNode","prevToken","_document","createTreeWalker","SHOW_TEXT","currentNode","createParser","setEditableState","cleanupOnChange","requestAnimationFrame","preventScroll","cleanupOnReadonly","ex","pasted","observer","onMutationIgnored","isInputing","queue","process","records","mo","MutationObserver","sync","takeRecords","flush","observe","characterData","characterDataOldValue","childList","subtree","_revert","pop","removedNodes","addedNodes","insertBefore","removeChild","oldValue","_record","enable","_flush","_dispose","disconnect","createMutationObserver","syncSelection","domRange","focusNode","anchorOffset","focusOffset","takeSelectionSnapshot","flushInput","removeEventListener","onSelectionChange","addEventListener","onKeyDown","handler","preventDefault","onInput","onBeforeInput","inputType","startsWith","onCompositionStart","onCompositionEnd","onFocus","onBlur","onCopy","clipboardData","onCut","onPaste","onDrop","droppedPosition","clientX","clientY","caretPositionFromPoint","offsetNode","caretRangeFromPoint","getPointedCaretPosition","afterSelection","onDragStart","onDragEnd","mountHooks","unmountHooks","mount","h","singlelinePlugin","replaceAll","onValue","offValue","texts","flatMap","filter","some","singleline","opts","log","handlerByMime","item","items","kind","mapper","file","getAsFile","_","wrapper","createElement","appendChild","cloneContents","innerHTML","serializeText","serializers","html","dom","DOMParser","parseFromString","body","isWindowsCopy","DocumentFragment","serializeVoid","row","hasContent","rows","completeText","completeRow","docNode","domToFragment","JSON","stringify"],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export { Transaction } from "./doc/edit.js";
2
+ export { Delete, InsertText, InsertNode, ReplaceText, ReplaceDoc, Format, ToggleFormat, SetBlockAttr, ToggleBlockAttr, } from "./commands.js";
3
+ export { createEditor } from "./editor.js";
4
+ export type { EditorOptions, Editor } from "./editor.js";
5
+ export * from "./hooks/index.js";
6
+ export * from "./presets/index.js";
7
+ export * from "./plugins/index.js";