@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
1 lines • 5.59 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 if (node.type === 'raw' && parent && typeof index === 'number') {\n if (skipHtml) {\n parent.children.splice(index, 1);\n } else {\n parent.children[index] = { type: 'text', value: node.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,EAAE;AACvC,MAAM,gCAAgC,EAAE,oBAAoB,MAAM;;;;;;;;;AAUlE,MAAa,kBAAkB,YAAqB;CAClD,MAAM,EAAE,UAAU,eAAe,eAAe,wBAAwB;CAExE,MAAM,YAAY,cAAc;AAC9B,SAAO,SAAS,CACb,IAAI,YAAY,CAChB,IAAI,iBAAiB,cAAc,CACnC,IACC,cACA,sBACI;GAAE,GAAG;GAAqB,GAAG;GAA+B,GAC5D,8BACL,CACA,IAAI,iBAAiB,cAAc;IACrC;EAAC;EAAe;EAAe;EAAoB,CAAC;CAEvD,MAAM,OAAO,IAAI,OAAO;AACxB,MAAK,QAAQ,OAAO,aAAa,WAAW,WAAW;AAEvD,QAAO,KAAK,UAAU,QAAQ,UAAU,MAAM,KAAK,EAAE,KAAK,EAAW,QAAQ;;AAG/E,SAAS,KAAK,MAAa,SAAkB;CAC3C,MAAM,EACJ,iBACA,cACA,YACA,oBACA,UACA,qBACE;CACJ,MAAM,eAAe,QAAQ,gBAAgB;AAE7C,KAAI,mBAAmB,mBACrB,OAAM,IAAI,MACR,4FACD;CAGH,MAAM,aAAiC,MAAM,OAAO,WAAW;AAC7D,MAAI,KAAK,SAAS,SAAS,UAAU,OAAO,UAAU,UAAU;AAC9D,OAAI,SACF,QAAO,SAAS,OAAO,OAAO,EAAE;OAEhC,QAAO,SAAS,SAAS;IAAE,MAAM;IAAQ,OAAO,KAAK;IAAO;AAG9D,UAAO;;AAGT,MAAI,KAAK,SAAS,WAAW;GAC3B,IAAI;AAEJ,QAAK,OAAO,cACV,KAAI,OAAO,OAAO,eAAe,IAAI,IAAI,OAAO,OAAO,KAAK,YAAY,IAAI,EAAE;IAC5E,MAAM,QAAQ,KAAK,WAAW;IAC9B,MAAM,OAAO,cAAc;AAC3B,QAAI,SAAS,QAAQ,KAAK,SAAS,KAAK,QAAQ,CAC9C,MAAK,WAAW,OAAO,aAAa,OAAO,SAAS,GAAG,EAAE,KAAK,KAAK;;GAKzE,IAAI,SAAS,kBACT,CAAC,gBAAgB,SAAS,KAAK,QAAQ,GACvC,qBACE,mBAAmB,SAAS,KAAK,QAAQ,GACzC;AAEN,OAAI,CAAC,UAAU,gBAAgB,OAAO,UAAU,SAC9C,UAAS,CAAC,aAAa,MAAM,OAAO,OAAO;AAG7C,OAAI,UAAU,UAAU,OAAO,UAAU,UAAU;AACjD,QAAI,oBAAoB,KAAK,SAC3B,QAAO,SAAS,OAAO,OAAO,GAAG,GAAG,KAAK,SAAS;QAElD,QAAO,SAAS,OAAO,OAAO,EAAE;AAGlC,WAAO;;;;AAKb,OAAM,MAAc,UAAU;AAE9B,QAAO,aAAa,MAAM;EACxB,UAAA;EACA;EACA,oBAAoB;EACpB;EACA;EACA,UAAU;EACV,UAAU;EACX,CAAC"}