@contember/react-slate-editor-base 2.1.0-beta.1 → 2.1.0-rc.1

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.
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const Slate = require("slate");
3
4
  const ignoredElements = ["SCRIPT", "STYLE", "TEMPLATE"];
4
5
  class HtmlDeserializer {
5
6
  constructor(createDefaultElement, plugins) {
@@ -49,7 +50,7 @@ class HtmlDeserializer {
49
50
  return {
50
51
  elements: processed.flatMap((item) => {
51
52
  if (item.text !== void 0) {
52
- return item.isWhiteSpace ? [] : [this.createDefaultElement([item.text])];
53
+ return item.isWhiteSpace ? [] : [this.createDefaultElement(this.trimBlockBoundaryWhitespace([item.text]))];
53
54
  } else if (item.element !== void 0) {
54
55
  return [item.element];
55
56
  }
@@ -73,7 +74,39 @@ class HtmlDeserializer {
73
74
  }
74
75
  deserializeBlocks(list, cumulativeTextAttrs) {
75
76
  const result = this.processNodeListPaste(list, cumulativeTextAttrs);
76
- return result?.texts ?? result?.elements ?? [];
77
+ if (result?.texts !== void 0) {
78
+ return this.trimBlockBoundaryWhitespace(result.texts);
79
+ }
80
+ return result?.elements ?? [];
81
+ }
82
+ // Collapsible whitespace at the start/end of a block renders as nothing in HTML,
83
+ // so strip it from the edges of a block's inline content. Non-breaking spaces are kept.
84
+ trimBlockBoundaryWhitespace(texts) {
85
+ const trimmed = [...texts];
86
+ const trimEdge = (direction) => {
87
+ for (let i = direction === "start" ? 0 : trimmed.length - 1; i >= 0 && i < trimmed.length; ) {
88
+ const node = trimmed[i];
89
+ if (!Slate.Text.isText(node)) {
90
+ return;
91
+ }
92
+ const text = direction === "start" ? node.text.replace(/^[ \t\r\n]+/, "") : node.text.replace(/[ \t\r\n]+$/, "");
93
+ if (text !== "") {
94
+ trimmed[i] = { ...node, text };
95
+ return;
96
+ }
97
+ if (trimmed.length === 1) {
98
+ trimmed[i] = { ...node, text };
99
+ return;
100
+ }
101
+ trimmed.splice(i, 1);
102
+ if (direction === "end") {
103
+ i--;
104
+ }
105
+ }
106
+ };
107
+ trimEdge("start");
108
+ trimEdge("end");
109
+ return trimmed;
77
110
  }
78
111
  deserializeTextNode(node, cumulativeTextAttrs) {
79
112
  if (node.nodeType === Node.TEXT_NODE) {
@@ -1 +1 @@
1
- {"version":3,"file":"HtmlDeserializer.cjs","sources":["../../../../../../../packages/react-slate-editor-base/src/plugins/behaviour/paste/HtmlDeserializer.ts"],"sourcesContent":["import { Descendant, Element as SlateElement, Text as SlateText } from 'slate'\nimport { HtmlDeserializerNextCallback, HtmlDeserializerPlugin } from '../../../types/htmlDeserializer'\nimport { EditorDefaultElementFactory } from '../../../types/editor'\n\nconst ignoredElements = ['SCRIPT', 'STYLE', 'TEMPLATE']\n\nexport interface TextAttrs {\n\t[key: string]: any\n}\n\nexport type NodesWithTypeFiltered =\n\t| { texts: Descendant[]; elements?: undefined }\n\t| { elements: SlateElement[]; texts?: undefined }\n\nexport type NodesWithType = NodesWithTypeFiltered | null\n\nexport class HtmlDeserializer {\n\tconstructor(\n\t\tpublic createDefaultElement: EditorDefaultElementFactory,\n\t\tprivate plugins: HtmlDeserializerPlugin[],\n\t) {\n\t}\n\n\tregisterPlugin(plugin: HtmlDeserializerPlugin, prepend: boolean = true) {\n\t\tprepend ? this.plugins.unshift(plugin) : this.plugins.push(plugin)\n\t}\n\n\tpublic processNodeListPaste(nodeList: Node[], cumulativeTextAttrs: TextAttrs) {\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processNodeListPaste?.({ nodeList, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\tconst processed: (\n\t\t\t| { text: SlateText | SlateElement; element?: undefined; isWhiteSpace: boolean }\n\t\t\t| { element: SlateElement; text?: undefined }\n\t\t)[] = []\n\n\t\tfor (const childNode of nodeList) {\n\t\t\tconst isWhiteSpace = childNode.nodeType === Node.TEXT_NODE && childNode.textContent?.match(/^\\s*$/) !== null\n\n\t\t\t// Block\n\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\tconst result = childNode instanceof HTMLElement\n\t\t\t\t? this.processBlockPaste(\n\t\t\t\t\tchildNode,\n\t\t\t\t\tcumulativeTextAttrs,\n\t\t\t\t)\n\t\t\t\t: null\n\t\t\tif (result !== null) {\n\t\t\t\tprocessed.push(...(Array.isArray(result) ? result : [result]).map(element => ({ element })))\n\t\t\t} else {\n\t\t\t\t// Inline\n\t\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\t\tif (result !== null) {\n\t\t\t\t\tprocessed.push(...result.map(text => ({ text, isWhiteSpace })))\n\t\t\t\t} else {\n\t\t\t\t\t// Unknown element\n\t\t\t\t\tconst deserializedChildren = this.processNodeListPaste(\n\t\t\t\t\t\tArray.from(childNode.childNodes),\n\t\t\t\t\t\tattrs,\n\t\t\t\t\t)\n\t\t\t\t\tprocessed.push(\n\t\t\t\t\t\t...(deserializedChildren === null\n\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t: deserializedChildren.texts !== undefined\n\t\t\t\t\t\t\t? deserializedChildren.texts.map(text => ({ text, isWhiteSpace }))\n\t\t\t\t\t\t\t: deserializedChildren.elements.map(element => ({ element }))),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (processed.length === 0) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst containsBlock = processed.find(({ element }) => element !== undefined) !== undefined\n\n\t\tif (containsBlock) {\n\t\t\treturn {\n\t\t\t\telements: processed.flatMap(item => {\n\t\t\t\t\tif (item.text !== undefined) {\n\t\t\t\t\t\treturn item.isWhiteSpace ? [] : [this.createDefaultElement([item.text])]\n\t\t\t\t\t} else if (item.element !== undefined) {\n\t\t\t\t\t\treturn [item.element]\n\t\t\t\t\t}\n\t\t\t\t\treturn []\n\t\t\t\t}),\n\t\t\t}\n\t\t} else {\n\t\t\treturn { texts: processed.map(item => item.text as SlateText) }\n\t\t}\n\t}\n\n\tdeserializeInline(list: NodeList | Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\treturn Array.from(list).flatMap(childNode => {\n\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t} else {\n\t\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\t\treturn this.deserializeInline(childNode.childNodes, attrs)\n\t\t\t}\n\t\t})\n\t}\n\n\tdeserializeBlocks(list: Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\tconst result = this.processNodeListPaste(list, cumulativeTextAttrs)\n\t\treturn result?.texts ?? result?.elements ?? []\n\t}\n\n\tprivate deserializeTextNode(node: Node, cumulativeTextAttrs: TextAttrs): Descendant[] | null {\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = node.textContent ?? ''\n\t\t\treturn [{ ...cumulativeTextAttrs, text: text.replace(/[ \\t]*(?:\\r?\\n[ \\t]*)+/g, ' ') }]\n\t\t} else if (node instanceof HTMLElement) {\n\t\t\tconst result = this.processInlinePaste(\n\t\t\t\tnode,\n\t\t\t\tcumulativeTextAttrs,\n\t\t\t)\n\t\t\tif (result !== null) {\n\t\t\t\treturn Array.isArray(result) ? result : [result]\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate processInlinePaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): (SlateElement | SlateText)[] | SlateElement | SlateText | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tif (element.tagName === 'BR') {\n\t\t\treturn { ...cumulativeTextAttrs, text: ' ' }\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => {\n\t\t\tconst attrs = this.processWithAttributeProcessor(element, cta)\n\t\t\treturn this.deserializeInline(list, attrs)\n\t\t}\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processInlinePaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n\n\tprivate processWithAttributeProcessor(element: Node, cumulativeTextAttrs: TextAttrs): TextAttrs {\n\t\tif (!(element instanceof HTMLElement)) {\n\t\t\treturn {}\n\t\t}\n\t\treturn this.plugins.reduce(\n\t\t\t(cta, plugin) => plugin.processAttributesPaste?.({ element, cumulativeTextAttrs, deserializer: this }) ?? cta,\n\t\t\tcumulativeTextAttrs,\n\t\t)\n\t}\n\n\tprivate processBlockPaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): SlateElement[] | SlateElement | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => this.deserializeBlocks(Array.from(list), { ...cumulativeTextAttrs, ...cta })\n\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processBlockPaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n}\n"],"names":["result"],"mappings":"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"}
1
+ {"version":3,"file":"HtmlDeserializer.cjs","sources":["../../../../../../../packages/react-slate-editor-base/src/plugins/behaviour/paste/HtmlDeserializer.ts"],"sourcesContent":["import { Descendant, Element as SlateElement, Text as SlateText } from 'slate'\nimport { HtmlDeserializerNextCallback, HtmlDeserializerPlugin } from '../../../types/htmlDeserializer'\nimport { EditorDefaultElementFactory } from '../../../types/editor'\n\nconst ignoredElements = ['SCRIPT', 'STYLE', 'TEMPLATE']\n\nexport interface TextAttrs {\n\t[key: string]: any\n}\n\nexport type NodesWithTypeFiltered =\n\t| { texts: Descendant[]; elements?: undefined }\n\t| { elements: SlateElement[]; texts?: undefined }\n\nexport type NodesWithType = NodesWithTypeFiltered | null\n\nexport class HtmlDeserializer {\n\tconstructor(\n\t\tpublic createDefaultElement: EditorDefaultElementFactory,\n\t\tprivate plugins: HtmlDeserializerPlugin[],\n\t) {\n\t}\n\n\tregisterPlugin(plugin: HtmlDeserializerPlugin, prepend: boolean = true) {\n\t\tprepend ? this.plugins.unshift(plugin) : this.plugins.push(plugin)\n\t}\n\n\tpublic processNodeListPaste(nodeList: Node[], cumulativeTextAttrs: TextAttrs) {\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processNodeListPaste?.({ nodeList, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\tconst processed: (\n\t\t\t| { text: SlateText | SlateElement; element?: undefined; isWhiteSpace: boolean }\n\t\t\t| { element: SlateElement; text?: undefined }\n\t\t)[] = []\n\n\t\tfor (const childNode of nodeList) {\n\t\t\tconst isWhiteSpace = childNode.nodeType === Node.TEXT_NODE && childNode.textContent?.match(/^\\s*$/) !== null\n\n\t\t\t// Block\n\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\tconst result = childNode instanceof HTMLElement\n\t\t\t\t? this.processBlockPaste(\n\t\t\t\t\tchildNode,\n\t\t\t\t\tcumulativeTextAttrs,\n\t\t\t\t)\n\t\t\t\t: null\n\t\t\tif (result !== null) {\n\t\t\t\tprocessed.push(...(Array.isArray(result) ? result : [result]).map(element => ({ element })))\n\t\t\t} else {\n\t\t\t\t// Inline\n\t\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\t\tif (result !== null) {\n\t\t\t\t\tprocessed.push(...result.map(text => ({ text, isWhiteSpace })))\n\t\t\t\t} else {\n\t\t\t\t\t// Unknown element\n\t\t\t\t\tconst deserializedChildren = this.processNodeListPaste(\n\t\t\t\t\t\tArray.from(childNode.childNodes),\n\t\t\t\t\t\tattrs,\n\t\t\t\t\t)\n\t\t\t\t\tprocessed.push(\n\t\t\t\t\t\t...(deserializedChildren === null\n\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t: deserializedChildren.texts !== undefined\n\t\t\t\t\t\t\t? deserializedChildren.texts.map(text => ({ text, isWhiteSpace }))\n\t\t\t\t\t\t\t: deserializedChildren.elements.map(element => ({ element }))),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (processed.length === 0) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst containsBlock = processed.find(({ element }) => element !== undefined) !== undefined\n\n\t\tif (containsBlock) {\n\t\t\treturn {\n\t\t\t\telements: processed.flatMap(item => {\n\t\t\t\t\tif (item.text !== undefined) {\n\t\t\t\t\t\treturn item.isWhiteSpace ? [] : [this.createDefaultElement(this.trimBlockBoundaryWhitespace([item.text]))]\n\t\t\t\t\t} else if (item.element !== undefined) {\n\t\t\t\t\t\treturn [item.element]\n\t\t\t\t\t}\n\t\t\t\t\treturn []\n\t\t\t\t}),\n\t\t\t}\n\t\t} else {\n\t\t\treturn { texts: processed.map(item => item.text as SlateText) }\n\t\t}\n\t}\n\n\tdeserializeInline(list: NodeList | Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\treturn Array.from(list).flatMap(childNode => {\n\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t} else {\n\t\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\t\treturn this.deserializeInline(childNode.childNodes, attrs)\n\t\t\t}\n\t\t})\n\t}\n\n\tdeserializeBlocks(list: Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\tconst result = this.processNodeListPaste(list, cumulativeTextAttrs)\n\t\tif (result?.texts !== undefined) {\n\t\t\treturn this.trimBlockBoundaryWhitespace(result.texts)\n\t\t}\n\t\treturn result?.elements ?? []\n\t}\n\n\t// Collapsible whitespace at the start/end of a block renders as nothing in HTML,\n\t// so strip it from the edges of a block's inline content. Non-breaking spaces are kept.\n\tprivate trimBlockBoundaryWhitespace(texts: Descendant[]): Descendant[] {\n\t\tconst trimmed = [...texts]\n\t\tconst trimEdge = (direction: 'start' | 'end') => {\n\t\t\tfor (let i = direction === 'start' ? 0 : trimmed.length - 1; i >= 0 && i < trimmed.length;) {\n\t\t\t\tconst node = trimmed[i]\n\t\t\t\tif (!SlateText.isText(node)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst text = direction === 'start' ? node.text.replace(/^[ \\t\\r\\n]+/, '') : node.text.replace(/[ \\t\\r\\n]+$/, '')\n\t\t\t\tif (text !== '') {\n\t\t\t\t\ttrimmed[i] = { ...node, text }\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif (trimmed.length === 1) {\n\t\t\t\t\ttrimmed[i] = { ...node, text }\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\ttrimmed.splice(i, 1)\n\t\t\t\tif (direction === 'end') {\n\t\t\t\t\ti--\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\ttrimEdge('start')\n\t\ttrimEdge('end')\n\t\treturn trimmed\n\t}\n\n\tprivate deserializeTextNode(node: Node, cumulativeTextAttrs: TextAttrs): Descendant[] | null {\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = node.textContent ?? ''\n\t\t\treturn [{ ...cumulativeTextAttrs, text: text.replace(/[ \\t]*(?:\\r?\\n[ \\t]*)+/g, ' ') }]\n\t\t} else if (node instanceof HTMLElement) {\n\t\t\tconst result = this.processInlinePaste(\n\t\t\t\tnode,\n\t\t\t\tcumulativeTextAttrs,\n\t\t\t)\n\t\t\tif (result !== null) {\n\t\t\t\treturn Array.isArray(result) ? result : [result]\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate processInlinePaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): (SlateElement | SlateText)[] | SlateElement | SlateText | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tif (element.tagName === 'BR') {\n\t\t\treturn { ...cumulativeTextAttrs, text: ' ' }\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => {\n\t\t\tconst attrs = this.processWithAttributeProcessor(element, cta)\n\t\t\treturn this.deserializeInline(list, attrs)\n\t\t}\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processInlinePaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n\n\tprivate processWithAttributeProcessor(element: Node, cumulativeTextAttrs: TextAttrs): TextAttrs {\n\t\tif (!(element instanceof HTMLElement)) {\n\t\t\treturn {}\n\t\t}\n\t\treturn this.plugins.reduce(\n\t\t\t(cta, plugin) => plugin.processAttributesPaste?.({ element, cumulativeTextAttrs, deserializer: this }) ?? cta,\n\t\t\tcumulativeTextAttrs,\n\t\t)\n\t}\n\n\tprivate processBlockPaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): SlateElement[] | SlateElement | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => this.deserializeBlocks(Array.from(list), { ...cumulativeTextAttrs, ...cta })\n\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processBlockPaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n}\n"],"names":["result","SlateText"],"mappings":";;;AAIA,MAAM,kBAAkB,CAAC,UAAU,SAAS,UAAU;AAY/C,MAAM,iBAAiB;AAAA,EAC7B,YACQ,sBACC,SACP;AAFM,SAAA,uBAAA;AACC,SAAA,UAAA;AAAA,EAET;AAAA,EAEA,eAAe,QAAgC,UAAmB,MAAM;AACvE,cAAU,KAAK,QAAQ,QAAQ,MAAM,IAAI,KAAK,QAAQ,KAAK,MAAM;AAAA,EAClE;AAAA,EAEO,qBAAqB,UAAkB,qBAAgC;AAC7E,eAAW,UAAU,KAAK,SAAS;AAClC,YAAM,SAAS,OAAO,uBAAuB,EAAE,UAAU,qBAAqB,cAAc,KAAA,CAAM,KAAK;AACvG,UAAI,WAAW,MAAM;AACpB,eAAO;AAAA,MACR;AAAA,IACD;AACA,UAAM,YAGA,CAAA;AAEN,eAAW,aAAa,UAAU;AACjC,YAAM,eAAe,UAAU,aAAa,KAAK,aAAa,UAAU,aAAa,MAAM,OAAO,MAAM;AAGxG,YAAM,QAAQ,KAAK,8BAA8B,WAAW,mBAAmB;AAC/E,YAAM,SAAS,qBAAqB,cACjC,KAAK;AAAA,QACN;AAAA,QACA;AAAA,MAAA,IAEC;AACH,UAAI,WAAW,MAAM;AACpB,kBAAU,KAAK,IAAI,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM,GAAG,IAAI,CAAA,aAAY,EAAE,QAAA,EAAU,CAAC;AAAA,MAC5F,OAAO;AAEN,cAAMA,UAAS,KAAK,oBAAoB,WAAW,mBAAmB;AACtE,YAAIA,YAAW,MAAM;AACpB,oBAAU,KAAK,GAAGA,QAAO,IAAI,WAAS,EAAE,MAAM,aAAA,EAAe,CAAC;AAAA,QAC/D,OAAO;AAEN,gBAAM,uBAAuB,KAAK;AAAA,YACjC,MAAM,KAAK,UAAU,UAAU;AAAA,YAC/B;AAAA,UAAA;AAED,oBAAU;AAAA,YACT,GAAI,yBAAyB,OAC1B,CAAA,IACA,qBAAqB,UAAU,SAC/B,qBAAqB,MAAM,IAAI,WAAS,EAAE,MAAM,eAAe,IAC/D,qBAAqB,SAAS,IAAI,CAAA,aAAY,EAAE,UAAU;AAAA,UAAA;AAAA,QAE/D;AAAA,MACD;AAAA,IACD;AAEA,QAAI,UAAU,WAAW,GAAG;AAC3B,aAAO;AAAA,IACR;AAEA,UAAM,gBAAgB,UAAU,KAAK,CAAC,EAAE,cAAc,YAAY,MAAS,MAAM;AAEjF,QAAI,eAAe;AAClB,aAAO;AAAA,QACN,UAAU,UAAU,QAAQ,CAAA,SAAQ;AACnC,cAAI,KAAK,SAAS,QAAW;AAC5B,mBAAO,KAAK,eAAe,CAAA,IAAK,CAAC,KAAK,qBAAqB,KAAK,4BAA4B,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;AAAA,UAC1G,WAAW,KAAK,YAAY,QAAW;AACtC,mBAAO,CAAC,KAAK,OAAO;AAAA,UACrB;AACA,iBAAO,CAAA;AAAA,QACR,CAAC;AAAA,MAAA;AAAA,IAEH,OAAO;AACN,aAAO,EAAE,OAAO,UAAU,IAAI,CAAA,SAAQ,KAAK,IAAiB,EAAA;AAAA,IAC7D;AAAA,EACD;AAAA,EAEA,kBAAkB,MAAyB,qBAA8C;AACxF,WAAO,MAAM,KAAK,IAAI,EAAE,QAAQ,CAAA,cAAa;AAC5C,YAAM,SAAS,KAAK,oBAAoB,WAAW,mBAAmB;AACtE,UAAI,WAAW,MAAM;AACpB,eAAO;AAAA,MACR,OAAO;AACN,cAAM,QAAQ,KAAK,8BAA8B,WAAW,mBAAmB;AAC/E,eAAO,KAAK,kBAAkB,UAAU,YAAY,KAAK;AAAA,MAC1D;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,kBAAkB,MAAc,qBAA8C;AAC7E,UAAM,SAAS,KAAK,qBAAqB,MAAM,mBAAmB;AAClE,QAAI,QAAQ,UAAU,QAAW;AAChC,aAAO,KAAK,4BAA4B,OAAO,KAAK;AAAA,IACrD;AACA,WAAO,QAAQ,YAAY,CAAA;AAAA,EAC5B;AAAA;AAAA;AAAA,EAIQ,4BAA4B,OAAmC;AACtE,UAAM,UAAU,CAAC,GAAG,KAAK;AACzB,UAAM,WAAW,CAAC,cAA+B;AAChD,eAAS,IAAI,cAAc,UAAU,IAAI,QAAQ,SAAS,GAAG,KAAK,KAAK,IAAI,QAAQ,UAAS;AAC3F,cAAM,OAAO,QAAQ,CAAC;AACtB,YAAI,CAACC,MAAAA,KAAU,OAAO,IAAI,GAAG;AAC5B;AAAA,QACD;AACA,cAAM,OAAO,cAAc,UAAU,KAAK,KAAK,QAAQ,eAAe,EAAE,IAAI,KAAK,KAAK,QAAQ,eAAe,EAAE;AAC/G,YAAI,SAAS,IAAI;AAChB,kBAAQ,CAAC,IAAI,EAAE,GAAG,MAAM,KAAA;AACxB;AAAA,QACD;AACA,YAAI,QAAQ,WAAW,GAAG;AACzB,kBAAQ,CAAC,IAAI,EAAE,GAAG,MAAM,KAAA;AACxB;AAAA,QACD;AACA,gBAAQ,OAAO,GAAG,CAAC;AACnB,YAAI,cAAc,OAAO;AACxB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AACA,aAAS,OAAO;AAChB,aAAS,KAAK;AACd,WAAO;AAAA,EACR;AAAA,EAEQ,oBAAoB,MAAY,qBAAqD;AAC5F,QAAI,KAAK,aAAa,KAAK,WAAW;AACrC,YAAM,OAAO,KAAK,eAAe;AACjC,aAAO,CAAC,EAAE,GAAG,qBAAqB,MAAM,KAAK,QAAQ,2BAA2B,GAAG,GAAG;AAAA,IACvF,WAAW,gBAAgB,aAAa;AACvC,YAAM,SAAS,KAAK;AAAA,QACnB;AAAA,QACA;AAAA,MAAA;AAED,UAAI,WAAW,MAAM;AACpB,eAAO,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AAAA,MAChD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEQ,mBAAmB,SAAsB,qBAAgG;AAChJ,QAAI,gBAAgB,SAAS,QAAQ,OAAO,GAAG;AAC9C,aAAO,CAAA;AAAA,IACR;AACA,QAAI,QAAQ,YAAY,MAAM;AAC7B,aAAO,EAAE,GAAG,qBAAqB,MAAM,IAAA;AAAA,IACxC;AACA,UAAM,OAAqC,CAAC,MAAM,QAAQ;AACzD,YAAM,QAAQ,KAAK,8BAA8B,SAAS,GAAG;AAC7D,aAAO,KAAK,kBAAkB,MAAM,KAAK;AAAA,IAC1C;AACA,eAAW,UAAU,KAAK,SAAS;AAClC,YAAM,SAAS,OAAO,qBAAqB,EAAE,SAAS,MAAM,qBAAqB,cAAc,KAAA,CAAM,KAAK;AAC1G,UAAI,WAAW,MAAM;AACpB,eAAO;AAAA,MACR;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA,EAEQ,8BAA8B,SAAe,qBAA2C;AAC/F,QAAI,EAAE,mBAAmB,cAAc;AACtC,aAAO,CAAA;AAAA,IACR;AACA,WAAO,KAAK,QAAQ;AAAA,MACnB,CAAC,KAAK,WAAW,OAAO,yBAAyB,EAAE,SAAS,qBAAqB,cAAc,KAAA,CAAM,KAAK;AAAA,MAC1G;AAAA,IAAA;AAAA,EAEF;AAAA,EAEQ,kBAAkB,SAAsB,qBAAsE;AACrH,QAAI,gBAAgB,SAAS,QAAQ,OAAO,GAAG;AAC9C,aAAO,CAAA;AAAA,IACR;AACA,UAAM,OAAqC,CAAC,MAAM,QAAQ,KAAK,kBAAkB,MAAM,KAAK,IAAI,GAAG,EAAE,GAAG,qBAAqB,GAAG,KAAK;AAErI,eAAW,UAAU,KAAK,SAAS;AAClC,YAAM,SAAS,OAAO,oBAAoB,EAAE,SAAS,MAAM,qBAAqB,cAAc,KAAA,CAAM,KAAK;AACzG,UAAI,WAAW,MAAM;AACpB,eAAO;AAAA,MACR;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;;"}
@@ -1,3 +1,4 @@
1
+ import { Text } from "slate";
1
2
  const ignoredElements = ["SCRIPT", "STYLE", "TEMPLATE"];
2
3
  class HtmlDeserializer {
3
4
  constructor(createDefaultElement, plugins) {
@@ -47,7 +48,7 @@ class HtmlDeserializer {
47
48
  return {
48
49
  elements: processed.flatMap((item) => {
49
50
  if (item.text !== void 0) {
50
- return item.isWhiteSpace ? [] : [this.createDefaultElement([item.text])];
51
+ return item.isWhiteSpace ? [] : [this.createDefaultElement(this.trimBlockBoundaryWhitespace([item.text]))];
51
52
  } else if (item.element !== void 0) {
52
53
  return [item.element];
53
54
  }
@@ -71,7 +72,39 @@ class HtmlDeserializer {
71
72
  }
72
73
  deserializeBlocks(list, cumulativeTextAttrs) {
73
74
  const result = this.processNodeListPaste(list, cumulativeTextAttrs);
74
- return result?.texts ?? result?.elements ?? [];
75
+ if (result?.texts !== void 0) {
76
+ return this.trimBlockBoundaryWhitespace(result.texts);
77
+ }
78
+ return result?.elements ?? [];
79
+ }
80
+ // Collapsible whitespace at the start/end of a block renders as nothing in HTML,
81
+ // so strip it from the edges of a block's inline content. Non-breaking spaces are kept.
82
+ trimBlockBoundaryWhitespace(texts) {
83
+ const trimmed = [...texts];
84
+ const trimEdge = (direction) => {
85
+ for (let i = direction === "start" ? 0 : trimmed.length - 1; i >= 0 && i < trimmed.length; ) {
86
+ const node = trimmed[i];
87
+ if (!Text.isText(node)) {
88
+ return;
89
+ }
90
+ const text = direction === "start" ? node.text.replace(/^[ \t\r\n]+/, "") : node.text.replace(/[ \t\r\n]+$/, "");
91
+ if (text !== "") {
92
+ trimmed[i] = { ...node, text };
93
+ return;
94
+ }
95
+ if (trimmed.length === 1) {
96
+ trimmed[i] = { ...node, text };
97
+ return;
98
+ }
99
+ trimmed.splice(i, 1);
100
+ if (direction === "end") {
101
+ i--;
102
+ }
103
+ }
104
+ };
105
+ trimEdge("start");
106
+ trimEdge("end");
107
+ return trimmed;
75
108
  }
76
109
  deserializeTextNode(node, cumulativeTextAttrs) {
77
110
  if (node.nodeType === Node.TEXT_NODE) {
@@ -1 +1 @@
1
- {"version":3,"file":"HtmlDeserializer.js","sources":["../../../../../../../packages/react-slate-editor-base/src/plugins/behaviour/paste/HtmlDeserializer.ts"],"sourcesContent":["import { Descendant, Element as SlateElement, Text as SlateText } from 'slate'\nimport { HtmlDeserializerNextCallback, HtmlDeserializerPlugin } from '../../../types/htmlDeserializer'\nimport { EditorDefaultElementFactory } from '../../../types/editor'\n\nconst ignoredElements = ['SCRIPT', 'STYLE', 'TEMPLATE']\n\nexport interface TextAttrs {\n\t[key: string]: any\n}\n\nexport type NodesWithTypeFiltered =\n\t| { texts: Descendant[]; elements?: undefined }\n\t| { elements: SlateElement[]; texts?: undefined }\n\nexport type NodesWithType = NodesWithTypeFiltered | null\n\nexport class HtmlDeserializer {\n\tconstructor(\n\t\tpublic createDefaultElement: EditorDefaultElementFactory,\n\t\tprivate plugins: HtmlDeserializerPlugin[],\n\t) {\n\t}\n\n\tregisterPlugin(plugin: HtmlDeserializerPlugin, prepend: boolean = true) {\n\t\tprepend ? this.plugins.unshift(plugin) : this.plugins.push(plugin)\n\t}\n\n\tpublic processNodeListPaste(nodeList: Node[], cumulativeTextAttrs: TextAttrs) {\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processNodeListPaste?.({ nodeList, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\tconst processed: (\n\t\t\t| { text: SlateText | SlateElement; element?: undefined; isWhiteSpace: boolean }\n\t\t\t| { element: SlateElement; text?: undefined }\n\t\t)[] = []\n\n\t\tfor (const childNode of nodeList) {\n\t\t\tconst isWhiteSpace = childNode.nodeType === Node.TEXT_NODE && childNode.textContent?.match(/^\\s*$/) !== null\n\n\t\t\t// Block\n\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\tconst result = childNode instanceof HTMLElement\n\t\t\t\t? this.processBlockPaste(\n\t\t\t\t\tchildNode,\n\t\t\t\t\tcumulativeTextAttrs,\n\t\t\t\t)\n\t\t\t\t: null\n\t\t\tif (result !== null) {\n\t\t\t\tprocessed.push(...(Array.isArray(result) ? result : [result]).map(element => ({ element })))\n\t\t\t} else {\n\t\t\t\t// Inline\n\t\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\t\tif (result !== null) {\n\t\t\t\t\tprocessed.push(...result.map(text => ({ text, isWhiteSpace })))\n\t\t\t\t} else {\n\t\t\t\t\t// Unknown element\n\t\t\t\t\tconst deserializedChildren = this.processNodeListPaste(\n\t\t\t\t\t\tArray.from(childNode.childNodes),\n\t\t\t\t\t\tattrs,\n\t\t\t\t\t)\n\t\t\t\t\tprocessed.push(\n\t\t\t\t\t\t...(deserializedChildren === null\n\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t: deserializedChildren.texts !== undefined\n\t\t\t\t\t\t\t? deserializedChildren.texts.map(text => ({ text, isWhiteSpace }))\n\t\t\t\t\t\t\t: deserializedChildren.elements.map(element => ({ element }))),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (processed.length === 0) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst containsBlock = processed.find(({ element }) => element !== undefined) !== undefined\n\n\t\tif (containsBlock) {\n\t\t\treturn {\n\t\t\t\telements: processed.flatMap(item => {\n\t\t\t\t\tif (item.text !== undefined) {\n\t\t\t\t\t\treturn item.isWhiteSpace ? [] : [this.createDefaultElement([item.text])]\n\t\t\t\t\t} else if (item.element !== undefined) {\n\t\t\t\t\t\treturn [item.element]\n\t\t\t\t\t}\n\t\t\t\t\treturn []\n\t\t\t\t}),\n\t\t\t}\n\t\t} else {\n\t\t\treturn { texts: processed.map(item => item.text as SlateText) }\n\t\t}\n\t}\n\n\tdeserializeInline(list: NodeList | Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\treturn Array.from(list).flatMap(childNode => {\n\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t} else {\n\t\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\t\treturn this.deserializeInline(childNode.childNodes, attrs)\n\t\t\t}\n\t\t})\n\t}\n\n\tdeserializeBlocks(list: Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\tconst result = this.processNodeListPaste(list, cumulativeTextAttrs)\n\t\treturn result?.texts ?? result?.elements ?? []\n\t}\n\n\tprivate deserializeTextNode(node: Node, cumulativeTextAttrs: TextAttrs): Descendant[] | null {\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = node.textContent ?? ''\n\t\t\treturn [{ ...cumulativeTextAttrs, text: text.replace(/[ \\t]*(?:\\r?\\n[ \\t]*)+/g, ' ') }]\n\t\t} else if (node instanceof HTMLElement) {\n\t\t\tconst result = this.processInlinePaste(\n\t\t\t\tnode,\n\t\t\t\tcumulativeTextAttrs,\n\t\t\t)\n\t\t\tif (result !== null) {\n\t\t\t\treturn Array.isArray(result) ? result : [result]\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate processInlinePaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): (SlateElement | SlateText)[] | SlateElement | SlateText | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tif (element.tagName === 'BR') {\n\t\t\treturn { ...cumulativeTextAttrs, text: ' ' }\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => {\n\t\t\tconst attrs = this.processWithAttributeProcessor(element, cta)\n\t\t\treturn this.deserializeInline(list, attrs)\n\t\t}\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processInlinePaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n\n\tprivate processWithAttributeProcessor(element: Node, cumulativeTextAttrs: TextAttrs): TextAttrs {\n\t\tif (!(element instanceof HTMLElement)) {\n\t\t\treturn {}\n\t\t}\n\t\treturn this.plugins.reduce(\n\t\t\t(cta, plugin) => plugin.processAttributesPaste?.({ element, cumulativeTextAttrs, deserializer: this }) ?? cta,\n\t\t\tcumulativeTextAttrs,\n\t\t)\n\t}\n\n\tprivate processBlockPaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): SlateElement[] | SlateElement | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => this.deserializeBlocks(Array.from(list), { ...cumulativeTextAttrs, ...cta })\n\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processBlockPaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n}\n"],"names":["result"],"mappings":"AAIA,MAAM,kBAAkB,CAAC,UAAU,SAAS,UAAU;AAY/C,MAAM,iBAAiB;AAAA,EAC7B,YACQ,sBACC,SACP;AAFM,SAAA,uBAAA;AACC,SAAA,UAAA;AAAA,EAET;AAAA,EAEA,eAAe,QAAgC,UAAmB,MAAM;AACvE,cAAU,KAAK,QAAQ,QAAQ,MAAM,IAAI,KAAK,QAAQ,KAAK,MAAM;AAAA,EAClE;AAAA,EAEO,qBAAqB,UAAkB,qBAAgC;AAC7E,eAAW,UAAU,KAAK,SAAS;AAClC,YAAM,SAAS,OAAO,uBAAuB,EAAE,UAAU,qBAAqB,cAAc,KAAA,CAAM,KAAK;AACvG,UAAI,WAAW,MAAM;AACpB,eAAO;AAAA,MACR;AAAA,IACD;AACA,UAAM,YAGA,CAAA;AAEN,eAAW,aAAa,UAAU;AACjC,YAAM,eAAe,UAAU,aAAa,KAAK,aAAa,UAAU,aAAa,MAAM,OAAO,MAAM;AAGxG,YAAM,QAAQ,KAAK,8BAA8B,WAAW,mBAAmB;AAC/E,YAAM,SAAS,qBAAqB,cACjC,KAAK;AAAA,QACN;AAAA,QACA;AAAA,MAAA,IAEC;AACH,UAAI,WAAW,MAAM;AACpB,kBAAU,KAAK,IAAI,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM,GAAG,IAAI,CAAA,aAAY,EAAE,QAAA,EAAU,CAAC;AAAA,MAC5F,OAAO;AAEN,cAAMA,UAAS,KAAK,oBAAoB,WAAW,mBAAmB;AACtE,YAAIA,YAAW,MAAM;AACpB,oBAAU,KAAK,GAAGA,QAAO,IAAI,WAAS,EAAE,MAAM,aAAA,EAAe,CAAC;AAAA,QAC/D,OAAO;AAEN,gBAAM,uBAAuB,KAAK;AAAA,YACjC,MAAM,KAAK,UAAU,UAAU;AAAA,YAC/B;AAAA,UAAA;AAED,oBAAU;AAAA,YACT,GAAI,yBAAyB,OAC1B,CAAA,IACA,qBAAqB,UAAU,SAC/B,qBAAqB,MAAM,IAAI,WAAS,EAAE,MAAM,eAAe,IAC/D,qBAAqB,SAAS,IAAI,CAAA,aAAY,EAAE,UAAU;AAAA,UAAA;AAAA,QAE/D;AAAA,MACD;AAAA,IACD;AAEA,QAAI,UAAU,WAAW,GAAG;AAC3B,aAAO;AAAA,IACR;AAEA,UAAM,gBAAgB,UAAU,KAAK,CAAC,EAAE,cAAc,YAAY,MAAS,MAAM;AAEjF,QAAI,eAAe;AAClB,aAAO;AAAA,QACN,UAAU,UAAU,QAAQ,CAAA,SAAQ;AACnC,cAAI,KAAK,SAAS,QAAW;AAC5B,mBAAO,KAAK,eAAe,CAAA,IAAK,CAAC,KAAK,qBAAqB,CAAC,KAAK,IAAI,CAAC,CAAC;AAAA,UACxE,WAAW,KAAK,YAAY,QAAW;AACtC,mBAAO,CAAC,KAAK,OAAO;AAAA,UACrB;AACA,iBAAO,CAAA;AAAA,QACR,CAAC;AAAA,MAAA;AAAA,IAEH,OAAO;AACN,aAAO,EAAE,OAAO,UAAU,IAAI,CAAA,SAAQ,KAAK,IAAiB,EAAA;AAAA,IAC7D;AAAA,EACD;AAAA,EAEA,kBAAkB,MAAyB,qBAA8C;AACxF,WAAO,MAAM,KAAK,IAAI,EAAE,QAAQ,CAAA,cAAa;AAC5C,YAAM,SAAS,KAAK,oBAAoB,WAAW,mBAAmB;AACtE,UAAI,WAAW,MAAM;AACpB,eAAO;AAAA,MACR,OAAO;AACN,cAAM,QAAQ,KAAK,8BAA8B,WAAW,mBAAmB;AAC/E,eAAO,KAAK,kBAAkB,UAAU,YAAY,KAAK;AAAA,MAC1D;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,kBAAkB,MAAc,qBAA8C;AAC7E,UAAM,SAAS,KAAK,qBAAqB,MAAM,mBAAmB;AAClE,WAAO,QAAQ,SAAS,QAAQ,YAAY,CAAA;AAAA,EAC7C;AAAA,EAEQ,oBAAoB,MAAY,qBAAqD;AAC5F,QAAI,KAAK,aAAa,KAAK,WAAW;AACrC,YAAM,OAAO,KAAK,eAAe;AACjC,aAAO,CAAC,EAAE,GAAG,qBAAqB,MAAM,KAAK,QAAQ,2BAA2B,GAAG,GAAG;AAAA,IACvF,WAAW,gBAAgB,aAAa;AACvC,YAAM,SAAS,KAAK;AAAA,QACnB;AAAA,QACA;AAAA,MAAA;AAED,UAAI,WAAW,MAAM;AACpB,eAAO,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AAAA,MAChD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEQ,mBAAmB,SAAsB,qBAAgG;AAChJ,QAAI,gBAAgB,SAAS,QAAQ,OAAO,GAAG;AAC9C,aAAO,CAAA;AAAA,IACR;AACA,QAAI,QAAQ,YAAY,MAAM;AAC7B,aAAO,EAAE,GAAG,qBAAqB,MAAM,IAAA;AAAA,IACxC;AACA,UAAM,OAAqC,CAAC,MAAM,QAAQ;AACzD,YAAM,QAAQ,KAAK,8BAA8B,SAAS,GAAG;AAC7D,aAAO,KAAK,kBAAkB,MAAM,KAAK;AAAA,IAC1C;AACA,eAAW,UAAU,KAAK,SAAS;AAClC,YAAM,SAAS,OAAO,qBAAqB,EAAE,SAAS,MAAM,qBAAqB,cAAc,KAAA,CAAM,KAAK;AAC1G,UAAI,WAAW,MAAM;AACpB,eAAO;AAAA,MACR;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA,EAEQ,8BAA8B,SAAe,qBAA2C;AAC/F,QAAI,EAAE,mBAAmB,cAAc;AACtC,aAAO,CAAA;AAAA,IACR;AACA,WAAO,KAAK,QAAQ;AAAA,MACnB,CAAC,KAAK,WAAW,OAAO,yBAAyB,EAAE,SAAS,qBAAqB,cAAc,KAAA,CAAM,KAAK;AAAA,MAC1G;AAAA,IAAA;AAAA,EAEF;AAAA,EAEQ,kBAAkB,SAAsB,qBAAsE;AACrH,QAAI,gBAAgB,SAAS,QAAQ,OAAO,GAAG;AAC9C,aAAO,CAAA;AAAA,IACR;AACA,UAAM,OAAqC,CAAC,MAAM,QAAQ,KAAK,kBAAkB,MAAM,KAAK,IAAI,GAAG,EAAE,GAAG,qBAAqB,GAAG,KAAK;AAErI,eAAW,UAAU,KAAK,SAAS;AAClC,YAAM,SAAS,OAAO,oBAAoB,EAAE,SAAS,MAAM,qBAAqB,cAAc,KAAA,CAAM,KAAK;AACzG,UAAI,WAAW,MAAM;AACpB,eAAO;AAAA,MACR;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;"}
1
+ {"version":3,"file":"HtmlDeserializer.js","sources":["../../../../../../../packages/react-slate-editor-base/src/plugins/behaviour/paste/HtmlDeserializer.ts"],"sourcesContent":["import { Descendant, Element as SlateElement, Text as SlateText } from 'slate'\nimport { HtmlDeserializerNextCallback, HtmlDeserializerPlugin } from '../../../types/htmlDeserializer'\nimport { EditorDefaultElementFactory } from '../../../types/editor'\n\nconst ignoredElements = ['SCRIPT', 'STYLE', 'TEMPLATE']\n\nexport interface TextAttrs {\n\t[key: string]: any\n}\n\nexport type NodesWithTypeFiltered =\n\t| { texts: Descendant[]; elements?: undefined }\n\t| { elements: SlateElement[]; texts?: undefined }\n\nexport type NodesWithType = NodesWithTypeFiltered | null\n\nexport class HtmlDeserializer {\n\tconstructor(\n\t\tpublic createDefaultElement: EditorDefaultElementFactory,\n\t\tprivate plugins: HtmlDeserializerPlugin[],\n\t) {\n\t}\n\n\tregisterPlugin(plugin: HtmlDeserializerPlugin, prepend: boolean = true) {\n\t\tprepend ? this.plugins.unshift(plugin) : this.plugins.push(plugin)\n\t}\n\n\tpublic processNodeListPaste(nodeList: Node[], cumulativeTextAttrs: TextAttrs) {\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processNodeListPaste?.({ nodeList, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\tconst processed: (\n\t\t\t| { text: SlateText | SlateElement; element?: undefined; isWhiteSpace: boolean }\n\t\t\t| { element: SlateElement; text?: undefined }\n\t\t)[] = []\n\n\t\tfor (const childNode of nodeList) {\n\t\t\tconst isWhiteSpace = childNode.nodeType === Node.TEXT_NODE && childNode.textContent?.match(/^\\s*$/) !== null\n\n\t\t\t// Block\n\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\tconst result = childNode instanceof HTMLElement\n\t\t\t\t? this.processBlockPaste(\n\t\t\t\t\tchildNode,\n\t\t\t\t\tcumulativeTextAttrs,\n\t\t\t\t)\n\t\t\t\t: null\n\t\t\tif (result !== null) {\n\t\t\t\tprocessed.push(...(Array.isArray(result) ? result : [result]).map(element => ({ element })))\n\t\t\t} else {\n\t\t\t\t// Inline\n\t\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\t\tif (result !== null) {\n\t\t\t\t\tprocessed.push(...result.map(text => ({ text, isWhiteSpace })))\n\t\t\t\t} else {\n\t\t\t\t\t// Unknown element\n\t\t\t\t\tconst deserializedChildren = this.processNodeListPaste(\n\t\t\t\t\t\tArray.from(childNode.childNodes),\n\t\t\t\t\t\tattrs,\n\t\t\t\t\t)\n\t\t\t\t\tprocessed.push(\n\t\t\t\t\t\t...(deserializedChildren === null\n\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t: deserializedChildren.texts !== undefined\n\t\t\t\t\t\t\t? deserializedChildren.texts.map(text => ({ text, isWhiteSpace }))\n\t\t\t\t\t\t\t: deserializedChildren.elements.map(element => ({ element }))),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (processed.length === 0) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst containsBlock = processed.find(({ element }) => element !== undefined) !== undefined\n\n\t\tif (containsBlock) {\n\t\t\treturn {\n\t\t\t\telements: processed.flatMap(item => {\n\t\t\t\t\tif (item.text !== undefined) {\n\t\t\t\t\t\treturn item.isWhiteSpace ? [] : [this.createDefaultElement(this.trimBlockBoundaryWhitespace([item.text]))]\n\t\t\t\t\t} else if (item.element !== undefined) {\n\t\t\t\t\t\treturn [item.element]\n\t\t\t\t\t}\n\t\t\t\t\treturn []\n\t\t\t\t}),\n\t\t\t}\n\t\t} else {\n\t\t\treturn { texts: processed.map(item => item.text as SlateText) }\n\t\t}\n\t}\n\n\tdeserializeInline(list: NodeList | Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\treturn Array.from(list).flatMap(childNode => {\n\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t} else {\n\t\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\t\treturn this.deserializeInline(childNode.childNodes, attrs)\n\t\t\t}\n\t\t})\n\t}\n\n\tdeserializeBlocks(list: Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\tconst result = this.processNodeListPaste(list, cumulativeTextAttrs)\n\t\tif (result?.texts !== undefined) {\n\t\t\treturn this.trimBlockBoundaryWhitespace(result.texts)\n\t\t}\n\t\treturn result?.elements ?? []\n\t}\n\n\t// Collapsible whitespace at the start/end of a block renders as nothing in HTML,\n\t// so strip it from the edges of a block's inline content. Non-breaking spaces are kept.\n\tprivate trimBlockBoundaryWhitespace(texts: Descendant[]): Descendant[] {\n\t\tconst trimmed = [...texts]\n\t\tconst trimEdge = (direction: 'start' | 'end') => {\n\t\t\tfor (let i = direction === 'start' ? 0 : trimmed.length - 1; i >= 0 && i < trimmed.length;) {\n\t\t\t\tconst node = trimmed[i]\n\t\t\t\tif (!SlateText.isText(node)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst text = direction === 'start' ? node.text.replace(/^[ \\t\\r\\n]+/, '') : node.text.replace(/[ \\t\\r\\n]+$/, '')\n\t\t\t\tif (text !== '') {\n\t\t\t\t\ttrimmed[i] = { ...node, text }\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif (trimmed.length === 1) {\n\t\t\t\t\ttrimmed[i] = { ...node, text }\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\ttrimmed.splice(i, 1)\n\t\t\t\tif (direction === 'end') {\n\t\t\t\t\ti--\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\ttrimEdge('start')\n\t\ttrimEdge('end')\n\t\treturn trimmed\n\t}\n\n\tprivate deserializeTextNode(node: Node, cumulativeTextAttrs: TextAttrs): Descendant[] | null {\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = node.textContent ?? ''\n\t\t\treturn [{ ...cumulativeTextAttrs, text: text.replace(/[ \\t]*(?:\\r?\\n[ \\t]*)+/g, ' ') }]\n\t\t} else if (node instanceof HTMLElement) {\n\t\t\tconst result = this.processInlinePaste(\n\t\t\t\tnode,\n\t\t\t\tcumulativeTextAttrs,\n\t\t\t)\n\t\t\tif (result !== null) {\n\t\t\t\treturn Array.isArray(result) ? result : [result]\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate processInlinePaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): (SlateElement | SlateText)[] | SlateElement | SlateText | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tif (element.tagName === 'BR') {\n\t\t\treturn { ...cumulativeTextAttrs, text: ' ' }\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => {\n\t\t\tconst attrs = this.processWithAttributeProcessor(element, cta)\n\t\t\treturn this.deserializeInline(list, attrs)\n\t\t}\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processInlinePaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n\n\tprivate processWithAttributeProcessor(element: Node, cumulativeTextAttrs: TextAttrs): TextAttrs {\n\t\tif (!(element instanceof HTMLElement)) {\n\t\t\treturn {}\n\t\t}\n\t\treturn this.plugins.reduce(\n\t\t\t(cta, plugin) => plugin.processAttributesPaste?.({ element, cumulativeTextAttrs, deserializer: this }) ?? cta,\n\t\t\tcumulativeTextAttrs,\n\t\t)\n\t}\n\n\tprivate processBlockPaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): SlateElement[] | SlateElement | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => this.deserializeBlocks(Array.from(list), { ...cumulativeTextAttrs, ...cta })\n\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processBlockPaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n}\n"],"names":["result","SlateText"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const Slate = require("slate");
3
4
  const ignoredElements = ["SCRIPT", "STYLE", "TEMPLATE"];
4
5
  class HtmlDeserializer {
5
6
  constructor(createDefaultElement, plugins) {
@@ -49,7 +50,7 @@ class HtmlDeserializer {
49
50
  return {
50
51
  elements: processed.flatMap((item) => {
51
52
  if (item.text !== void 0) {
52
- return item.isWhiteSpace ? [] : [this.createDefaultElement([item.text])];
53
+ return item.isWhiteSpace ? [] : [this.createDefaultElement(this.trimBlockBoundaryWhitespace([item.text]))];
53
54
  } else if (item.element !== void 0) {
54
55
  return [item.element];
55
56
  }
@@ -73,7 +74,39 @@ class HtmlDeserializer {
73
74
  }
74
75
  deserializeBlocks(list, cumulativeTextAttrs) {
75
76
  const result = this.processNodeListPaste(list, cumulativeTextAttrs);
76
- return result?.texts ?? result?.elements ?? [];
77
+ if (result?.texts !== void 0) {
78
+ return this.trimBlockBoundaryWhitespace(result.texts);
79
+ }
80
+ return result?.elements ?? [];
81
+ }
82
+ // Collapsible whitespace at the start/end of a block renders as nothing in HTML,
83
+ // so strip it from the edges of a block's inline content. Non-breaking spaces are kept.
84
+ trimBlockBoundaryWhitespace(texts) {
85
+ const trimmed = [...texts];
86
+ const trimEdge = (direction) => {
87
+ for (let i = direction === "start" ? 0 : trimmed.length - 1; i >= 0 && i < trimmed.length; ) {
88
+ const node = trimmed[i];
89
+ if (!Slate.Text.isText(node)) {
90
+ return;
91
+ }
92
+ const text = direction === "start" ? node.text.replace(/^[ \t\r\n]+/, "") : node.text.replace(/[ \t\r\n]+$/, "");
93
+ if (text !== "") {
94
+ trimmed[i] = { ...node, text };
95
+ return;
96
+ }
97
+ if (trimmed.length === 1) {
98
+ trimmed[i] = { ...node, text };
99
+ return;
100
+ }
101
+ trimmed.splice(i, 1);
102
+ if (direction === "end") {
103
+ i--;
104
+ }
105
+ }
106
+ };
107
+ trimEdge("start");
108
+ trimEdge("end");
109
+ return trimmed;
77
110
  }
78
111
  deserializeTextNode(node, cumulativeTextAttrs) {
79
112
  if (node.nodeType === Node.TEXT_NODE) {
@@ -1 +1 @@
1
- {"version":3,"file":"HtmlDeserializer.cjs","sources":["../../../../../../../packages/react-slate-editor-base/src/plugins/behaviour/paste/HtmlDeserializer.ts"],"sourcesContent":["import { Descendant, Element as SlateElement, Text as SlateText } from 'slate'\nimport { HtmlDeserializerNextCallback, HtmlDeserializerPlugin } from '../../../types/htmlDeserializer'\nimport { EditorDefaultElementFactory } from '../../../types/editor'\n\nconst ignoredElements = ['SCRIPT', 'STYLE', 'TEMPLATE']\n\nexport interface TextAttrs {\n\t[key: string]: any\n}\n\nexport type NodesWithTypeFiltered =\n\t| { texts: Descendant[]; elements?: undefined }\n\t| { elements: SlateElement[]; texts?: undefined }\n\nexport type NodesWithType = NodesWithTypeFiltered | null\n\nexport class HtmlDeserializer {\n\tconstructor(\n\t\tpublic createDefaultElement: EditorDefaultElementFactory,\n\t\tprivate plugins: HtmlDeserializerPlugin[],\n\t) {\n\t}\n\n\tregisterPlugin(plugin: HtmlDeserializerPlugin, prepend: boolean = true) {\n\t\tprepend ? this.plugins.unshift(plugin) : this.plugins.push(plugin)\n\t}\n\n\tpublic processNodeListPaste(nodeList: Node[], cumulativeTextAttrs: TextAttrs) {\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processNodeListPaste?.({ nodeList, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\tconst processed: (\n\t\t\t| { text: SlateText | SlateElement; element?: undefined; isWhiteSpace: boolean }\n\t\t\t| { element: SlateElement; text?: undefined }\n\t\t)[] = []\n\n\t\tfor (const childNode of nodeList) {\n\t\t\tconst isWhiteSpace = childNode.nodeType === Node.TEXT_NODE && childNode.textContent?.match(/^\\s*$/) !== null\n\n\t\t\t// Block\n\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\tconst result = childNode instanceof HTMLElement\n\t\t\t\t? this.processBlockPaste(\n\t\t\t\t\tchildNode,\n\t\t\t\t\tcumulativeTextAttrs,\n\t\t\t\t)\n\t\t\t\t: null\n\t\t\tif (result !== null) {\n\t\t\t\tprocessed.push(...(Array.isArray(result) ? result : [result]).map(element => ({ element })))\n\t\t\t} else {\n\t\t\t\t// Inline\n\t\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\t\tif (result !== null) {\n\t\t\t\t\tprocessed.push(...result.map(text => ({ text, isWhiteSpace })))\n\t\t\t\t} else {\n\t\t\t\t\t// Unknown element\n\t\t\t\t\tconst deserializedChildren = this.processNodeListPaste(\n\t\t\t\t\t\tArray.from(childNode.childNodes),\n\t\t\t\t\t\tattrs,\n\t\t\t\t\t)\n\t\t\t\t\tprocessed.push(\n\t\t\t\t\t\t...(deserializedChildren === null\n\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t: deserializedChildren.texts !== undefined\n\t\t\t\t\t\t\t? deserializedChildren.texts.map(text => ({ text, isWhiteSpace }))\n\t\t\t\t\t\t\t: deserializedChildren.elements.map(element => ({ element }))),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (processed.length === 0) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst containsBlock = processed.find(({ element }) => element !== undefined) !== undefined\n\n\t\tif (containsBlock) {\n\t\t\treturn {\n\t\t\t\telements: processed.flatMap(item => {\n\t\t\t\t\tif (item.text !== undefined) {\n\t\t\t\t\t\treturn item.isWhiteSpace ? [] : [this.createDefaultElement([item.text])]\n\t\t\t\t\t} else if (item.element !== undefined) {\n\t\t\t\t\t\treturn [item.element]\n\t\t\t\t\t}\n\t\t\t\t\treturn []\n\t\t\t\t}),\n\t\t\t}\n\t\t} else {\n\t\t\treturn { texts: processed.map(item => item.text as SlateText) }\n\t\t}\n\t}\n\n\tdeserializeInline(list: NodeList | Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\treturn Array.from(list).flatMap(childNode => {\n\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t} else {\n\t\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\t\treturn this.deserializeInline(childNode.childNodes, attrs)\n\t\t\t}\n\t\t})\n\t}\n\n\tdeserializeBlocks(list: Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\tconst result = this.processNodeListPaste(list, cumulativeTextAttrs)\n\t\treturn result?.texts ?? result?.elements ?? []\n\t}\n\n\tprivate deserializeTextNode(node: Node, cumulativeTextAttrs: TextAttrs): Descendant[] | null {\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = node.textContent ?? ''\n\t\t\treturn [{ ...cumulativeTextAttrs, text: text.replace(/[ \\t]*(?:\\r?\\n[ \\t]*)+/g, ' ') }]\n\t\t} else if (node instanceof HTMLElement) {\n\t\t\tconst result = this.processInlinePaste(\n\t\t\t\tnode,\n\t\t\t\tcumulativeTextAttrs,\n\t\t\t)\n\t\t\tif (result !== null) {\n\t\t\t\treturn Array.isArray(result) ? result : [result]\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate processInlinePaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): (SlateElement | SlateText)[] | SlateElement | SlateText | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tif (element.tagName === 'BR') {\n\t\t\treturn { ...cumulativeTextAttrs, text: ' ' }\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => {\n\t\t\tconst attrs = this.processWithAttributeProcessor(element, cta)\n\t\t\treturn this.deserializeInline(list, attrs)\n\t\t}\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processInlinePaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n\n\tprivate processWithAttributeProcessor(element: Node, cumulativeTextAttrs: TextAttrs): TextAttrs {\n\t\tif (!(element instanceof HTMLElement)) {\n\t\t\treturn {}\n\t\t}\n\t\treturn this.plugins.reduce(\n\t\t\t(cta, plugin) => plugin.processAttributesPaste?.({ element, cumulativeTextAttrs, deserializer: this }) ?? cta,\n\t\t\tcumulativeTextAttrs,\n\t\t)\n\t}\n\n\tprivate processBlockPaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): SlateElement[] | SlateElement | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => this.deserializeBlocks(Array.from(list), { ...cumulativeTextAttrs, ...cta })\n\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processBlockPaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n}\n"],"names":["result"],"mappings":"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"}
1
+ {"version":3,"file":"HtmlDeserializer.cjs","sources":["../../../../../../../packages/react-slate-editor-base/src/plugins/behaviour/paste/HtmlDeserializer.ts"],"sourcesContent":["import { Descendant, Element as SlateElement, Text as SlateText } from 'slate'\nimport { HtmlDeserializerNextCallback, HtmlDeserializerPlugin } from '../../../types/htmlDeserializer'\nimport { EditorDefaultElementFactory } from '../../../types/editor'\n\nconst ignoredElements = ['SCRIPT', 'STYLE', 'TEMPLATE']\n\nexport interface TextAttrs {\n\t[key: string]: any\n}\n\nexport type NodesWithTypeFiltered =\n\t| { texts: Descendant[]; elements?: undefined }\n\t| { elements: SlateElement[]; texts?: undefined }\n\nexport type NodesWithType = NodesWithTypeFiltered | null\n\nexport class HtmlDeserializer {\n\tconstructor(\n\t\tpublic createDefaultElement: EditorDefaultElementFactory,\n\t\tprivate plugins: HtmlDeserializerPlugin[],\n\t) {\n\t}\n\n\tregisterPlugin(plugin: HtmlDeserializerPlugin, prepend: boolean = true) {\n\t\tprepend ? this.plugins.unshift(plugin) : this.plugins.push(plugin)\n\t}\n\n\tpublic processNodeListPaste(nodeList: Node[], cumulativeTextAttrs: TextAttrs) {\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processNodeListPaste?.({ nodeList, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\tconst processed: (\n\t\t\t| { text: SlateText | SlateElement; element?: undefined; isWhiteSpace: boolean }\n\t\t\t| { element: SlateElement; text?: undefined }\n\t\t)[] = []\n\n\t\tfor (const childNode of nodeList) {\n\t\t\tconst isWhiteSpace = childNode.nodeType === Node.TEXT_NODE && childNode.textContent?.match(/^\\s*$/) !== null\n\n\t\t\t// Block\n\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\tconst result = childNode instanceof HTMLElement\n\t\t\t\t? this.processBlockPaste(\n\t\t\t\t\tchildNode,\n\t\t\t\t\tcumulativeTextAttrs,\n\t\t\t\t)\n\t\t\t\t: null\n\t\t\tif (result !== null) {\n\t\t\t\tprocessed.push(...(Array.isArray(result) ? result : [result]).map(element => ({ element })))\n\t\t\t} else {\n\t\t\t\t// Inline\n\t\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\t\tif (result !== null) {\n\t\t\t\t\tprocessed.push(...result.map(text => ({ text, isWhiteSpace })))\n\t\t\t\t} else {\n\t\t\t\t\t// Unknown element\n\t\t\t\t\tconst deserializedChildren = this.processNodeListPaste(\n\t\t\t\t\t\tArray.from(childNode.childNodes),\n\t\t\t\t\t\tattrs,\n\t\t\t\t\t)\n\t\t\t\t\tprocessed.push(\n\t\t\t\t\t\t...(deserializedChildren === null\n\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t: deserializedChildren.texts !== undefined\n\t\t\t\t\t\t\t? deserializedChildren.texts.map(text => ({ text, isWhiteSpace }))\n\t\t\t\t\t\t\t: deserializedChildren.elements.map(element => ({ element }))),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (processed.length === 0) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst containsBlock = processed.find(({ element }) => element !== undefined) !== undefined\n\n\t\tif (containsBlock) {\n\t\t\treturn {\n\t\t\t\telements: processed.flatMap(item => {\n\t\t\t\t\tif (item.text !== undefined) {\n\t\t\t\t\t\treturn item.isWhiteSpace ? [] : [this.createDefaultElement(this.trimBlockBoundaryWhitespace([item.text]))]\n\t\t\t\t\t} else if (item.element !== undefined) {\n\t\t\t\t\t\treturn [item.element]\n\t\t\t\t\t}\n\t\t\t\t\treturn []\n\t\t\t\t}),\n\t\t\t}\n\t\t} else {\n\t\t\treturn { texts: processed.map(item => item.text as SlateText) }\n\t\t}\n\t}\n\n\tdeserializeInline(list: NodeList | Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\treturn Array.from(list).flatMap(childNode => {\n\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t} else {\n\t\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\t\treturn this.deserializeInline(childNode.childNodes, attrs)\n\t\t\t}\n\t\t})\n\t}\n\n\tdeserializeBlocks(list: Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\tconst result = this.processNodeListPaste(list, cumulativeTextAttrs)\n\t\tif (result?.texts !== undefined) {\n\t\t\treturn this.trimBlockBoundaryWhitespace(result.texts)\n\t\t}\n\t\treturn result?.elements ?? []\n\t}\n\n\t// Collapsible whitespace at the start/end of a block renders as nothing in HTML,\n\t// so strip it from the edges of a block's inline content. Non-breaking spaces are kept.\n\tprivate trimBlockBoundaryWhitespace(texts: Descendant[]): Descendant[] {\n\t\tconst trimmed = [...texts]\n\t\tconst trimEdge = (direction: 'start' | 'end') => {\n\t\t\tfor (let i = direction === 'start' ? 0 : trimmed.length - 1; i >= 0 && i < trimmed.length;) {\n\t\t\t\tconst node = trimmed[i]\n\t\t\t\tif (!SlateText.isText(node)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst text = direction === 'start' ? node.text.replace(/^[ \\t\\r\\n]+/, '') : node.text.replace(/[ \\t\\r\\n]+$/, '')\n\t\t\t\tif (text !== '') {\n\t\t\t\t\ttrimmed[i] = { ...node, text }\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif (trimmed.length === 1) {\n\t\t\t\t\ttrimmed[i] = { ...node, text }\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\ttrimmed.splice(i, 1)\n\t\t\t\tif (direction === 'end') {\n\t\t\t\t\ti--\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\ttrimEdge('start')\n\t\ttrimEdge('end')\n\t\treturn trimmed\n\t}\n\n\tprivate deserializeTextNode(node: Node, cumulativeTextAttrs: TextAttrs): Descendant[] | null {\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = node.textContent ?? ''\n\t\t\treturn [{ ...cumulativeTextAttrs, text: text.replace(/[ \\t]*(?:\\r?\\n[ \\t]*)+/g, ' ') }]\n\t\t} else if (node instanceof HTMLElement) {\n\t\t\tconst result = this.processInlinePaste(\n\t\t\t\tnode,\n\t\t\t\tcumulativeTextAttrs,\n\t\t\t)\n\t\t\tif (result !== null) {\n\t\t\t\treturn Array.isArray(result) ? result : [result]\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate processInlinePaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): (SlateElement | SlateText)[] | SlateElement | SlateText | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tif (element.tagName === 'BR') {\n\t\t\treturn { ...cumulativeTextAttrs, text: ' ' }\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => {\n\t\t\tconst attrs = this.processWithAttributeProcessor(element, cta)\n\t\t\treturn this.deserializeInline(list, attrs)\n\t\t}\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processInlinePaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n\n\tprivate processWithAttributeProcessor(element: Node, cumulativeTextAttrs: TextAttrs): TextAttrs {\n\t\tif (!(element instanceof HTMLElement)) {\n\t\t\treturn {}\n\t\t}\n\t\treturn this.plugins.reduce(\n\t\t\t(cta, plugin) => plugin.processAttributesPaste?.({ element, cumulativeTextAttrs, deserializer: this }) ?? cta,\n\t\t\tcumulativeTextAttrs,\n\t\t)\n\t}\n\n\tprivate processBlockPaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): SlateElement[] | SlateElement | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => this.deserializeBlocks(Array.from(list), { ...cumulativeTextAttrs, ...cta })\n\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processBlockPaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n}\n"],"names":["result","SlateText"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { Text } from "slate";
1
2
  const ignoredElements = ["SCRIPT", "STYLE", "TEMPLATE"];
2
3
  class HtmlDeserializer {
3
4
  constructor(createDefaultElement, plugins) {
@@ -47,7 +48,7 @@ class HtmlDeserializer {
47
48
  return {
48
49
  elements: processed.flatMap((item) => {
49
50
  if (item.text !== void 0) {
50
- return item.isWhiteSpace ? [] : [this.createDefaultElement([item.text])];
51
+ return item.isWhiteSpace ? [] : [this.createDefaultElement(this.trimBlockBoundaryWhitespace([item.text]))];
51
52
  } else if (item.element !== void 0) {
52
53
  return [item.element];
53
54
  }
@@ -71,7 +72,39 @@ class HtmlDeserializer {
71
72
  }
72
73
  deserializeBlocks(list, cumulativeTextAttrs) {
73
74
  const result = this.processNodeListPaste(list, cumulativeTextAttrs);
74
- return result?.texts ?? result?.elements ?? [];
75
+ if (result?.texts !== void 0) {
76
+ return this.trimBlockBoundaryWhitespace(result.texts);
77
+ }
78
+ return result?.elements ?? [];
79
+ }
80
+ // Collapsible whitespace at the start/end of a block renders as nothing in HTML,
81
+ // so strip it from the edges of a block's inline content. Non-breaking spaces are kept.
82
+ trimBlockBoundaryWhitespace(texts) {
83
+ const trimmed = [...texts];
84
+ const trimEdge = (direction) => {
85
+ for (let i = direction === "start" ? 0 : trimmed.length - 1; i >= 0 && i < trimmed.length; ) {
86
+ const node = trimmed[i];
87
+ if (!Text.isText(node)) {
88
+ return;
89
+ }
90
+ const text = direction === "start" ? node.text.replace(/^[ \t\r\n]+/, "") : node.text.replace(/[ \t\r\n]+$/, "");
91
+ if (text !== "") {
92
+ trimmed[i] = { ...node, text };
93
+ return;
94
+ }
95
+ if (trimmed.length === 1) {
96
+ trimmed[i] = { ...node, text };
97
+ return;
98
+ }
99
+ trimmed.splice(i, 1);
100
+ if (direction === "end") {
101
+ i--;
102
+ }
103
+ }
104
+ };
105
+ trimEdge("start");
106
+ trimEdge("end");
107
+ return trimmed;
75
108
  }
76
109
  deserializeTextNode(node, cumulativeTextAttrs) {
77
110
  if (node.nodeType === Node.TEXT_NODE) {
@@ -1 +1 @@
1
- {"version":3,"file":"HtmlDeserializer.js","sources":["../../../../../../../packages/react-slate-editor-base/src/plugins/behaviour/paste/HtmlDeserializer.ts"],"sourcesContent":["import { Descendant, Element as SlateElement, Text as SlateText } from 'slate'\nimport { HtmlDeserializerNextCallback, HtmlDeserializerPlugin } from '../../../types/htmlDeserializer'\nimport { EditorDefaultElementFactory } from '../../../types/editor'\n\nconst ignoredElements = ['SCRIPT', 'STYLE', 'TEMPLATE']\n\nexport interface TextAttrs {\n\t[key: string]: any\n}\n\nexport type NodesWithTypeFiltered =\n\t| { texts: Descendant[]; elements?: undefined }\n\t| { elements: SlateElement[]; texts?: undefined }\n\nexport type NodesWithType = NodesWithTypeFiltered | null\n\nexport class HtmlDeserializer {\n\tconstructor(\n\t\tpublic createDefaultElement: EditorDefaultElementFactory,\n\t\tprivate plugins: HtmlDeserializerPlugin[],\n\t) {\n\t}\n\n\tregisterPlugin(plugin: HtmlDeserializerPlugin, prepend: boolean = true) {\n\t\tprepend ? this.plugins.unshift(plugin) : this.plugins.push(plugin)\n\t}\n\n\tpublic processNodeListPaste(nodeList: Node[], cumulativeTextAttrs: TextAttrs) {\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processNodeListPaste?.({ nodeList, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\tconst processed: (\n\t\t\t| { text: SlateText | SlateElement; element?: undefined; isWhiteSpace: boolean }\n\t\t\t| { element: SlateElement; text?: undefined }\n\t\t)[] = []\n\n\t\tfor (const childNode of nodeList) {\n\t\t\tconst isWhiteSpace = childNode.nodeType === Node.TEXT_NODE && childNode.textContent?.match(/^\\s*$/) !== null\n\n\t\t\t// Block\n\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\tconst result = childNode instanceof HTMLElement\n\t\t\t\t? this.processBlockPaste(\n\t\t\t\t\tchildNode,\n\t\t\t\t\tcumulativeTextAttrs,\n\t\t\t\t)\n\t\t\t\t: null\n\t\t\tif (result !== null) {\n\t\t\t\tprocessed.push(...(Array.isArray(result) ? result : [result]).map(element => ({ element })))\n\t\t\t} else {\n\t\t\t\t// Inline\n\t\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\t\tif (result !== null) {\n\t\t\t\t\tprocessed.push(...result.map(text => ({ text, isWhiteSpace })))\n\t\t\t\t} else {\n\t\t\t\t\t// Unknown element\n\t\t\t\t\tconst deserializedChildren = this.processNodeListPaste(\n\t\t\t\t\t\tArray.from(childNode.childNodes),\n\t\t\t\t\t\tattrs,\n\t\t\t\t\t)\n\t\t\t\t\tprocessed.push(\n\t\t\t\t\t\t...(deserializedChildren === null\n\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t: deserializedChildren.texts !== undefined\n\t\t\t\t\t\t\t? deserializedChildren.texts.map(text => ({ text, isWhiteSpace }))\n\t\t\t\t\t\t\t: deserializedChildren.elements.map(element => ({ element }))),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (processed.length === 0) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst containsBlock = processed.find(({ element }) => element !== undefined) !== undefined\n\n\t\tif (containsBlock) {\n\t\t\treturn {\n\t\t\t\telements: processed.flatMap(item => {\n\t\t\t\t\tif (item.text !== undefined) {\n\t\t\t\t\t\treturn item.isWhiteSpace ? [] : [this.createDefaultElement([item.text])]\n\t\t\t\t\t} else if (item.element !== undefined) {\n\t\t\t\t\t\treturn [item.element]\n\t\t\t\t\t}\n\t\t\t\t\treturn []\n\t\t\t\t}),\n\t\t\t}\n\t\t} else {\n\t\t\treturn { texts: processed.map(item => item.text as SlateText) }\n\t\t}\n\t}\n\n\tdeserializeInline(list: NodeList | Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\treturn Array.from(list).flatMap(childNode => {\n\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t} else {\n\t\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\t\treturn this.deserializeInline(childNode.childNodes, attrs)\n\t\t\t}\n\t\t})\n\t}\n\n\tdeserializeBlocks(list: Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\tconst result = this.processNodeListPaste(list, cumulativeTextAttrs)\n\t\treturn result?.texts ?? result?.elements ?? []\n\t}\n\n\tprivate deserializeTextNode(node: Node, cumulativeTextAttrs: TextAttrs): Descendant[] | null {\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = node.textContent ?? ''\n\t\t\treturn [{ ...cumulativeTextAttrs, text: text.replace(/[ \\t]*(?:\\r?\\n[ \\t]*)+/g, ' ') }]\n\t\t} else if (node instanceof HTMLElement) {\n\t\t\tconst result = this.processInlinePaste(\n\t\t\t\tnode,\n\t\t\t\tcumulativeTextAttrs,\n\t\t\t)\n\t\t\tif (result !== null) {\n\t\t\t\treturn Array.isArray(result) ? result : [result]\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate processInlinePaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): (SlateElement | SlateText)[] | SlateElement | SlateText | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tif (element.tagName === 'BR') {\n\t\t\treturn { ...cumulativeTextAttrs, text: ' ' }\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => {\n\t\t\tconst attrs = this.processWithAttributeProcessor(element, cta)\n\t\t\treturn this.deserializeInline(list, attrs)\n\t\t}\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processInlinePaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n\n\tprivate processWithAttributeProcessor(element: Node, cumulativeTextAttrs: TextAttrs): TextAttrs {\n\t\tif (!(element instanceof HTMLElement)) {\n\t\t\treturn {}\n\t\t}\n\t\treturn this.plugins.reduce(\n\t\t\t(cta, plugin) => plugin.processAttributesPaste?.({ element, cumulativeTextAttrs, deserializer: this }) ?? cta,\n\t\t\tcumulativeTextAttrs,\n\t\t)\n\t}\n\n\tprivate processBlockPaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): SlateElement[] | SlateElement | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => this.deserializeBlocks(Array.from(list), { ...cumulativeTextAttrs, ...cta })\n\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processBlockPaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n}\n"],"names":["result"],"mappings":"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"}
1
+ {"version":3,"file":"HtmlDeserializer.js","sources":["../../../../../../../packages/react-slate-editor-base/src/plugins/behaviour/paste/HtmlDeserializer.ts"],"sourcesContent":["import { Descendant, Element as SlateElement, Text as SlateText } from 'slate'\nimport { HtmlDeserializerNextCallback, HtmlDeserializerPlugin } from '../../../types/htmlDeserializer'\nimport { EditorDefaultElementFactory } from '../../../types/editor'\n\nconst ignoredElements = ['SCRIPT', 'STYLE', 'TEMPLATE']\n\nexport interface TextAttrs {\n\t[key: string]: any\n}\n\nexport type NodesWithTypeFiltered =\n\t| { texts: Descendant[]; elements?: undefined }\n\t| { elements: SlateElement[]; texts?: undefined }\n\nexport type NodesWithType = NodesWithTypeFiltered | null\n\nexport class HtmlDeserializer {\n\tconstructor(\n\t\tpublic createDefaultElement: EditorDefaultElementFactory,\n\t\tprivate plugins: HtmlDeserializerPlugin[],\n\t) {\n\t}\n\n\tregisterPlugin(plugin: HtmlDeserializerPlugin, prepend: boolean = true) {\n\t\tprepend ? this.plugins.unshift(plugin) : this.plugins.push(plugin)\n\t}\n\n\tpublic processNodeListPaste(nodeList: Node[], cumulativeTextAttrs: TextAttrs) {\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processNodeListPaste?.({ nodeList, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\tconst processed: (\n\t\t\t| { text: SlateText | SlateElement; element?: undefined; isWhiteSpace: boolean }\n\t\t\t| { element: SlateElement; text?: undefined }\n\t\t)[] = []\n\n\t\tfor (const childNode of nodeList) {\n\t\t\tconst isWhiteSpace = childNode.nodeType === Node.TEXT_NODE && childNode.textContent?.match(/^\\s*$/) !== null\n\n\t\t\t// Block\n\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\tconst result = childNode instanceof HTMLElement\n\t\t\t\t? this.processBlockPaste(\n\t\t\t\t\tchildNode,\n\t\t\t\t\tcumulativeTextAttrs,\n\t\t\t\t)\n\t\t\t\t: null\n\t\t\tif (result !== null) {\n\t\t\t\tprocessed.push(...(Array.isArray(result) ? result : [result]).map(element => ({ element })))\n\t\t\t} else {\n\t\t\t\t// Inline\n\t\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\t\tif (result !== null) {\n\t\t\t\t\tprocessed.push(...result.map(text => ({ text, isWhiteSpace })))\n\t\t\t\t} else {\n\t\t\t\t\t// Unknown element\n\t\t\t\t\tconst deserializedChildren = this.processNodeListPaste(\n\t\t\t\t\t\tArray.from(childNode.childNodes),\n\t\t\t\t\t\tattrs,\n\t\t\t\t\t)\n\t\t\t\t\tprocessed.push(\n\t\t\t\t\t\t...(deserializedChildren === null\n\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t: deserializedChildren.texts !== undefined\n\t\t\t\t\t\t\t? deserializedChildren.texts.map(text => ({ text, isWhiteSpace }))\n\t\t\t\t\t\t\t: deserializedChildren.elements.map(element => ({ element }))),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (processed.length === 0) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst containsBlock = processed.find(({ element }) => element !== undefined) !== undefined\n\n\t\tif (containsBlock) {\n\t\t\treturn {\n\t\t\t\telements: processed.flatMap(item => {\n\t\t\t\t\tif (item.text !== undefined) {\n\t\t\t\t\t\treturn item.isWhiteSpace ? [] : [this.createDefaultElement(this.trimBlockBoundaryWhitespace([item.text]))]\n\t\t\t\t\t} else if (item.element !== undefined) {\n\t\t\t\t\t\treturn [item.element]\n\t\t\t\t\t}\n\t\t\t\t\treturn []\n\t\t\t\t}),\n\t\t\t}\n\t\t} else {\n\t\t\treturn { texts: processed.map(item => item.text as SlateText) }\n\t\t}\n\t}\n\n\tdeserializeInline(list: NodeList | Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\treturn Array.from(list).flatMap(childNode => {\n\t\t\tconst result = this.deserializeTextNode(childNode, cumulativeTextAttrs)\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t} else {\n\t\t\t\tconst attrs = this.processWithAttributeProcessor(childNode, cumulativeTextAttrs)\n\t\t\t\treturn this.deserializeInline(childNode.childNodes, attrs)\n\t\t\t}\n\t\t})\n\t}\n\n\tdeserializeBlocks(list: Node[], cumulativeTextAttrs: TextAttrs): Descendant[] {\n\t\tconst result = this.processNodeListPaste(list, cumulativeTextAttrs)\n\t\tif (result?.texts !== undefined) {\n\t\t\treturn this.trimBlockBoundaryWhitespace(result.texts)\n\t\t}\n\t\treturn result?.elements ?? []\n\t}\n\n\t// Collapsible whitespace at the start/end of a block renders as nothing in HTML,\n\t// so strip it from the edges of a block's inline content. Non-breaking spaces are kept.\n\tprivate trimBlockBoundaryWhitespace(texts: Descendant[]): Descendant[] {\n\t\tconst trimmed = [...texts]\n\t\tconst trimEdge = (direction: 'start' | 'end') => {\n\t\t\tfor (let i = direction === 'start' ? 0 : trimmed.length - 1; i >= 0 && i < trimmed.length;) {\n\t\t\t\tconst node = trimmed[i]\n\t\t\t\tif (!SlateText.isText(node)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst text = direction === 'start' ? node.text.replace(/^[ \\t\\r\\n]+/, '') : node.text.replace(/[ \\t\\r\\n]+$/, '')\n\t\t\t\tif (text !== '') {\n\t\t\t\t\ttrimmed[i] = { ...node, text }\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif (trimmed.length === 1) {\n\t\t\t\t\ttrimmed[i] = { ...node, text }\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\ttrimmed.splice(i, 1)\n\t\t\t\tif (direction === 'end') {\n\t\t\t\t\ti--\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\ttrimEdge('start')\n\t\ttrimEdge('end')\n\t\treturn trimmed\n\t}\n\n\tprivate deserializeTextNode(node: Node, cumulativeTextAttrs: TextAttrs): Descendant[] | null {\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\tconst text = node.textContent ?? ''\n\t\t\treturn [{ ...cumulativeTextAttrs, text: text.replace(/[ \\t]*(?:\\r?\\n[ \\t]*)+/g, ' ') }]\n\t\t} else if (node instanceof HTMLElement) {\n\t\t\tconst result = this.processInlinePaste(\n\t\t\t\tnode,\n\t\t\t\tcumulativeTextAttrs,\n\t\t\t)\n\t\t\tif (result !== null) {\n\t\t\t\treturn Array.isArray(result) ? result : [result]\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate processInlinePaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): (SlateElement | SlateText)[] | SlateElement | SlateText | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tif (element.tagName === 'BR') {\n\t\t\treturn { ...cumulativeTextAttrs, text: ' ' }\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => {\n\t\t\tconst attrs = this.processWithAttributeProcessor(element, cta)\n\t\t\treturn this.deserializeInline(list, attrs)\n\t\t}\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processInlinePaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n\n\tprivate processWithAttributeProcessor(element: Node, cumulativeTextAttrs: TextAttrs): TextAttrs {\n\t\tif (!(element instanceof HTMLElement)) {\n\t\t\treturn {}\n\t\t}\n\t\treturn this.plugins.reduce(\n\t\t\t(cta, plugin) => plugin.processAttributesPaste?.({ element, cumulativeTextAttrs, deserializer: this }) ?? cta,\n\t\t\tcumulativeTextAttrs,\n\t\t)\n\t}\n\n\tprivate processBlockPaste(element: HTMLElement, cumulativeTextAttrs: TextAttrs): SlateElement[] | SlateElement | null {\n\t\tif (ignoredElements.includes(element.tagName)) {\n\t\t\treturn []\n\t\t}\n\t\tconst next: HtmlDeserializerNextCallback = (list, cta) => this.deserializeBlocks(Array.from(list), { ...cumulativeTextAttrs, ...cta })\n\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst result = plugin.processBlockPaste?.({ element, next, cumulativeTextAttrs, deserializer: this }) ?? null\n\t\t\tif (result !== null) {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n}\n"],"names":["result","SlateText"],"mappings":"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"}
@@ -26,6 +26,7 @@ export declare class HtmlDeserializer {
26
26
  } | null;
27
27
  deserializeInline(list: NodeList | Node[], cumulativeTextAttrs: TextAttrs): Descendant[];
28
28
  deserializeBlocks(list: Node[], cumulativeTextAttrs: TextAttrs): Descendant[];
29
+ private trimBlockBoundaryWhitespace;
29
30
  private deserializeTextNode;
30
31
  private processInlinePaste;
31
32
  private processWithAttributeProcessor;
@@ -1 +1 @@
1
- {"version":3,"file":"HtmlDeserializer.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/behaviour/paste/HtmlDeserializer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,IAAI,YAAY,EAAqB,MAAM,OAAO,CAAA;AAC9E,OAAO,EAAgC,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AACtG,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AAInE,MAAM,WAAW,SAAS;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAClB;AAED,MAAM,MAAM,qBAAqB,GAC9B;IAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,GAC7C;IAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,CAAA;AAElD,MAAM,MAAM,aAAa,GAAG,qBAAqB,GAAG,IAAI,CAAA;AAExD,qBAAa,gBAAgB;IAEpB,oBAAoB,EAAE,2BAA2B;IACxD,OAAO,CAAC,OAAO;gBADR,oBAAoB,EAAE,2BAA2B,EAChD,OAAO,EAAE,sBAAsB,EAAE;IAI1C,cAAc,CAAC,MAAM,EAAE,sBAAsB,EAAE,OAAO,GAAE,OAAc;IAI/D,oBAAoB,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,mBAAmB,EAAE,SAAS;;;;;;;IAqE5E,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,EAAE,EAAE,mBAAmB,EAAE,SAAS,GAAG,UAAU,EAAE;IAYxF,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,mBAAmB,EAAE,SAAS,GAAG,UAAU,EAAE;IAK7E,OAAO,CAAC,mBAAmB;IAiB3B,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,6BAA6B;IAUrC,OAAO,CAAC,iBAAiB;CAczB"}
1
+ {"version":3,"file":"HtmlDeserializer.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/behaviour/paste/HtmlDeserializer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,IAAI,YAAY,EAAqB,MAAM,OAAO,CAAA;AAC9E,OAAO,EAAgC,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AACtG,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AAInE,MAAM,WAAW,SAAS;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAClB;AAED,MAAM,MAAM,qBAAqB,GAC9B;IAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,GAC7C;IAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,CAAA;AAElD,MAAM,MAAM,aAAa,GAAG,qBAAqB,GAAG,IAAI,CAAA;AAExD,qBAAa,gBAAgB;IAEpB,oBAAoB,EAAE,2BAA2B;IACxD,OAAO,CAAC,OAAO;gBADR,oBAAoB,EAAE,2BAA2B,EAChD,OAAO,EAAE,sBAAsB,EAAE;IAI1C,cAAc,CAAC,MAAM,EAAE,sBAAsB,EAAE,OAAO,GAAE,OAAc;IAI/D,oBAAoB,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,mBAAmB,EAAE,SAAS;;;;;;;IAqE5E,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,EAAE,EAAE,mBAAmB,EAAE,SAAS,GAAG,UAAU,EAAE;IAYxF,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,mBAAmB,EAAE,SAAS,GAAG,UAAU,EAAE;IAU7E,OAAO,CAAC,2BAA2B;IA4BnC,OAAO,CAAC,mBAAmB;IAiB3B,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,6BAA6B;IAUrC,OAAO,CAAC,iBAAiB;CAczB"}