UNPKG

@portabletext/block-tools

Version:

Sanity-flavored HTML to Portable Text conversion (wraps @portabletext/html)

113 lines (112 loc) 3.88 kB
import { htmlToPortableText } from "@portabletext/html"; import { sanitySchemaToPortableTextSchema } from "@portabletext/sanity-bridge"; import { isSpan } from "@portabletext/schema"; function isEqualMarks(a, b) { if (!a || !b) return a === b; if (a.length !== b.length) return !1; for (let index = 0; index < a.length; index++) if (a[index] !== b[index]) return !1; return !0; } function keyGenerator() { return randomKey(12); } function whatwgRNG(length = 16) { const rnds8 = new Uint8Array(length); return crypto.getRandomValues(rnds8), rnds8; } const byteToHex = []; for (let i = 0; i < 256; ++i) byteToHex[i] = (i + 256).toString(16).slice(1); function randomKey(length) { return whatwgRNG(length).reduce((str, n) => str + byteToHex[n], "").slice(0, length); } function normalizeBlock(node, options = {}) { const schema = { block: { name: options.blockTypeName || "block" }, span: { name: "span" }, styles: [], lists: [], decorators: [], annotations: [], blockObjects: [], inlineObjects: [] }; if (node._type !== (options.blockTypeName || "block")) return "_key" in node ? node : { ...node, _key: options.keyGenerator ? options.keyGenerator() : keyGenerator() }; const block = { _key: options.keyGenerator ? options.keyGenerator() : keyGenerator(), children: [], markDefs: [], ...node }, lastChild = block.children[block.children.length - 1]; if (!lastChild) return block.children = [ { _type: "span", _key: options.keyGenerator ? options.keyGenerator() : keyGenerator(), text: "", marks: [] } ], block; const usedMarkDefs = [], allowedDecorators = options.allowedDecorators && Array.isArray(options.allowedDecorators) ? options.allowedDecorators : !1; return block.children = block.children.reduce( (acc, child) => { const previousChild = acc[acc.length - 1]; return previousChild && isSpan({ schema }, child) && isSpan({ schema }, previousChild) && isEqualMarks(previousChild.marks, child.marks) ? (lastChild && lastChild === child && child.text === "" && block.children.length > 1 || (previousChild.text += child.text), acc) : (acc.push(child), acc); }, [] ).map((child) => { if (!child) throw new Error("missing child"); return child._key = options.keyGenerator ? options.keyGenerator() : keyGenerator(), isSpan({ schema }, child) && (child.marks ? allowedDecorators && (child.marks = child.marks.filter((mark) => { const isAllowed = allowedDecorators.includes(mark), isUsed = block.markDefs?.some((def) => def._key === mark); return isAllowed || isUsed; })) : child.marks = [], usedMarkDefs.push(...child.marks)), child; }), block.markDefs = (block.markDefs || []).filter( (markDef) => usedMarkDefs.includes(markDef._key) ), block; } function htmlToBlocks(html, schemaType, options = {}) { const schema = isSanitySchema(schemaType) ? sanitySchemaToPortableTextSchema(schemaType) : schemaType; return htmlToPortableText(html, { schema, keyGenerator: options.keyGenerator, parseHtml: options.parseHtml, rules: options.rules, whitespaceMode: options.unstable_whitespaceOnPasteMode, types: adaptMatchers(options.matchers) }); } function adaptMatchers(matchers) { if (!(!matchers?.image && !matchers?.inlineImage)) return { image: ({ context, value, isInline }) => { const matcher = isInline ? matchers.inlineImage : matchers.image; if (!matcher) return; const result = matcher({ context, props: value }); if (result) return result; } }; } function isSanitySchema(schema) { return schema.hasOwnProperty("jsonType"); } export { htmlToBlocks, normalizeBlock, randomKey }; //# sourceMappingURL=index.js.map