@portabletext/html 1.0.0 → 1.0.2
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.
|
@@ -167,8 +167,6 @@ const PRESERVE_WHITESPACE_TAGS = ["pre", "textarea", "code"], BLOCK_DEFAULT_STYL
|
|
|
167
167
|
h4: { ...DEFAULT_BLOCK, style: "h4" },
|
|
168
168
|
h5: { ...DEFAULT_BLOCK, style: "h5" },
|
|
169
169
|
h6: { ...DEFAULT_BLOCK, style: "h6" }
|
|
170
|
-
}, HTML_MISC_TAGS = {
|
|
171
|
-
br: { ...DEFAULT_BLOCK, style: BLOCK_DEFAULT_STYLE }
|
|
172
170
|
}, HTML_DECORATOR_TAGS = {
|
|
173
171
|
b: "strong",
|
|
174
172
|
strong: "strong",
|
|
@@ -191,23 +189,7 @@ const PRESERVE_WHITESPACE_TAGS = ["pre", "textarea", "code"], BLOCK_DEFAULT_STYL
|
|
|
191
189
|
level: 1,
|
|
192
190
|
listItem: "bullet"
|
|
193
191
|
}
|
|
194
|
-
},
|
|
195
|
-
...HTML_BLOCK_TAGS,
|
|
196
|
-
...HTML_SPAN_TAGS,
|
|
197
|
-
...HTML_LIST_CONTAINER_TAGS,
|
|
198
|
-
...HTML_LIST_ITEM_TAGS,
|
|
199
|
-
...HTML_HEADER_TAGS,
|
|
200
|
-
...HTML_MISC_TAGS
|
|
201
|
-
};
|
|
202
|
-
[
|
|
203
|
-
...new Set(
|
|
204
|
-
Object.values(ELEMENT_MAP).filter((tag) => "style" in tag).map((tag) => tag.style)
|
|
205
|
-
)
|
|
206
|
-
];
|
|
207
|
-
[
|
|
208
|
-
...new Set(Object.values(HTML_DECORATOR_TAGS))
|
|
209
|
-
];
|
|
210
|
-
const objectToString = Object.prototype.toString;
|
|
192
|
+
}, objectToString = Object.prototype.toString;
|
|
211
193
|
function resolveJsType(val) {
|
|
212
194
|
switch (objectToString.call(val)) {
|
|
213
195
|
case "[object Function]":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sources":["../../src/types.ts","../../src/deserializer/equality.ts","../../src/deserializer/flatten-nested-blocks.ts","../../src/deserializer/constants.ts","../../src/deserializer/resolve-js-type.ts","../../src/deserializer/helpers.ts"],"sourcesContent":["import type {PortableTextObject} from '@portabletext/schema'\n\n/**\n * @public\n */\nexport interface TypedObject {\n _type: string\n _key?: string\n}\n\n/**\n * @public\n */\nexport interface ArbitraryTypedObject extends TypedObject {\n [key: string]: unknown\n}\n\nexport function isArbitraryTypedObject(\n object: unknown,\n): object is ArbitraryTypedObject {\n return isRecord(object) && typeof object['_type'] === 'string'\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && (typeof value === 'object' || typeof value === 'function')\n}\n\nexport interface MinimalSpan {\n _type: 'span'\n _key?: string\n text: string\n marks?: string[]\n}\n\nexport interface MinimalBlock extends TypedObject {\n _type: 'block'\n children: TypedObject[]\n markDefs?: TypedObject[]\n style?: string\n level?: number\n listItem?: string\n}\n\nexport interface PlaceholderDecorator {\n _type: '__decorator'\n name: string\n children: TypedObject[]\n}\n\nexport interface PlaceholderAnnotation {\n _type: '__annotation'\n markDef: PortableTextObject\n children: TypedObject[]\n}\n\n/**\n * @public\n */\nexport type HtmlParser = (html: string) => Document\n\n/**\n * @public\n */\nexport interface DeserializerRule {\n deserialize: (\n el: Node,\n next: (\n elements: Node | Node[] | NodeList,\n ) => TypedObject | TypedObject[] | undefined,\n createBlock: (props: ArbitraryTypedObject) => {\n _type: string\n block: ArbitraryTypedObject\n },\n ) => TypedObject | TypedObject[] | undefined\n}\n","export function isEqualMarks(\n a: Array<string> | undefined,\n b: Array<string> | undefined,\n): boolean {\n if (!a || !b) {\n return a === b\n }\n\n if (a.length !== b.length) {\n return false\n }\n\n for (let index = 0; index < a.length; index++) {\n if (a[index] !== b[index]) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * More or less copied from Remeda (https://github.com/remeda/remeda/blob/main/packages/remeda/src/isDeepEqual.ts)\n */\nexport function isDeepEqual<A, B>(data: A, other: B) {\n return isDeepEqualImplementation(data, other)\n}\n\nfunction isDeepEqualImplementation<T>(data: unknown, other: T): data is T {\n if (data === other) {\n return true\n }\n\n if (Object.is(data, other)) {\n // We want to ignore the slight differences between `===` and `Object.is` as\n // both of them largely define equality from a semantic point-of-view.\n return true\n }\n\n if (typeof data !== 'object' || typeof other !== 'object') {\n return false\n }\n\n if (data === null || other === null) {\n return false\n }\n\n if (Object.getPrototypeOf(data) !== Object.getPrototypeOf(other)) {\n // If the objects don't share a prototype it's unlikely that they are\n // semantically equal. It is technically possible to build 2 prototypes that\n // act the same but are not equal (at the reference level, checked via\n // `===`) and then create 2 objects that are equal although we would fail on\n // them. Because this is so unlikely, the optimization we gain here for the\n // rest of the function by assuming that `other` is of the same type as\n // `data` is more than worth it.\n return false\n }\n\n if (Array.isArray(data)) {\n return isDeepEqualArrays(data, other as unknown as ReadonlyArray<unknown>)\n }\n\n if (data instanceof Map) {\n return isDeepEqualMaps(data, other as unknown as Map<unknown, unknown>)\n }\n\n if (data instanceof Set) {\n return isDeepEqualSets(data, other as unknown as Set<unknown>)\n }\n\n if (data instanceof Date) {\n return data.getTime() === (other as unknown as Date).getTime()\n }\n\n if (data instanceof RegExp) {\n return data.toString() === (other as unknown as RegExp).toString()\n }\n\n // At this point we only know that the 2 objects share a prototype and are not\n // any of the previous types. They could be plain objects (Object.prototype),\n // they could be classes, they could be other built-ins, or they could be\n // something weird. We assume that comparing values by keys is enough to judge\n // their equality.\n\n if (Object.keys(data).length !== Object.keys(other).length) {\n return false\n }\n\n for (const [key, value] of Object.entries(data)) {\n if (!(key in other)) {\n return false\n }\n\n if (\n !isDeepEqualImplementation(\n value,\n // @ts-expect-error [ts7053] - We already checked that `other` has `key`\n other[key],\n )\n ) {\n return false\n }\n }\n\n return true\n}\n\nfunction isDeepEqualArrays(\n data: ReadonlyArray<unknown>,\n other: ReadonlyArray<unknown>,\n): boolean {\n if (data.length !== other.length) {\n return false\n }\n\n for (const [index, item] of data.entries()) {\n if (!isDeepEqualImplementation(item, other[index])) {\n return false\n }\n }\n\n return true\n}\n\nfunction isDeepEqualMaps(\n data: ReadonlyMap<unknown, unknown>,\n other: ReadonlyMap<unknown, unknown>,\n): boolean {\n if (data.size !== other.size) {\n return false\n }\n\n for (const [key, value] of data.entries()) {\n if (!other.has(key)) {\n return false\n }\n\n if (!isDeepEqualImplementation(value, other.get(key))) {\n return false\n }\n }\n\n return true\n}\n\nfunction isDeepEqualSets(\n data: ReadonlySet<unknown>,\n other: ReadonlySet<unknown>,\n): boolean {\n if (data.size !== other.size) {\n return false\n }\n\n // To ensure we only count each item once we need to \"remember\" which items of\n // the other set we've already matched against. We do this by creating a copy\n // of the other set and removing items from it as we find them in the data\n // set.\n const otherCopy = [...other]\n\n for (const dataItem of data) {\n let isFound = false\n\n for (const [index, otherItem] of otherCopy.entries()) {\n if (isDeepEqualImplementation(dataItem, otherItem)) {\n isFound = true\n otherCopy.splice(index, 1)\n break\n }\n }\n\n if (!isFound) {\n return false\n }\n }\n\n return true\n}\n","import type {Schema} from '@portabletext/schema'\nimport {\n isSpan,\n isTextBlock,\n type PortableTextBlock,\n type PortableTextObject,\n type PortableTextSpan,\n type PortableTextTextBlock,\n} from '@portabletext/schema'\nimport {\n isArbitraryTypedObject,\n type ArbitraryTypedObject,\n type TypedObject,\n} from '../types'\nimport {isDeepEqual} from './equality'\n\nexport function flattenNestedBlocks(\n context: {\n schema: Schema\n },\n blocks: Array<ArbitraryTypedObject>,\n): TypedObject[] {\n const flattened = blocks.flatMap((block) => {\n if (isBlockContainer(block)) {\n return flattenNestedBlocks(context, [block.block])\n }\n\n if (isTextBlock(context, block)) {\n const hasBlockObjects = block.children.some((child) => {\n const knownBlockObject = context.schema.blockObjects.some(\n (blockObject) => blockObject.name === child._type,\n )\n return knownBlockObject\n })\n const hasBlocks = block.children.some(\n (child) => child._type === '__block' || child._type === 'block',\n )\n\n if (hasBlockObjects || hasBlocks) {\n const splitChildren = getSplitChildren(context, block)\n\n const firstSlice = splitChildren[0]\n if (\n splitChildren.length === 1 &&\n firstSlice &&\n firstSlice.type === 'children' &&\n isDeepEqual(firstSlice.children, block.children)\n ) {\n return [block]\n }\n\n return splitChildren.flatMap((slice) => {\n if (slice.type === 'block object') {\n return [slice.block]\n }\n\n if (slice.type === 'block') {\n return flattenNestedBlocks(context, [\n slice.block as ArbitraryTypedObject,\n ])\n }\n\n if (slice.children.length > 0) {\n if (\n slice.children.every(\n (child) => isSpan(context, child) && child.text.trim() === '',\n )\n ) {\n return []\n }\n\n return flattenNestedBlocks(context, [\n {\n ...block,\n children: slice.children,\n },\n ])\n }\n\n return []\n })\n }\n\n return [block]\n }\n\n return [block]\n })\n\n return flattened\n}\n\nfunction isBlockContainer(\n block: ArbitraryTypedObject,\n): block is BlockContainer {\n return block['_type'] === '__block' && isArbitraryTypedObject(block['block'])\n}\n\ntype BlockContainer = {\n _type: '__block'\n block: ArbitraryTypedObject\n}\n\nfunction getSplitChildren(\n context: {schema: Schema},\n block: PortableTextTextBlock,\n) {\n return block.children.reduce(\n (slices, child) => {\n const knownInlineObject = context.schema.inlineObjects.some(\n (inlineObject) => inlineObject.name === child._type,\n )\n const knownBlockObject = context.schema.blockObjects.some(\n (blockObject) => blockObject.name === child._type,\n )\n\n const lastSlice = slices.pop()\n\n if (!isSpan(context, child) && !knownInlineObject) {\n if (knownBlockObject) {\n return [\n ...slices,\n ...(lastSlice ? [lastSlice] : []),\n {type: 'block object' as const, block: child},\n ]\n }\n }\n\n if (child._type === '__block') {\n return [\n ...slices,\n ...(lastSlice ? [lastSlice] : []),\n {\n type: 'block object' as const,\n block: (child as any).block,\n },\n ]\n }\n\n if (child._type === 'block') {\n return [\n ...slices,\n ...(lastSlice ? [lastSlice] : []),\n {type: 'block' as const, block: child},\n ]\n }\n\n if (lastSlice) {\n if (lastSlice.type === 'children') {\n return [\n ...slices,\n {\n type: 'children' as const,\n children: [...lastSlice.children, child],\n },\n ]\n }\n }\n\n return [\n ...slices,\n ...(lastSlice ? [lastSlice] : []),\n {type: 'children' as const, children: [child]},\n ]\n },\n [] as Array<\n | {\n type: 'children'\n children: Array<PortableTextSpan | PortableTextObject>\n }\n | {type: 'block object'; block: PortableTextObject}\n | {type: 'block'; block: PortableTextBlock}\n >,\n )\n}\n","export interface PartialBlock {\n _type: string\n markDefs: string[]\n style: string\n level?: number\n listItem?: string\n}\n\nexport const PRESERVE_WHITESPACE_TAGS = ['pre', 'textarea', 'code']\n\nexport const BLOCK_DEFAULT_STYLE = 'normal'\n\nexport const DEFAULT_BLOCK: PartialBlock = Object.freeze({\n _type: 'block',\n markDefs: [],\n style: BLOCK_DEFAULT_STYLE,\n})\n\nexport const DEFAULT_SPAN = Object.freeze({\n _type: 'span',\n marks: [] as string[],\n})\n\nexport const HTML_BLOCK_TAGS = {\n p: DEFAULT_BLOCK,\n blockquote: {...DEFAULT_BLOCK, style: 'blockquote'} as PartialBlock,\n}\n\nexport const HTML_SPAN_TAGS = {\n span: {object: 'text'},\n}\n\nexport const HTML_LIST_CONTAINER_TAGS: Record<\n string,\n {object: null} | undefined\n> = {\n ol: {object: null},\n ul: {object: null},\n}\n\nexport const HTML_HEADER_TAGS: Record<string, PartialBlock | undefined> = {\n h1: {...DEFAULT_BLOCK, style: 'h1'},\n h2: {...DEFAULT_BLOCK, style: 'h2'},\n h3: {...DEFAULT_BLOCK, style: 'h3'},\n h4: {...DEFAULT_BLOCK, style: 'h4'},\n h5: {...DEFAULT_BLOCK, style: 'h5'},\n h6: {...DEFAULT_BLOCK, style: 'h6'},\n}\n\nexport const HTML_MISC_TAGS = {\n br: {...DEFAULT_BLOCK, style: BLOCK_DEFAULT_STYLE} as PartialBlock,\n}\n\nexport const HTML_DECORATOR_TAGS: Record<string, string | undefined> = {\n b: 'strong',\n strong: 'strong',\n\n i: 'em',\n em: 'em',\n\n u: 'underline',\n s: 'strike-through',\n strike: 'strike-through',\n del: 'strike-through',\n\n code: 'code',\n sup: 'sup',\n sub: 'sub',\n ins: 'ins',\n mark: 'mark',\n small: 'small',\n}\n\nexport const HTML_LIST_ITEM_TAGS: Record<string, PartialBlock | undefined> = {\n li: {\n ...DEFAULT_BLOCK,\n style: BLOCK_DEFAULT_STYLE,\n level: 1,\n listItem: 'bullet',\n },\n}\n\nexport const ELEMENT_MAP = {\n ...HTML_BLOCK_TAGS,\n ...HTML_SPAN_TAGS,\n ...HTML_LIST_CONTAINER_TAGS,\n ...HTML_LIST_ITEM_TAGS,\n ...HTML_HEADER_TAGS,\n ...HTML_MISC_TAGS,\n}\n\nexport const DEFAULT_SUPPORTED_STYLES = [\n ...new Set(\n Object.values(ELEMENT_MAP)\n .filter((tag): tag is PartialBlock => 'style' in tag)\n .map((tag) => tag.style),\n ),\n]\n\nexport const DEFAULT_SUPPORTED_DECORATORS = [\n ...new Set(Object.values(HTML_DECORATOR_TAGS)),\n]\n\nexport const DEFAULT_SUPPORTED_ANNOTATIONS = ['link']\n","const objectToString = Object.prototype.toString\n\n// Copied from https://github.com/ForbesLindesay/type-of\n// but inlined to have fine grained control\nexport function resolveJsType(val: unknown) {\n switch (objectToString.call(val)) {\n case '[object Function]':\n return 'function'\n case '[object Date]':\n return 'date'\n case '[object RegExp]':\n return 'regexp'\n case '[object Arguments]':\n return 'arguments'\n case '[object Array]':\n return 'array'\n case '[object String]':\n return 'string'\n default:\n }\n\n if (val === null) {\n return 'null'\n }\n\n if (val === undefined) {\n return 'undefined'\n }\n\n if (\n val &&\n typeof val === 'object' &&\n 'nodeType' in val &&\n (val as {nodeType: unknown}).nodeType === 1\n ) {\n return 'element'\n }\n\n if (val === Object(val)) {\n return 'object'\n }\n\n return typeof val\n}\n","import type {Schema} from '@portabletext/schema'\nimport {isTextBlock, type PortableTextObject} from '@portabletext/schema'\nimport type {\n ArbitraryTypedObject,\n HtmlParser,\n MinimalBlock,\n MinimalSpan,\n PlaceholderAnnotation,\n PlaceholderDecorator,\n TypedObject,\n} from '../types'\nimport {DEFAULT_BLOCK} from './constants'\nimport {resolveJsType} from './resolve-js-type'\n\n/**\n * Utility function that always return a lowerCase version of the element.tagName\n *\n * @param el - Element to get tag name for\n * @returns Lowercase tagName for that element, or undefined if not an element\n */\nexport function tagName(el: HTMLElement | Node | null): string | undefined {\n if (el && 'tagName' in el) {\n return el.tagName.toLowerCase()\n }\n\n return undefined\n}\n\n/**\n * A default `parseHtml` function that returns the html using `DOMParser`.\n *\n * @returns HTML Parser based on `DOMParser`\n */\nexport function defaultParseHtml(): HtmlParser {\n if (resolveJsType(DOMParser) === 'undefined') {\n throw new Error(\n 'The native `DOMParser` global which the `Html` deserializer uses by ' +\n 'default is not present in this environment. ' +\n 'You must supply the `options.parseHtml` function instead.',\n )\n }\n return (html) => {\n return new DOMParser().parseFromString(html, 'text/html')\n }\n}\n\nexport function ensureRootIsBlocks(\n schema: Schema,\n objects: Array<ArbitraryTypedObject>,\n): ArbitraryTypedObject[] {\n return objects.reduce((blocks, node, i, original) => {\n if (node._type === 'block') {\n blocks.push(node)\n return blocks\n }\n\n if (node._type === '__block') {\n blocks.push((node as any).block)\n return blocks\n }\n\n const lastBlock = blocks[blocks.length - 1]\n if (\n i > 0 &&\n !isTextBlock({schema}, original[i - 1]) &&\n isTextBlock({schema}, lastBlock)\n ) {\n lastBlock.children.push(node as PortableTextObject)\n return blocks\n }\n\n const block = {\n ...DEFAULT_BLOCK,\n children: [node],\n }\n\n blocks.push(block)\n return blocks\n }, [] as ArbitraryTypedObject[])\n}\n\nexport function isNodeList(node: unknown): node is NodeList {\n return Object.prototype.toString.call(node) === '[object NodeList]'\n}\n\nexport function isMinimalSpan(node: TypedObject): node is MinimalSpan {\n return node._type === 'span'\n}\n\nexport function isMinimalBlock(node: TypedObject): node is MinimalBlock {\n return node._type === 'block'\n}\n\nexport function isPlaceholderDecorator(\n node: TypedObject,\n): node is PlaceholderDecorator {\n return node._type === '__decorator'\n}\n\nexport function isPlaceholderAnnotation(\n node: TypedObject,\n): node is PlaceholderAnnotation {\n return node._type === '__annotation'\n}\n\nexport function isElement(node: Node): node is Element {\n return node.nodeType === 1\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"helpers.js","sources":["../../src/types.ts","../../src/deserializer/equality.ts","../../src/deserializer/flatten-nested-blocks.ts","../../src/deserializer/constants.ts","../../src/deserializer/resolve-js-type.ts","../../src/deserializer/helpers.ts"],"sourcesContent":["import type {PortableTextObject} from '@portabletext/schema'\n\n/**\n * @public\n */\nexport interface TypedObject {\n _type: string\n _key?: string\n}\n\n/**\n * @public\n */\nexport interface ArbitraryTypedObject extends TypedObject {\n [key: string]: unknown\n}\n\nexport function isArbitraryTypedObject(\n object: unknown,\n): object is ArbitraryTypedObject {\n return isRecord(object) && typeof object['_type'] === 'string'\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && (typeof value === 'object' || typeof value === 'function')\n}\n\nexport interface MinimalSpan {\n _type: 'span'\n _key?: string\n text: string\n marks?: string[]\n}\n\nexport interface MinimalBlock extends TypedObject {\n _type: 'block'\n children: TypedObject[]\n markDefs?: TypedObject[]\n style?: string\n level?: number\n listItem?: string\n}\n\nexport interface PlaceholderDecorator {\n _type: '__decorator'\n name: string\n children: TypedObject[]\n}\n\nexport interface PlaceholderAnnotation {\n _type: '__annotation'\n markDef: PortableTextObject\n children: TypedObject[]\n}\n\n/**\n * @public\n */\nexport type HtmlParser = (html: string) => Document\n\n/**\n * @public\n */\nexport interface DeserializerRule {\n deserialize: (\n el: Node,\n next: (\n elements: Node | Node[] | NodeList,\n ) => TypedObject | TypedObject[] | undefined,\n createBlock: (props: ArbitraryTypedObject) => {\n _type: string\n block: ArbitraryTypedObject\n },\n ) => TypedObject | TypedObject[] | undefined\n}\n","export function isEqualMarks(\n a: Array<string> | undefined,\n b: Array<string> | undefined,\n): boolean {\n if (!a || !b) {\n return a === b\n }\n\n if (a.length !== b.length) {\n return false\n }\n\n for (let index = 0; index < a.length; index++) {\n if (a[index] !== b[index]) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * More or less copied from Remeda (https://github.com/remeda/remeda/blob/main/packages/remeda/src/isDeepEqual.ts)\n */\nexport function isDeepEqual<A, B>(data: A, other: B) {\n return isDeepEqualImplementation(data, other)\n}\n\nfunction isDeepEqualImplementation<T>(data: unknown, other: T): data is T {\n if (data === other) {\n return true\n }\n\n if (Object.is(data, other)) {\n // We want to ignore the slight differences between `===` and `Object.is` as\n // both of them largely define equality from a semantic point-of-view.\n return true\n }\n\n if (typeof data !== 'object' || typeof other !== 'object') {\n return false\n }\n\n if (data === null || other === null) {\n return false\n }\n\n if (Object.getPrototypeOf(data) !== Object.getPrototypeOf(other)) {\n // If the objects don't share a prototype it's unlikely that they are\n // semantically equal. It is technically possible to build 2 prototypes that\n // act the same but are not equal (at the reference level, checked via\n // `===`) and then create 2 objects that are equal although we would fail on\n // them. Because this is so unlikely, the optimization we gain here for the\n // rest of the function by assuming that `other` is of the same type as\n // `data` is more than worth it.\n return false\n }\n\n if (Array.isArray(data)) {\n return isDeepEqualArrays(data, other as unknown as ReadonlyArray<unknown>)\n }\n\n if (data instanceof Map) {\n return isDeepEqualMaps(data, other as unknown as Map<unknown, unknown>)\n }\n\n if (data instanceof Set) {\n return isDeepEqualSets(data, other as unknown as Set<unknown>)\n }\n\n if (data instanceof Date) {\n return data.getTime() === (other as unknown as Date).getTime()\n }\n\n if (data instanceof RegExp) {\n return data.toString() === (other as unknown as RegExp).toString()\n }\n\n // At this point we only know that the 2 objects share a prototype and are not\n // any of the previous types. They could be plain objects (Object.prototype),\n // they could be classes, they could be other built-ins, or they could be\n // something weird. We assume that comparing values by keys is enough to judge\n // their equality.\n\n if (Object.keys(data).length !== Object.keys(other).length) {\n return false\n }\n\n for (const [key, value] of Object.entries(data)) {\n if (!(key in other)) {\n return false\n }\n\n if (\n !isDeepEqualImplementation(\n value,\n // @ts-expect-error [ts7053] - We already checked that `other` has `key`\n other[key],\n )\n ) {\n return false\n }\n }\n\n return true\n}\n\nfunction isDeepEqualArrays(\n data: ReadonlyArray<unknown>,\n other: ReadonlyArray<unknown>,\n): boolean {\n if (data.length !== other.length) {\n return false\n }\n\n for (const [index, item] of data.entries()) {\n if (!isDeepEqualImplementation(item, other[index])) {\n return false\n }\n }\n\n return true\n}\n\nfunction isDeepEqualMaps(\n data: ReadonlyMap<unknown, unknown>,\n other: ReadonlyMap<unknown, unknown>,\n): boolean {\n if (data.size !== other.size) {\n return false\n }\n\n for (const [key, value] of data.entries()) {\n if (!other.has(key)) {\n return false\n }\n\n if (!isDeepEqualImplementation(value, other.get(key))) {\n return false\n }\n }\n\n return true\n}\n\nfunction isDeepEqualSets(\n data: ReadonlySet<unknown>,\n other: ReadonlySet<unknown>,\n): boolean {\n if (data.size !== other.size) {\n return false\n }\n\n // To ensure we only count each item once we need to \"remember\" which items of\n // the other set we've already matched against. We do this by creating a copy\n // of the other set and removing items from it as we find them in the data\n // set.\n const otherCopy = [...other]\n\n for (const dataItem of data) {\n let isFound = false\n\n for (const [index, otherItem] of otherCopy.entries()) {\n if (isDeepEqualImplementation(dataItem, otherItem)) {\n isFound = true\n otherCopy.splice(index, 1)\n break\n }\n }\n\n if (!isFound) {\n return false\n }\n }\n\n return true\n}\n","import type {Schema} from '@portabletext/schema'\nimport {\n isSpan,\n isTextBlock,\n type PortableTextBlock,\n type PortableTextObject,\n type PortableTextSpan,\n type PortableTextTextBlock,\n} from '@portabletext/schema'\nimport {\n isArbitraryTypedObject,\n type ArbitraryTypedObject,\n type TypedObject,\n} from '../types'\nimport {isDeepEqual} from './equality'\n\nexport function flattenNestedBlocks(\n context: {\n schema: Schema\n },\n blocks: Array<ArbitraryTypedObject>,\n): TypedObject[] {\n const flattened = blocks.flatMap((block) => {\n if (isBlockContainer(block)) {\n return flattenNestedBlocks(context, [block.block])\n }\n\n if (isTextBlock(context, block)) {\n const hasBlockObjects = block.children.some((child) => {\n const knownBlockObject = context.schema.blockObjects.some(\n (blockObject) => blockObject.name === child._type,\n )\n return knownBlockObject\n })\n const hasBlocks = block.children.some(\n (child) => child._type === '__block' || child._type === 'block',\n )\n\n if (hasBlockObjects || hasBlocks) {\n const splitChildren = getSplitChildren(context, block)\n\n const firstSlice = splitChildren[0]\n if (\n splitChildren.length === 1 &&\n firstSlice &&\n firstSlice.type === 'children' &&\n isDeepEqual(firstSlice.children, block.children)\n ) {\n return [block]\n }\n\n return splitChildren.flatMap((slice) => {\n if (slice.type === 'block object') {\n return [slice.block]\n }\n\n if (slice.type === 'block') {\n return flattenNestedBlocks(context, [\n slice.block as ArbitraryTypedObject,\n ])\n }\n\n if (slice.children.length > 0) {\n if (\n slice.children.every(\n (child) => isSpan(context, child) && child.text.trim() === '',\n )\n ) {\n return []\n }\n\n return flattenNestedBlocks(context, [\n {\n ...block,\n children: slice.children,\n },\n ])\n }\n\n return []\n })\n }\n\n return [block]\n }\n\n return [block]\n })\n\n return flattened\n}\n\nfunction isBlockContainer(\n block: ArbitraryTypedObject,\n): block is BlockContainer {\n return block['_type'] === '__block' && isArbitraryTypedObject(block['block'])\n}\n\ntype BlockContainer = {\n _type: '__block'\n block: ArbitraryTypedObject\n}\n\nfunction getSplitChildren(\n context: {schema: Schema},\n block: PortableTextTextBlock,\n) {\n return block.children.reduce(\n (slices, child) => {\n const knownInlineObject = context.schema.inlineObjects.some(\n (inlineObject) => inlineObject.name === child._type,\n )\n const knownBlockObject = context.schema.blockObjects.some(\n (blockObject) => blockObject.name === child._type,\n )\n\n const lastSlice = slices.pop()\n\n if (!isSpan(context, child) && !knownInlineObject) {\n if (knownBlockObject) {\n return [\n ...slices,\n ...(lastSlice ? [lastSlice] : []),\n {type: 'block object' as const, block: child},\n ]\n }\n }\n\n if (child._type === '__block') {\n return [\n ...slices,\n ...(lastSlice ? [lastSlice] : []),\n {\n type: 'block object' as const,\n block: (child as any).block,\n },\n ]\n }\n\n if (child._type === 'block') {\n return [\n ...slices,\n ...(lastSlice ? [lastSlice] : []),\n {type: 'block' as const, block: child},\n ]\n }\n\n if (lastSlice) {\n if (lastSlice.type === 'children') {\n return [\n ...slices,\n {\n type: 'children' as const,\n children: [...lastSlice.children, child],\n },\n ]\n }\n }\n\n return [\n ...slices,\n ...(lastSlice ? [lastSlice] : []),\n {type: 'children' as const, children: [child]},\n ]\n },\n [] as Array<\n | {\n type: 'children'\n children: Array<PortableTextSpan | PortableTextObject>\n }\n | {type: 'block object'; block: PortableTextObject}\n | {type: 'block'; block: PortableTextBlock}\n >,\n )\n}\n","export interface PartialBlock {\n _type: string\n markDefs: string[]\n style: string\n level?: number\n listItem?: string\n}\n\nexport const PRESERVE_WHITESPACE_TAGS = ['pre', 'textarea', 'code']\n\nexport const BLOCK_DEFAULT_STYLE = 'normal'\n\nexport const DEFAULT_BLOCK: PartialBlock = Object.freeze({\n _type: 'block',\n markDefs: [],\n style: BLOCK_DEFAULT_STYLE,\n})\n\nexport const DEFAULT_SPAN = Object.freeze({\n _type: 'span',\n marks: [] as string[],\n})\n\nexport const HTML_BLOCK_TAGS = {\n p: DEFAULT_BLOCK,\n blockquote: {...DEFAULT_BLOCK, style: 'blockquote'} as PartialBlock,\n}\n\nexport const HTML_SPAN_TAGS = {\n span: {object: 'text'},\n}\n\nexport const HTML_LIST_CONTAINER_TAGS: Record<\n string,\n {object: null} | undefined\n> = {\n ol: {object: null},\n ul: {object: null},\n}\n\nexport const HTML_HEADER_TAGS: Record<string, PartialBlock | undefined> = {\n h1: {...DEFAULT_BLOCK, style: 'h1'},\n h2: {...DEFAULT_BLOCK, style: 'h2'},\n h3: {...DEFAULT_BLOCK, style: 'h3'},\n h4: {...DEFAULT_BLOCK, style: 'h4'},\n h5: {...DEFAULT_BLOCK, style: 'h5'},\n h6: {...DEFAULT_BLOCK, style: 'h6'},\n}\n\nexport const HTML_DECORATOR_TAGS: Record<string, string | undefined> = {\n b: 'strong',\n strong: 'strong',\n\n i: 'em',\n em: 'em',\n\n u: 'underline',\n s: 'strike-through',\n strike: 'strike-through',\n del: 'strike-through',\n\n code: 'code',\n sup: 'sup',\n sub: 'sub',\n ins: 'ins',\n mark: 'mark',\n small: 'small',\n}\n\nexport const HTML_LIST_ITEM_TAGS: Record<string, PartialBlock | undefined> = {\n li: {\n ...DEFAULT_BLOCK,\n style: BLOCK_DEFAULT_STYLE,\n level: 1,\n listItem: 'bullet',\n },\n}\n","const objectToString = Object.prototype.toString\n\n// Copied from https://github.com/ForbesLindesay/type-of\n// but inlined to have fine grained control\nexport function resolveJsType(val: unknown) {\n switch (objectToString.call(val)) {\n case '[object Function]':\n return 'function'\n case '[object Date]':\n return 'date'\n case '[object RegExp]':\n return 'regexp'\n case '[object Arguments]':\n return 'arguments'\n case '[object Array]':\n return 'array'\n case '[object String]':\n return 'string'\n default:\n }\n\n if (val === null) {\n return 'null'\n }\n\n if (val === undefined) {\n return 'undefined'\n }\n\n if (\n val &&\n typeof val === 'object' &&\n 'nodeType' in val &&\n (val as {nodeType: unknown}).nodeType === 1\n ) {\n return 'element'\n }\n\n if (val === Object(val)) {\n return 'object'\n }\n\n return typeof val\n}\n","import type {Schema} from '@portabletext/schema'\nimport {isTextBlock, type PortableTextObject} from '@portabletext/schema'\nimport type {\n ArbitraryTypedObject,\n HtmlParser,\n MinimalBlock,\n MinimalSpan,\n PlaceholderAnnotation,\n PlaceholderDecorator,\n TypedObject,\n} from '../types'\nimport {DEFAULT_BLOCK} from './constants'\nimport {resolveJsType} from './resolve-js-type'\n\n/**\n * Utility function that always return a lowerCase version of the element.tagName\n *\n * @param el - Element to get tag name for\n * @returns Lowercase tagName for that element, or undefined if not an element\n */\nexport function tagName(el: HTMLElement | Node | null): string | undefined {\n if (el && 'tagName' in el) {\n return el.tagName.toLowerCase()\n }\n\n return undefined\n}\n\n/**\n * A default `parseHtml` function that returns the html using `DOMParser`.\n *\n * @returns HTML Parser based on `DOMParser`\n */\nexport function defaultParseHtml(): HtmlParser {\n if (resolveJsType(DOMParser) === 'undefined') {\n throw new Error(\n 'The native `DOMParser` global which the `Html` deserializer uses by ' +\n 'default is not present in this environment. ' +\n 'You must supply the `options.parseHtml` function instead.',\n )\n }\n return (html) => {\n return new DOMParser().parseFromString(html, 'text/html')\n }\n}\n\nexport function ensureRootIsBlocks(\n schema: Schema,\n objects: Array<ArbitraryTypedObject>,\n): ArbitraryTypedObject[] {\n return objects.reduce((blocks, node, i, original) => {\n if (node._type === 'block') {\n blocks.push(node)\n return blocks\n }\n\n if (node._type === '__block') {\n blocks.push((node as any).block)\n return blocks\n }\n\n const lastBlock = blocks[blocks.length - 1]\n if (\n i > 0 &&\n !isTextBlock({schema}, original[i - 1]) &&\n isTextBlock({schema}, lastBlock)\n ) {\n lastBlock.children.push(node as PortableTextObject)\n return blocks\n }\n\n const block = {\n ...DEFAULT_BLOCK,\n children: [node],\n }\n\n blocks.push(block)\n return blocks\n }, [] as ArbitraryTypedObject[])\n}\n\nexport function isNodeList(node: unknown): node is NodeList {\n return Object.prototype.toString.call(node) === '[object NodeList]'\n}\n\nexport function isMinimalSpan(node: TypedObject): node is MinimalSpan {\n return node._type === 'span'\n}\n\nexport function isMinimalBlock(node: TypedObject): node is MinimalBlock {\n return node._type === 'block'\n}\n\nexport function isPlaceholderDecorator(\n node: TypedObject,\n): node is PlaceholderDecorator {\n return node._type === '__decorator'\n}\n\nexport function isPlaceholderAnnotation(\n node: TypedObject,\n): node is PlaceholderAnnotation {\n return node._type === '__annotation'\n}\n\nexport function isElement(node: Node): node is Element {\n return node.nodeType === 1\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/matchers.ts","../src/html-to-portable-text.ts","../src/default-schema.ts"],"sourcesContent":[],"mappings":";;;;;;;;KAuJY,6BACK,0BAA0B;;;;;;YAMvB;;;SACX;;MAEH;;;;iBAKU;;eACF,cACX,cAAc,aAAa;;;;KAqClB,iCACU,YAAY,wCAC9B;UAA6B;;;IAC7B,OAAO,4BACP;;AA1DJ;;;;AAIE,KC9IU,yBAAA,GD8IV;EACA,MAAA,CAAA,EC9IS,MD8IT;EAEkB,YAAA,CAAA,EAAA,GAAA,GAAA,MAAA;EACX,SAAA,CAAA,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GC/IuB,QD+IvB;EAEH,KAAA,CAAA,EChJI,gBDgJJ,EAAA;EAAkB,cAAA,CAAA,EAAA,UAAA,GAAA,QAAA,GAAA,WAAA;EAKR,KAAA,CAAA,EAAA;IACF,KAAA,CAAA,ECnJF,aDmJE,CAAA;MACgB,GAAA,CAAA,EAAA,MAAA;MAAb,GAAA,CAAA,EAAA,MAAA;IAAd,CAAA,CAAA;EAAa,CAAA;AAqChB,CAAA;;;;;;;;;iBC7KgB,kBAAA,yBAEL,6BAA8B,KAAA,WAAA,GAAA,qBAAA,CAAA,sBAAA,WAAA,GAAA,qBAAA,CAAA;EArB7B,IAAA,EAAA,MAAA;CACD,CAAA,EAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/matchers.ts","../src/html-to-portable-text.ts","../src/default-schema.ts"],"sourcesContent":[],"mappings":";;;;;;;;KAuJY,6BACK,0BAA0B;;;;;;YAMvB;;;SACX;;MAEH;;;;iBAKU;;eACF,cACX,cAAc,aAAa;;;;KAqClB,iCACU,YAAY,wCAC9B;UAA6B;;;IAC7B,OAAO,4BACP;;AA1DJ;;;;AAIE,KC9IU,yBAAA,GD8IV;EACA,MAAA,CAAA,EC9IS,MD8IT;EAEkB,YAAA,CAAA,EAAA,GAAA,GAAA,MAAA;EACX,SAAA,CAAA,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GC/IuB,QD+IvB;EAEH,KAAA,CAAA,EChJI,gBDgJJ,EAAA;EAAkB,cAAA,CAAA,EAAA,UAAA,GAAA,QAAA,GAAA,WAAA;EAKR,KAAA,CAAA,EAAA;IACF,KAAA,CAAA,ECnJF,aDmJE,CAAA;MACgB,GAAA,CAAA,EAAA,MAAA;MAAb,GAAA,CAAA,EAAA,MAAA;IAAd,CAAA,CAAA;EAAa,CAAA;AAqChB,CAAA;;;;;;;;;iBC7KgB,kBAAA,yBAEL,6BAA8B,KAAA,WAAA,GAAA,qBAAA,CAAA,sBAAA,WAAA,GAAA,qBAAA,CAAA;EArB7B,IAAA,EAAA,MAAA;CACD,CAAA,EAAA;;;;;ADyIX;AACiB,cEnBJ,aFmBI,EEahB,qBAAA,CAhCyB,MFmBT"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/default-schema.ts","../src/deserializer/word-online/asserters.word-online.ts","../src/deserializer/word-online/preprocessor.word-online.ts","../src/deserializer/preprocessors/xpathResult.ts","../src/deserializer/preprocessors/preprocessor.gdocs.ts","../src/deserializer/preprocessors/preprocessor.html.ts","../src/deserializer/preprocessors/preprocessor.notion.ts","../src/deserializer/preprocessors/preprocessor.whitespace.ts","../src/deserializer/preprocessors/preprocessor.word.ts","../src/deserializer/preprocessors/index.ts","../src/deserializer/random-key.ts","../src/deserializer/word-online/rules.word-online.ts","../src/deserializer/rules/rules.gdocs.ts","../src/deserializer/rules/rules.whitespace-text-node.ts","../src/deserializer/rules/rules.html.ts","../src/deserializer/rules/rules.notion.ts","../src/deserializer/rules/rules.word.ts","../src/deserializer/rules/index.ts","../src/deserializer/trim-whitespace.ts","../src/deserializer/html-deserializer.ts","../src/deserializer/normalize-block.ts","../src/html-to-portable-text.ts","../src/matchers.ts"],"sourcesContent":["import {\n compileSchema,\n defineSchema,\n type AnnotationDefinition,\n type BlockObjectDefinition,\n type DecoratorDefinition,\n type ListDefinition,\n type StyleDefinition,\n} from '@portabletext/schema'\n\n/********************\n * Default style definitions\n ********************/\n\nexport const normalStyleDefinition = {\n name: 'normal',\n} as const satisfies StyleDefinition\n\nexport const h1StyleDefinition = {\n name: 'h1',\n} as const satisfies StyleDefinition\n\nexport const h2StyleDefinition = {\n name: 'h2',\n} as const satisfies StyleDefinition\n\nexport const h3StyleDefinition = {\n name: 'h3',\n} as const satisfies StyleDefinition\n\nexport const h4StyleDefinition = {\n name: 'h4',\n} as const satisfies StyleDefinition\n\nexport const h5StyleDefinition = {\n name: 'h5',\n} as const satisfies StyleDefinition\n\nexport const h6StyleDefinition = {\n name: 'h6',\n} as const satisfies StyleDefinition\n\nexport const blockquoteStyleDefinition = {\n name: 'blockquote',\n} as const satisfies StyleDefinition\n\n/********************\n * Default list definitions\n ********************/\n\nexport const defaultOrderedListItemDefinition = {\n name: 'number',\n} as const satisfies ListDefinition\n\nexport const defaultUnorderedListItemDefinition = {\n name: 'bullet',\n} as const satisfies ListDefinition\n\n/********************\n * Default decorator definitions\n ********************/\n\nexport const defaultStrongDecoratorDefinition = {\n name: 'strong',\n} as const satisfies DecoratorDefinition\n\nexport const defaultEmDecoratorDefinition = {\n name: 'em',\n} as const satisfies DecoratorDefinition\n\nexport const defaultCodeDecoratorDefinition = {\n name: 'code',\n} as const satisfies DecoratorDefinition\n\nexport const defaultStrikeThroughDecoratorDefinition = {\n name: 'strike-through',\n} as const satisfies DecoratorDefinition\n\n/********************\n * Default annotation definitions\n ********************/\n\nexport const defaultLinkObjectDefinition = {\n name: 'link',\n fields: [\n {name: 'href', type: 'string'},\n {name: 'title', type: 'string'},\n ],\n} as const satisfies AnnotationDefinition\n\n/********************\n * Default object definitions\n ********************/\n\nexport const defaultCodeObjectDefinition = {\n name: 'code',\n fields: [\n {name: 'language', type: 'string'},\n {name: 'code', type: 'string'},\n ],\n} as const satisfies BlockObjectDefinition\n\nexport const defaultImageObjectDefinition = {\n name: 'image',\n fields: [\n {name: 'src', type: 'string'},\n {name: 'alt', type: 'string'},\n {name: 'title', type: 'string'},\n ],\n} as const satisfies BlockObjectDefinition\n\nexport const defaultHorizontalRuleObjectDefinition = {\n name: 'horizontal-rule',\n} as const satisfies BlockObjectDefinition\n\nexport const defaultHtmlObjectDefinition = {\n name: 'html',\n fields: [{name: 'html', type: 'string'}],\n} as const satisfies BlockObjectDefinition\n\nexport const defaultTableObjectDefinition = {\n name: 'table',\n fields: [\n {name: 'headerRows', type: 'number'},\n {name: 'rows', type: 'array'},\n ],\n} as const satisfies BlockObjectDefinition\n\n/**\n * The default schema for converting HTML to Portable Text.\n *\n * @public\n */\nexport const defaultSchema = compileSchema(\n defineSchema({\n styles: [\n normalStyleDefinition,\n h1StyleDefinition,\n h2StyleDefinition,\n h3StyleDefinition,\n h4StyleDefinition,\n h5StyleDefinition,\n h6StyleDefinition,\n blockquoteStyleDefinition,\n ],\n lists: [\n defaultOrderedListItemDefinition,\n defaultUnorderedListItemDefinition,\n ],\n decorators: [\n defaultStrongDecoratorDefinition,\n defaultEmDecoratorDefinition,\n defaultCodeDecoratorDefinition,\n defaultStrikeThroughDecoratorDefinition,\n ],\n annotations: [defaultLinkObjectDefinition],\n blockObjects: [\n defaultCodeObjectDefinition,\n defaultHorizontalRuleObjectDefinition,\n defaultImageObjectDefinition,\n defaultHtmlObjectDefinition,\n defaultTableObjectDefinition,\n ],\n inlineObjects: [defaultImageObjectDefinition],\n }),\n)\n","import {isElement, tagName} from '../helpers'\n\nexport function isWordOnlineHtml(html: string): boolean {\n return (\n /class=\"(?:TextRun|NormalTextRun)[^\"]*SCXW\\d+[^\"]*BCX\\d+/.test(html) ||\n /class=\"EOP[^\"]*SCXW\\d+/.test(html)\n )\n}\n\nexport function isWordOnlineTextRun(el: Node): boolean {\n if (!isElement(el) || tagName(el) !== 'span') {\n return false\n }\n\n return el.classList.contains('TextRun') && !el.classList.contains('EOP')\n}\n\n/**\n * Identifies the inner text holder spans in Word Online's nested structure.\n * Word Online uses: <span class=\"TextRun\"><span class=\"NormalTextRun\">text</span></span>\n * This function matches the inner span where actual text content lives.\n * Use this to find the text-bearing children within a TextRun container.\n */\nexport function isNormalTextRun(el: Node): boolean {\n if (!isElement(el) || tagName(el) !== 'span') {\n return false\n }\n\n return el.classList.contains('NormalTextRun')\n}\n\n/**\n * Identifies the outer container spans in Word Online's nested structure.\n * Word Online uses: <span class=\"TextRun\"><span class=\"NormalTextRun\">text</span></span>\n * This function matches the outer span that holds formatting and contains NormalTextRun children.\n * Use this to find the top-level containers, then search within for NormalTextRun spans.\n * Note: Excludes spans that also have \"NormalTextRun\" or \"EOP\" classes.\n */\nexport function isTextRunSpan(el: Node): boolean {\n if (!isElement(el) || tagName(el) !== 'span') {\n return false\n }\n\n return (\n el.classList.contains('TextRun') &&\n !el.classList.contains('NormalTextRun') &&\n !el.classList.contains('EOP')\n )\n}\n\nexport function isEmptyOutlineElement(el: Element): boolean {\n if (!isElement(el)) {\n return false\n }\n\n if (!el.classList.contains('OutlineElement')) {\n return false\n }\n\n return el.textContent.trim() === ''\n}\n\nexport function isFindHit(el: Node): boolean {\n if (!isElement(el) || tagName(el) !== 'span') {\n return false\n }\n\n return el.classList.contains('FindHit')\n}\n\nexport function isInHeading(el: Node): boolean {\n let current: Node | null = el\n\n while (current) {\n if (isElement(current)) {\n if (\n tagName(current) === 'word-online-block' &&\n /^heading \\d$/.test(current.getAttribute('data-parastyle') ?? '')\n ) {\n return true\n }\n }\n\n current = current.parentNode\n }\n\n return false\n}\n\nexport function isInBlockquote(el: Node): boolean {\n let current: Node | null = el\n\n while (current) {\n if (isElement(current)) {\n if (\n tagName(current) === 'word-online-block' &&\n current.getAttribute('data-parastyle') === 'Quote'\n ) {\n return true\n }\n }\n\n current = current.parentNode\n }\n\n return false\n}\n\n/**********************\n * Formatting asserters\n **********************/\n\nexport function hasStrongFormatting(el: Element): boolean {\n const style = el.getAttribute('style') ?? ''\n\n return (\n el.classList.contains('MacChromeBold') ||\n /font-weight\\s*:\\s*bold/.test(style)\n )\n}\n\nexport function hasEmphasisFormatting(el: Element): boolean {\n const style = el.getAttribute('style') ?? ''\n\n return /font-style\\s*:\\s*italic/.test(style)\n}\n\nexport function hasUnderlineFormatting(el: Element): boolean {\n const style = el.getAttribute('style') ?? ''\n\n return (\n el.classList.contains('Underlined') ||\n /text-decoration\\s*:\\s*underline/.test(style)\n )\n}\n\nexport function hasStrikethroughFormatting(el: Element): boolean {\n const style = el.getAttribute('style') ?? ''\n\n return (\n el.classList.contains('Strikethrough') ||\n /text-decoration\\s*:\\s*line-through/.test(style)\n )\n}\n\nexport function hasFormatting(el: Element): boolean {\n return (\n hasStrongFormatting(el) ||\n hasEmphasisFormatting(el) ||\n hasUnderlineFormatting(el) ||\n hasStrikethroughFormatting(el)\n )\n}\n","import {isElement, tagName} from '../helpers'\nimport {\n hasFormatting,\n isNormalTextRun,\n isTextRunSpan,\n isWordOnlineHtml,\n} from './asserters.word-online'\n\nexport function preprocessWordOnline(html: string, doc: Document): Document {\n if (!isWordOnlineHtml(html)) {\n return doc\n }\n\n const paragraphs = Array.from(\n doc.querySelectorAll('p.Paragraph[role=\"heading\"]'),\n )\n\n for (const paragraph of paragraphs) {\n const ariaLevel = paragraph.getAttribute('aria-level')\n\n if (ariaLevel) {\n const wrapper = doc.createElement('word-online-block')\n\n wrapper.setAttribute('data-parastyle', `heading ${ariaLevel}`)\n\n const parent = paragraph.parentNode\n\n if (parent) {\n parent.insertBefore(wrapper, paragraph)\n\n while (paragraph.firstChild) {\n wrapper.appendChild(paragraph.firstChild)\n }\n\n parent.removeChild(paragraph)\n }\n }\n }\n\n // Group NormalTextRun spans with the same data-ccp-parastyle attribute\n // This handles cases like blockquotes, headings where multiple spans should form one block\n // Process from the body directly to handle DOM mutations\n let child = doc.body.firstChild\n\n while (child) {\n const next = child.nextSibling\n\n if (!isElement(child) || !tagName(child)?.includes('span')) {\n child = next\n\n continue\n }\n\n const paraStyle = getParaStyle(child)\n\n if (!paraStyle) {\n child = next\n\n continue\n }\n\n // Found a span with paragraph style - collect all consecutive siblings with same style\n const group: Element[] = [child]\n let sibling = next\n\n while (sibling) {\n if (!isElement(sibling) || getParaStyle(sibling) !== paraStyle) {\n break\n }\n\n group.push(sibling)\n sibling = sibling.nextSibling\n }\n\n // Wrap the spans in a container\n // Use a custom element name to avoid conflicts with HTML rules\n const wrapper = doc.createElement('word-online-block')\n wrapper.setAttribute('data-parastyle', paraStyle)\n\n // Insert the wrapper before the first span\n doc.body.insertBefore(wrapper, child)\n\n // Move all grouped spans into the wrapper\n for (const span of group) {\n wrapper.appendChild(span)\n }\n\n // Continue with the sibling after the last grouped span\n child = sibling\n }\n\n // Find all TextRun spans\n const textRunSpans = Array.from(doc.body.querySelectorAll('span')).filter(\n isTextRunSpan,\n )\n\n for (const textRunSpan of textRunSpans) {\n // Find ALL NormalTextRun children (Word Online can have multiple per TextRun)\n const normalTextRuns = Array.from(textRunSpan.childNodes).filter(\n isNormalTextRun,\n )\n\n for (const normalTextRun of normalTextRuns) {\n // Process ALL nested spans with whitespace in this NormalTextRun\n // We need to process them in a loop since removing one might affect indices\n let foundNestedSpan = true\n\n while (foundNestedSpan) {\n const children = Array.from(normalTextRun.childNodes)\n const nestedSpanIndex = children.findIndex(\n (node) =>\n isElement(node) &&\n tagName(node) === 'span' &&\n node.textContent.trim() === '',\n )\n\n if (nestedSpanIndex === -1) {\n foundNestedSpan = false\n break\n }\n\n const nestedSpan = children.at(nestedSpanIndex)\n\n if (!nestedSpan) {\n foundNestedSpan = false\n break\n }\n\n // Word Online uses non-breaking spaces, convert to regular spaces\n const spaceText = nestedSpan.textContent?.replace(/\\u00a0/g, ' ') ?? ''\n\n // Determine if the space is at the beginning or end BEFORE removing it\n // Check if there are any text nodes before this position\n const hasTextBefore = children\n .slice(0, nestedSpanIndex)\n .some((n) => n.nodeType === 3)\n const isSpaceAtBeginning = !hasTextBefore\n\n // Remove the nested span\n normalTextRun.removeChild(nestedSpan)\n\n if (isSpaceAtBeginning) {\n // Space at the beginning - keep it at the beginning\n const firstTextNode = Array.from(normalTextRun.childNodes).find(\n (n) => n.nodeType === 3,\n )\n\n if (firstTextNode) {\n firstTextNode.textContent =\n spaceText + (firstTextNode.textContent || '')\n } else {\n // No text node exists, create one with the space\n const spaceNode = doc.createTextNode(spaceText)\n normalTextRun.insertBefore(spaceNode, normalTextRun.firstChild)\n }\n } else {\n // Space at the end - check if we should move it to the next TextRun\n // Only move if the formatting (marks) are different\n const nextSibling = textRunSpan.nextSibling\n const currentHasFormatting = hasFormatting(textRunSpan)\n\n if (\n nextSibling &&\n isElement(nextSibling) &&\n isTextRunSpan(nextSibling)\n ) {\n const nextHasFormatting = hasFormatting(nextSibling)\n\n // If current has formatting but next doesn't, move space to the next span\n // This makes semantic sense: \"**bar** baz\" or \"*bar* baz\" - space should be outside the formatting\n if (currentHasFormatting && !nextHasFormatting) {\n const nextNormalTextRun = Array.from(nextSibling.childNodes).find(\n isNormalTextRun,\n )\n\n if (nextNormalTextRun && isElement(nextNormalTextRun)) {\n // Prepend space to the first text node of the next NormalTextRun\n const firstChild = nextNormalTextRun.firstChild\n\n if (firstChild && firstChild.nodeType === 3) {\n firstChild.textContent =\n spaceText + (firstChild.textContent ?? '')\n } else {\n // No text node, insert a new one at the beginning\n const spaceNode = doc.createTextNode(spaceText)\n nextNormalTextRun.insertBefore(\n spaceNode,\n nextNormalTextRun.firstChild,\n )\n }\n }\n // Don't add the space back to the current span - it's been moved\n } else {\n // Same formatting, keep the space in the current span\n const lastTextNode = Array.from(normalTextRun.childNodes).find(\n (n) => n.nodeType === 3,\n )\n\n if (lastTextNode) {\n lastTextNode.textContent =\n (lastTextNode.textContent ?? '') + spaceText\n } else {\n // No text node exists, create one with the space\n const spaceNode = doc.createTextNode(spaceText)\n normalTextRun.appendChild(spaceNode)\n }\n }\n } else {\n // No next TextRun, keep the space at the end of this span's text\n const lastTextNode = Array.from(normalTextRun.childNodes).find(\n (n) => n.nodeType === 3,\n )\n\n if (lastTextNode) {\n lastTextNode.textContent =\n (lastTextNode.textContent ?? '') + spaceText\n } else {\n // No text node exists, create one with the space\n const spaceNode = doc.createTextNode(spaceText)\n normalTextRun.appendChild(spaceNode)\n }\n }\n }\n }\n }\n }\n\n return doc\n}\n\n// Helper to get paragraph style from a span (either directly or from NormalTextRun child)\nfunction getParaStyle(element: Element): string | undefined {\n // Check direct attribute first\n const directStyle = element.getAttribute('data-ccp-parastyle')\n\n if (directStyle) {\n return directStyle\n }\n\n // Check if it's a TextRun with NormalTextRun children that have the attribute\n if (tagName(element) === 'span' && element.classList.contains('TextRun')) {\n const normalTextRuns = Array.from(\n element.querySelectorAll('.NormalTextRun'),\n )\n\n if (normalTextRuns.length > 0) {\n const firstRun = normalTextRuns[0]\n const firstStyle = firstRun?.getAttribute('data-ccp-parastyle')\n\n // Verify all NormalTextRuns have the same style\n if (\n firstStyle &&\n normalTextRuns.every(\n (normalTextRun) =>\n normalTextRun.getAttribute('data-ccp-parastyle') === firstStyle,\n )\n ) {\n return firstStyle\n }\n }\n }\n\n return undefined\n}\n","// We need this here if run server side\nexport const _XPathResult = {\n ANY_TYPE: 0,\n NUMBER_TYPE: 1,\n STRING_TYPE: 2,\n BOOLEAN_TYPE: 3,\n UNORDERED_NODE_ITERATOR_TYPE: 4,\n ORDERED_NODE_ITERATOR_TYPE: 5,\n UNORDERED_NODE_SNAPSHOT_TYPE: 6,\n ORDERED_NODE_SNAPSHOT_TYPE: 7,\n ANY_UNORDERED_NODE_TYPE: 8,\n FIRST_ORDERED_NODE_TYPE: 9,\n}\n","import {tagName} from '../helpers'\nimport {_XPathResult} from './xpathResult'\n\nexport function preprocessGDocs(_html: string, doc: Document): Document {\n let gDocsRootOrSiblingNode = doc\n .evaluate(\n '//*[@id and contains(@id, \"docs-internal-guid\")]',\n doc,\n null,\n _XPathResult.ORDERED_NODE_ITERATOR_TYPE,\n null,\n )\n .iterateNext()\n\n if (gDocsRootOrSiblingNode) {\n const isWrappedRootTag = tagName(gDocsRootOrSiblingNode) === 'b'\n\n // If this document isn't wrapped in a 'b' tag, then assume all siblings live on the root level\n if (!isWrappedRootTag) {\n gDocsRootOrSiblingNode = doc.body\n }\n\n // Tag every child with attribute 'is-google-docs' so that the GDocs rule-set can\n // work exclusivly on these children\n const childNodes = doc.evaluate(\n '//*',\n doc,\n null,\n _XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,\n null,\n )\n\n for (let i = childNodes.snapshotLength - 1; i >= 0; i--) {\n const elm = childNodes.snapshotItem(i) as HTMLElement\n elm?.setAttribute('data-is-google-docs', 'true')\n\n if (\n elm?.parentElement === gDocsRootOrSiblingNode ||\n (!isWrappedRootTag && elm.parentElement === doc.body)\n ) {\n elm?.setAttribute('data-is-root-node', 'true')\n tagName(elm)\n }\n\n // Handle checkmark lists - The first child of a list item is an image with a checkmark, and the serializer\n // expects the first child to be the text node\n if (\n tagName(elm) === 'li' &&\n elm.firstChild &&\n tagName(elm?.firstChild) === 'img'\n ) {\n elm.removeChild(elm.firstChild)\n }\n }\n\n // Remove that 'b' which Google Docs wraps the HTML content in\n if (isWrappedRootTag) {\n doc.body.firstElementChild?.replaceWith(\n ...Array.from(gDocsRootOrSiblingNode.childNodes),\n )\n }\n\n return doc\n }\n return doc\n}\n","import {_XPathResult} from './xpathResult'\n\n// Remove this cruft from the document\nconst unwantedWordDocumentPaths = [\n '/html/text()',\n '/html/head/text()',\n '/html/body/text()',\n '/html/body/ul/text()',\n '/html/body/ol/text()',\n '//comment()',\n '//style',\n '//xml',\n '//script',\n '//meta',\n '//link',\n]\n\nexport function preprocessHTML(_html: string, doc: Document): Document {\n // Make sure text directly on the body is wrapped in spans.\n // This mimics what the browser does before putting html on the clipboard,\n // when used in a script context with JSDOM\n const bodyTextNodes = doc.evaluate(\n '/html/body/text()',\n doc,\n null,\n _XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,\n null,\n )\n\n for (let i = bodyTextNodes.snapshotLength - 1; i >= 0; i--) {\n const node = bodyTextNodes.snapshotItem(i) as HTMLElement\n const text = node.textContent || ''\n if (text.replace(/[^\\S\\n]+$/g, '')) {\n const newNode = doc.createElement('span')\n newNode.appendChild(doc.createTextNode(text))\n node.parentNode?.replaceChild(newNode, node)\n } else {\n node.parentNode?.removeChild(node)\n }\n }\n\n const unwantedNodes = doc.evaluate(\n unwantedWordDocumentPaths.join('|'),\n doc,\n null,\n _XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,\n null,\n )\n for (let i = unwantedNodes.snapshotLength - 1; i >= 0; i--) {\n const unwanted = unwantedNodes.snapshotItem(i)\n if (!unwanted) {\n continue\n }\n unwanted.parentNode?.removeChild(unwanted)\n }\n return doc\n}\n","import {_XPathResult} from './xpathResult'\n\nexport function preprocessNotion(html: string, doc: Document): Document {\n const NOTION_REGEX = /<!-- notionvc:.*?-->/g\n\n if (html.match(NOTION_REGEX)) {\n // Tag every child with attribute 'is-notion' so that the Notion rule-set can\n // work exclusivly on these children\n const childNodes = doc.evaluate(\n '//*',\n doc,\n null,\n _XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,\n null,\n )\n\n for (let i = childNodes.snapshotLength - 1; i >= 0; i--) {\n const elm = childNodes.snapshotItem(i) as HTMLElement\n elm?.setAttribute('data-is-notion', 'true')\n }\n\n return doc\n }\n return doc\n}\n","import {PRESERVE_WHITESPACE_TAGS} from '../constants'\nimport {_XPathResult} from './xpathResult'\n\n// Elements that only contain block-level children (not inline text content)\nconst BLOCK_CONTAINER_ELEMENTS = [\n 'body',\n 'table',\n 'tbody',\n 'thead',\n 'tfoot',\n 'tr',\n 'ul',\n 'ol',\n]\n\nexport function preprocessWhitespace(_: string, doc: Document): Document {\n // Recursively process all nodes.\n function processNode(node: Node) {\n // If this is a text node and not inside a tag where whitespace should be preserved, process it.\n if (\n node.nodeType === _XPathResult.BOOLEAN_TYPE &&\n !PRESERVE_WHITESPACE_TAGS.includes(\n node.parentElement?.tagName.toLowerCase() || '',\n )\n ) {\n const normalized =\n node.textContent\n ?.replace(/\\s\\s+/g, ' ') // Remove multiple whitespace\n .replace(/[\\r\\n]+/g, ' ') || '' // Replace newlines with spaces\n const parentTag = node.parentElement?.tagName.toLowerCase()\n\n if (\n parentTag &&\n BLOCK_CONTAINER_ELEMENTS.includes(parentTag) &&\n normalized.trim() === ''\n ) {\n // If parent is a block container and text is only whitespace, remove it\n node.parentNode?.removeChild(node)\n } else {\n node.textContent = normalized\n }\n }\n // Otherwise, if this node has children, process them.\n else {\n // Process children in reverse to handle removals safely\n for (let i = node.childNodes.length - 1; i >= 0; i--) {\n const child = node.childNodes[i]\n if (child) {\n processNode(child)\n }\n }\n }\n }\n\n // Process all nodes starting from the root.\n processNode(doc.body)\n\n return doc\n}\n","import {_XPathResult} from './xpathResult'\n\nconst WORD_HTML_REGEX =\n /(class=\"?Mso|style=(?:\"|')[^\"]*?\\bmso-|w:WordDocument|<o:\\w+>|<\\/font>)/\n\n// xPaths for elements that will be removed from the document\nconst unwantedPaths = [\n '//o:p',\n \"//span[@style='mso-list:Ignore']\",\n \"//span[@style='mso-list: Ignore']\",\n]\n\n// xPaths for elements that needs to be remapped into other tags\nconst mappedPaths = [\n \"//p[@class='MsoTocHeading']\",\n \"//p[@class='MsoTitle']\",\n \"//p[@class='MsoToaHeading']\",\n \"//p[@class='MsoSubtitle']\",\n \"//span[@class='MsoSubtleEmphasis']\",\n \"//span[@class='MsoIntenseEmphasis']\",\n]\n\n// Which HTML element(s) to map the elements matching mappedPaths into\nconst elementMap: Record<string, string[] | undefined> = {\n MsoTocHeading: ['h3'],\n MsoTitle: ['h1'],\n MsoToaHeading: ['h2'],\n MsoSubtitle: ['h5'],\n MsoSubtleEmphasis: ['span', 'em'],\n MsoIntenseEmphasis: ['span', 'em', 'strong'],\n // Remove cruft\n}\n\nfunction isWordHtml(html: string) {\n return WORD_HTML_REGEX.test(html)\n}\n\n/**\n * Extract @list CSS definitions from the document's <style> blocks and store\n * the results as a data attribute on <body>. This must run before the HTML\n * preprocessor strips <style> elements.\n *\n * Word embeds list type information in CSS like:\n * @list l0:level1 { mso-level-number-format:bullet; ... }\n * @list l1:level1 { mso-level-number-position:left; ... }\n *\n * The map is keyed by \"listId:levelN\" (e.g. \"l0:level1\") because a single\n * list definition can have numbered top-level items with bullet sub-levels.\n */\nfunction extractListStyles(doc: Document): void {\n const map: Record<string, 'bullet' | 'number'> = {}\n let found = false\n\n const styleEls = doc.querySelectorAll('style')\n for (const styleEl of styleEls) {\n const css = styleEl.textContent || ''\n\n const listRulePattern = /@list\\s+(l\\d+):(level\\d+)\\s*\\{([^}]*)\\}/g\n\n for (\n let match = listRulePattern.exec(css);\n match !== null;\n match = listRulePattern.exec(css)\n ) {\n const listId = match[1] || ''\n const level = match[2] || ''\n const ruleBody = match[3] || ''\n const key = `${listId}:${level}`\n\n if (/mso-level-number-format\\s*:\\s*bullet/i.test(ruleBody)) {\n map[key] = 'bullet'\n } else {\n map[key] = 'number'\n }\n found = true\n }\n }\n\n if (found && doc.body) {\n doc.body.setAttribute('data-word-list-styles', JSON.stringify(map))\n }\n}\n\nexport function preprocessWord(html: string, doc: Document): Document {\n if (!isWordHtml(html)) {\n return doc\n }\n\n extractListStyles(doc)\n\n const unwantedNodes = doc.evaluate(\n unwantedPaths.join('|'),\n doc,\n (prefix) => {\n if (prefix === 'o') {\n return 'urn:schemas-microsoft-com:office:office'\n }\n return null\n },\n _XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,\n null,\n )\n\n for (let i = unwantedNodes.snapshotLength - 1; i >= 0; i--) {\n const unwanted = unwantedNodes.snapshotItem(i)\n if (unwanted?.parentNode) {\n unwanted.parentNode.removeChild(unwanted)\n }\n }\n\n // Transform mapped elements into what they should be mapped to\n const mappedElements = doc.evaluate(\n mappedPaths.join('|'),\n doc,\n null,\n _XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,\n null,\n )\n for (let i = mappedElements.snapshotLength - 1; i >= 0; i--) {\n const mappedElm = mappedElements.snapshotItem(i) as HTMLElement\n const tags = elementMap[mappedElm.className]\n const text = doc.createTextNode(mappedElm.textContent || '')\n if (!tags) {\n continue\n }\n\n const firstTag = tags[0]\n if (!firstTag) {\n continue\n }\n const parentElement = doc.createElement(firstTag)\n let parent = parentElement\n let child = parentElement\n tags.slice(1).forEach((tag) => {\n child = doc.createElement(tag)\n parent.appendChild(child)\n parent = child\n })\n child.appendChild(text)\n mappedElm?.parentNode?.replaceChild(parentElement, mappedElm)\n }\n\n return doc\n}\n","import {preprocessWordOnline} from '../word-online/preprocessor.word-online'\nimport {preprocessGDocs} from './preprocessor.gdocs'\nimport {preprocessHTML} from './preprocessor.html'\nimport {preprocessNotion} from './preprocessor.notion'\nimport {preprocessWhitespace} from './preprocessor.whitespace'\nimport {preprocessWord} from './preprocessor.word'\n\nexport const preprocessors = [\n preprocessWhitespace,\n preprocessNotion,\n preprocessWord,\n preprocessWordOnline,\n preprocessGDocs,\n preprocessHTML,\n]\n","export function keyGenerator() {\n return randomKey(12)\n}\n\n// WHATWG crypto RNG - https://w3c.github.io/webcrypto/Overview.html\nfunction whatwgRNG(length = 16) {\n const rnds8 = new Uint8Array(length)\n crypto.getRandomValues(rnds8)\n return rnds8\n}\n\nconst byteToHex: string[] = []\nfor (let i = 0; i < 256; ++i) {\n byteToHex[i] = (i + 0x100).toString(16).slice(1)\n}\n\n/**\n * Generate a random key of the given length\n *\n * @param length - Length of string to generate\n * @returns A string of the given length\n */\nexport function randomKey(length: number): string {\n return whatwgRNG(length)\n .reduce((str, n) => str + byteToHex[n], '')\n .slice(0, length)\n}\n","import type {Schema} from '@portabletext/schema'\nimport type {DeserializerRule} from '../../types'\nimport {DEFAULT_SPAN, HTML_BLOCK_TAGS, HTML_HEADER_TAGS} from '../constants'\nimport {isElement, tagName} from '../helpers'\nimport {keyGenerator} from '../random-key'\nimport type {SchemaMatchers} from '../schema-matchers'\nimport {\n hasEmphasisFormatting,\n hasStrikethroughFormatting,\n hasStrongFormatting,\n hasUnderlineFormatting,\n isFindHit,\n isInBlockquote,\n isInHeading,\n isNormalTextRun,\n isWordOnlineTextRun,\n} from './asserters.word-online'\n\nfunction mapParaStyleToBlockStyle(schema: Schema, paraStyle: string) {\n const blockStyleMap: Record<string, string> = {\n 'heading 1': 'h1',\n 'heading 2': 'h2',\n 'heading 3': 'h3',\n 'heading 4': 'h4',\n 'heading 5': 'h5',\n 'heading 6': 'h6',\n 'Quote': 'blockquote',\n }\n\n const blockStyle = blockStyleMap[paraStyle] ?? 'normal'\n\n return schema.styles.find((style) => style.name === blockStyle)?.name\n}\n\nexport function createWordOnlineRules(\n schema: Schema,\n options: {keyGenerator?: () => string; matchers?: SchemaMatchers},\n): DeserializerRule[] {\n return [\n // Image rule - handles bare Word Online <img> tags with WACImage class\n {\n deserialize(el) {\n if (!isElement(el) || tagName(el) !== 'img') {\n return undefined\n }\n\n // Handle className which might be a string or SVGAnimatedString\n const classNameRaw = el.className\n let className = ''\n if (typeof classNameRaw === 'string') {\n className = classNameRaw\n } else if (classNameRaw && typeof classNameRaw === 'object') {\n // SVGAnimatedString has baseVal property\n className = (classNameRaw as {baseVal?: string}).baseVal || ''\n }\n\n if (!className.includes('WACImage')) {\n return undefined\n }\n\n const src = el.getAttribute('src') ?? undefined\n const alt = el.getAttribute('alt') ?? undefined\n\n const props = Object.fromEntries(\n Array.from(el.attributes).map((attr) => [attr.name, attr.value]),\n )\n\n // Bare <img> tags are typically block-level, not inline\n // They should be returned as block images\n const image = options.matchers?.image?.({\n context: {\n schema: schema,\n keyGenerator: options.keyGenerator ?? keyGenerator,\n },\n props: {\n ...props,\n ...(src ? {src} : {}),\n ...(alt ? {alt} : {}),\n },\n })\n\n if (image) {\n return {\n _type: '__block',\n block: image,\n }\n }\n\n return undefined\n },\n },\n // Image rule - handles Word Online images wrapped in WACImageContainer\n {\n deserialize(el) {\n if (!isElement(el)) {\n return undefined\n }\n\n // Handle className which might be a string or SVGAnimatedString\n const classNameRaw = el.className\n let className = ''\n if (typeof classNameRaw === 'string') {\n className = classNameRaw\n } else if (classNameRaw && typeof classNameRaw === 'object') {\n // SVGAnimatedString has baseVal property\n className = (classNameRaw as {baseVal?: string}).baseVal || ''\n }\n if (!className.includes('WACImageContainer')) {\n return undefined\n }\n\n // Find the img element inside\n const img = el.querySelector('img')\n if (!img) {\n return undefined\n }\n\n const src = img.getAttribute('src') ?? undefined\n const alt = img.getAttribute('alt') ?? undefined\n\n const props = Object.fromEntries(\n Array.from(img.attributes).map((attr) => [attr.name, attr.value]),\n )\n\n // Determine if this should be an inline or block-level image\n // Word Online inline images:\n // 1. Siblings of TextRun spans (not wrapped in paragraphs)\n // 2. Inside list items (should be inline relative to the list item)\n const isInsideListItem = el.closest('li') !== null\n const isInsideParagraph = el.closest('p') !== null\n\n if (!isInsideParagraph || isInsideListItem) {\n // Inline image (either not in a paragraph, or inside a list item)\n const inlineImage = options.matchers?.inlineImage?.({\n context: {\n schema: schema,\n keyGenerator: options.keyGenerator ?? keyGenerator,\n },\n props: {\n ...props,\n ...(src ? {src} : {}),\n ...(alt ? {alt} : {}),\n },\n })\n\n if (inlineImage) {\n return inlineImage\n }\n }\n\n // Block-level image (or fallback if inline image not supported)\n const image = options.matchers?.image?.({\n context: {\n schema: schema,\n keyGenerator: options.keyGenerator ?? keyGenerator,\n },\n props: {\n ...props,\n ...(src ? {src} : {}),\n ...(alt ? {alt} : {}),\n },\n })\n\n if (image) {\n return {\n _type: '__block',\n block: image,\n }\n }\n\n return undefined\n },\n },\n // List item rule - handles <li> elements with aria-level\n {\n deserialize(el, next) {\n if (!isElement(el) || tagName(el) !== 'li') {\n return undefined\n }\n\n const ariaLevel = el.getAttribute('data-aria-level')\n\n if (!ariaLevel) {\n return undefined\n }\n\n const listItem = tagName(el.parentNode) === 'ol' ? 'number' : 'bullet'\n\n let childNodesToProcess = el.childNodes\n let blockStyle = 'normal'\n\n if (\n el.childNodes.length === 1 &&\n el.firstChild &&\n isElement(el.firstChild)\n ) {\n const childTag = tagName(el.firstChild)\n\n if (\n childTag &&\n (HTML_BLOCK_TAGS[childTag as keyof typeof HTML_BLOCK_TAGS] ||\n HTML_HEADER_TAGS[childTag as keyof typeof HTML_HEADER_TAGS] ||\n childTag === 'word-online-block')\n ) {\n // If it's a word-online-block, extract the style before skipping it\n if (childTag === 'word-online-block') {\n const paraStyle = el.firstChild.getAttribute('data-parastyle')\n const foundBlockStyle = paraStyle\n ? mapParaStyleToBlockStyle(schema, paraStyle)\n : undefined\n\n if (foundBlockStyle) {\n blockStyle = foundBlockStyle\n }\n }\n\n // Skip the block wrapper and process its children directly\n childNodesToProcess = el.firstChild.childNodes\n }\n }\n\n const children = next(childNodesToProcess)\n let childArray = Array.isArray(children)\n ? children\n : [children].filter(Boolean)\n\n // Clean up trailing empty or whitespace-only spans\n // Word Online often adds trailing tabs/breaks and extra spaces in list items\n while (childArray.length > 0) {\n const lastChild = childArray[childArray.length - 1]\n\n if (\n lastChild &&\n typeof lastChild === 'object' &&\n 'text' in lastChild\n ) {\n const text = (lastChild.text as string).trimEnd()\n if (text === '') {\n // Remove empty span\n childArray = childArray.slice(0, -1)\n } else if (text !== lastChild.text) {\n // Update with trimmed text\n lastChild.text = text\n break\n } else {\n break\n }\n } else {\n break\n }\n }\n\n return {\n _type: schema.block.name,\n children: childArray,\n markDefs: [],\n style: blockStyle,\n listItem,\n level: parseInt(ariaLevel, 10),\n }\n },\n },\n // Block style rule - handles paragraph styles like Quote\n // The preprocessor wraps grouped NormalTextRun spans in a word-online-block element\n {\n deserialize(el, next) {\n if (!isElement(el)) {\n return undefined\n }\n\n const paraStyle = el.getAttribute('data-parastyle')\n const blockStyle = paraStyle\n ? mapParaStyleToBlockStyle(schema, paraStyle)\n : undefined\n\n if (!blockStyle) {\n return undefined\n }\n\n const children = next(el.childNodes)\n\n return {\n _type: schema.block.name,\n style: blockStyle,\n markDefs: [],\n children: Array.isArray(children)\n ? children\n : children\n ? [children]\n : [],\n }\n },\n },\n // TextRun rule\n {\n deserialize(el) {\n if (isWordOnlineTextRun(el)) {\n if (!isElement(el)) {\n return undefined\n }\n\n if (!el.textContent) {\n return undefined\n }\n\n // Find ALL NormalTextRun and FindHit children and extract text from them\n // (Word Online sometimes splits text across multiple spans)\n // FindHit is used for search result highlighting\n const textSpans = Array.from(el.childNodes).filter(\n (node) => isNormalTextRun(node) || isFindHit(node),\n )\n const text = textSpans\n .map((span) => (isElement(span) ? (span.textContent ?? '') : ''))\n .join('')\n\n if (!text) {\n return undefined\n }\n\n const span = {\n ...DEFAULT_SPAN,\n marks: [] as Array<string>,\n text,\n }\n\n if (hasStrongFormatting(el)) {\n span.marks.push('strong')\n }\n\n // Don't add italic mark if we're in a heading or blockquote (it's part of their default style)\n if (\n hasEmphasisFormatting(el) &&\n !isInHeading(el) &&\n !isInBlockquote(el)\n ) {\n span.marks.push('em')\n }\n\n // Add underline mark if the element has explicit underline formatting\n // Word Online always adds underline to links, so we need to distinguish between:\n // 1. Default link underline (skip)\n // 2. Explicit user underline that includes the link (add)\n // We check: if the link is surrounded by underlined content, it's explicit user underline\n if (hasUnderlineFormatting(el)) {\n const isInsideLink =\n isElement(el) &&\n el.parentElement &&\n tagName(el.parentElement) === 'a'\n\n if (isInsideLink) {\n // Check if there are underlined siblings of the link\n const linkElement = el.parentElement\n if (linkElement) {\n const prevSibling = linkElement.previousSibling\n const nextSibling = linkElement.nextSibling\n\n // If either sibling is an underlined TextRun, the link is part of explicit underline\n const hasPrevUnderline =\n prevSibling &&\n isElement(prevSibling) &&\n hasUnderlineFormatting(prevSibling)\n const hasNextUnderline =\n nextSibling &&\n isElement(nextSibling) &&\n hasUnderlineFormatting(nextSibling)\n\n if (hasPrevUnderline || hasNextUnderline) {\n span.marks.push('underline')\n }\n // Otherwise, it's just default link styling, don't add underline mark\n }\n } else {\n // Not in a link, always add underline\n span.marks.push('underline')\n }\n }\n\n // Add strikethrough mark if the element has strikethrough formatting\n if (hasStrikethroughFormatting(el)) {\n span.marks.push('strike-through')\n }\n\n return span\n }\n\n return undefined\n },\n },\n ]\n}\n","import type {Schema} from '@portabletext/schema'\nimport type {DeserializerRule} from '../../types'\nimport {\n BLOCK_DEFAULT_STYLE,\n DEFAULT_BLOCK,\n DEFAULT_SPAN,\n HTML_BLOCK_TAGS,\n HTML_HEADER_TAGS,\n HTML_LIST_CONTAINER_TAGS,\n} from '../constants'\nimport {isElement, tagName} from '../helpers'\n\nconst LIST_CONTAINER_TAGS = Object.keys(HTML_LIST_CONTAINER_TAGS)\n\n// font-style:italic seems like the most important rule for italic / emphasis in their html\nfunction isEmphasis(el: Node): boolean {\n const style = isElement(el) && el.getAttribute('style')\n return /font-style\\s*:\\s*italic/.test(style || '')\n}\n\n// font-weight:700 seems like the most important rule for bold in their html\nfunction isStrong(el: Node): boolean {\n const style = isElement(el) && el.getAttribute('style')\n return /font-weight\\s*:\\s*700/.test(style || '')\n}\n\n// text-decoration seems like the most important rule for underline in their html\nfunction isUnderline(el: Node): boolean {\n if (!isElement(el) || tagName(el.parentNode) === 'a') {\n return false\n }\n\n const style = isElement(el) && el.getAttribute('style')\n\n return /text-decoration\\s*:\\s*underline/.test(style || '')\n}\n\n// text-decoration seems like the most important rule for strike-through in their html\n// allows for line-through regex to be more lineient to allow for other text-decoration before or after\nfunction isStrikethrough(el: Node): boolean {\n const style = isElement(el) && el.getAttribute('style')\n return /text-decoration\\s*:\\s*(?:.*line-through.*;)/.test(style || '')\n}\n\n// Check for attribute given by the gdocs preprocessor\nfunction isGoogleDocs(el: Node): boolean {\n return isElement(el) && Boolean(el.getAttribute('data-is-google-docs'))\n}\n\nfunction isRootNode(el: Node): boolean {\n return isElement(el) && Boolean(el.getAttribute('data-is-root-node'))\n}\n\nfunction getListItemStyle(el: Node): 'bullet' | 'number' | undefined {\n const parentTag = tagName(el.parentNode)\n if (parentTag && !LIST_CONTAINER_TAGS.includes(parentTag)) {\n return undefined\n }\n return tagName(el.parentNode) === 'ul' ? 'bullet' : 'number'\n}\n\nfunction getListItemLevel(el: Node): number {\n let level = 0\n if (tagName(el) === 'li') {\n let parentNode = el.parentNode\n while (parentNode) {\n const parentTag = tagName(parentNode)\n if (parentTag && LIST_CONTAINER_TAGS.includes(parentTag)) {\n level++\n }\n parentNode = parentNode.parentNode\n }\n } else {\n level = 1\n }\n return level\n}\n\nconst blocks: Record<string, {style: string} | undefined> = {\n ...HTML_BLOCK_TAGS,\n ...HTML_HEADER_TAGS,\n}\n\nfunction getBlockStyle(schema: Schema, el: Node): string {\n const childTag = tagName(el.firstChild)\n const block = childTag && blocks[childTag]\n if (!block) {\n return BLOCK_DEFAULT_STYLE\n }\n if (!schema.styles.some((style) => style.name === block.style)) {\n return BLOCK_DEFAULT_STYLE\n }\n return block.style\n}\n\nexport function createGDocsRules(schema: Schema): DeserializerRule[] {\n return [\n {\n deserialize(el, next) {\n if (isElement(el) && tagName(el) === 'span' && isGoogleDocs(el)) {\n if (!el.textContent) {\n if (!el.previousSibling && !el.nextSibling) {\n el.setAttribute('data-lonely-child', 'true')\n }\n\n return next(el.childNodes)\n }\n\n const span = {\n ...DEFAULT_SPAN,\n marks: [] as string[],\n text: el.textContent,\n }\n if (isStrong(el)) {\n span.marks.push('strong')\n }\n if (isUnderline(el)) {\n span.marks.push('underline')\n }\n if (isStrikethrough(el)) {\n span.marks.push('strike-through')\n }\n if (isEmphasis(el)) {\n span.marks.push('em')\n }\n return span\n }\n return undefined\n },\n },\n {\n deserialize(el, next) {\n if (tagName(el) === 'li' && isGoogleDocs(el)) {\n return {\n ...DEFAULT_BLOCK,\n listItem: getListItemStyle(el),\n level: getListItemLevel(el),\n style: getBlockStyle(schema, el),\n children: next(el.firstChild?.childNodes || []),\n }\n }\n return undefined\n },\n },\n {\n deserialize(el) {\n if (\n tagName(el) === 'br' &&\n isGoogleDocs(el) &&\n isElement(el) &&\n el.classList.contains('apple-interchange-newline')\n ) {\n return {\n ...DEFAULT_SPAN,\n text: '',\n }\n }\n\n // BRs inside empty paragraphs\n if (\n tagName(el) === 'br' &&\n isGoogleDocs(el) &&\n isElement(el) &&\n el?.parentNode?.textContent === ''\n ) {\n return {\n ...DEFAULT_SPAN,\n text: '',\n }\n }\n\n // BRs on the root\n if (\n tagName(el) === 'br' &&\n isGoogleDocs(el) &&\n isElement(el) &&\n isRootNode(el)\n ) {\n return {\n ...DEFAULT_SPAN,\n text: '',\n }\n }\n return undefined\n },\n },\n ]\n}\n","import type {DeserializerRule} from '../../types'\nimport {DEFAULT_SPAN} from '../constants'\nimport {tagName} from '../helpers'\n\nexport const whitespaceTextNodeRule: DeserializerRule = {\n deserialize(node) {\n return node.nodeName === '#text' && isWhitespaceTextNode(node)\n ? {\n ...DEFAULT_SPAN,\n marks: [],\n text: (node.textContent ?? '').replace(/\\s\\s+/g, ' '),\n }\n : undefined\n },\n}\n\nfunction isWhitespaceTextNode(node: Node) {\n const isWhitespaceOnly =\n node.nodeType === 3 &&\n (node.textContent || '').replace(/[\\r\\n]/g, ' ').replace(/\\s\\s+/g, ' ') ===\n ' '\n\n const hasSiblingContext =\n node.nextSibling &&\n node.nextSibling.nodeType !== 3 &&\n node.previousSibling &&\n node.previousSibling.nodeType !== 3\n\n // When a whitespace text node is the sole child of an inline element (e.g.\n // <span> </span>), check the parent element's siblings instead. The parent\n // must have non-text siblings on both sides (matching the same pattern as\n // the direct sibling check above).\n const parentIsInline = node.parentNode && tagName(node.parentNode) === 'span'\n const hasParentSiblingContext =\n parentIsInline &&\n !node.nextSibling &&\n !node.previousSibling &&\n node.parentNode!.previousSibling &&\n node.parentNode!.previousSibling.nodeType !== 3 &&\n node.parentNode!.nextSibling &&\n node.parentNode!.nextSibling.nodeType !== 3\n\n const isValidWhiteSpace =\n isWhitespaceOnly && (hasSiblingContext || hasParentSiblingContext)\n\n return (\n (isValidWhiteSpace || node.textContent !== ' ') &&\n tagName(node.parentNode) !== 'body'\n )\n}\n","import type {Schema} from '@portabletext/schema'\nimport type {DeserializerRule} from '../../types'\nimport {\n DEFAULT_BLOCK,\n DEFAULT_SPAN,\n HTML_BLOCK_TAGS,\n HTML_DECORATOR_TAGS,\n HTML_HEADER_TAGS,\n HTML_LIST_CONTAINER_TAGS,\n HTML_LIST_ITEM_TAGS,\n HTML_SPAN_TAGS,\n type PartialBlock,\n} from '../constants'\nimport {isElement, tagName} from '../helpers'\nimport {keyGenerator} from '../random-key'\nimport type {SchemaMatchers} from '../schema-matchers'\nimport {whitespaceTextNodeRule} from './rules.whitespace-text-node'\n\nfunction resolveListItem(\n schema: Schema,\n listNodeTagName: string,\n): string | undefined {\n if (\n listNodeTagName === 'ul' &&\n schema.lists.some((list) => list.name === 'bullet')\n ) {\n return 'bullet'\n }\n if (\n listNodeTagName === 'ol' &&\n schema.lists.some((list) => list.name === 'number')\n ) {\n return 'number'\n }\n return undefined\n}\n\nexport function createHTMLRules(\n schema: Schema,\n options: {keyGenerator?: () => string; matchers?: SchemaMatchers},\n): DeserializerRule[] {\n return [\n whitespaceTextNodeRule,\n {\n // Pre element\n deserialize(el) {\n if (tagName(el) !== 'pre') {\n return undefined\n }\n\n const isCodeEnabled = schema.styles.some(\n (style) => style.name === 'code',\n )\n\n return {\n _type: 'block',\n style: 'normal',\n markDefs: [],\n children: [\n {\n ...DEFAULT_SPAN,\n marks: isCodeEnabled ? ['code'] : [],\n text: el.textContent || '',\n },\n ],\n }\n },\n }, // Blockquote element\n {\n deserialize(el, next) {\n if (tagName(el) !== 'blockquote') {\n return undefined\n }\n const blocks: Record<string, PartialBlock | undefined> = {\n ...HTML_BLOCK_TAGS,\n ...HTML_HEADER_TAGS,\n }\n delete blocks['blockquote']\n const nonBlockquoteBlocks = Object.keys(blocks)\n\n const children: HTMLElement[] = []\n\n el.childNodes.forEach((node, index) => {\n if (!el.ownerDocument) {\n return\n }\n\n if (\n node.nodeType === 1 &&\n nonBlockquoteBlocks.includes(\n (node as Element).localName.toLowerCase(),\n )\n ) {\n const span = el.ownerDocument.createElement('span')\n\n const previousChild = children[children.length - 1]\n\n if (\n previousChild &&\n previousChild.nodeType === 3 &&\n previousChild.textContent?.trim()\n ) {\n // Only prepend line break if the previous node is a non-empty\n // text node.\n span.appendChild(el.ownerDocument.createTextNode('\\r'))\n }\n\n node.childNodes.forEach((cn) => {\n span.appendChild(cn.cloneNode(true))\n })\n\n if (index !== el.childNodes.length) {\n // Only append line break if this is not the last child\n span.appendChild(el.ownerDocument.createTextNode('\\r'))\n }\n\n children.push(span)\n } else {\n children.push(node as HTMLElement)\n }\n })\n\n return {\n _type: 'block',\n style: 'blockquote',\n markDefs: [],\n children: next(children),\n }\n },\n }, // Block elements\n {\n deserialize(el, next) {\n const blocks: Record<string, PartialBlock | undefined> = {\n ...HTML_BLOCK_TAGS,\n ...HTML_HEADER_TAGS,\n }\n const tag = tagName(el)\n let block = tag ? blocks[tag] : undefined\n if (!block) {\n return undefined\n }\n // Don't add blocks into list items\n if (el.parentNode && tagName(el.parentNode) === 'li') {\n return next(el.childNodes)\n }\n const blockStyle = block.style\n // If style is not supported, return a defaultBlockType\n if (!schema.styles.some((style) => style.name === blockStyle)) {\n block = DEFAULT_BLOCK\n }\n return {\n ...block,\n children: next(el.childNodes),\n }\n },\n }, // Ignore span tags\n {\n deserialize(el, next) {\n const tag = tagName(el)\n if (!tag || !(tag in HTML_SPAN_TAGS)) {\n return undefined\n }\n return next(el.childNodes)\n },\n }, // Ignore div tags\n {\n deserialize(el, next) {\n const div = tagName(el) === 'div'\n if (!div) {\n return undefined\n }\n return next(el.childNodes)\n },\n }, // Ignore list containers\n {\n deserialize(el, next) {\n const tag = tagName(el)\n if (!tag || !(tag in HTML_LIST_CONTAINER_TAGS)) {\n return undefined\n }\n return next(el.childNodes)\n },\n }, // Deal with br's\n {\n deserialize(el) {\n if (tagName(el) === 'br') {\n return {\n ...DEFAULT_SPAN,\n text: '\\n',\n }\n }\n return undefined\n },\n }, // Deal with list items\n {\n deserialize(el, next, block) {\n const tag = tagName(el)\n const listItem = tag ? HTML_LIST_ITEM_TAGS[tag] : undefined\n if (!listItem) {\n return undefined\n }\n // Fall back to 'ul' when the list item has no list container parent\n // (e.g. orphan <li> elements without a <ul> or <ol> wrapper).\n const parentTag = tagName(el.parentNode) || ''\n const listTag = HTML_LIST_CONTAINER_TAGS[parentTag] ? parentTag : 'ul'\n const enabledListItem = resolveListItem(schema, listTag)\n // If the list item style is not supported, return a new default block\n if (!enabledListItem) {\n return block({_type: 'block', children: next(el.childNodes)})\n }\n listItem.listItem = enabledListItem\n return {\n ...listItem,\n children: next(el.childNodes),\n }\n },\n }, // Deal with decorators - this is a limited set of known html elements that we know how to deserialize\n {\n deserialize(el, next) {\n const decorator = HTML_DECORATOR_TAGS[tagName(el) || '']\n if (\n !decorator ||\n !schema.decorators.some(\n (decoratorType) => decoratorType.name === decorator,\n )\n ) {\n return undefined\n }\n return {\n _type: '__decorator',\n name: decorator,\n children: next(el.childNodes),\n }\n },\n }, // Special case for hyperlinks, add annotation (if allowed by schema),\n // If not supported just write out the link text and href in plain text.\n {\n deserialize(el, next) {\n if (tagName(el) !== 'a') {\n return undefined\n }\n const linkEnabled = schema.annotations.some(\n (annotation) => annotation.name === 'link',\n )\n const href = isElement(el) && el.getAttribute('href')\n if (!href) {\n return next(el.childNodes)\n }\n if (linkEnabled) {\n return {\n _type: '__annotation',\n markDef: {\n _key: options.keyGenerator\n ? options.keyGenerator()\n : keyGenerator(),\n _type: 'link',\n href: href,\n },\n children: next(el.childNodes),\n }\n }\n return (\n el.appendChild(el.ownerDocument.createTextNode(` (${href})`)) &&\n next(el.childNodes)\n )\n },\n },\n {\n deserialize(el, next) {\n if (isElement(el) && (tagName(el) === 'td' || tagName(el) === 'th')) {\n return {\n ...DEFAULT_BLOCK,\n children: next(el.childNodes),\n }\n }\n\n return undefined\n },\n },\n {\n deserialize(el) {\n if (isElement(el) && tagName(el) === 'img') {\n const src = el.getAttribute('src') ?? undefined\n const alt = el.getAttribute('alt') ?? undefined\n\n const props = Object.fromEntries(\n Array.from(el.attributes).map((attr) => [attr.name, attr.value]),\n )\n\n const ancestorOfLonelyChild =\n el?.parentElement?.parentElement?.getAttribute('data-lonely-child')\n const ancestorOfListItem = el.closest('li') !== null\n\n if (ancestorOfLonelyChild && !ancestorOfListItem) {\n const image = options.matchers?.image?.({\n context: {\n schema,\n keyGenerator: options.keyGenerator ?? keyGenerator,\n },\n props: {\n ...props,\n ...(src ? {src} : {}),\n ...(alt ? {alt} : {}),\n },\n })\n\n if (image) {\n return {\n _type: '__block',\n block: image,\n }\n }\n }\n\n const inlineImage = options.matchers?.inlineImage?.({\n context: {\n schema,\n keyGenerator: options.keyGenerator ?? keyGenerator,\n },\n props: {\n ...props,\n ...(src ? {src} : {}),\n ...(alt ? {alt} : {}),\n },\n })\n\n if (inlineImage) {\n return inlineImage\n }\n\n const image = options.matchers?.image?.({\n context: {\n schema,\n keyGenerator: options.keyGenerator ?? keyGenerator,\n },\n props: {\n ...props,\n ...(src ? {src} : {}),\n ...(alt ? {alt} : {}),\n },\n })\n\n if (image) {\n return {\n _type: '__block',\n block: image,\n }\n }\n }\n\n return undefined\n },\n },\n ]\n}\n","import type {DeserializerRule} from '../../types'\nimport {DEFAULT_SPAN} from '../constants'\nimport {isElement, tagName} from '../helpers'\n\n// font-style:italic seems like the most important rule for italic / emphasis in their html\nfunction isEmphasis(el: Node): boolean {\n const style = isElement(el) && el.getAttribute('style')\n return /font-style:italic/.test(style || '')\n}\n\n// font-weight:700 or 600 seems like the most important rule for bold in their html\nfunction isStrong(el: Node): boolean {\n const style = isElement(el) && el.getAttribute('style')\n return (\n /font-weight:700/.test(style || '') || /font-weight:600/.test(style || '')\n )\n}\n\n// text-decoration seems like the most important rule for underline in their html\nfunction isUnderline(el: Node): boolean {\n const style = isElement(el) && el.getAttribute('style')\n return /text-decoration:underline/.test(style || '')\n}\n\n// Check for attribute given by the Notion preprocessor\nfunction isNotion(el: Node): boolean {\n return isElement(el) && Boolean(el.getAttribute('data-is-notion'))\n}\n\nexport function createNotionRules(): DeserializerRule[] {\n return [\n {\n deserialize(el) {\n // Notion normally exports semantic HTML. However, if you copy a single block, the formatting will be inline styles\n // This handles a limited set of styles\n if (isElement(el) && tagName(el) === 'span' && isNotion(el)) {\n const span = {\n ...DEFAULT_SPAN,\n marks: [] as string[],\n text: el.textContent,\n }\n if (isStrong(el)) {\n span.marks.push('strong')\n }\n if (isUnderline(el)) {\n span.marks.push('underline')\n }\n if (isEmphasis(el)) {\n span.marks.push('em')\n }\n return span\n }\n return undefined\n },\n },\n ]\n}\n","import type {DeserializerRule} from '../../types'\nimport {\n BLOCK_DEFAULT_STYLE,\n DEFAULT_BLOCK,\n HTML_HEADER_TAGS,\n} from '../constants'\nimport {isElement, tagName} from '../helpers'\n\n/**\n * Read the list style map stored by the Word preprocessor on the document body.\n * Returns a map from list ID (e.g. \"l0\") to list type (\"bullet\" or \"number\").\n */\nfunction getListStyleMap(el: Node): Record<string, string> {\n if (!isElement(el)) {\n return {}\n }\n\n const body = el.closest('body') || el.ownerDocument?.body\n if (!body) {\n return {}\n }\n\n const data = body.getAttribute('data-word-list-styles')\n if (!data) {\n return {}\n }\n\n try {\n return JSON.parse(data)\n } catch {\n return {}\n }\n}\n\nfunction getListItemStyle(el: Node): string | undefined {\n const style = isElement(el) && el.getAttribute('style')\n if (!style) {\n return undefined\n }\n\n // Extract list ID and level from mso-list: e.g. \"mso-list:l1 level1 lfo1\"\n const msoListMatch = style.match(/mso-list:\\s*(l\\d+)\\s+(level\\d+)\\s+lfo\\d+/)\n if (!msoListMatch) {\n return undefined\n }\n\n const key = `${msoListMatch[1]}:${msoListMatch[2]}`\n const listStyles = getListStyleMap(el)\n return (listStyles[key] as 'bullet' | 'number') || 'bullet'\n}\n\nfunction getListItemLevel(el: Node): number | undefined {\n const style = isElement(el) && el.getAttribute('style')\n if (!style) {\n return undefined\n }\n\n const levelMatch = style.match(/level\\d+/)\n if (!levelMatch) {\n return undefined\n }\n\n const [level] = levelMatch[0].match(/\\d/) || []\n const levelNum = level ? Number.parseInt(level, 10) : 1\n return levelNum || 1\n}\n\nfunction isWordListElement(el: Node): boolean {\n if (!isElement(el)) {\n return false\n }\n\n // Check for specific class names\n if (el.className) {\n if (\n el.className === 'MsoListParagraphCxSpFirst' ||\n el.className === 'MsoListParagraphCxSpMiddle' ||\n el.className === 'MsoListParagraphCxSpLast'\n ) {\n return true\n }\n }\n\n // Check for mso-list in style attribute\n const style = el.getAttribute('style')\n if (style && /mso-list:\\s*l\\d+\\s+level\\d+\\s+lfo\\d+/.test(style)) {\n return true\n }\n\n return false\n}\n\nfunction getHeadingStyle(el: Node): string | undefined {\n const tag = tagName(el)\n if (tag && HTML_HEADER_TAGS[tag]) {\n return HTML_HEADER_TAGS[tag]?.style\n }\n return undefined\n}\n\nexport function createWordRules(): DeserializerRule[] {\n return [\n {\n deserialize(el, next) {\n const tag = tagName(el)\n\n // Handle list items (both paragraphs and headings)\n if (\n (tag === 'p' || HTML_HEADER_TAGS[tag || '']) &&\n isWordListElement(el)\n ) {\n const headingStyle = getHeadingStyle(el)\n return {\n ...DEFAULT_BLOCK,\n listItem: getListItemStyle(el),\n level: getListItemLevel(el),\n style: headingStyle || BLOCK_DEFAULT_STYLE,\n children: next(el.childNodes),\n }\n }\n return undefined\n },\n },\n ]\n}\n","import type {Schema} from '@portabletext/schema'\nimport type {DeserializerRule} from '../../types'\nimport type {SchemaMatchers} from '../schema-matchers'\nimport {createWordOnlineRules} from '../word-online/rules.word-online'\nimport {createGDocsRules} from './rules.gdocs'\nimport {createHTMLRules} from './rules.html'\nimport {createNotionRules} from './rules.notion'\nimport {createWordRules} from './rules.word'\n\nexport function createRules(\n schema: Schema,\n options: {keyGenerator?: () => string; matchers?: SchemaMatchers},\n): DeserializerRule[] {\n return [\n ...createWordRules(),\n ...createWordOnlineRules(schema, options),\n ...createNotionRules(),\n ...createGDocsRules(schema),\n ...createHTMLRules(schema, options),\n ]\n}\n","import {\n isSpan,\n isTextBlock,\n type PortableTextTextBlock,\n type Schema,\n} from '@portabletext/schema'\nimport type {TypedObject} from '../types'\nimport {isEqualMarks} from './equality'\nimport {isMinimalSpan} from './helpers'\n\nexport type WhiteSpacePasteMode = 'preserve' | 'remove' | 'normalize'\n\nexport function trimWhitespace(\n context: {schema: Schema},\n mode: WhiteSpacePasteMode,\n blocks: TypedObject[],\n): TypedObject[] {\n const trimmedBlocks: TypedObject[] = []\n let consecutiveEmptyCount = 0\n\n for (const block of blocks) {\n const trimmedBlock = isTextBlock(context, block)\n ? trimTextBlockWhitespace(block)\n : block\n\n if (mode === 'preserve') {\n trimmedBlocks.push(trimmedBlock)\n\n continue\n }\n\n if (mode === 'remove') {\n if (isEmptyTextBlock(context, trimmedBlock)) {\n continue\n }\n\n trimmedBlocks.push(trimmedBlock)\n\n continue\n }\n\n if (mode === 'normalize') {\n if (isEmptyTextBlock(context, trimmedBlock)) {\n consecutiveEmptyCount++\n\n if (consecutiveEmptyCount === 1) {\n trimmedBlocks.push(trimmedBlock)\n }\n\n continue\n }\n\n trimmedBlocks.push(trimmedBlock)\n\n consecutiveEmptyCount = 0\n }\n }\n\n return trimmedBlocks\n}\n\nfunction isEmptyTextBlock(\n context: {schema: Schema},\n block: TypedObject,\n): boolean {\n if (!isTextBlock(context, block)) {\n return false\n }\n\n if (\n block.children.some(\n (child) => !isSpan(context, child) || child.text.trim() !== '',\n )\n ) {\n return false\n }\n\n return true\n}\n\nfunction trimTextBlockWhitespace(\n block: PortableTextTextBlock,\n): PortableTextTextBlock {\n let index = 0\n\n for (const child of block.children) {\n if (!isMinimalSpan(child)) {\n index++\n continue\n }\n\n const nextChild = nextSpan(block, index)\n const prevChild = prevSpan(block, index)\n\n if (index === 0) {\n child.text = child.text.replace(/^[^\\S\\n]+/g, '')\n }\n\n if (index === block.children.length - 1) {\n child.text = child.text.replace(/[^\\S\\n]+$/g, '')\n }\n\n if (\n /\\s/.test(child.text.slice(Math.max(0, child.text.length - 1))) &&\n nextChild &&\n isMinimalSpan(nextChild) &&\n /\\s/.test(nextChild.text.slice(0, 1))\n ) {\n child.text = child.text.replace(/[^\\S\\n]+$/g, '')\n }\n\n if (\n /\\s/.test(child.text.slice(0, 1)) &&\n prevChild &&\n isMinimalSpan(prevChild) &&\n /\\s/.test(prevChild.text.slice(Math.max(0, prevChild.text.length - 1)))\n ) {\n child.text = child.text.replace(/^[^\\S\\n]+/g, '')\n }\n\n if (!child.text) {\n block.children.splice(index, 1)\n }\n\n if (\n prevChild &&\n Array.isArray(prevChild.marks) &&\n isEqualMarks(prevChild.marks, child.marks) &&\n isWhiteSpaceChar(child.text)\n ) {\n prevChild.text += ' '\n block.children.splice(index, 1)\n } else if (\n nextChild &&\n Array.isArray(nextChild.marks) &&\n isEqualMarks(nextChild.marks, child.marks) &&\n isWhiteSpaceChar(child.text)\n ) {\n nextChild.text = ` ${nextChild.text}`\n block.children.splice(index, 1)\n }\n\n index++\n }\n\n return block\n}\n\nfunction nextSpan(block: PortableTextTextBlock, index: number) {\n const next = block.children[index + 1]\n return next && next._type === 'span' ? next : null\n}\n\nfunction prevSpan(block: PortableTextTextBlock, index: number) {\n const prev = block.children[index - 1]\n return prev && prev._type === 'span' ? prev : null\n}\n\nfunction isWhiteSpaceChar(text: string) {\n return ['\\xa0', ' '].includes(text)\n}\n","import type {Schema} from '@portabletext/schema'\nimport {\n isTextBlock,\n type PortableTextBlock,\n type PortableTextObject,\n} from '@portabletext/schema'\nimport {vercelStegaClean} from '@vercel/stega'\nimport type {\n ArbitraryTypedObject,\n DeserializerRule,\n HtmlParser,\n PlaceholderAnnotation,\n PlaceholderDecorator,\n TypedObject,\n} from '../types'\nimport {flattenNestedBlocks} from './flatten-nested-blocks'\nimport {\n defaultParseHtml,\n ensureRootIsBlocks,\n isMinimalBlock,\n isMinimalSpan,\n isNodeList,\n isPlaceholderAnnotation,\n isPlaceholderDecorator,\n tagName,\n} from './helpers'\nimport {preprocessors} from './preprocessors'\nimport {keyGenerator} from './random-key'\nimport {resolveJsType} from './resolve-js-type'\nimport {createRules} from './rules'\nimport type {SchemaMatchers} from './schema-matchers'\nimport {trimWhitespace} from './trim-whitespace'\n\nexport interface HtmlDeserializerOptions {\n keyGenerator?: () => string\n rules?: DeserializerRule[]\n parseHtml?: HtmlParser\n whitespaceMode?: 'preserve' | 'remove' | 'normalize'\n matchers?: SchemaMatchers\n}\n\n/**\n * HTML Deserializer\n *\n */\nexport class HtmlDeserializer {\n keyGenerator: () => string\n schema: Schema\n rules: DeserializerRule[]\n parseHtml: (html: string) => HTMLElement\n whitespaceMode: 'preserve' | 'remove' | 'normalize'\n _markDefs: PortableTextObject[] = []\n\n /**\n * Create a new serializer respecting a Sanity block content type's schema\n *\n * @param schema - Schema definition\n * @param options - Options for the deserialization process\n */\n constructor(schema: Schema, options: HtmlDeserializerOptions = {}) {\n const {rules = [], whitespaceMode = 'preserve'} = options\n const standardRules = createRules(schema, {\n keyGenerator: options.keyGenerator,\n matchers: options.matchers,\n })\n this.schema = schema\n this.keyGenerator = options.keyGenerator ?? keyGenerator\n this.rules = [...rules, ...standardRules]\n this.whitespaceMode = whitespaceMode\n const parseHtml = options.parseHtml || defaultParseHtml()\n this.parseHtml = (html) => {\n const cleanHTML = vercelStegaClean(html)\n const doc = parseHtml(cleanHTML)\n\n for (const processor of preprocessors) {\n processor(cleanHTML, doc)\n }\n\n return doc.body\n }\n }\n\n /**\n * Deserialize HTML.\n *\n * @param html - The HTML to deserialize, as a string\n * @returns Array of blocks - either portable text blocks or other allowed blocks\n */\n deserialize = (html: string): TypedObject[] => {\n this._markDefs = []\n const {parseHtml} = this\n const fragment = parseHtml(html)\n const children = Array.from(fragment.childNodes) as HTMLElement[]\n\n const blocks = trimWhitespace(\n {schema: this.schema},\n this.whitespaceMode,\n flattenNestedBlocks(\n {schema: this.schema},\n ensureRootIsBlocks(\n this.schema,\n this.deserializeElements(children) as Array<ArbitraryTypedObject>,\n ),\n ),\n )\n\n if (this._markDefs.length > 0) {\n blocks\n .filter((block) => isTextBlock({schema: this.schema}, block))\n .forEach((block) => {\n block.markDefs = block.markDefs || []\n block.markDefs = block.markDefs.concat(\n this._markDefs.filter((def) => {\n return block.children\n .flatMap((child) => child.marks || [])\n .includes(def._key)\n }),\n )\n })\n }\n\n return blocks.map((block) => {\n if (block._type === 'block') {\n block._type = this.schema.block.name\n }\n return block\n })\n }\n\n /**\n * Deserialize an array of DOM elements.\n *\n * @param elements - Array of DOM elements to deserialize\n * @returns\n */\n deserializeElements = (elements: Node[] = []): TypedObject[] => {\n let nodes: TypedObject[] = []\n elements.forEach((element) => {\n nodes = nodes.concat(this.deserializeElement(element))\n })\n return nodes\n }\n\n /**\n * Deserialize a DOM element\n *\n * @param element - Deserialize a DOM element\n * @returns\n */\n deserializeElement = (element: Node): TypedObject | TypedObject[] => {\n const next = (\n elements: Node | Node[] | NodeList,\n ): TypedObject | TypedObject[] | undefined => {\n if (isNodeList(elements)) {\n return this.deserializeElements(Array.from(elements))\n }\n\n if (Array.isArray(elements)) {\n return this.deserializeElements(elements)\n }\n\n if (!elements) {\n return undefined\n }\n\n return this.deserializeElement(elements)\n }\n\n const block = (props: ArbitraryTypedObject) => {\n return {\n _type: '__block',\n block: props,\n }\n }\n\n let node: TypedObject | Array<TypedObject> | undefined\n for (let i = 0; i < this.rules.length; i++) {\n const rule = this.rules[i]\n if (!rule || !rule.deserialize) {\n continue\n }\n\n const ret = rule.deserialize(element, next, block)\n const type = resolveJsType(ret)\n\n if (\n type !== 'array' &&\n type !== 'object' &&\n type !== 'null' &&\n type !== 'undefined'\n ) {\n throw new Error(\n `A rule returned an invalid deserialized representation: \"${node}\".`,\n )\n }\n\n if (ret === undefined) {\n continue\n } else if (ret === null) {\n throw new Error('Deserializer rule returned `null`')\n } else if (Array.isArray(ret)) {\n node = ret\n } else if (isPlaceholderDecorator(ret)) {\n node = this.deserializeDecorator(ret)\n } else if (isPlaceholderAnnotation(ret)) {\n node = this.deserializeAnnotation(ret)\n } else {\n node = ret\n }\n\n // Set list level on list item\n if (\n ret &&\n !Array.isArray(ret) &&\n isMinimalBlock(ret) &&\n 'listItem' in ret\n ) {\n let parent = element.parentNode?.parentNode\n while (parent && tagName(parent) === 'li') {\n parent = parent.parentNode?.parentNode\n ret.level = ret.level ? ret.level + 1 : 1\n }\n }\n\n // Set newlines on spans orginating from a block element within a blockquote\n if (\n ret &&\n !Array.isArray(ret) &&\n isMinimalBlock(ret) &&\n ret.style === 'blockquote'\n ) {\n ret.children.forEach((child, index) => {\n if (isMinimalSpan(child) && child.text === '\\r') {\n child.text = '\\n'\n if (index === 0 || index === ret.children.length - 1) {\n ret.children.splice(index, 1)\n }\n }\n })\n }\n break\n }\n\n return node || next(element.childNodes) || []\n }\n\n /**\n * Deserialize a `__decorator` type\n * (an internal made up type to process decorators exclusively)\n *\n * @param decorator -\n * @returns array of ...\n */\n deserializeDecorator = (decorator: PlaceholderDecorator): TypedObject[] => {\n const {name} = decorator\n const applyDecorator = (node: TypedObject) => {\n if (isPlaceholderDecorator(node)) {\n return this.deserializeDecorator(node)\n } else if (isMinimalSpan(node)) {\n node.marks = node.marks || []\n if (node.text.trim()) {\n // Only apply marks if this is an actual text\n node.marks.unshift(name)\n }\n } else if (\n 'children' in node &&\n Array.isArray((node as PortableTextBlock).children)\n ) {\n const block = node as any\n block.children = block.children.map(applyDecorator)\n }\n return node\n }\n return decorator.children.reduce((children, node) => {\n const ret = applyDecorator(node)\n if (Array.isArray(ret)) {\n return children.concat(ret)\n }\n children.push(ret)\n return children\n }, [] as TypedObject[])\n }\n\n /**\n * Deserialize a `__annotation` object.\n * (an internal made up type to process annotations exclusively)\n *\n * @param annotation -\n * @returns Array of...\n */\n deserializeAnnotation = (\n annotation: PlaceholderAnnotation,\n ): TypedObject[] => {\n const {markDef} = annotation\n this._markDefs.push(markDef)\n const applyAnnotation = (node: TypedObject) => {\n if (isPlaceholderAnnotation(node)) {\n return this.deserializeAnnotation(node)\n } else if (isMinimalSpan(node)) {\n node.marks = node.marks || []\n if (node.text.trim()) {\n // Only apply marks if this is an actual text\n node.marks.unshift(markDef._key)\n }\n } else if (\n 'children' in node &&\n Array.isArray((node as PortableTextBlock).children)\n ) {\n const block = node as any\n block.children = block.children.map(applyAnnotation)\n }\n return node\n }\n return annotation.children.reduce((children, node) => {\n const ret = applyAnnotation(node)\n if (Array.isArray(ret)) {\n return children.concat(ret)\n }\n children.push(ret)\n return children\n }, [] as TypedObject[])\n }\n}\n","import type {Schema} from '@portabletext/schema'\nimport {\n isSpan,\n type PortableTextSpan,\n type PortableTextTextBlock,\n} from '@portabletext/schema'\nimport type {TypedObject} from '../types'\nimport {isEqualMarks} from './equality'\nimport {keyGenerator} from './random-key'\n\n/**\n * Block normalization options\n */\nexport interface BlockNormalizationOptions {\n /**\n * Decorator names that are allowed within portable text blocks, eg `em`, `strong`\n */\n allowedDecorators?: string[]\n\n /**\n * Name of the portable text block type, if not `block`\n */\n blockTypeName?: string\n\n /**\n * Custom key generator function\n */\n keyGenerator?: () => string\n}\n\n/**\n * Normalizes a block by ensuring it has a `_key` property. If the block is a\n * portable text block, additional normalization is applied:\n *\n * - Ensures it has `children` and `markDefs` properties\n * - Ensures it has at least one child (adds an empty span if empty)\n * - Joins sibling spans that has the same marks\n * - Removes decorators that are not allowed according to the schema\n * - Removes marks that have no annotation definition\n *\n * @param node - The block to normalize\n * @param options - Options for normalization process. See {@link BlockNormalizationOptions}\n * @returns Normalized block\n */\nexport function normalizeBlock(\n node: TypedObject,\n options: BlockNormalizationOptions = {},\n): Omit<\n TypedObject | PortableTextTextBlock<TypedObject | PortableTextSpan>,\n '_key'\n> & {\n _key: string\n} {\n const schema: Schema = {\n block: {\n name: options.blockTypeName || 'block',\n },\n span: {\n name: 'span',\n },\n styles: [],\n lists: [],\n decorators: [],\n annotations: [],\n blockObjects: [],\n inlineObjects: [],\n }\n\n if (node._type !== (options.blockTypeName || 'block')) {\n return '_key' in node\n ? (node as TypedObject & {_key: string})\n : {\n ...node,\n _key: options.keyGenerator ? options.keyGenerator() : keyGenerator(),\n }\n }\n\n const block: Omit<\n PortableTextTextBlock<TypedObject | PortableTextSpan>,\n 'style'\n > = {\n _key: options.keyGenerator ? options.keyGenerator() : keyGenerator(),\n children: [],\n markDefs: [],\n ...node,\n }\n\n const lastChild = block.children[block.children.length - 1]\n\n if (!lastChild) {\n // A block must at least have an empty span type child\n block.children = [\n {\n _type: 'span',\n _key: options.keyGenerator ? options.keyGenerator() : keyGenerator(),\n text: '',\n marks: [],\n },\n ]\n return block\n }\n\n const usedMarkDefs: string[] = []\n const allowedDecorators =\n options.allowedDecorators && Array.isArray(options.allowedDecorators)\n ? options.allowedDecorators\n : false\n\n block.children = block.children\n .reduce(\n (acc, child) => {\n const previousChild = acc[acc.length - 1]\n if (\n previousChild &&\n isSpan({schema}, child) &&\n isSpan({schema}, previousChild) &&\n isEqualMarks(previousChild.marks, child.marks)\n ) {\n if (\n lastChild &&\n lastChild === child &&\n child.text === '' &&\n block.children.length > 1\n ) {\n return acc\n }\n\n previousChild.text += child.text\n return acc\n }\n acc.push(child)\n return acc\n },\n [] as (TypedObject | PortableTextSpan)[],\n )\n .map((child) => {\n if (!child) {\n throw new Error('missing child')\n }\n\n child._key = options.keyGenerator\n ? options.keyGenerator()\n : keyGenerator()\n\n if (isSpan({schema}, child)) {\n if (!child.marks) {\n child.marks = []\n } else if (allowedDecorators) {\n child.marks = child.marks.filter((mark) => {\n const isAllowed = allowedDecorators.includes(mark)\n const isUsed = block.markDefs?.some((def) => def._key === mark)\n return isAllowed || isUsed\n })\n }\n\n usedMarkDefs.push(...child.marks)\n }\n\n return child\n })\n\n // Remove leftover (unused) markDefs\n block.markDefs = (block.markDefs || []).filter((markDef) =>\n usedMarkDefs.includes(markDef._key),\n )\n\n return block\n}\n","import type {Schema} from '@portabletext/schema'\nimport {defaultSchema} from './default-schema'\nimport {HtmlDeserializer} from './deserializer/html-deserializer'\nimport {normalizeBlock} from './deserializer/normalize-block'\nimport type {SchemaMatchers} from './deserializer/schema-matchers'\nimport type {ObjectMatcher} from './matchers'\nimport type {DeserializerRule} from './types'\n\n/**\n * Options for converting HTML to Portable Text\n *\n * @public\n */\nexport type HtmlToPortableTextOptions = {\n schema?: Schema\n keyGenerator?: () => string\n parseHtml?: (html: string) => Document\n rules?: DeserializerRule[]\n whitespaceMode?: 'preserve' | 'remove' | 'normalize'\n types?: {\n image?: ObjectMatcher<{src?: string; alt?: string}>\n }\n}\n\n/**\n * Convert HTML to Portable Text\n *\n * @param html - The HTML string to convert\n * @param options - Options for the conversion\n * @returns Array of Portable Text blocks\n * @public\n */\nexport function htmlToPortableText(\n html: string,\n options: HtmlToPortableTextOptions = {},\n) {\n const schema = options.schema ?? defaultSchema\n const keyGen = options.keyGenerator\n\n const matchers = toSchemaMatchers(options.types)\n\n const deserializer = new HtmlDeserializer(schema, {\n keyGenerator: keyGen,\n rules: options.rules,\n parseHtml: options.parseHtml,\n whitespaceMode: options.whitespaceMode,\n matchers,\n })\n return deserializer\n .deserialize(html)\n .map((block) => normalizeBlock(block, {keyGenerator: keyGen}))\n}\n\n/**\n * Convert public ObjectMatcher options to internal SchemaMatchers.\n *\n * ObjectMatcher uses ({context, value, isInline}) matching the\n * @portabletext/markdown API. SchemaMatchers uses ({context, props})\n * matching the internal block-tools engine.\n *\n * If the ObjectMatcher returns a _key, it is preserved. normalizeBlock\n * only assigns a key when one is missing.\n */\nfunction toSchemaMatchers(\n types: HtmlToPortableTextOptions['types'],\n): SchemaMatchers | undefined {\n if (!types?.image) {\n return undefined\n }\n\n const objectMatcher = types.image\n\n const adapt =\n (isInline: boolean): NonNullable<SchemaMatchers['image']> =>\n ({context, props}) => {\n const result = objectMatcher({\n context,\n value: props as {src?: string; alt?: string},\n isInline,\n })\n if (!result) {\n return undefined\n }\n return result as ReturnType<NonNullable<SchemaMatchers['image']>>\n }\n\n return {\n image: adapt(false),\n inlineImage: adapt(true),\n }\n}\n","import type {\n PortableTextObject,\n Schema,\n SchemaDefinition,\n} from '@portabletext/schema'\n\n/**\n * Matcher function for mapping HTML elements to Portable Text block styles.\n *\n * @public\n */\nexport type StyleMatcher = ({\n context,\n}: {\n context: {schema: Schema}\n}) => string | undefined\n\n/**\n * @public\n */\nexport function buildStyleMatcher<TDefinition extends {name: string}>(\n definition: TDefinition,\n): StyleMatcher {\n return ({context}) => {\n const schemaDefinition = context.schema.styles.find(\n (item) => item.name === definition.name,\n )\n\n if (!schemaDefinition) {\n return undefined\n }\n\n return schemaDefinition.name\n }\n}\n\n/**\n * Matcher function for mapping HTML list items to Portable Text list types.\n *\n * @public\n */\nexport type ListItemMatcher = ({\n context,\n}: {\n context: {schema: Schema}\n}) => string | undefined\n\n/**\n * @public\n */\nexport function buildListItemMatcher<TDefinition extends {name: string}>(\n definition: TDefinition,\n): ListItemMatcher {\n return ({context}) => {\n const schemaDefinition = context.schema.lists.find(\n (item) => item.name === definition.name,\n )\n\n if (!schemaDefinition) {\n return undefined\n }\n\n return schemaDefinition.name\n }\n}\n\n/**\n * Matcher function for mapping HTML inline formatting to Portable Text decorators.\n *\n * @public\n */\nexport type DecoratorMatcher = ({\n context,\n}: {\n context: {schema: Schema}\n}) => string | undefined\n\n/**\n * @public\n */\nexport function buildDecoratorMatcher<TDefinition extends {name: string}>(\n definition: TDefinition,\n): DecoratorMatcher {\n return ({context}) => {\n const schemaDefinition = context.schema.decorators.find(\n (item) => item.name === definition.name,\n )\n\n if (!schemaDefinition) {\n return undefined\n }\n\n return schemaDefinition.name\n }\n}\n\n/**\n * Matcher function for mapping HTML links to Portable Text annotations.\n *\n * @public\n */\nexport type AnnotationMatcher<\n TValue extends Record<string, unknown> = Record<string, never>,\n> = ({\n context,\n value,\n}: {\n context: {schema: Schema; keyGenerator: () => string}\n value: TValue\n}) => PortableTextObject | undefined\n\n/**\n * @public\n */\nexport function buildAnnotationMatcher<TDefinition extends {name: string}>(\n definition: TDefinition,\n): AnnotationMatcher<ExtractValue<TDefinition>> {\n return ({context, value}) => {\n const schemaDefinition = context.schema.annotations.find(\n (item) => item.name === definition.name,\n )\n\n if (!schemaDefinition) {\n return undefined\n }\n\n const filteredValue = schemaDefinition.fields.reduce<\n Record<string, unknown>\n >((filteredValue, field) => {\n const fieldValue = value[field.name as keyof typeof value]\n\n if (fieldValue !== undefined) {\n filteredValue[field.name] = fieldValue\n }\n\n return filteredValue\n }, {})\n\n return {\n _key: context.keyGenerator(),\n _type: schemaDefinition.name,\n ...filteredValue,\n }\n }\n}\n\n/**\n * Matcher function for mapping HTML objects to Portable Text block or inline objects.\n *\n * @public\n */\nexport type ObjectMatcher<\n TValue extends Record<string, unknown> = Record<string, never>,\n> = ({\n context,\n value,\n isInline,\n}: {\n context: {schema: Schema; keyGenerator: () => string}\n value: TValue\n isInline: boolean\n}) => PortableTextObject | undefined\n\n/**\n * @public\n */\nexport function buildObjectMatcher<TDefinition extends {name: string}>(\n definition: TDefinition,\n): ObjectMatcher<ExtractValue<TDefinition>> {\n return ({context, value, isInline}) => {\n const schemaCollection = isInline\n ? context.schema.inlineObjects\n : context.schema.blockObjects\n\n const schemaDefinition = schemaCollection.find(\n (item) => item.name === definition.name,\n )\n\n if (!schemaDefinition) {\n return undefined\n }\n\n const filteredValue = schemaDefinition.fields.reduce<\n Record<string, unknown>\n >((filteredValue, field) => {\n const fieldValue = value[field.name as keyof typeof value]\n\n if (fieldValue !== undefined) {\n filteredValue[field.name] = fieldValue\n }\n\n return filteredValue\n }, {})\n\n return {\n _key: context.keyGenerator(),\n _type: schemaDefinition.name,\n ...filteredValue,\n }\n }\n}\n\n/**\n * @public\n */\nexport type ExtractValue<\n TDefinition extends NonNullable<SchemaDefinition['blockObjects']>[0],\n> = TDefinition extends {fields: ReadonlyArray<{name: infer TNames}>}\n ? Record<TNames & string, unknown>\n : Record<string, never>\n"],"names":["span","isEmphasis","isStrong","isUnderline","getListItemStyle","getListItemLevel","blocks","image","filteredValue"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/default-schema.ts","../src/deserializer/word-online/asserters.word-online.ts","../src/deserializer/word-online/preprocessor.word-online.ts","../src/deserializer/preprocessors/xpathResult.ts","../src/deserializer/preprocessors/preprocessor.gdocs.ts","../src/deserializer/preprocessors/preprocessor.html.ts","../src/deserializer/preprocessors/preprocessor.notion.ts","../src/deserializer/preprocessors/preprocessor.whitespace.ts","../src/deserializer/preprocessors/preprocessor.word.ts","../src/deserializer/preprocessors/index.ts","../src/deserializer/random-key.ts","../src/deserializer/word-online/rules.word-online.ts","../src/deserializer/rules/rules.gdocs.ts","../src/deserializer/rules/rules.whitespace-text-node.ts","../src/deserializer/rules/rules.html.ts","../src/deserializer/rules/rules.notion.ts","../src/deserializer/rules/rules.word.ts","../src/deserializer/rules/index.ts","../src/deserializer/trim-whitespace.ts","../src/deserializer/html-deserializer.ts","../src/deserializer/normalize-block.ts","../src/html-to-portable-text.ts","../src/matchers.ts"],"sourcesContent":["import {\n compileSchema,\n defineSchema,\n type AnnotationDefinition,\n type BlockObjectDefinition,\n type DecoratorDefinition,\n type ListDefinition,\n type StyleDefinition,\n} from '@portabletext/schema'\n\n/********************\n * Default style definitions\n ********************/\n\nconst normalStyleDefinition = {\n name: 'normal',\n} as const satisfies StyleDefinition\n\nconst h1StyleDefinition = {\n name: 'h1',\n} as const satisfies StyleDefinition\n\nconst h2StyleDefinition = {\n name: 'h2',\n} as const satisfies StyleDefinition\n\nconst h3StyleDefinition = {\n name: 'h3',\n} as const satisfies StyleDefinition\n\nconst h4StyleDefinition = {\n name: 'h4',\n} as const satisfies StyleDefinition\n\nconst h5StyleDefinition = {\n name: 'h5',\n} as const satisfies StyleDefinition\n\nconst h6StyleDefinition = {\n name: 'h6',\n} as const satisfies StyleDefinition\n\nconst blockquoteStyleDefinition = {\n name: 'blockquote',\n} as const satisfies StyleDefinition\n\n/********************\n * Default list definitions\n ********************/\n\nconst defaultOrderedListItemDefinition = {\n name: 'number',\n} as const satisfies ListDefinition\n\nconst defaultUnorderedListItemDefinition = {\n name: 'bullet',\n} as const satisfies ListDefinition\n\n/********************\n * Default decorator definitions\n ********************/\n\nconst defaultStrongDecoratorDefinition = {\n name: 'strong',\n} as const satisfies DecoratorDefinition\n\nconst defaultEmDecoratorDefinition = {\n name: 'em',\n} as const satisfies DecoratorDefinition\n\nconst defaultCodeDecoratorDefinition = {\n name: 'code',\n} as const satisfies DecoratorDefinition\n\nconst defaultStrikeThroughDecoratorDefinition = {\n name: 'strike-through',\n} as const satisfies DecoratorDefinition\n\n/********************\n * Default annotation definitions\n ********************/\n\nconst defaultLinkObjectDefinition = {\n name: 'link',\n fields: [\n {name: 'href', type: 'string'},\n {name: 'title', type: 'string'},\n ],\n} as const satisfies AnnotationDefinition\n\n/********************\n * Default object definitions\n ********************/\n\nconst defaultCodeObjectDefinition = {\n name: 'code',\n fields: [\n {name: 'language', type: 'string'},\n {name: 'code', type: 'string'},\n ],\n} as const satisfies BlockObjectDefinition\n\nconst defaultImageObjectDefinition = {\n name: 'image',\n fields: [\n {name: 'src', type: 'string'},\n {name: 'alt', type: 'string'},\n {name: 'title', type: 'string'},\n ],\n} as const satisfies BlockObjectDefinition\n\nconst defaultHorizontalRuleObjectDefinition = {\n name: 'horizontal-rule',\n} as const satisfies BlockObjectDefinition\n\nconst defaultHtmlObjectDefinition = {\n name: 'html',\n fields: [{name: 'html', type: 'string'}],\n} as const satisfies BlockObjectDefinition\n\nconst defaultTableObjectDefinition = {\n name: 'table',\n fields: [\n {name: 'headerRows', type: 'number'},\n {name: 'rows', type: 'array'},\n ],\n} as const satisfies BlockObjectDefinition\n\n/**\n * The default schema for converting HTML to Portable Text.\n *\n * @public\n */\nexport const defaultSchema = compileSchema(\n defineSchema({\n styles: [\n normalStyleDefinition,\n h1StyleDefinition,\n h2StyleDefinition,\n h3StyleDefinition,\n h4StyleDefinition,\n h5StyleDefinition,\n h6StyleDefinition,\n blockquoteStyleDefinition,\n ],\n lists: [\n defaultOrderedListItemDefinition,\n defaultUnorderedListItemDefinition,\n ],\n decorators: [\n defaultStrongDecoratorDefinition,\n defaultEmDecoratorDefinition,\n defaultCodeDecoratorDefinition,\n defaultStrikeThroughDecoratorDefinition,\n ],\n annotations: [defaultLinkObjectDefinition],\n blockObjects: [\n defaultCodeObjectDefinition,\n defaultHorizontalRuleObjectDefinition,\n defaultImageObjectDefinition,\n defaultHtmlObjectDefinition,\n defaultTableObjectDefinition,\n ],\n inlineObjects: [defaultImageObjectDefinition],\n }),\n)\n","import {isElement, tagName} from '../helpers'\n\nexport function isWordOnlineHtml(html: string): boolean {\n return (\n /class=\"(?:TextRun|NormalTextRun)[^\"]*SCXW\\d+[^\"]*BCX\\d+/.test(html) ||\n /class=\"EOP[^\"]*SCXW\\d+/.test(html)\n )\n}\n\nexport function isWordOnlineTextRun(el: Node): boolean {\n if (!isElement(el) || tagName(el) !== 'span') {\n return false\n }\n\n return el.classList.contains('TextRun') && !el.classList.contains('EOP')\n}\n\n/**\n * Identifies the inner text holder spans in Word Online's nested structure.\n * Word Online uses: <span class=\"TextRun\"><span class=\"NormalTextRun\">text</span></span>\n * This function matches the inner span where actual text content lives.\n * Use this to find the text-bearing children within a TextRun container.\n */\nexport function isNormalTextRun(el: Node): boolean {\n if (!isElement(el) || tagName(el) !== 'span') {\n return false\n }\n\n return el.classList.contains('NormalTextRun')\n}\n\n/**\n * Identifies the outer container spans in Word Online's nested structure.\n * Word Online uses: <span class=\"TextRun\"><span class=\"NormalTextRun\">text</span></span>\n * This function matches the outer span that holds formatting and contains NormalTextRun children.\n * Use this to find the top-level containers, then search within for NormalTextRun spans.\n * Note: Excludes spans that also have \"NormalTextRun\" or \"EOP\" classes.\n */\nexport function isTextRunSpan(el: Node): boolean {\n if (!isElement(el) || tagName(el) !== 'span') {\n return false\n }\n\n return (\n el.classList.contains('TextRun') &&\n !el.classList.contains('NormalTextRun') &&\n !el.classList.contains('EOP')\n )\n}\n\nexport function isFindHit(el: Node): boolean {\n if (!isElement(el) || tagName(el) !== 'span') {\n return false\n }\n\n return el.classList.contains('FindHit')\n}\n\nexport function isInHeading(el: Node): boolean {\n let current: Node | null = el\n\n while (current) {\n if (isElement(current)) {\n if (\n tagName(current) === 'word-online-block' &&\n /^heading \\d$/.test(current.getAttribute('data-parastyle') ?? '')\n ) {\n return true\n }\n }\n\n current = current.parentNode\n }\n\n return false\n}\n\nexport function isInBlockquote(el: Node): boolean {\n let current: Node | null = el\n\n while (current) {\n if (isElement(current)) {\n if (\n tagName(current) === 'word-online-block' &&\n current.getAttribute('data-parastyle') === 'Quote'\n ) {\n return true\n }\n }\n\n current = current.parentNode\n }\n\n return false\n}\n\n/**********************\n * Formatting asserters\n **********************/\n\nexport function hasStrongFormatting(el: Element): boolean {\n const style = el.getAttribute('style') ?? ''\n\n return (\n el.classList.contains('MacChromeBold') ||\n /font-weight\\s*:\\s*bold/.test(style)\n )\n}\n\nexport function hasEmphasisFormatting(el: Element): boolean {\n const style = el.getAttribute('style') ?? ''\n\n return /font-style\\s*:\\s*italic/.test(style)\n}\n\nexport function hasUnderlineFormatting(el: Element): boolean {\n const style = el.getAttribute('style') ?? ''\n\n return (\n el.classList.contains('Underlined') ||\n /text-decoration\\s*:\\s*underline/.test(style)\n )\n}\n\nexport function hasStrikethroughFormatting(el: Element): boolean {\n const style = el.getAttribute('style') ?? ''\n\n return (\n el.classList.contains('Strikethrough') ||\n /text-decoration\\s*:\\s*line-through/.test(style)\n )\n}\n\nexport function hasFormatting(el: Element): boolean {\n return (\n hasStrongFormatting(el) ||\n hasEmphasisFormatting(el) ||\n hasUnderlineFormatting(el) ||\n hasStrikethroughFormatting(el)\n )\n}\n","import {isElement, tagName} from '../helpers'\nimport {\n hasFormatting,\n isNormalTextRun,\n isTextRunSpan,\n isWordOnlineHtml,\n} from './asserters.word-online'\n\nexport function preprocessWordOnline(html: string, doc: Document): Document {\n if (!isWordOnlineHtml(html)) {\n return doc\n }\n\n const paragraphs = Array.from(\n doc.querySelectorAll('p.Paragraph[role=\"heading\"]'),\n )\n\n for (const paragraph of paragraphs) {\n const ariaLevel = paragraph.getAttribute('aria-level')\n\n if (ariaLevel) {\n const wrapper = doc.createElement('word-online-block')\n\n wrapper.setAttribute('data-parastyle', `heading ${ariaLevel}`)\n\n const parent = paragraph.parentNode\n\n if (parent) {\n parent.insertBefore(wrapper, paragraph)\n\n while (paragraph.firstChild) {\n wrapper.appendChild(paragraph.firstChild)\n }\n\n parent.removeChild(paragraph)\n }\n }\n }\n\n // Group NormalTextRun spans with the same data-ccp-parastyle attribute\n // This handles cases like blockquotes, headings where multiple spans should form one block\n // Process from the body directly to handle DOM mutations\n let child = doc.body.firstChild\n\n while (child) {\n const next = child.nextSibling\n\n if (!isElement(child) || !tagName(child)?.includes('span')) {\n child = next\n\n continue\n }\n\n const paraStyle = getParaStyle(child)\n\n if (!paraStyle) {\n child = next\n\n continue\n }\n\n // Found a span with paragraph style - collect all consecutive siblings with same style\n const group: Element[] = [child]\n let sibling = next\n\n while (sibling) {\n if (!isElement(sibling) || getParaStyle(sibling) !== paraStyle) {\n break\n }\n\n group.push(sibling)\n sibling = sibling.nextSibling\n }\n\n // Wrap the spans in a container\n // Use a custom element name to avoid conflicts with HTML rules\n const wrapper = doc.createElement('word-online-block')\n wrapper.setAttribute('data-parastyle', paraStyle)\n\n // Insert the wrapper before the first span\n doc.body.insertBefore(wrapper, child)\n\n // Move all grouped spans into the wrapper\n for (const span of group) {\n wrapper.appendChild(span)\n }\n\n // Continue with the sibling after the last grouped span\n child = sibling\n }\n\n // Find all TextRun spans\n const textRunSpans = Array.from(doc.body.querySelectorAll('span')).filter(\n isTextRunSpan,\n )\n\n for (const textRunSpan of textRunSpans) {\n // Find ALL NormalTextRun children (Word Online can have multiple per TextRun)\n const normalTextRuns = Array.from(textRunSpan.childNodes).filter(\n isNormalTextRun,\n )\n\n for (const normalTextRun of normalTextRuns) {\n // Process ALL nested spans with whitespace in this NormalTextRun\n // We need to process them in a loop since removing one might affect indices\n let foundNestedSpan = true\n\n while (foundNestedSpan) {\n const children = Array.from(normalTextRun.childNodes)\n const nestedSpanIndex = children.findIndex(\n (node) =>\n isElement(node) &&\n tagName(node) === 'span' &&\n node.textContent.trim() === '',\n )\n\n if (nestedSpanIndex === -1) {\n foundNestedSpan = false\n break\n }\n\n const nestedSpan = children.at(nestedSpanIndex)\n\n if (!nestedSpan) {\n foundNestedSpan = false\n break\n }\n\n // Word Online uses non-breaking spaces, convert to regular spaces\n const spaceText = nestedSpan.textContent?.replace(/\\u00a0/g, ' ') ?? ''\n\n // Determine if the space is at the beginning or end BEFORE removing it\n // Check if there are any text nodes before this position\n const hasTextBefore = children\n .slice(0, nestedSpanIndex)\n .some((n) => n.nodeType === 3)\n const isSpaceAtBeginning = !hasTextBefore\n\n // Remove the nested span\n normalTextRun.removeChild(nestedSpan)\n\n if (isSpaceAtBeginning) {\n // Space at the beginning - keep it at the beginning\n const firstTextNode = Array.from(normalTextRun.childNodes).find(\n (n) => n.nodeType === 3,\n )\n\n if (firstTextNode) {\n firstTextNode.textContent =\n spaceText + (firstTextNode.textContent || '')\n } else {\n // No text node exists, create one with the space\n const spaceNode = doc.createTextNode(spaceText)\n normalTextRun.insertBefore(spaceNode, normalTextRun.firstChild)\n }\n } else {\n // Space at the end - check if we should move it to the next TextRun\n // Only move if the formatting (marks) are different\n const nextSibling = textRunSpan.nextSibling\n const currentHasFormatting = hasFormatting(textRunSpan)\n\n if (\n nextSibling &&\n isElement(nextSibling) &&\n isTextRunSpan(nextSibling)\n ) {\n const nextHasFormatting = hasFormatting(nextSibling)\n\n // If current has formatting but next doesn't, move space to the next span\n // This makes semantic sense: \"**bar** baz\" or \"*bar* baz\" - space should be outside the formatting\n if (currentHasFormatting && !nextHasFormatting) {\n const nextNormalTextRun = Array.from(nextSibling.childNodes).find(\n isNormalTextRun,\n )\n\n if (nextNormalTextRun && isElement(nextNormalTextRun)) {\n // Prepend space to the first text node of the next NormalTextRun\n const firstChild = nextNormalTextRun.firstChild\n\n if (firstChild && firstChild.nodeType === 3) {\n firstChild.textContent =\n spaceText + (firstChild.textContent ?? '')\n } else {\n // No text node, insert a new one at the beginning\n const spaceNode = doc.createTextNode(spaceText)\n nextNormalTextRun.insertBefore(\n spaceNode,\n nextNormalTextRun.firstChild,\n )\n }\n }\n // Don't add the space back to the current span - it's been moved\n } else {\n // Same formatting, keep the space in the current span\n const lastTextNode = Array.from(normalTextRun.childNodes).find(\n (n) => n.nodeType === 3,\n )\n\n if (lastTextNode) {\n lastTextNode.textContent =\n (lastTextNode.textContent ?? '') + spaceText\n } else {\n // No text node exists, create one with the space\n const spaceNode = doc.createTextNode(spaceText)\n normalTextRun.appendChild(spaceNode)\n }\n }\n } else {\n // No next TextRun, keep the space at the end of this span's text\n const lastTextNode = Array.from(normalTextRun.childNodes).find(\n (n) => n.nodeType === 3,\n )\n\n if (lastTextNode) {\n lastTextNode.textContent =\n (lastTextNode.textContent ?? '') + spaceText\n } else {\n // No text node exists, create one with the space\n const spaceNode = doc.createTextNode(spaceText)\n normalTextRun.appendChild(spaceNode)\n }\n }\n }\n }\n }\n }\n\n return doc\n}\n\n// Helper to get paragraph style from a span (either directly or from NormalTextRun child)\nfunction getParaStyle(element: Element): string | undefined {\n // Check direct attribute first\n const directStyle = element.getAttribute('data-ccp-parastyle')\n\n if (directStyle) {\n return directStyle\n }\n\n // Check if it's a TextRun with NormalTextRun children that have the attribute\n if (tagName(element) === 'span' && element.classList.contains('TextRun')) {\n const normalTextRuns = Array.from(\n element.querySelectorAll('.NormalTextRun'),\n )\n\n if (normalTextRuns.length > 0) {\n const firstRun = normalTextRuns[0]\n const firstStyle = firstRun?.getAttribute('data-ccp-parastyle')\n\n // Verify all NormalTextRuns have the same style\n if (\n firstStyle &&\n normalTextRuns.every(\n (normalTextRun) =>\n normalTextRun.getAttribute('data-ccp-parastyle') === firstStyle,\n )\n ) {\n return firstStyle\n }\n }\n }\n\n return undefined\n}\n","// We need this here if run server side\nexport const _XPathResult = {\n ANY_TYPE: 0,\n NUMBER_TYPE: 1,\n STRING_TYPE: 2,\n BOOLEAN_TYPE: 3,\n UNORDERED_NODE_ITERATOR_TYPE: 4,\n ORDERED_NODE_ITERATOR_TYPE: 5,\n UNORDERED_NODE_SNAPSHOT_TYPE: 6,\n ORDERED_NODE_SNAPSHOT_TYPE: 7,\n ANY_UNORDERED_NODE_TYPE: 8,\n FIRST_ORDERED_NODE_TYPE: 9,\n}\n","import {tagName} from '../helpers'\nimport {_XPathResult} from './xpathResult'\n\nexport function preprocessGDocs(_html: string, doc: Document): Document {\n let gDocsRootOrSiblingNode = doc\n .evaluate(\n '//*[@id and contains(@id, \"docs-internal-guid\")]',\n doc,\n null,\n _XPathResult.ORDERED_NODE_ITERATOR_TYPE,\n null,\n )\n .iterateNext()\n\n if (gDocsRootOrSiblingNode) {\n const isWrappedRootTag = tagName(gDocsRootOrSiblingNode) === 'b'\n\n // If this document isn't wrapped in a 'b' tag, then assume all siblings live on the root level\n if (!isWrappedRootTag) {\n gDocsRootOrSiblingNode = doc.body\n }\n\n // Tag every child with attribute 'is-google-docs' so that the GDocs rule-set can\n // work exclusivly on these children\n const childNodes = doc.evaluate(\n '//*',\n doc,\n null,\n _XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,\n null,\n )\n\n for (let i = childNodes.snapshotLength - 1; i >= 0; i--) {\n const elm = childNodes.snapshotItem(i) as HTMLElement\n elm?.setAttribute('data-is-google-docs', 'true')\n\n if (\n elm?.parentElement === gDocsRootOrSiblingNode ||\n (!isWrappedRootTag && elm.parentElement === doc.body)\n ) {\n elm?.setAttribute('data-is-root-node', 'true')\n tagName(elm)\n }\n\n // Handle checkmark lists - The first child of a list item is an image with a checkmark, and the serializer\n // expects the first child to be the text node\n if (\n tagName(elm) === 'li' &&\n elm.firstChild &&\n tagName(elm?.firstChild) === 'img'\n ) {\n elm.removeChild(elm.firstChild)\n }\n }\n\n // Remove that 'b' which Google Docs wraps the HTML content in\n if (isWrappedRootTag) {\n doc.body.firstElementChild?.replaceWith(\n ...Array.from(gDocsRootOrSiblingNode.childNodes),\n )\n }\n\n return doc\n }\n return doc\n}\n","import {_XPathResult} from './xpathResult'\n\n// Remove this cruft from the document\nconst unwantedWordDocumentPaths = [\n '/html/text()',\n '/html/head/text()',\n '/html/body/text()',\n '/html/body/ul/text()',\n '/html/body/ol/text()',\n '//comment()',\n '//style',\n '//xml',\n '//script',\n '//meta',\n '//link',\n]\n\nexport function preprocessHTML(_html: string, doc: Document): Document {\n // Make sure text directly on the body is wrapped in spans.\n // This mimics what the browser does before putting html on the clipboard,\n // when used in a script context with JSDOM\n const bodyTextNodes = doc.evaluate(\n '/html/body/text()',\n doc,\n null,\n _XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,\n null,\n )\n\n for (let i = bodyTextNodes.snapshotLength - 1; i >= 0; i--) {\n const node = bodyTextNodes.snapshotItem(i) as HTMLElement\n const text = node.textContent || ''\n if (text.replace(/[^\\S\\n]+$/g, '')) {\n const newNode = doc.createElement('span')\n newNode.appendChild(doc.createTextNode(text))\n node.parentNode?.replaceChild(newNode, node)\n } else {\n node.parentNode?.removeChild(node)\n }\n }\n\n const unwantedNodes = doc.evaluate(\n unwantedWordDocumentPaths.join('|'),\n doc,\n null,\n _XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,\n null,\n )\n for (let i = unwantedNodes.snapshotLength - 1; i >= 0; i--) {\n const unwanted = unwantedNodes.snapshotItem(i)\n if (!unwanted) {\n continue\n }\n unwanted.parentNode?.removeChild(unwanted)\n }\n return doc\n}\n","import {_XPathResult} from './xpathResult'\n\nexport function preprocessNotion(html: string, doc: Document): Document {\n const NOTION_REGEX = /<!-- notionvc:.*?-->/g\n\n if (html.match(NOTION_REGEX)) {\n // Tag every child with attribute 'is-notion' so that the Notion rule-set can\n // work exclusivly on these children\n const childNodes = doc.evaluate(\n '//*',\n doc,\n null,\n _XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,\n null,\n )\n\n for (let i = childNodes.snapshotLength - 1; i >= 0; i--) {\n const elm = childNodes.snapshotItem(i) as HTMLElement\n elm?.setAttribute('data-is-notion', 'true')\n }\n\n return doc\n }\n return doc\n}\n","import {PRESERVE_WHITESPACE_TAGS} from '../constants'\nimport {_XPathResult} from './xpathResult'\n\n// Elements that only contain block-level children (not inline text content)\nconst BLOCK_CONTAINER_ELEMENTS = [\n 'body',\n 'table',\n 'tbody',\n 'thead',\n 'tfoot',\n 'tr',\n 'ul',\n 'ol',\n]\n\nexport function preprocessWhitespace(_: string, doc: Document): Document {\n // Recursively process all nodes.\n function processNode(node: Node) {\n // If this is a text node and not inside a tag where whitespace should be preserved, process it.\n if (\n node.nodeType === _XPathResult.BOOLEAN_TYPE &&\n !PRESERVE_WHITESPACE_TAGS.includes(\n node.parentElement?.tagName.toLowerCase() || '',\n )\n ) {\n const normalized =\n node.textContent\n ?.replace(/\\s\\s+/g, ' ') // Remove multiple whitespace\n .replace(/[\\r\\n]+/g, ' ') || '' // Replace newlines with spaces\n const parentTag = node.parentElement?.tagName.toLowerCase()\n\n if (\n parentTag &&\n BLOCK_CONTAINER_ELEMENTS.includes(parentTag) &&\n normalized.trim() === ''\n ) {\n // If parent is a block container and text is only whitespace, remove it\n node.parentNode?.removeChild(node)\n } else {\n node.textContent = normalized\n }\n }\n // Otherwise, if this node has children, process them.\n else {\n // Process children in reverse to handle removals safely\n for (let i = node.childNodes.length - 1; i >= 0; i--) {\n const child = node.childNodes[i]\n if (child) {\n processNode(child)\n }\n }\n }\n }\n\n // Process all nodes starting from the root.\n processNode(doc.body)\n\n return doc\n}\n","import {_XPathResult} from './xpathResult'\n\nconst WORD_HTML_REGEX =\n /(class=\"?Mso|style=(?:\"|')[^\"]*?\\bmso-|w:WordDocument|<o:\\w+>|<\\/font>)/\n\n// xPaths for elements that will be removed from the document\nconst unwantedPaths = [\n '//o:p',\n \"//span[@style='mso-list:Ignore']\",\n \"//span[@style='mso-list: Ignore']\",\n]\n\n// xPaths for elements that needs to be remapped into other tags\nconst mappedPaths = [\n \"//p[@class='MsoTocHeading']\",\n \"//p[@class='MsoTitle']\",\n \"//p[@class='MsoToaHeading']\",\n \"//p[@class='MsoSubtitle']\",\n \"//span[@class='MsoSubtleEmphasis']\",\n \"//span[@class='MsoIntenseEmphasis']\",\n]\n\n// Which HTML element(s) to map the elements matching mappedPaths into\nconst elementMap: Record<string, string[] | undefined> = {\n MsoTocHeading: ['h3'],\n MsoTitle: ['h1'],\n MsoToaHeading: ['h2'],\n MsoSubtitle: ['h5'],\n MsoSubtleEmphasis: ['span', 'em'],\n MsoIntenseEmphasis: ['span', 'em', 'strong'],\n // Remove cruft\n}\n\nfunction isWordHtml(html: string) {\n return WORD_HTML_REGEX.test(html)\n}\n\n/**\n * Extract @list CSS definitions from the document's <style> blocks and store\n * the results as a data attribute on <body>. This must run before the HTML\n * preprocessor strips <style> elements.\n *\n * Word embeds list type information in CSS like:\n * @list l0:level1 { mso-level-number-format:bullet; ... }\n * @list l1:level1 { mso-level-number-position:left; ... }\n *\n * The map is keyed by \"listId:levelN\" (e.g. \"l0:level1\") because a single\n * list definition can have numbered top-level items with bullet sub-levels.\n */\nfunction extractListStyles(doc: Document): void {\n const map: Record<string, 'bullet' | 'number'> = {}\n let found = false\n\n const styleEls = doc.querySelectorAll('style')\n for (const styleEl of styleEls) {\n const css = styleEl.textContent || ''\n\n const listRulePattern = /@list\\s+(l\\d+):(level\\d+)\\s*\\{([^}]*)\\}/g\n\n for (\n let match = listRulePattern.exec(css);\n match !== null;\n match = listRulePattern.exec(css)\n ) {\n const listId = match[1] || ''\n const level = match[2] || ''\n const ruleBody = match[3] || ''\n const key = `${listId}:${level}`\n\n if (/mso-level-number-format\\s*:\\s*bullet/i.test(ruleBody)) {\n map[key] = 'bullet'\n } else {\n map[key] = 'number'\n }\n found = true\n }\n }\n\n if (found && doc.body) {\n doc.body.setAttribute('data-word-list-styles', JSON.stringify(map))\n }\n}\n\nexport function preprocessWord(html: string, doc: Document): Document {\n if (!isWordHtml(html)) {\n return doc\n }\n\n extractListStyles(doc)\n\n const unwantedNodes = doc.evaluate(\n unwantedPaths.join('|'),\n doc,\n (prefix) => {\n if (prefix === 'o') {\n return 'urn:schemas-microsoft-com:office:office'\n }\n return null\n },\n _XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,\n null,\n )\n\n for (let i = unwantedNodes.snapshotLength - 1; i >= 0; i--) {\n const unwanted = unwantedNodes.snapshotItem(i)\n if (unwanted?.parentNode) {\n unwanted.parentNode.removeChild(unwanted)\n }\n }\n\n // Transform mapped elements into what they should be mapped to\n const mappedElements = doc.evaluate(\n mappedPaths.join('|'),\n doc,\n null,\n _XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,\n null,\n )\n for (let i = mappedElements.snapshotLength - 1; i >= 0; i--) {\n const mappedElm = mappedElements.snapshotItem(i) as HTMLElement\n const tags = elementMap[mappedElm.className]\n const text = doc.createTextNode(mappedElm.textContent || '')\n if (!tags) {\n continue\n }\n\n const firstTag = tags[0]\n if (!firstTag) {\n continue\n }\n const parentElement = doc.createElement(firstTag)\n let parent = parentElement\n let child = parentElement\n tags.slice(1).forEach((tag) => {\n child = doc.createElement(tag)\n parent.appendChild(child)\n parent = child\n })\n child.appendChild(text)\n mappedElm?.parentNode?.replaceChild(parentElement, mappedElm)\n }\n\n return doc\n}\n","import {preprocessWordOnline} from '../word-online/preprocessor.word-online'\nimport {preprocessGDocs} from './preprocessor.gdocs'\nimport {preprocessHTML} from './preprocessor.html'\nimport {preprocessNotion} from './preprocessor.notion'\nimport {preprocessWhitespace} from './preprocessor.whitespace'\nimport {preprocessWord} from './preprocessor.word'\n\nexport const preprocessors = [\n preprocessWhitespace,\n preprocessNotion,\n preprocessWord,\n preprocessWordOnline,\n preprocessGDocs,\n preprocessHTML,\n]\n","export function keyGenerator() {\n return randomKey(12)\n}\n\n// WHATWG crypto RNG - https://w3c.github.io/webcrypto/Overview.html\nfunction whatwgRNG(length = 16) {\n const rnds8 = new Uint8Array(length)\n crypto.getRandomValues(rnds8)\n return rnds8\n}\n\nconst byteToHex: string[] = []\nfor (let i = 0; i < 256; ++i) {\n byteToHex[i] = (i + 0x100).toString(16).slice(1)\n}\n\n/**\n * Generate a random key of the given length\n *\n * @param length - Length of string to generate\n * @returns A string of the given length\n */\nfunction randomKey(length: number): string {\n return whatwgRNG(length)\n .reduce((str, n) => str + byteToHex[n], '')\n .slice(0, length)\n}\n","import type {Schema} from '@portabletext/schema'\nimport type {DeserializerRule} from '../../types'\nimport {DEFAULT_SPAN, HTML_BLOCK_TAGS, HTML_HEADER_TAGS} from '../constants'\nimport {isElement, tagName} from '../helpers'\nimport {keyGenerator} from '../random-key'\nimport type {SchemaMatchers} from '../schema-matchers'\nimport {\n hasEmphasisFormatting,\n hasStrikethroughFormatting,\n hasStrongFormatting,\n hasUnderlineFormatting,\n isFindHit,\n isInBlockquote,\n isInHeading,\n isNormalTextRun,\n isWordOnlineTextRun,\n} from './asserters.word-online'\n\nfunction mapParaStyleToBlockStyle(schema: Schema, paraStyle: string) {\n const blockStyleMap: Record<string, string> = {\n 'heading 1': 'h1',\n 'heading 2': 'h2',\n 'heading 3': 'h3',\n 'heading 4': 'h4',\n 'heading 5': 'h5',\n 'heading 6': 'h6',\n 'Quote': 'blockquote',\n }\n\n const blockStyle = blockStyleMap[paraStyle] ?? 'normal'\n\n return schema.styles.find((style) => style.name === blockStyle)?.name\n}\n\nexport function createWordOnlineRules(\n schema: Schema,\n options: {keyGenerator?: () => string; matchers?: SchemaMatchers},\n): DeserializerRule[] {\n return [\n // Image rule - handles bare Word Online <img> tags with WACImage class\n {\n deserialize(el) {\n if (!isElement(el) || tagName(el) !== 'img') {\n return undefined\n }\n\n // Handle className which might be a string or SVGAnimatedString\n const classNameRaw = el.className\n let className = ''\n if (typeof classNameRaw === 'string') {\n className = classNameRaw\n } else if (classNameRaw && typeof classNameRaw === 'object') {\n // SVGAnimatedString has baseVal property\n className = (classNameRaw as {baseVal?: string}).baseVal || ''\n }\n\n if (!className.includes('WACImage')) {\n return undefined\n }\n\n const src = el.getAttribute('src') ?? undefined\n const alt = el.getAttribute('alt') ?? undefined\n\n const props = Object.fromEntries(\n Array.from(el.attributes).map((attr) => [attr.name, attr.value]),\n )\n\n // Bare <img> tags are typically block-level, not inline\n // They should be returned as block images\n const image = options.matchers?.image?.({\n context: {\n schema: schema,\n keyGenerator: options.keyGenerator ?? keyGenerator,\n },\n props: {\n ...props,\n ...(src ? {src} : {}),\n ...(alt ? {alt} : {}),\n },\n })\n\n if (image) {\n return {\n _type: '__block',\n block: image,\n }\n }\n\n return undefined\n },\n },\n // Image rule - handles Word Online images wrapped in WACImageContainer\n {\n deserialize(el) {\n if (!isElement(el)) {\n return undefined\n }\n\n // Handle className which might be a string or SVGAnimatedString\n const classNameRaw = el.className\n let className = ''\n if (typeof classNameRaw === 'string') {\n className = classNameRaw\n } else if (classNameRaw && typeof classNameRaw === 'object') {\n // SVGAnimatedString has baseVal property\n className = (classNameRaw as {baseVal?: string}).baseVal || ''\n }\n if (!className.includes('WACImageContainer')) {\n return undefined\n }\n\n // Find the img element inside\n const img = el.querySelector('img')\n if (!img) {\n return undefined\n }\n\n const src = img.getAttribute('src') ?? undefined\n const alt = img.getAttribute('alt') ?? undefined\n\n const props = Object.fromEntries(\n Array.from(img.attributes).map((attr) => [attr.name, attr.value]),\n )\n\n // Determine if this should be an inline or block-level image\n // Word Online inline images:\n // 1. Siblings of TextRun spans (not wrapped in paragraphs)\n // 2. Inside list items (should be inline relative to the list item)\n const isInsideListItem = el.closest('li') !== null\n const isInsideParagraph = el.closest('p') !== null\n\n if (!isInsideParagraph || isInsideListItem) {\n // Inline image (either not in a paragraph, or inside a list item)\n const inlineImage = options.matchers?.inlineImage?.({\n context: {\n schema: schema,\n keyGenerator: options.keyGenerator ?? keyGenerator,\n },\n props: {\n ...props,\n ...(src ? {src} : {}),\n ...(alt ? {alt} : {}),\n },\n })\n\n if (inlineImage) {\n return inlineImage\n }\n }\n\n // Block-level image (or fallback if inline image not supported)\n const image = options.matchers?.image?.({\n context: {\n schema: schema,\n keyGenerator: options.keyGenerator ?? keyGenerator,\n },\n props: {\n ...props,\n ...(src ? {src} : {}),\n ...(alt ? {alt} : {}),\n },\n })\n\n if (image) {\n return {\n _type: '__block',\n block: image,\n }\n }\n\n return undefined\n },\n },\n // List item rule - handles <li> elements with aria-level\n {\n deserialize(el, next) {\n if (!isElement(el) || tagName(el) !== 'li') {\n return undefined\n }\n\n const ariaLevel = el.getAttribute('data-aria-level')\n\n if (!ariaLevel) {\n return undefined\n }\n\n const listItem = tagName(el.parentNode) === 'ol' ? 'number' : 'bullet'\n\n let childNodesToProcess = el.childNodes\n let blockStyle = 'normal'\n\n if (\n el.childNodes.length === 1 &&\n el.firstChild &&\n isElement(el.firstChild)\n ) {\n const childTag = tagName(el.firstChild)\n\n if (\n childTag &&\n (HTML_BLOCK_TAGS[childTag as keyof typeof HTML_BLOCK_TAGS] ||\n HTML_HEADER_TAGS[childTag as keyof typeof HTML_HEADER_TAGS] ||\n childTag === 'word-online-block')\n ) {\n // If it's a word-online-block, extract the style before skipping it\n if (childTag === 'word-online-block') {\n const paraStyle = el.firstChild.getAttribute('data-parastyle')\n const foundBlockStyle = paraStyle\n ? mapParaStyleToBlockStyle(schema, paraStyle)\n : undefined\n\n if (foundBlockStyle) {\n blockStyle = foundBlockStyle\n }\n }\n\n // Skip the block wrapper and process its children directly\n childNodesToProcess = el.firstChild.childNodes\n }\n }\n\n const children = next(childNodesToProcess)\n let childArray = Array.isArray(children)\n ? children\n : [children].filter(Boolean)\n\n // Clean up trailing empty or whitespace-only spans\n // Word Online often adds trailing tabs/breaks and extra spaces in list items\n while (childArray.length > 0) {\n const lastChild = childArray[childArray.length - 1]\n\n if (\n lastChild &&\n typeof lastChild === 'object' &&\n 'text' in lastChild\n ) {\n const text = (lastChild.text as string).trimEnd()\n if (text === '') {\n // Remove empty span\n childArray = childArray.slice(0, -1)\n } else if (text !== lastChild.text) {\n // Update with trimmed text\n lastChild.text = text\n break\n } else {\n break\n }\n } else {\n break\n }\n }\n\n return {\n _type: schema.block.name,\n children: childArray,\n markDefs: [],\n style: blockStyle,\n listItem,\n level: parseInt(ariaLevel, 10),\n }\n },\n },\n // Block style rule - handles paragraph styles like Quote\n // The preprocessor wraps grouped NormalTextRun spans in a word-online-block element\n {\n deserialize(el, next) {\n if (!isElement(el)) {\n return undefined\n }\n\n const paraStyle = el.getAttribute('data-parastyle')\n const blockStyle = paraStyle\n ? mapParaStyleToBlockStyle(schema, paraStyle)\n : undefined\n\n if (!blockStyle) {\n return undefined\n }\n\n const children = next(el.childNodes)\n\n return {\n _type: schema.block.name,\n style: blockStyle,\n markDefs: [],\n children: Array.isArray(children)\n ? children\n : children\n ? [children]\n : [],\n }\n },\n },\n // TextRun rule\n {\n deserialize(el) {\n if (isWordOnlineTextRun(el)) {\n if (!isElement(el)) {\n return undefined\n }\n\n if (!el.textContent) {\n return undefined\n }\n\n // Find ALL NormalTextRun and FindHit children and extract text from them\n // (Word Online sometimes splits text across multiple spans)\n // FindHit is used for search result highlighting\n const textSpans = Array.from(el.childNodes).filter(\n (node) => isNormalTextRun(node) || isFindHit(node),\n )\n const text = textSpans\n .map((span) => (isElement(span) ? (span.textContent ?? '') : ''))\n .join('')\n\n if (!text) {\n return undefined\n }\n\n const span = {\n ...DEFAULT_SPAN,\n marks: [] as Array<string>,\n text,\n }\n\n if (hasStrongFormatting(el)) {\n span.marks.push('strong')\n }\n\n // Don't add italic mark if we're in a heading or blockquote (it's part of their default style)\n if (\n hasEmphasisFormatting(el) &&\n !isInHeading(el) &&\n !isInBlockquote(el)\n ) {\n span.marks.push('em')\n }\n\n // Add underline mark if the element has explicit underline formatting\n // Word Online always adds underline to links, so we need to distinguish between:\n // 1. Default link underline (skip)\n // 2. Explicit user underline that includes the link (add)\n // We check: if the link is surrounded by underlined content, it's explicit user underline\n if (hasUnderlineFormatting(el)) {\n const isInsideLink =\n isElement(el) &&\n el.parentElement &&\n tagName(el.parentElement) === 'a'\n\n if (isInsideLink) {\n // Check if there are underlined siblings of the link\n const linkElement = el.parentElement\n if (linkElement) {\n const prevSibling = linkElement.previousSibling\n const nextSibling = linkElement.nextSibling\n\n // If either sibling is an underlined TextRun, the link is part of explicit underline\n const hasPrevUnderline =\n prevSibling &&\n isElement(prevSibling) &&\n hasUnderlineFormatting(prevSibling)\n const hasNextUnderline =\n nextSibling &&\n isElement(nextSibling) &&\n hasUnderlineFormatting(nextSibling)\n\n if (hasPrevUnderline || hasNextUnderline) {\n span.marks.push('underline')\n }\n // Otherwise, it's just default link styling, don't add underline mark\n }\n } else {\n // Not in a link, always add underline\n span.marks.push('underline')\n }\n }\n\n // Add strikethrough mark if the element has strikethrough formatting\n if (hasStrikethroughFormatting(el)) {\n span.marks.push('strike-through')\n }\n\n return span\n }\n\n return undefined\n },\n },\n ]\n}\n","import type {Schema} from '@portabletext/schema'\nimport type {DeserializerRule} from '../../types'\nimport {\n BLOCK_DEFAULT_STYLE,\n DEFAULT_BLOCK,\n DEFAULT_SPAN,\n HTML_BLOCK_TAGS,\n HTML_HEADER_TAGS,\n HTML_LIST_CONTAINER_TAGS,\n} from '../constants'\nimport {isElement, tagName} from '../helpers'\n\nconst LIST_CONTAINER_TAGS = Object.keys(HTML_LIST_CONTAINER_TAGS)\n\n// font-style:italic seems like the most important rule for italic / emphasis in their html\nfunction isEmphasis(el: Node): boolean {\n const style = isElement(el) && el.getAttribute('style')\n return /font-style\\s*:\\s*italic/.test(style || '')\n}\n\n// font-weight:700 seems like the most important rule for bold in their html\nfunction isStrong(el: Node): boolean {\n const style = isElement(el) && el.getAttribute('style')\n return /font-weight\\s*:\\s*700/.test(style || '')\n}\n\n// text-decoration seems like the most important rule for underline in their html\nfunction isUnderline(el: Node): boolean {\n if (!isElement(el) || tagName(el.parentNode) === 'a') {\n return false\n }\n\n const style = isElement(el) && el.getAttribute('style')\n\n return /text-decoration\\s*:\\s*underline/.test(style || '')\n}\n\n// text-decoration seems like the most important rule for strike-through in their html\n// allows for line-through regex to be more lineient to allow for other text-decoration before or after\nfunction isStrikethrough(el: Node): boolean {\n const style = isElement(el) && el.getAttribute('style')\n return /text-decoration\\s*:\\s*(?:.*line-through.*;)/.test(style || '')\n}\n\n// Check for attribute given by the gdocs preprocessor\nfunction isGoogleDocs(el: Node): boolean {\n return isElement(el) && Boolean(el.getAttribute('data-is-google-docs'))\n}\n\nfunction isRootNode(el: Node): boolean {\n return isElement(el) && Boolean(el.getAttribute('data-is-root-node'))\n}\n\nfunction getListItemStyle(el: Node): 'bullet' | 'number' | undefined {\n const parentTag = tagName(el.parentNode)\n if (parentTag && !LIST_CONTAINER_TAGS.includes(parentTag)) {\n return undefined\n }\n return tagName(el.parentNode) === 'ul' ? 'bullet' : 'number'\n}\n\nfunction getListItemLevel(el: Node): number {\n let level = 0\n if (tagName(el) === 'li') {\n let parentNode = el.parentNode\n while (parentNode) {\n const parentTag = tagName(parentNode)\n if (parentTag && LIST_CONTAINER_TAGS.includes(parentTag)) {\n level++\n }\n parentNode = parentNode.parentNode\n }\n } else {\n level = 1\n }\n return level\n}\n\nconst blocks: Record<string, {style: string} | undefined> = {\n ...HTML_BLOCK_TAGS,\n ...HTML_HEADER_TAGS,\n}\n\nfunction getBlockStyle(schema: Schema, el: Node): string {\n const childTag = tagName(el.firstChild)\n const block = childTag && blocks[childTag]\n if (!block) {\n return BLOCK_DEFAULT_STYLE\n }\n if (!schema.styles.some((style) => style.name === block.style)) {\n return BLOCK_DEFAULT_STYLE\n }\n return block.style\n}\n\nexport function createGDocsRules(schema: Schema): DeserializerRule[] {\n return [\n {\n deserialize(el, next) {\n if (isElement(el) && tagName(el) === 'span' && isGoogleDocs(el)) {\n if (!el.textContent) {\n if (!el.previousSibling && !el.nextSibling) {\n el.setAttribute('data-lonely-child', 'true')\n }\n\n return next(el.childNodes)\n }\n\n const span = {\n ...DEFAULT_SPAN,\n marks: [] as string[],\n text: el.textContent,\n }\n if (isStrong(el)) {\n span.marks.push('strong')\n }\n if (isUnderline(el)) {\n span.marks.push('underline')\n }\n if (isStrikethrough(el)) {\n span.marks.push('strike-through')\n }\n if (isEmphasis(el)) {\n span.marks.push('em')\n }\n return span\n }\n return undefined\n },\n },\n {\n deserialize(el, next) {\n if (tagName(el) === 'li' && isGoogleDocs(el)) {\n return {\n ...DEFAULT_BLOCK,\n listItem: getListItemStyle(el),\n level: getListItemLevel(el),\n style: getBlockStyle(schema, el),\n children: next(el.firstChild?.childNodes || []),\n }\n }\n return undefined\n },\n },\n {\n deserialize(el) {\n if (\n tagName(el) === 'br' &&\n isGoogleDocs(el) &&\n isElement(el) &&\n el.classList.contains('apple-interchange-newline')\n ) {\n return {\n ...DEFAULT_SPAN,\n text: '',\n }\n }\n\n // BRs inside empty paragraphs\n if (\n tagName(el) === 'br' &&\n isGoogleDocs(el) &&\n isElement(el) &&\n el?.parentNode?.textContent === ''\n ) {\n return {\n ...DEFAULT_SPAN,\n text: '',\n }\n }\n\n // BRs on the root\n if (\n tagName(el) === 'br' &&\n isGoogleDocs(el) &&\n isElement(el) &&\n isRootNode(el)\n ) {\n return {\n ...DEFAULT_SPAN,\n text: '',\n }\n }\n return undefined\n },\n },\n ]\n}\n","import type {DeserializerRule} from '../../types'\nimport {DEFAULT_SPAN} from '../constants'\nimport {tagName} from '../helpers'\n\nexport const whitespaceTextNodeRule: DeserializerRule = {\n deserialize(node) {\n return node.nodeName === '#text' && isWhitespaceTextNode(node)\n ? {\n ...DEFAULT_SPAN,\n marks: [],\n text: (node.textContent ?? '').replace(/\\s\\s+/g, ' '),\n }\n : undefined\n },\n}\n\nfunction isWhitespaceTextNode(node: Node) {\n const isWhitespaceOnly =\n node.nodeType === 3 &&\n (node.textContent || '').replace(/[\\r\\n]/g, ' ').replace(/\\s\\s+/g, ' ') ===\n ' '\n\n const hasSiblingContext =\n node.nextSibling &&\n node.nextSibling.nodeType !== 3 &&\n node.previousSibling &&\n node.previousSibling.nodeType !== 3\n\n // When a whitespace text node is the sole child of an inline element (e.g.\n // <span> </span>), check the parent element's siblings instead. The parent\n // must have non-text siblings on both sides (matching the same pattern as\n // the direct sibling check above).\n const parentIsInline = node.parentNode && tagName(node.parentNode) === 'span'\n const hasParentSiblingContext =\n parentIsInline &&\n !node.nextSibling &&\n !node.previousSibling &&\n node.parentNode!.previousSibling &&\n node.parentNode!.previousSibling.nodeType !== 3 &&\n node.parentNode!.nextSibling &&\n node.parentNode!.nextSibling.nodeType !== 3\n\n const isValidWhiteSpace =\n isWhitespaceOnly && (hasSiblingContext || hasParentSiblingContext)\n\n return (\n (isValidWhiteSpace || node.textContent !== ' ') &&\n tagName(node.parentNode) !== 'body'\n )\n}\n","import type {Schema} from '@portabletext/schema'\nimport type {DeserializerRule} from '../../types'\nimport {\n DEFAULT_BLOCK,\n DEFAULT_SPAN,\n HTML_BLOCK_TAGS,\n HTML_DECORATOR_TAGS,\n HTML_HEADER_TAGS,\n HTML_LIST_CONTAINER_TAGS,\n HTML_LIST_ITEM_TAGS,\n HTML_SPAN_TAGS,\n type PartialBlock,\n} from '../constants'\nimport {isElement, tagName} from '../helpers'\nimport {keyGenerator} from '../random-key'\nimport type {SchemaMatchers} from '../schema-matchers'\nimport {whitespaceTextNodeRule} from './rules.whitespace-text-node'\n\nfunction resolveListItem(\n schema: Schema,\n listNodeTagName: string,\n): string | undefined {\n if (\n listNodeTagName === 'ul' &&\n schema.lists.some((list) => list.name === 'bullet')\n ) {\n return 'bullet'\n }\n if (\n listNodeTagName === 'ol' &&\n schema.lists.some((list) => list.name === 'number')\n ) {\n return 'number'\n }\n return undefined\n}\n\nexport function createHTMLRules(\n schema: Schema,\n options: {keyGenerator?: () => string; matchers?: SchemaMatchers},\n): DeserializerRule[] {\n return [\n whitespaceTextNodeRule,\n {\n // Pre element\n deserialize(el) {\n if (tagName(el) !== 'pre') {\n return undefined\n }\n\n const isCodeEnabled = schema.styles.some(\n (style) => style.name === 'code',\n )\n\n return {\n _type: 'block',\n style: 'normal',\n markDefs: [],\n children: [\n {\n ...DEFAULT_SPAN,\n marks: isCodeEnabled ? ['code'] : [],\n text: el.textContent || '',\n },\n ],\n }\n },\n }, // Blockquote element\n {\n deserialize(el, next) {\n if (tagName(el) !== 'blockquote') {\n return undefined\n }\n const blocks: Record<string, PartialBlock | undefined> = {\n ...HTML_BLOCK_TAGS,\n ...HTML_HEADER_TAGS,\n }\n delete blocks['blockquote']\n const nonBlockquoteBlocks = Object.keys(blocks)\n\n const children: HTMLElement[] = []\n\n el.childNodes.forEach((node, index) => {\n if (!el.ownerDocument) {\n return\n }\n\n if (\n node.nodeType === 1 &&\n nonBlockquoteBlocks.includes(\n (node as Element).localName.toLowerCase(),\n )\n ) {\n const span = el.ownerDocument.createElement('span')\n\n const previousChild = children[children.length - 1]\n\n if (\n previousChild &&\n previousChild.nodeType === 3 &&\n previousChild.textContent?.trim()\n ) {\n // Only prepend line break if the previous node is a non-empty\n // text node.\n span.appendChild(el.ownerDocument.createTextNode('\\r'))\n }\n\n node.childNodes.forEach((cn) => {\n span.appendChild(cn.cloneNode(true))\n })\n\n if (index !== el.childNodes.length) {\n // Only append line break if this is not the last child\n span.appendChild(el.ownerDocument.createTextNode('\\r'))\n }\n\n children.push(span)\n } else {\n children.push(node as HTMLElement)\n }\n })\n\n return {\n _type: 'block',\n style: 'blockquote',\n markDefs: [],\n children: next(children),\n }\n },\n }, // Block elements\n {\n deserialize(el, next) {\n const blocks: Record<string, PartialBlock | undefined> = {\n ...HTML_BLOCK_TAGS,\n ...HTML_HEADER_TAGS,\n }\n const tag = tagName(el)\n let block = tag ? blocks[tag] : undefined\n if (!block) {\n return undefined\n }\n // Don't add blocks into list items\n if (el.parentNode && tagName(el.parentNode) === 'li') {\n return next(el.childNodes)\n }\n const blockStyle = block.style\n // If style is not supported, return a defaultBlockType\n if (!schema.styles.some((style) => style.name === blockStyle)) {\n block = DEFAULT_BLOCK\n }\n return {\n ...block,\n children: next(el.childNodes),\n }\n },\n }, // Ignore span tags\n {\n deserialize(el, next) {\n const tag = tagName(el)\n if (!tag || !(tag in HTML_SPAN_TAGS)) {\n return undefined\n }\n return next(el.childNodes)\n },\n }, // Ignore div tags\n {\n deserialize(el, next) {\n const div = tagName(el) === 'div'\n if (!div) {\n return undefined\n }\n return next(el.childNodes)\n },\n }, // Ignore list containers\n {\n deserialize(el, next) {\n const tag = tagName(el)\n if (!tag || !(tag in HTML_LIST_CONTAINER_TAGS)) {\n return undefined\n }\n return next(el.childNodes)\n },\n }, // Deal with br's\n {\n deserialize(el) {\n if (tagName(el) === 'br') {\n return {\n ...DEFAULT_SPAN,\n text: '\\n',\n }\n }\n return undefined\n },\n }, // Deal with list items\n {\n deserialize(el, next, block) {\n const tag = tagName(el)\n const listItem = tag ? HTML_LIST_ITEM_TAGS[tag] : undefined\n if (!listItem) {\n return undefined\n }\n // Fall back to 'ul' when the list item has no list container parent\n // (e.g. orphan <li> elements without a <ul> or <ol> wrapper).\n const parentTag = tagName(el.parentNode) || ''\n const listTag = HTML_LIST_CONTAINER_TAGS[parentTag] ? parentTag : 'ul'\n const enabledListItem = resolveListItem(schema, listTag)\n // If the list item style is not supported, return a new default block\n if (!enabledListItem) {\n return block({_type: 'block', children: next(el.childNodes)})\n }\n listItem.listItem = enabledListItem\n return {\n ...listItem,\n children: next(el.childNodes),\n }\n },\n }, // Deal with decorators - this is a limited set of known html elements that we know how to deserialize\n {\n deserialize(el, next) {\n const decorator = HTML_DECORATOR_TAGS[tagName(el) || '']\n if (\n !decorator ||\n !schema.decorators.some(\n (decoratorType) => decoratorType.name === decorator,\n )\n ) {\n return undefined\n }\n return {\n _type: '__decorator',\n name: decorator,\n children: next(el.childNodes),\n }\n },\n }, // Special case for hyperlinks, add annotation (if allowed by schema),\n // If not supported just write out the link text and href in plain text.\n {\n deserialize(el, next) {\n if (tagName(el) !== 'a') {\n return undefined\n }\n const linkEnabled = schema.annotations.some(\n (annotation) => annotation.name === 'link',\n )\n const href = isElement(el) && el.getAttribute('href')\n if (!href) {\n return next(el.childNodes)\n }\n if (linkEnabled) {\n return {\n _type: '__annotation',\n markDef: {\n _key: options.keyGenerator\n ? options.keyGenerator()\n : keyGenerator(),\n _type: 'link',\n href: href,\n },\n children: next(el.childNodes),\n }\n }\n return (\n el.appendChild(el.ownerDocument.createTextNode(` (${href})`)) &&\n next(el.childNodes)\n )\n },\n },\n {\n deserialize(el, next) {\n if (isElement(el) && (tagName(el) === 'td' || tagName(el) === 'th')) {\n return {\n ...DEFAULT_BLOCK,\n children: next(el.childNodes),\n }\n }\n\n return undefined\n },\n },\n {\n deserialize(el) {\n if (isElement(el) && tagName(el) === 'img') {\n const src = el.getAttribute('src') ?? undefined\n const alt = el.getAttribute('alt') ?? undefined\n\n const props = Object.fromEntries(\n Array.from(el.attributes).map((attr) => [attr.name, attr.value]),\n )\n\n const ancestorOfLonelyChild =\n el?.parentElement?.parentElement?.getAttribute('data-lonely-child')\n const ancestorOfListItem = el.closest('li') !== null\n\n if (ancestorOfLonelyChild && !ancestorOfListItem) {\n const image = options.matchers?.image?.({\n context: {\n schema,\n keyGenerator: options.keyGenerator ?? keyGenerator,\n },\n props: {\n ...props,\n ...(src ? {src} : {}),\n ...(alt ? {alt} : {}),\n },\n })\n\n if (image) {\n return {\n _type: '__block',\n block: image,\n }\n }\n }\n\n const inlineImage = options.matchers?.inlineImage?.({\n context: {\n schema,\n keyGenerator: options.keyGenerator ?? keyGenerator,\n },\n props: {\n ...props,\n ...(src ? {src} : {}),\n ...(alt ? {alt} : {}),\n },\n })\n\n if (inlineImage) {\n return inlineImage\n }\n\n const image = options.matchers?.image?.({\n context: {\n schema,\n keyGenerator: options.keyGenerator ?? keyGenerator,\n },\n props: {\n ...props,\n ...(src ? {src} : {}),\n ...(alt ? {alt} : {}),\n },\n })\n\n if (image) {\n return {\n _type: '__block',\n block: image,\n }\n }\n }\n\n return undefined\n },\n },\n ]\n}\n","import type {DeserializerRule} from '../../types'\nimport {DEFAULT_SPAN} from '../constants'\nimport {isElement, tagName} from '../helpers'\n\n// font-style:italic seems like the most important rule for italic / emphasis in their html\nfunction isEmphasis(el: Node): boolean {\n const style = isElement(el) && el.getAttribute('style')\n return /font-style:italic/.test(style || '')\n}\n\n// font-weight:700 or 600 seems like the most important rule for bold in their html\nfunction isStrong(el: Node): boolean {\n const style = isElement(el) && el.getAttribute('style')\n return (\n /font-weight:700/.test(style || '') || /font-weight:600/.test(style || '')\n )\n}\n\n// text-decoration seems like the most important rule for underline in their html\nfunction isUnderline(el: Node): boolean {\n const style = isElement(el) && el.getAttribute('style')\n return /text-decoration:underline/.test(style || '')\n}\n\n// Check for attribute given by the Notion preprocessor\nfunction isNotion(el: Node): boolean {\n return isElement(el) && Boolean(el.getAttribute('data-is-notion'))\n}\n\nexport function createNotionRules(): DeserializerRule[] {\n return [\n {\n deserialize(el) {\n // Notion normally exports semantic HTML. However, if you copy a single block, the formatting will be inline styles\n // This handles a limited set of styles\n if (isElement(el) && tagName(el) === 'span' && isNotion(el)) {\n const span = {\n ...DEFAULT_SPAN,\n marks: [] as string[],\n text: el.textContent,\n }\n if (isStrong(el)) {\n span.marks.push('strong')\n }\n if (isUnderline(el)) {\n span.marks.push('underline')\n }\n if (isEmphasis(el)) {\n span.marks.push('em')\n }\n return span\n }\n return undefined\n },\n },\n ]\n}\n","import type {DeserializerRule} from '../../types'\nimport {\n BLOCK_DEFAULT_STYLE,\n DEFAULT_BLOCK,\n HTML_HEADER_TAGS,\n} from '../constants'\nimport {isElement, tagName} from '../helpers'\n\n/**\n * Read the list style map stored by the Word preprocessor on the document body.\n * Returns a map from list ID (e.g. \"l0\") to list type (\"bullet\" or \"number\").\n */\nfunction getListStyleMap(el: Node): Record<string, string> {\n if (!isElement(el)) {\n return {}\n }\n\n const body = el.closest('body') || el.ownerDocument?.body\n if (!body) {\n return {}\n }\n\n const data = body.getAttribute('data-word-list-styles')\n if (!data) {\n return {}\n }\n\n try {\n return JSON.parse(data)\n } catch {\n return {}\n }\n}\n\nfunction getListItemStyle(el: Node): string | undefined {\n const style = isElement(el) && el.getAttribute('style')\n if (!style) {\n return undefined\n }\n\n // Extract list ID and level from mso-list: e.g. \"mso-list:l1 level1 lfo1\"\n const msoListMatch = style.match(/mso-list:\\s*(l\\d+)\\s+(level\\d+)\\s+lfo\\d+/)\n if (!msoListMatch) {\n return undefined\n }\n\n const key = `${msoListMatch[1]}:${msoListMatch[2]}`\n const listStyles = getListStyleMap(el)\n return (listStyles[key] as 'bullet' | 'number') || 'bullet'\n}\n\nfunction getListItemLevel(el: Node): number | undefined {\n const style = isElement(el) && el.getAttribute('style')\n if (!style) {\n return undefined\n }\n\n const levelMatch = style.match(/level\\d+/)\n if (!levelMatch) {\n return undefined\n }\n\n const [level] = levelMatch[0].match(/\\d/) || []\n const levelNum = level ? Number.parseInt(level, 10) : 1\n return levelNum || 1\n}\n\nfunction isWordListElement(el: Node): boolean {\n if (!isElement(el)) {\n return false\n }\n\n // Check for specific class names\n if (el.className) {\n if (\n el.className === 'MsoListParagraphCxSpFirst' ||\n el.className === 'MsoListParagraphCxSpMiddle' ||\n el.className === 'MsoListParagraphCxSpLast'\n ) {\n return true\n }\n }\n\n // Check for mso-list in style attribute\n const style = el.getAttribute('style')\n if (style && /mso-list:\\s*l\\d+\\s+level\\d+\\s+lfo\\d+/.test(style)) {\n return true\n }\n\n return false\n}\n\nfunction getHeadingStyle(el: Node): string | undefined {\n const tag = tagName(el)\n if (tag && HTML_HEADER_TAGS[tag]) {\n return HTML_HEADER_TAGS[tag]?.style\n }\n return undefined\n}\n\nexport function createWordRules(): DeserializerRule[] {\n return [\n {\n deserialize(el, next) {\n const tag = tagName(el)\n\n // Handle list items (both paragraphs and headings)\n if (\n (tag === 'p' || HTML_HEADER_TAGS[tag || '']) &&\n isWordListElement(el)\n ) {\n const headingStyle = getHeadingStyle(el)\n return {\n ...DEFAULT_BLOCK,\n listItem: getListItemStyle(el),\n level: getListItemLevel(el),\n style: headingStyle || BLOCK_DEFAULT_STYLE,\n children: next(el.childNodes),\n }\n }\n return undefined\n },\n },\n ]\n}\n","import type {Schema} from '@portabletext/schema'\nimport type {DeserializerRule} from '../../types'\nimport type {SchemaMatchers} from '../schema-matchers'\nimport {createWordOnlineRules} from '../word-online/rules.word-online'\nimport {createGDocsRules} from './rules.gdocs'\nimport {createHTMLRules} from './rules.html'\nimport {createNotionRules} from './rules.notion'\nimport {createWordRules} from './rules.word'\n\nexport function createRules(\n schema: Schema,\n options: {keyGenerator?: () => string; matchers?: SchemaMatchers},\n): DeserializerRule[] {\n return [\n ...createWordRules(),\n ...createWordOnlineRules(schema, options),\n ...createNotionRules(),\n ...createGDocsRules(schema),\n ...createHTMLRules(schema, options),\n ]\n}\n","import {\n isSpan,\n isTextBlock,\n type PortableTextTextBlock,\n type Schema,\n} from '@portabletext/schema'\nimport type {TypedObject} from '../types'\nimport {isEqualMarks} from './equality'\nimport {isMinimalSpan} from './helpers'\n\nexport type WhiteSpacePasteMode = 'preserve' | 'remove' | 'normalize'\n\nexport function trimWhitespace(\n context: {schema: Schema},\n mode: WhiteSpacePasteMode,\n blocks: TypedObject[],\n): TypedObject[] {\n const trimmedBlocks: TypedObject[] = []\n let consecutiveEmptyCount = 0\n\n for (const block of blocks) {\n const trimmedBlock = isTextBlock(context, block)\n ? trimTextBlockWhitespace(block)\n : block\n\n if (mode === 'preserve') {\n trimmedBlocks.push(trimmedBlock)\n\n continue\n }\n\n if (mode === 'remove') {\n if (isEmptyTextBlock(context, trimmedBlock)) {\n continue\n }\n\n trimmedBlocks.push(trimmedBlock)\n\n continue\n }\n\n if (mode === 'normalize') {\n if (isEmptyTextBlock(context, trimmedBlock)) {\n consecutiveEmptyCount++\n\n if (consecutiveEmptyCount === 1) {\n trimmedBlocks.push(trimmedBlock)\n }\n\n continue\n }\n\n trimmedBlocks.push(trimmedBlock)\n\n consecutiveEmptyCount = 0\n }\n }\n\n return trimmedBlocks\n}\n\nfunction isEmptyTextBlock(\n context: {schema: Schema},\n block: TypedObject,\n): boolean {\n if (!isTextBlock(context, block)) {\n return false\n }\n\n if (\n block.children.some(\n (child) => !isSpan(context, child) || child.text.trim() !== '',\n )\n ) {\n return false\n }\n\n return true\n}\n\nfunction trimTextBlockWhitespace(\n block: PortableTextTextBlock,\n): PortableTextTextBlock {\n let index = 0\n\n for (const child of block.children) {\n if (!isMinimalSpan(child)) {\n index++\n continue\n }\n\n const nextChild = nextSpan(block, index)\n const prevChild = prevSpan(block, index)\n\n if (index === 0) {\n child.text = child.text.replace(/^[^\\S\\n]+/g, '')\n }\n\n if (index === block.children.length - 1) {\n child.text = child.text.replace(/[^\\S\\n]+$/g, '')\n }\n\n if (\n /\\s/.test(child.text.slice(Math.max(0, child.text.length - 1))) &&\n nextChild &&\n isMinimalSpan(nextChild) &&\n /\\s/.test(nextChild.text.slice(0, 1))\n ) {\n child.text = child.text.replace(/[^\\S\\n]+$/g, '')\n }\n\n if (\n /\\s/.test(child.text.slice(0, 1)) &&\n prevChild &&\n isMinimalSpan(prevChild) &&\n /\\s/.test(prevChild.text.slice(Math.max(0, prevChild.text.length - 1)))\n ) {\n child.text = child.text.replace(/^[^\\S\\n]+/g, '')\n }\n\n if (!child.text) {\n block.children.splice(index, 1)\n }\n\n if (\n prevChild &&\n Array.isArray(prevChild.marks) &&\n isEqualMarks(prevChild.marks, child.marks) &&\n isWhiteSpaceChar(child.text)\n ) {\n prevChild.text += ' '\n block.children.splice(index, 1)\n } else if (\n nextChild &&\n Array.isArray(nextChild.marks) &&\n isEqualMarks(nextChild.marks, child.marks) &&\n isWhiteSpaceChar(child.text)\n ) {\n nextChild.text = ` ${nextChild.text}`\n block.children.splice(index, 1)\n }\n\n index++\n }\n\n return block\n}\n\nfunction nextSpan(block: PortableTextTextBlock, index: number) {\n const next = block.children[index + 1]\n return next && next._type === 'span' ? next : null\n}\n\nfunction prevSpan(block: PortableTextTextBlock, index: number) {\n const prev = block.children[index - 1]\n return prev && prev._type === 'span' ? prev : null\n}\n\nfunction isWhiteSpaceChar(text: string) {\n return ['\\xa0', ' '].includes(text)\n}\n","import type {Schema} from '@portabletext/schema'\nimport {\n isTextBlock,\n type PortableTextBlock,\n type PortableTextObject,\n} from '@portabletext/schema'\nimport {vercelStegaClean} from '@vercel/stega'\nimport type {\n ArbitraryTypedObject,\n DeserializerRule,\n HtmlParser,\n PlaceholderAnnotation,\n PlaceholderDecorator,\n TypedObject,\n} from '../types'\nimport {flattenNestedBlocks} from './flatten-nested-blocks'\nimport {\n defaultParseHtml,\n ensureRootIsBlocks,\n isMinimalBlock,\n isMinimalSpan,\n isNodeList,\n isPlaceholderAnnotation,\n isPlaceholderDecorator,\n tagName,\n} from './helpers'\nimport {preprocessors} from './preprocessors'\nimport {keyGenerator} from './random-key'\nimport {resolveJsType} from './resolve-js-type'\nimport {createRules} from './rules'\nimport type {SchemaMatchers} from './schema-matchers'\nimport {trimWhitespace} from './trim-whitespace'\n\ninterface HtmlDeserializerOptions {\n keyGenerator?: () => string\n rules?: DeserializerRule[]\n parseHtml?: HtmlParser\n whitespaceMode?: 'preserve' | 'remove' | 'normalize'\n matchers?: SchemaMatchers\n}\n\n/**\n * HTML Deserializer\n *\n */\nexport class HtmlDeserializer {\n keyGenerator: () => string\n schema: Schema\n rules: DeserializerRule[]\n parseHtml: (html: string) => HTMLElement\n whitespaceMode: 'preserve' | 'remove' | 'normalize'\n _markDefs: PortableTextObject[] = []\n\n /**\n * Create a new serializer respecting a Sanity block content type's schema\n *\n * @param schema - Schema definition\n * @param options - Options for the deserialization process\n */\n constructor(schema: Schema, options: HtmlDeserializerOptions = {}) {\n const {rules = [], whitespaceMode = 'preserve'} = options\n const standardRules = createRules(schema, {\n keyGenerator: options.keyGenerator,\n matchers: options.matchers,\n })\n this.schema = schema\n this.keyGenerator = options.keyGenerator ?? keyGenerator\n this.rules = [...rules, ...standardRules]\n this.whitespaceMode = whitespaceMode\n const parseHtml = options.parseHtml || defaultParseHtml()\n this.parseHtml = (html) => {\n const cleanHTML = vercelStegaClean(html)\n const doc = parseHtml(cleanHTML)\n\n for (const processor of preprocessors) {\n processor(cleanHTML, doc)\n }\n\n return doc.body\n }\n }\n\n /**\n * Deserialize HTML.\n *\n * @param html - The HTML to deserialize, as a string\n * @returns Array of blocks - either portable text blocks or other allowed blocks\n */\n deserialize = (html: string): TypedObject[] => {\n this._markDefs = []\n const {parseHtml} = this\n const fragment = parseHtml(html)\n const children = Array.from(fragment.childNodes) as HTMLElement[]\n\n const blocks = trimWhitespace(\n {schema: this.schema},\n this.whitespaceMode,\n flattenNestedBlocks(\n {schema: this.schema},\n ensureRootIsBlocks(\n this.schema,\n this.deserializeElements(children) as Array<ArbitraryTypedObject>,\n ),\n ),\n )\n\n if (this._markDefs.length > 0) {\n blocks\n .filter((block) => isTextBlock({schema: this.schema}, block))\n .forEach((block) => {\n block.markDefs = block.markDefs || []\n block.markDefs = block.markDefs.concat(\n this._markDefs.filter((def) => {\n return block.children\n .flatMap((child) => child.marks || [])\n .includes(def._key)\n }),\n )\n })\n }\n\n return blocks.map((block) => {\n if (block._type === 'block') {\n block._type = this.schema.block.name\n }\n return block\n })\n }\n\n /**\n * Deserialize an array of DOM elements.\n *\n * @param elements - Array of DOM elements to deserialize\n * @returns\n */\n deserializeElements = (elements: Node[] = []): TypedObject[] => {\n let nodes: TypedObject[] = []\n elements.forEach((element) => {\n nodes = nodes.concat(this.deserializeElement(element))\n })\n return nodes\n }\n\n /**\n * Deserialize a DOM element\n *\n * @param element - Deserialize a DOM element\n * @returns\n */\n deserializeElement = (element: Node): TypedObject | TypedObject[] => {\n const next = (\n elements: Node | Node[] | NodeList,\n ): TypedObject | TypedObject[] | undefined => {\n if (isNodeList(elements)) {\n return this.deserializeElements(Array.from(elements))\n }\n\n if (Array.isArray(elements)) {\n return this.deserializeElements(elements)\n }\n\n if (!elements) {\n return undefined\n }\n\n return this.deserializeElement(elements)\n }\n\n const block = (props: ArbitraryTypedObject) => {\n return {\n _type: '__block',\n block: props,\n }\n }\n\n let node: TypedObject | Array<TypedObject> | undefined\n for (let i = 0; i < this.rules.length; i++) {\n const rule = this.rules[i]\n if (!rule || !rule.deserialize) {\n continue\n }\n\n const ret = rule.deserialize(element, next, block)\n const type = resolveJsType(ret)\n\n if (\n type !== 'array' &&\n type !== 'object' &&\n type !== 'null' &&\n type !== 'undefined'\n ) {\n throw new Error(\n `A rule returned an invalid deserialized representation: \"${node}\".`,\n )\n }\n\n if (ret === undefined) {\n continue\n } else if (ret === null) {\n throw new Error('Deserializer rule returned `null`')\n } else if (Array.isArray(ret)) {\n node = ret\n } else if (isPlaceholderDecorator(ret)) {\n node = this.deserializeDecorator(ret)\n } else if (isPlaceholderAnnotation(ret)) {\n node = this.deserializeAnnotation(ret)\n } else {\n node = ret\n }\n\n // Set list level on list item\n if (\n ret &&\n !Array.isArray(ret) &&\n isMinimalBlock(ret) &&\n 'listItem' in ret\n ) {\n let parent = element.parentNode?.parentNode\n while (parent && tagName(parent) === 'li') {\n parent = parent.parentNode?.parentNode\n ret.level = ret.level ? ret.level + 1 : 1\n }\n }\n\n // Set newlines on spans orginating from a block element within a blockquote\n if (\n ret &&\n !Array.isArray(ret) &&\n isMinimalBlock(ret) &&\n ret.style === 'blockquote'\n ) {\n ret.children.forEach((child, index) => {\n if (isMinimalSpan(child) && child.text === '\\r') {\n child.text = '\\n'\n if (index === 0 || index === ret.children.length - 1) {\n ret.children.splice(index, 1)\n }\n }\n })\n }\n break\n }\n\n return node || next(element.childNodes) || []\n }\n\n /**\n * Deserialize a `__decorator` type\n * (an internal made up type to process decorators exclusively)\n *\n * @param decorator -\n * @returns array of ...\n */\n deserializeDecorator = (decorator: PlaceholderDecorator): TypedObject[] => {\n const {name} = decorator\n const applyDecorator = (node: TypedObject) => {\n if (isPlaceholderDecorator(node)) {\n return this.deserializeDecorator(node)\n } else if (isMinimalSpan(node)) {\n node.marks = node.marks || []\n if (node.text.trim()) {\n // Only apply marks if this is an actual text\n node.marks.unshift(name)\n }\n } else if (\n 'children' in node &&\n Array.isArray((node as PortableTextBlock).children)\n ) {\n const block = node as any\n block.children = block.children.map(applyDecorator)\n }\n return node\n }\n return decorator.children.reduce((children, node) => {\n const ret = applyDecorator(node)\n if (Array.isArray(ret)) {\n return children.concat(ret)\n }\n children.push(ret)\n return children\n }, [] as TypedObject[])\n }\n\n /**\n * Deserialize a `__annotation` object.\n * (an internal made up type to process annotations exclusively)\n *\n * @param annotation -\n * @returns Array of...\n */\n deserializeAnnotation = (\n annotation: PlaceholderAnnotation,\n ): TypedObject[] => {\n const {markDef} = annotation\n this._markDefs.push(markDef)\n const applyAnnotation = (node: TypedObject) => {\n if (isPlaceholderAnnotation(node)) {\n return this.deserializeAnnotation(node)\n } else if (isMinimalSpan(node)) {\n node.marks = node.marks || []\n if (node.text.trim()) {\n // Only apply marks if this is an actual text\n node.marks.unshift(markDef._key)\n }\n } else if (\n 'children' in node &&\n Array.isArray((node as PortableTextBlock).children)\n ) {\n const block = node as any\n block.children = block.children.map(applyAnnotation)\n }\n return node\n }\n return annotation.children.reduce((children, node) => {\n const ret = applyAnnotation(node)\n if (Array.isArray(ret)) {\n return children.concat(ret)\n }\n children.push(ret)\n return children\n }, [] as TypedObject[])\n }\n}\n","import type {Schema} from '@portabletext/schema'\nimport {\n isSpan,\n type PortableTextSpan,\n type PortableTextTextBlock,\n} from '@portabletext/schema'\nimport type {TypedObject} from '../types'\nimport {isEqualMarks} from './equality'\nimport {keyGenerator} from './random-key'\n\n/**\n * Block normalization options\n */\nexport interface BlockNormalizationOptions {\n /**\n * Decorator names that are allowed within portable text blocks, eg `em`, `strong`\n */\n allowedDecorators?: string[]\n\n /**\n * Name of the portable text block type, if not `block`\n */\n blockTypeName?: string\n\n /**\n * Custom key generator function\n */\n keyGenerator?: () => string\n}\n\n/**\n * Normalizes a block by ensuring it has a `_key` property. If the block is a\n * portable text block, additional normalization is applied:\n *\n * - Ensures it has `children` and `markDefs` properties\n * - Ensures it has at least one child (adds an empty span if empty)\n * - Joins sibling spans that has the same marks\n * - Removes decorators that are not allowed according to the schema\n * - Removes marks that have no annotation definition\n *\n * @param node - The block to normalize\n * @param options - Options for normalization process. See {@link BlockNormalizationOptions}\n * @returns Normalized block\n */\nexport function normalizeBlock(\n node: TypedObject,\n options: BlockNormalizationOptions = {},\n): Omit<\n TypedObject | PortableTextTextBlock<TypedObject | PortableTextSpan>,\n '_key'\n> & {\n _key: string\n} {\n const schema: Schema = {\n block: {\n name: options.blockTypeName || 'block',\n },\n span: {\n name: 'span',\n },\n styles: [],\n lists: [],\n decorators: [],\n annotations: [],\n blockObjects: [],\n inlineObjects: [],\n }\n\n if (node._type !== (options.blockTypeName || 'block')) {\n return '_key' in node\n ? (node as TypedObject & {_key: string})\n : {\n ...node,\n _key: options.keyGenerator ? options.keyGenerator() : keyGenerator(),\n }\n }\n\n const block: Omit<\n PortableTextTextBlock<TypedObject | PortableTextSpan>,\n 'style'\n > = {\n _key: options.keyGenerator ? options.keyGenerator() : keyGenerator(),\n children: [],\n markDefs: [],\n ...node,\n }\n\n const lastChild = block.children[block.children.length - 1]\n\n if (!lastChild) {\n // A block must at least have an empty span type child\n block.children = [\n {\n _type: 'span',\n _key: options.keyGenerator ? options.keyGenerator() : keyGenerator(),\n text: '',\n marks: [],\n },\n ]\n return block\n }\n\n const usedMarkDefs: string[] = []\n const allowedDecorators =\n options.allowedDecorators && Array.isArray(options.allowedDecorators)\n ? options.allowedDecorators\n : false\n\n block.children = block.children\n .reduce(\n (acc, child) => {\n const previousChild = acc[acc.length - 1]\n if (\n previousChild &&\n isSpan({schema}, child) &&\n isSpan({schema}, previousChild) &&\n isEqualMarks(previousChild.marks, child.marks)\n ) {\n if (\n lastChild &&\n lastChild === child &&\n child.text === '' &&\n block.children.length > 1\n ) {\n return acc\n }\n\n previousChild.text += child.text\n return acc\n }\n acc.push(child)\n return acc\n },\n [] as (TypedObject | PortableTextSpan)[],\n )\n .map((child) => {\n if (!child) {\n throw new Error('missing child')\n }\n\n child._key = options.keyGenerator\n ? options.keyGenerator()\n : keyGenerator()\n\n if (isSpan({schema}, child)) {\n if (!child.marks) {\n child.marks = []\n } else if (allowedDecorators) {\n child.marks = child.marks.filter((mark) => {\n const isAllowed = allowedDecorators.includes(mark)\n const isUsed = block.markDefs?.some((def) => def._key === mark)\n return isAllowed || isUsed\n })\n }\n\n usedMarkDefs.push(...child.marks)\n }\n\n return child\n })\n\n // Remove leftover (unused) markDefs\n block.markDefs = (block.markDefs || []).filter((markDef) =>\n usedMarkDefs.includes(markDef._key),\n )\n\n return block\n}\n","import type {Schema} from '@portabletext/schema'\nimport {defaultSchema} from './default-schema'\nimport {HtmlDeserializer} from './deserializer/html-deserializer'\nimport {normalizeBlock} from './deserializer/normalize-block'\nimport type {SchemaMatchers} from './deserializer/schema-matchers'\nimport type {ObjectMatcher} from './matchers'\nimport type {DeserializerRule} from './types'\n\n/**\n * Options for converting HTML to Portable Text\n *\n * @public\n */\nexport type HtmlToPortableTextOptions = {\n schema?: Schema\n keyGenerator?: () => string\n parseHtml?: (html: string) => Document\n rules?: DeserializerRule[]\n whitespaceMode?: 'preserve' | 'remove' | 'normalize'\n types?: {\n image?: ObjectMatcher<{src?: string; alt?: string}>\n }\n}\n\n/**\n * Convert HTML to Portable Text\n *\n * @param html - The HTML string to convert\n * @param options - Options for the conversion\n * @returns Array of Portable Text blocks\n * @public\n */\nexport function htmlToPortableText(\n html: string,\n options: HtmlToPortableTextOptions = {},\n) {\n const schema = options.schema ?? defaultSchema\n const keyGen = options.keyGenerator\n\n const matchers = toSchemaMatchers(options.types)\n\n const deserializer = new HtmlDeserializer(schema, {\n keyGenerator: keyGen,\n rules: options.rules,\n parseHtml: options.parseHtml,\n whitespaceMode: options.whitespaceMode,\n matchers,\n })\n return deserializer\n .deserialize(html)\n .map((block) => normalizeBlock(block, {keyGenerator: keyGen}))\n}\n\n/**\n * Convert public ObjectMatcher options to internal SchemaMatchers.\n *\n * ObjectMatcher uses ({context, value, isInline}) matching the\n * @portabletext/markdown API. SchemaMatchers uses ({context, props})\n * matching the internal block-tools engine.\n *\n * If the ObjectMatcher returns a _key, it is preserved. normalizeBlock\n * only assigns a key when one is missing.\n */\nfunction toSchemaMatchers(\n types: HtmlToPortableTextOptions['types'],\n): SchemaMatchers | undefined {\n if (!types?.image) {\n return undefined\n }\n\n const objectMatcher = types.image\n\n const adapt =\n (isInline: boolean): NonNullable<SchemaMatchers['image']> =>\n ({context, props}) => {\n const result = objectMatcher({\n context,\n value: props as {src?: string; alt?: string},\n isInline,\n })\n if (!result) {\n return undefined\n }\n return result as ReturnType<NonNullable<SchemaMatchers['image']>>\n }\n\n return {\n image: adapt(false),\n inlineImage: adapt(true),\n }\n}\n","import type {\n PortableTextObject,\n Schema,\n SchemaDefinition,\n} from '@portabletext/schema'\n\n/**\n * Matcher function for mapping HTML elements to Portable Text block styles.\n *\n * @public\n */\nexport type StyleMatcher = ({\n context,\n}: {\n context: {schema: Schema}\n}) => string | undefined\n\n/**\n * @public\n */\nexport function buildStyleMatcher<TDefinition extends {name: string}>(\n definition: TDefinition,\n): StyleMatcher {\n return ({context}) => {\n const schemaDefinition = context.schema.styles.find(\n (item) => item.name === definition.name,\n )\n\n if (!schemaDefinition) {\n return undefined\n }\n\n return schemaDefinition.name\n }\n}\n\n/**\n * Matcher function for mapping HTML list items to Portable Text list types.\n *\n * @public\n */\nexport type ListItemMatcher = ({\n context,\n}: {\n context: {schema: Schema}\n}) => string | undefined\n\n/**\n * @public\n */\nexport function buildListItemMatcher<TDefinition extends {name: string}>(\n definition: TDefinition,\n): ListItemMatcher {\n return ({context}) => {\n const schemaDefinition = context.schema.lists.find(\n (item) => item.name === definition.name,\n )\n\n if (!schemaDefinition) {\n return undefined\n }\n\n return schemaDefinition.name\n }\n}\n\n/**\n * Matcher function for mapping HTML inline formatting to Portable Text decorators.\n *\n * @public\n */\nexport type DecoratorMatcher = ({\n context,\n}: {\n context: {schema: Schema}\n}) => string | undefined\n\n/**\n * @public\n */\nexport function buildDecoratorMatcher<TDefinition extends {name: string}>(\n definition: TDefinition,\n): DecoratorMatcher {\n return ({context}) => {\n const schemaDefinition = context.schema.decorators.find(\n (item) => item.name === definition.name,\n )\n\n if (!schemaDefinition) {\n return undefined\n }\n\n return schemaDefinition.name\n }\n}\n\n/**\n * Matcher function for mapping HTML links to Portable Text annotations.\n *\n * @public\n */\nexport type AnnotationMatcher<\n TValue extends Record<string, unknown> = Record<string, never>,\n> = ({\n context,\n value,\n}: {\n context: {schema: Schema; keyGenerator: () => string}\n value: TValue\n}) => PortableTextObject | undefined\n\n/**\n * @public\n */\nexport function buildAnnotationMatcher<TDefinition extends {name: string}>(\n definition: TDefinition,\n): AnnotationMatcher<ExtractValue<TDefinition>> {\n return ({context, value}) => {\n const schemaDefinition = context.schema.annotations.find(\n (item) => item.name === definition.name,\n )\n\n if (!schemaDefinition) {\n return undefined\n }\n\n const filteredValue = schemaDefinition.fields.reduce<\n Record<string, unknown>\n >((filteredValue, field) => {\n const fieldValue = value[field.name as keyof typeof value]\n\n if (fieldValue !== undefined) {\n filteredValue[field.name] = fieldValue\n }\n\n return filteredValue\n }, {})\n\n return {\n _key: context.keyGenerator(),\n _type: schemaDefinition.name,\n ...filteredValue,\n }\n }\n}\n\n/**\n * Matcher function for mapping HTML objects to Portable Text block or inline objects.\n *\n * @public\n */\nexport type ObjectMatcher<\n TValue extends Record<string, unknown> = Record<string, never>,\n> = ({\n context,\n value,\n isInline,\n}: {\n context: {schema: Schema; keyGenerator: () => string}\n value: TValue\n isInline: boolean\n}) => PortableTextObject | undefined\n\n/**\n * @public\n */\nexport function buildObjectMatcher<TDefinition extends {name: string}>(\n definition: TDefinition,\n): ObjectMatcher<ExtractValue<TDefinition>> {\n return ({context, value, isInline}) => {\n const schemaCollection = isInline\n ? context.schema.inlineObjects\n : context.schema.blockObjects\n\n const schemaDefinition = schemaCollection.find(\n (item) => item.name === definition.name,\n )\n\n if (!schemaDefinition) {\n return undefined\n }\n\n const filteredValue = schemaDefinition.fields.reduce<\n Record<string, unknown>\n >((filteredValue, field) => {\n const fieldValue = value[field.name as keyof typeof value]\n\n if (fieldValue !== undefined) {\n filteredValue[field.name] = fieldValue\n }\n\n return filteredValue\n }, {})\n\n return {\n _key: context.keyGenerator(),\n _type: schemaDefinition.name,\n ...filteredValue,\n }\n }\n}\n\n/**\n * @public\n */\nexport type ExtractValue<\n TDefinition extends NonNullable<SchemaDefinition['blockObjects']>[0],\n> = TDefinition extends {fields: ReadonlyArray<{name: infer TNames}>}\n ? Record<TNames & string, unknown>\n : Record<string, never>\n"],"names":["span","isEmphasis","isStrong","isUnderline","getListItemStyle","getListItemLevel","blocks","image","filteredValue"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/html",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Convert HTML to Portable Text with built-in support for Google Docs, Word, and Notion",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"portable-text",
|
|
@@ -30,18 +30,17 @@
|
|
|
30
30
|
"dist"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@vercel/stega": "1.
|
|
34
|
-
"@portabletext/schema": "^2.
|
|
33
|
+
"@vercel/stega": "^1.1.0",
|
|
34
|
+
"@portabletext/schema": "^2.2.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@portabletext/types": "^4.0.1",
|
|
38
37
|
"@sanity/pkg-utils": "^10.2.1",
|
|
39
38
|
"@sanity/tsconfig": "^2.1.0",
|
|
40
39
|
"@types/jsdom": "^27.0.0",
|
|
41
40
|
"@types/node": "^20",
|
|
42
41
|
"jsdom": "^27.0.0",
|
|
43
42
|
"typescript": "5.9.3",
|
|
44
|
-
"vitest": "^4.
|
|
43
|
+
"vitest": "^4.1.4",
|
|
45
44
|
"@portabletext/test": "^1.0.3"
|
|
46
45
|
},
|
|
47
46
|
"engines": {
|