@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
1 lines • 5.84 kB
Source Map (JSON)
{"version":3,"file":"CachedMarkdown.mjs","names":[],"sources":["../../../src/Markdown/SyntaxMarkdown/CachedMarkdown.tsx"],"sourcesContent":["'use client';\n\nimport { type Nodes, type Root } from 'hast';\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime';\nimport { urlAttributes } from 'html-url-attributes';\nimport { useMemo } from 'react';\nimport { Fragment, jsx, jsxs } from 'react/jsx-runtime';\nimport { defaultUrlTransform, type Options } from 'react-markdown';\nimport remarkParse from 'remark-parse';\nimport remarkRehype from 'remark-rehype';\nimport { type PluggableList, unified } from 'unified';\nimport { type BuildVisitor, visit } from 'unist-util-visit';\nimport { VFile } from 'vfile';\n\nconst EMPTY_PLUGINS: PluggableList = [];\nconst DEFAULT_REMARK_REHYPE_OPTIONS = { allowDangerousHtml: true };\n\n/**\n * Render-equivalent of react-markdown's synchronous `<Markdown>` that keeps\n * the unified processor across renders. react-markdown rebuilds the whole\n * plugin chain on every render; the streaming tail block re-renders on every\n * reveal commit (~20/s) with identical plugin identities, so caching the\n * processor removes the per-commit chain construction. `post`/`transform`\n * mirror react-markdown@10 — keep them in sync when upgrading it.\n */\nexport const CachedMarkdown = (options: Options) => {\n const { children, rehypePlugins, remarkPlugins, remarkRehypeOptions } = options;\n\n const processor = useMemo(() => {\n return unified()\n .use(remarkParse)\n .use(remarkPlugins || EMPTY_PLUGINS)\n .use(\n remarkRehype,\n remarkRehypeOptions\n ? { ...remarkRehypeOptions, ...DEFAULT_REMARK_REHYPE_OPTIONS }\n : DEFAULT_REMARK_REHYPE_OPTIONS,\n )\n .use(rehypePlugins || EMPTY_PLUGINS);\n }, [rehypePlugins, remarkPlugins, remarkRehypeOptions]);\n\n const file = new VFile();\n file.value = typeof children === 'string' ? children : '';\n\n return post(processor.runSync(processor.parse(file), file) as Nodes, options);\n};\n\nfunction post(tree: Nodes, options: Options) {\n const {\n allowedElements,\n allowElement,\n components,\n disallowedElements,\n skipHtml,\n unwrapDisallowed,\n } = options;\n const urlTransform = options.urlTransform || defaultUrlTransform;\n\n if (allowedElements && disallowedElements) {\n throw new Error(\n 'Unexpected combined `allowedElements` and `disallowedElements`, expected one or the other',\n );\n }\n\n const transform: BuildVisitor<Root> = (node, index, parent) => {\n const rawNode = node as unknown as { type?: string; value?: unknown };\n if (\n rawNode.type === 'raw' &&\n typeof rawNode.value === 'string' &&\n parent &&\n typeof index === 'number'\n ) {\n if (skipHtml) {\n parent.children.splice(index, 1);\n } else {\n parent.children[index] = { type: 'text', value: rawNode.value };\n }\n\n return index;\n }\n\n if (node.type === 'element') {\n let key: string;\n\n for (key in urlAttributes) {\n if (Object.hasOwn(urlAttributes, key) && Object.hasOwn(node.properties, key)) {\n const value = node.properties[key];\n const test = urlAttributes[key];\n if (test === null || test.includes(node.tagName)) {\n node.properties[key] = urlTransform(String(value || ''), key, node);\n }\n }\n }\n\n let remove = allowedElements\n ? !allowedElements.includes(node.tagName)\n : disallowedElements\n ? disallowedElements.includes(node.tagName)\n : false;\n\n if (!remove && allowElement && typeof index === 'number') {\n remove = !allowElement(node, index, parent);\n }\n\n if (remove && parent && typeof index === 'number') {\n if (unwrapDisallowed && node.children) {\n parent.children.splice(index, 1, ...node.children);\n } else {\n parent.children.splice(index, 1);\n }\n\n return index;\n }\n }\n };\n\n visit(tree as Root, transform);\n\n return toJsxRuntime(tree, {\n Fragment,\n components,\n ignoreInvalidStyle: true,\n jsx,\n jsxs,\n passKeys: true,\n passNode: true,\n });\n}\n"],"mappings":";;;;;;;;;;;;AAcA,MAAM,gBAA+B,CAAC;AACtC,MAAM,gCAAgC,EAAE,oBAAoB,KAAK;;;;;;;;;AAUjE,MAAa,kBAAkB,YAAqB;CAClD,MAAM,EAAE,UAAU,eAAe,eAAe,wBAAwB;CAExE,MAAM,YAAY,cAAc;EAC9B,OAAO,QAAQ,CAAC,CACb,IAAI,WAAW,CAAC,CAChB,IAAI,iBAAiB,aAAa,CAAC,CACnC,IACC,cACA,sBACI;GAAE,GAAG;GAAqB,GAAG;EAA8B,IAC3D,6BACN,CAAC,CACA,IAAI,iBAAiB,aAAa;CACvC,GAAG;EAAC;EAAe;EAAe;CAAmB,CAAC;CAEtD,MAAM,OAAO,IAAI,MAAM;CACvB,KAAK,QAAQ,OAAO,aAAa,WAAW,WAAW;CAEvD,OAAO,KAAK,UAAU,QAAQ,UAAU,MAAM,IAAI,GAAG,IAAI,GAAY,OAAO;AAC9E;AAEA,SAAS,KAAK,MAAa,SAAkB;CAC3C,MAAM,EACJ,iBACA,cACA,YACA,oBACA,UACA,qBACE;CACJ,MAAM,eAAe,QAAQ,gBAAgB;CAE7C,IAAI,mBAAmB,oBACrB,MAAM,IAAI,MACR,2FACF;CAGF,MAAM,aAAiC,MAAM,OAAO,WAAW;EAC7D,MAAM,UAAU;EAChB,IACE,QAAQ,SAAS,SACjB,OAAO,QAAQ,UAAU,YACzB,UACA,OAAO,UAAU,UACjB;GACA,IAAI,UACF,OAAO,SAAS,OAAO,OAAO,CAAC;QAE/B,OAAO,SAAS,SAAS;IAAE,MAAM;IAAQ,OAAO,QAAQ;GAAM;GAGhE,OAAO;EACT;EAEA,IAAI,KAAK,SAAS,WAAW;GAC3B,IAAI;GAEJ,KAAK,OAAO,eACV,IAAI,OAAO,OAAO,eAAe,GAAG,KAAK,OAAO,OAAO,KAAK,YAAY,GAAG,GAAG;IAC5E,MAAM,QAAQ,KAAK,WAAW;IAC9B,MAAM,OAAO,cAAc;IAC3B,IAAI,SAAS,QAAQ,KAAK,SAAS,KAAK,OAAO,GAC7C,KAAK,WAAW,OAAO,aAAa,OAAO,SAAS,EAAE,GAAG,KAAK,IAAI;GAEtE;GAGF,IAAI,SAAS,kBACT,CAAC,gBAAgB,SAAS,KAAK,OAAO,IACtC,qBACE,mBAAmB,SAAS,KAAK,OAAO,IACxC;GAEN,IAAI,CAAC,UAAU,gBAAgB,OAAO,UAAU,UAC9C,SAAS,CAAC,aAAa,MAAM,OAAO,MAAM;GAG5C,IAAI,UAAU,UAAU,OAAO,UAAU,UAAU;IACjD,IAAI,oBAAoB,KAAK,UAC3B,OAAO,SAAS,OAAO,OAAO,GAAG,GAAG,KAAK,QAAQ;SAEjD,OAAO,SAAS,OAAO,OAAO,CAAC;IAGjC,OAAO;GACT;EACF;CACF;CAEA,MAAM,MAAc,SAAS;CAE7B,OAAO,aAAa,MAAM;EACxB,UAAA;EACA;EACA,oBAAoB;EACpB;EACA;EACA,UAAU;EACV,UAAU;CACZ,CAAC;AACH"}