@hejiayue/x-markdown-test 0.0.1-beta.151 → 0.0.1-beta.152
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.
- package/dist/style.css +438 -1
- package/dist/types/config.d.ts +33 -0
- package/dist/types/hooks/useMermaid.d.ts +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/x-markdown.cjs.js +35 -1
- package/dist/x-markdown.cjs.js.map +1 -1
- package/dist/x-markdown.cjs10.js +52 -1
- package/dist/x-markdown.cjs10.js.map +1 -1
- package/dist/x-markdown.cjs11.js +57 -1
- package/dist/x-markdown.cjs11.js.map +1 -1
- package/dist/x-markdown.cjs12.js +18 -0
- package/dist/x-markdown.cjs12.js.map +1 -0
- package/dist/x-markdown.cjs14.js +92 -1
- package/dist/x-markdown.cjs14.js.map +1 -1
- package/dist/x-markdown.cjs15.js +36 -1
- package/dist/x-markdown.cjs15.js.map +1 -1
- package/dist/x-markdown.cjs16.js +9 -1
- package/dist/x-markdown.cjs16.js.map +1 -1
- package/dist/x-markdown.cjs17.js +10 -1
- package/dist/x-markdown.cjs17.js.map +1 -1
- package/dist/x-markdown.cjs18.js +11 -1
- package/dist/x-markdown.cjs18.js.map +1 -1
- package/dist/x-markdown.cjs19.js +11 -1
- package/dist/x-markdown.cjs19.js.map +1 -1
- package/dist/x-markdown.cjs2.js +86 -1
- package/dist/x-markdown.cjs2.js.map +1 -1
- package/dist/x-markdown.cjs20.js +211 -0
- package/dist/x-markdown.cjs20.js.map +1 -0
- package/dist/x-markdown.cjs22.js +13 -1
- package/dist/x-markdown.cjs22.js.map +1 -1
- package/dist/x-markdown.cjs23.js +79 -0
- package/dist/x-markdown.cjs23.js.map +1 -0
- package/dist/x-markdown.cjs25.js +409 -0
- package/dist/x-markdown.cjs25.js.map +1 -0
- package/dist/x-markdown.cjs27.js +199 -1
- package/dist/x-markdown.cjs27.js.map +1 -1
- package/dist/x-markdown.cjs28.js +135 -1
- package/dist/x-markdown.cjs28.js.map +1 -1
- package/dist/x-markdown.cjs3.js +97 -1
- package/dist/x-markdown.cjs3.js.map +1 -1
- package/dist/x-markdown.cjs30.js +11 -1
- package/dist/x-markdown.cjs30.js.map +1 -1
- package/dist/x-markdown.cjs31.js +122 -1
- package/dist/x-markdown.cjs31.js.map +1 -1
- package/dist/x-markdown.cjs32.js +11 -0
- package/dist/x-markdown.cjs32.js.map +1 -0
- package/dist/x-markdown.cjs33.js +128 -1
- package/dist/x-markdown.cjs33.js.map +1 -1
- package/dist/x-markdown.cjs4.js +153 -1
- package/dist/x-markdown.cjs4.js.map +1 -1
- package/dist/x-markdown.cjs5.js +43 -1
- package/dist/x-markdown.cjs5.js.map +1 -1
- package/dist/x-markdown.cjs6.js +27 -1
- package/dist/x-markdown.cjs6.js.map +1 -1
- package/dist/x-markdown.cjs7.js +310 -1
- package/dist/x-markdown.cjs7.js.map +1 -1
- package/dist/x-markdown.cjs8.js +30 -1
- package/dist/x-markdown.cjs8.js.map +1 -1
- package/dist/x-markdown.cjs9.js +435 -1
- package/dist/x-markdown.cjs9.js.map +1 -1
- package/dist/x-markdown.es.js +11 -28
- package/dist/x-markdown.es10.js +10 -10
- package/dist/x-markdown.es10.js.map +1 -1
- package/dist/x-markdown.es11.js +4 -5
- package/dist/x-markdown.es11.js.map +1 -1
- package/dist/x-markdown.es12.js +12 -0
- package/dist/x-markdown.es12.js.map +1 -0
- package/dist/x-markdown.es14.js +85 -29
- package/dist/x-markdown.es14.js.map +1 -1
- package/dist/x-markdown.es15.js +32 -4
- package/dist/x-markdown.es15.js.map +1 -1
- package/dist/x-markdown.es16.js +5 -5
- package/dist/x-markdown.es16.js.map +1 -1
- package/dist/x-markdown.es17.js +5 -6
- package/dist/x-markdown.es17.js.map +1 -1
- package/dist/x-markdown.es18.js +6 -6
- package/dist/x-markdown.es18.js.map +1 -1
- package/dist/x-markdown.es19.js +7 -206
- package/dist/x-markdown.es19.js.map +1 -1
- package/dist/x-markdown.es2.js +6 -7
- package/dist/x-markdown.es2.js.map +1 -1
- package/dist/x-markdown.es20.js +207 -0
- package/dist/x-markdown.es20.js.map +1 -0
- package/dist/x-markdown.es22.js +7 -72
- package/dist/x-markdown.es22.js.map +1 -1
- package/dist/x-markdown.es23.js +75 -0
- package/dist/x-markdown.es23.js.map +1 -0
- package/dist/{x-markdown.es24.js → x-markdown.es25.js} +12 -10
- package/dist/x-markdown.es25.js.map +1 -0
- package/dist/x-markdown.es27.js +182 -7
- package/dist/x-markdown.es27.js.map +1 -1
- package/dist/x-markdown.es28.js +7 -8
- package/dist/x-markdown.es28.js.map +1 -1
- package/dist/x-markdown.es3.js +7 -8
- package/dist/x-markdown.es3.js.map +1 -1
- package/dist/x-markdown.es30.js +7 -77
- package/dist/x-markdown.es30.js.map +1 -1
- package/dist/x-markdown.es31.js +112 -124
- package/dist/x-markdown.es31.js.map +1 -1
- package/dist/x-markdown.es32.js +7 -0
- package/dist/x-markdown.es32.js.map +1 -0
- package/dist/x-markdown.es33.js +124 -5
- package/dist/x-markdown.es33.js.map +1 -1
- package/dist/x-markdown.es4.js +5 -7
- package/dist/x-markdown.es4.js.map +1 -1
- package/dist/x-markdown.es5.js +9 -10
- package/dist/x-markdown.es5.js.map +1 -1
- package/dist/x-markdown.es6.js +5 -5
- package/dist/x-markdown.es6.js.map +1 -1
- package/dist/x-markdown.es7.js +61 -74
- package/dist/x-markdown.es7.js.map +1 -1
- package/dist/x-markdown.es8.js +4 -5
- package/dist/x-markdown.es8.js.map +1 -1
- package/dist/x-markdown.es9.js +22 -14
- package/dist/x-markdown.es9.js.map +1 -1
- package/package.json +3 -14
- package/dist/types/vite-plugin.d.ts +0 -29
- package/dist/vite-plugin.cjs +0 -128
- package/dist/vite-plugin.cjs.map +0 -1
- package/dist/vite-plugin.js +0 -128
- package/dist/vite-plugin.js.map +0 -1
- package/dist/x-markdown.cjs13.js +0 -2
- package/dist/x-markdown.cjs13.js.map +0 -1
- package/dist/x-markdown.cjs21.js +0 -2
- package/dist/x-markdown.cjs21.js.map +0 -1
- package/dist/x-markdown.cjs24.js +0 -2
- package/dist/x-markdown.cjs24.js.map +0 -1
- package/dist/x-markdown.cjs26.js +0 -2
- package/dist/x-markdown.cjs26.js.map +0 -1
- package/dist/x-markdown.es13.js +0 -89
- package/dist/x-markdown.es13.js.map +0 -1
- package/dist/x-markdown.es21.js +0 -11
- package/dist/x-markdown.es21.js.map +0 -1
- package/dist/x-markdown.es24.js.map +0 -1
- package/dist/x-markdown.es26.js +0 -160
- package/dist/x-markdown.es26.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs4.js","sources":["../src/core/hast-to-vnode.ts"],"sourcesContent":["import type { Element, Root, RootContent, Text } from 'hast'\r\nimport type { MaybeRefOrGetter, Slots, VNode, VNodeArrayChildren } from 'vue'\r\nimport type { AliasList, Attributes, Context, CustomAttrs, CustomAttrsObjectResult } from './types'\r\nimport { find, html, svg } from 'property-information'\r\nimport { h, toValue } from 'vue'\r\n\r\nexport function render(\r\n hast: Root,\r\n attrs: Record<string, unknown>,\r\n slots?: Slots,\r\n customAttrs?: MaybeRefOrGetter<CustomAttrs>,\r\n): VNode {\r\n const keyCounter: { [key: string]: number } = {}\r\n return h(\r\n 'div',\r\n attrs,\r\n renderChildren(\r\n hast.children,\r\n { listDepth: -1, listOrdered: false, listItemIndex: -1, svg: false },\r\n hast,\r\n slots ?? {},\r\n toValue(customAttrs) ?? {},\r\n keyCounter,\r\n ),\r\n )\r\n}\r\n\r\nexport function renderChildren(\r\n nodeList: (RootContent | Root)[],\r\n ctx: Context,\r\n parent: Element | Root,\r\n slots: Slots,\r\n customAttrs: CustomAttrs,\r\n keyCounter: { [key: string]: number },\r\n): VNodeArrayChildren {\r\n return nodeList.map((node) => {\r\n switch (node.type) {\r\n case 'text':\r\n return node.value\r\n case 'raw':\r\n return node.value\r\n case 'root':\r\n return renderChildren(node.children, ctx, parent, slots, customAttrs, keyCounter)\r\n case 'element': {\r\n const { attrs, context, aliasList, vnodeProps } = getVNodeInfos(node, parent, ctx, keyCounter, customAttrs)\r\n for (let i = aliasList.length - 1; i >= 0; i--) {\r\n const targetSlot = slots[aliasList[i]]\r\n if (typeof targetSlot === 'function') {\r\n return targetSlot({\r\n ...vnodeProps,\r\n ...attrs,\r\n children: () => renderChildren(node.children, context, node, slots, customAttrs, keyCounter),\r\n })\r\n }\r\n }\r\n\r\n return h(node.tagName, attrs, renderChildren(node.children, context, node, slots, customAttrs, keyCounter))\r\n }\r\n default:\r\n return null\r\n }\r\n })\r\n}\r\n\r\nexport function getVNodeInfos(\r\n node: RootContent,\r\n parent: Element | Root,\r\n context: Context,\r\n keyCounter: Record<string, number>,\r\n customAttrs: CustomAttrs,\r\n): {\r\n attrs: Record<string, unknown>\r\n context: Context\r\n aliasList: AliasList\r\n vnodeProps: Record<string, any>\r\n} {\r\n const aliasList: AliasList = []\r\n\r\n let attrs: Record<string, unknown> = {}\r\n const vnodeProps: Record<string, any> = {}\r\n const ctx = { ...context }\r\n\r\n if (node.type === 'element') {\r\n aliasList.push(node.tagName)\r\n keyCounter[node.tagName] = node.tagName in keyCounter ? keyCounter[node.tagName] + 1 : 0\r\n vnodeProps.key = `${node.tagName}-${keyCounter[node.tagName]}`\r\n node.properties = node.properties || {}\r\n\r\n if (node.tagName === 'svg') {\r\n ctx.svg = true\r\n }\r\n\r\n attrs = Object.entries(node.properties).reduce<Record<string, any>>((acc, [hastKey, value]) => {\r\n const attrInfo = find(ctx.svg ? svg : html, hastKey)\r\n acc[attrInfo.attribute] = value\r\n\r\n return acc\r\n }, {})\r\n\r\n switch (node.tagName) {\r\n case 'h1':\r\n case 'h2':\r\n case 'h3':\r\n case 'h4':\r\n case 'h5':\r\n case 'h6':\r\n vnodeProps.level = Number.parseFloat(node.tagName.slice(1))\r\n aliasList.push('heading')\r\n break\r\n // TODO: maybe use <pre> instead for customizing from <pre> not <code> ?\r\n case 'code':\r\n vnodeProps.languageOriginal = Array.isArray(attrs.class)\r\n ? attrs.class.find((cls) => cls.startsWith('language-'))\r\n : ''\r\n vnodeProps.language = vnodeProps.languageOriginal ? vnodeProps.languageOriginal.replace('language-', '') : ''\r\n vnodeProps.inline = 'tagName' in parent && parent.tagName !== 'pre'\r\n\r\n // when tagName is code, it definitely has children and the first child is text\r\n // https://github.com/syntax-tree/mdast-util-to-hast/blob/main/lib/handlers/code.js\r\n vnodeProps.content = (node.children[0] as unknown as Text)?.value ?? ''\r\n\r\n aliasList.push(vnodeProps.inline ? 'inline-code' : 'block-code')\r\n break\r\n case 'thead':\r\n case 'tbody':\r\n ctx.currentContext = node.tagName\r\n break\r\n case 'td':\r\n case 'th':\r\n case 'tr':\r\n vnodeProps.isHead = context.currentContext === 'thead'\r\n break\r\n\r\n case 'ul':\r\n case 'ol':\r\n ctx.listDepth = context.listDepth + 1\r\n ctx.listOrdered = node.tagName === 'ol'\r\n ctx.listItemIndex = -1\r\n vnodeProps.ordered = ctx.listOrdered\r\n vnodeProps.depth = ctx.listDepth\r\n\r\n aliasList.push('list')\r\n break\r\n\r\n case 'li':\r\n ctx.listItemIndex++\r\n\r\n vnodeProps.ordered = ctx.listOrdered\r\n vnodeProps.depth = ctx.listDepth\r\n vnodeProps.index = ctx.listItemIndex\r\n aliasList.push('list-item')\r\n\r\n break\r\n case 'slot':\r\n if (typeof node.properties['slot-name'] === 'string') {\r\n aliasList.push(`${node.properties['slot-name']}`)\r\n delete node.properties['slot-name']\r\n }\r\n break\r\n default:\r\n break\r\n }\r\n\r\n attrs = computeAttrs(\r\n node,\r\n aliasList,\r\n vnodeProps,\r\n { ...attrs } as Attributes, // TODO: fix this\r\n customAttrs,\r\n )\r\n }\r\n\r\n return {\r\n attrs,\r\n context: ctx,\r\n aliasList,\r\n vnodeProps,\r\n }\r\n}\r\n\r\n/**\r\n * TODO:\r\n * @param node - hast node\r\n * @param aliasList - html tag list. The earlier alias has higher priority. ?\r\n * @param attrs - attrs\r\n * @param customAttrs - custom attrs object\r\n * @returns attrs\r\n */\r\nfunction computeAttrs(\r\n node: Element,\r\n aliasList: AliasList,\r\n vnodeProps: Record<string, any>,\r\n attrs: Attributes,\r\n customAttrs: CustomAttrs,\r\n): CustomAttrsObjectResult {\r\n const result: CustomAttrsObjectResult = {\r\n ...attrs,\r\n }\r\n for (let i = aliasList.length - 1; i >= 0; i--) {\r\n const name = aliasList[i]\r\n // console.log(Object.keys(customAttrs))\r\n if (name in customAttrs) {\r\n const customAttr = customAttrs[name]\r\n return {\r\n ...result,\r\n ...(typeof customAttr === 'function' ? customAttr(node, { ...attrs, ...vnodeProps }) : customAttr),\r\n }\r\n }\r\n }\r\n return result\r\n}\r\n"],"names":["renderChildren","nodeList","ctx","parent","slots","customAttrs","keyCounter","map","node","type","value","children","attrs","context","aliasList","vnodeProps","getVNodeInfos","i","length","targetSlot","h","tagName","push","key","properties","svg","Object","entries","reduce","acc","hastKey","find","html","attribute","level","Number","parseFloat","slice","languageOriginal","Array","isArray","class","cls","startsWith","language","replace","inline","content","currentContext","isHead","listDepth","listOrdered","listItemIndex","ordered","depth","index","result","name","customAttr","computeAttrs","hast","toValue"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"x-markdown.cjs4.js","sources":["../src/core/hast-to-vnode.ts"],"sourcesContent":["import type { Element, Root, RootContent, Text } from 'hast'\r\nimport type { MaybeRefOrGetter, Slots, VNode, VNodeArrayChildren } from 'vue'\r\nimport type { AliasList, Attributes, Context, CustomAttrs, CustomAttrsObjectResult } from './types'\r\nimport { find, html, svg } from 'property-information'\r\nimport { h, toValue } from 'vue'\r\n\r\nexport function render(\r\n hast: Root,\r\n attrs: Record<string, unknown>,\r\n slots?: Slots,\r\n customAttrs?: MaybeRefOrGetter<CustomAttrs>,\r\n): VNode {\r\n const keyCounter: { [key: string]: number } = {}\r\n return h(\r\n 'div',\r\n attrs,\r\n renderChildren(\r\n hast.children,\r\n { listDepth: -1, listOrdered: false, listItemIndex: -1, svg: false },\r\n hast,\r\n slots ?? {},\r\n toValue(customAttrs) ?? {},\r\n keyCounter,\r\n ),\r\n )\r\n}\r\n\r\nexport function renderChildren(\r\n nodeList: (RootContent | Root)[],\r\n ctx: Context,\r\n parent: Element | Root,\r\n slots: Slots,\r\n customAttrs: CustomAttrs,\r\n keyCounter: { [key: string]: number },\r\n): VNodeArrayChildren {\r\n return nodeList.map((node) => {\r\n switch (node.type) {\r\n case 'text':\r\n return node.value\r\n case 'raw':\r\n return node.value\r\n case 'root':\r\n return renderChildren(node.children, ctx, parent, slots, customAttrs, keyCounter)\r\n case 'element': {\r\n const { attrs, context, aliasList, vnodeProps } = getVNodeInfos(node, parent, ctx, keyCounter, customAttrs)\r\n for (let i = aliasList.length - 1; i >= 0; i--) {\r\n const targetSlot = slots[aliasList[i]]\r\n if (typeof targetSlot === 'function') {\r\n return targetSlot({\r\n ...vnodeProps,\r\n ...attrs,\r\n children: () => renderChildren(node.children, context, node, slots, customAttrs, keyCounter),\r\n })\r\n }\r\n }\r\n\r\n return h(node.tagName, attrs, renderChildren(node.children, context, node, slots, customAttrs, keyCounter))\r\n }\r\n default:\r\n return null\r\n }\r\n })\r\n}\r\n\r\nexport function getVNodeInfos(\r\n node: RootContent,\r\n parent: Element | Root,\r\n context: Context,\r\n keyCounter: Record<string, number>,\r\n customAttrs: CustomAttrs,\r\n): {\r\n attrs: Record<string, unknown>\r\n context: Context\r\n aliasList: AliasList\r\n vnodeProps: Record<string, any>\r\n} {\r\n const aliasList: AliasList = []\r\n\r\n let attrs: Record<string, unknown> = {}\r\n const vnodeProps: Record<string, any> = {}\r\n const ctx = { ...context }\r\n\r\n if (node.type === 'element') {\r\n aliasList.push(node.tagName)\r\n keyCounter[node.tagName] = node.tagName in keyCounter ? keyCounter[node.tagName] + 1 : 0\r\n vnodeProps.key = `${node.tagName}-${keyCounter[node.tagName]}`\r\n node.properties = node.properties || {}\r\n\r\n if (node.tagName === 'svg') {\r\n ctx.svg = true\r\n }\r\n\r\n attrs = Object.entries(node.properties).reduce<Record<string, any>>((acc, [hastKey, value]) => {\r\n const attrInfo = find(ctx.svg ? svg : html, hastKey)\r\n acc[attrInfo.attribute] = value\r\n\r\n return acc\r\n }, {})\r\n\r\n switch (node.tagName) {\r\n case 'h1':\r\n case 'h2':\r\n case 'h3':\r\n case 'h4':\r\n case 'h5':\r\n case 'h6':\r\n vnodeProps.level = Number.parseFloat(node.tagName.slice(1))\r\n aliasList.push('heading')\r\n break\r\n // TODO: maybe use <pre> instead for customizing from <pre> not <code> ?\r\n case 'code':\r\n vnodeProps.languageOriginal = Array.isArray(attrs.class)\r\n ? attrs.class.find((cls) => cls.startsWith('language-'))\r\n : ''\r\n vnodeProps.language = vnodeProps.languageOriginal ? vnodeProps.languageOriginal.replace('language-', '') : ''\r\n vnodeProps.inline = 'tagName' in parent && parent.tagName !== 'pre'\r\n\r\n // when tagName is code, it definitely has children and the first child is text\r\n // https://github.com/syntax-tree/mdast-util-to-hast/blob/main/lib/handlers/code.js\r\n vnodeProps.content = (node.children[0] as unknown as Text)?.value ?? ''\r\n\r\n aliasList.push(vnodeProps.inline ? 'inline-code' : 'block-code')\r\n break\r\n case 'thead':\r\n case 'tbody':\r\n ctx.currentContext = node.tagName\r\n break\r\n case 'td':\r\n case 'th':\r\n case 'tr':\r\n vnodeProps.isHead = context.currentContext === 'thead'\r\n break\r\n\r\n case 'ul':\r\n case 'ol':\r\n ctx.listDepth = context.listDepth + 1\r\n ctx.listOrdered = node.tagName === 'ol'\r\n ctx.listItemIndex = -1\r\n vnodeProps.ordered = ctx.listOrdered\r\n vnodeProps.depth = ctx.listDepth\r\n\r\n aliasList.push('list')\r\n break\r\n\r\n case 'li':\r\n ctx.listItemIndex++\r\n\r\n vnodeProps.ordered = ctx.listOrdered\r\n vnodeProps.depth = ctx.listDepth\r\n vnodeProps.index = ctx.listItemIndex\r\n aliasList.push('list-item')\r\n\r\n break\r\n case 'slot':\r\n if (typeof node.properties['slot-name'] === 'string') {\r\n aliasList.push(`${node.properties['slot-name']}`)\r\n delete node.properties['slot-name']\r\n }\r\n break\r\n default:\r\n break\r\n }\r\n\r\n attrs = computeAttrs(\r\n node,\r\n aliasList,\r\n vnodeProps,\r\n { ...attrs } as Attributes, // TODO: fix this\r\n customAttrs,\r\n )\r\n }\r\n\r\n return {\r\n attrs,\r\n context: ctx,\r\n aliasList,\r\n vnodeProps,\r\n }\r\n}\r\n\r\n/**\r\n * TODO:\r\n * @param node - hast node\r\n * @param aliasList - html tag list. The earlier alias has higher priority. ?\r\n * @param attrs - attrs\r\n * @param customAttrs - custom attrs object\r\n * @returns attrs\r\n */\r\nfunction computeAttrs(\r\n node: Element,\r\n aliasList: AliasList,\r\n vnodeProps: Record<string, any>,\r\n attrs: Attributes,\r\n customAttrs: CustomAttrs,\r\n): CustomAttrsObjectResult {\r\n const result: CustomAttrsObjectResult = {\r\n ...attrs,\r\n }\r\n for (let i = aliasList.length - 1; i >= 0; i--) {\r\n const name = aliasList[i]\r\n // console.log(Object.keys(customAttrs))\r\n if (name in customAttrs) {\r\n const customAttr = customAttrs[name]\r\n return {\r\n ...result,\r\n ...(typeof customAttr === 'function' ? customAttr(node, { ...attrs, ...vnodeProps }) : customAttr),\r\n }\r\n }\r\n }\r\n return result\r\n}\r\n"],"names":["h","toValue","find","svg","html"],"mappings":"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"}
|
package/dist/x-markdown.cjs5.js
CHANGED
|
@@ -1,2 +1,44 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
|
|
5
|
+
const deepmerge = require('deepmerge');
|
|
6
|
+
const rehypeSanitize = require('rehype-sanitize');
|
|
7
|
+
const remarkParse = require('remark-parse');
|
|
8
|
+
const remarkRehype = require('remark-rehype');
|
|
9
|
+
const unified = require('unified');
|
|
10
|
+
const vue = require('vue');
|
|
11
|
+
|
|
12
|
+
function useMarkdownProcessor(options) {
|
|
13
|
+
const processor = vue.computed(() => {
|
|
14
|
+
return createProcessor({
|
|
15
|
+
prePlugins: [remarkParse, ...vue.toValue(options?.remarkPlugins) ?? []],
|
|
16
|
+
rehypePlugins: vue.toValue(options?.rehypePlugins),
|
|
17
|
+
rehypeOptions: vue.toValue(options?.rehypeOptions),
|
|
18
|
+
sanitize: vue.toValue(options?.sanitize),
|
|
19
|
+
sanitizeOptions: vue.toValue(options?.sanitizeOptions)
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
return { processor };
|
|
23
|
+
}
|
|
24
|
+
function createProcessor(options) {
|
|
25
|
+
return unified.unified().use(options?.prePlugins ?? []).use(remarkRehype, {
|
|
26
|
+
allowDangerousHtml: true,
|
|
27
|
+
...options?.rehypeOptions || {}
|
|
28
|
+
}).use(options?.rehypePlugins ?? []).use(
|
|
29
|
+
options?.sanitize ? [
|
|
30
|
+
[
|
|
31
|
+
rehypeSanitize,
|
|
32
|
+
deepmerge(
|
|
33
|
+
rehypeSanitize.defaultSchema,
|
|
34
|
+
options?.sanitizeOptions?.sanitizeOptions || {},
|
|
35
|
+
options?.sanitizeOptions?.mergeOptions || {}
|
|
36
|
+
)
|
|
37
|
+
]
|
|
38
|
+
] : []
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
exports.createProcessor = createProcessor;
|
|
43
|
+
exports.useMarkdownProcessor = useMarkdownProcessor;
|
|
2
44
|
//# sourceMappingURL=x-markdown.cjs5.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs5.js","sources":["../src/core/useProcessor.ts"],"sourcesContent":["import type { Root } from 'hast'\r\nimport type { Root as MdastRoot } from 'mdast'\r\nimport type { Options as TRehypeOptions } from 'mdast-util-to-hast'\r\nimport type { PluggableList, Processor } from 'unified'\r\nimport type { ComputedRef, MaybeRefOrGetter } from 'vue'\r\nimport type { SanitizeOptions } from './types'\r\nimport deepmerge from 'deepmerge'\r\nimport rehypeSanitize, { defaultSchema } from 'rehype-sanitize'\r\nimport remarkParse from 'remark-parse'\r\nimport remarkRehype from 'remark-rehype'\r\nimport { unified } from 'unified'\r\nimport { computed, toValue } from 'vue'\r\n\r\nexport interface TUseMarkdownProcessorOptions {\r\n remarkPlugins?: MaybeRefOrGetter<PluggableList>\r\n rehypePlugins?: MaybeRefOrGetter<PluggableList>\r\n rehypeOptions?: MaybeRefOrGetter<Omit<TRehypeOptions, 'file'>>\r\n sanitize?: MaybeRefOrGetter<boolean>\r\n sanitizeOptions?: MaybeRefOrGetter<SanitizeOptions>\r\n}\r\nexport function useMarkdownProcessor(options?: TUseMarkdownProcessorOptions): {\r\n processor: ComputedRef<Processor<MdastRoot, MdastRoot, Root, undefined, undefined>>\r\n} {\r\n const processor = computed(() => {\r\n return createProcessor({\r\n prePlugins: [remarkParse, ...(toValue(options?.remarkPlugins) ?? [])],\r\n rehypePlugins: toValue(options?.rehypePlugins),\r\n rehypeOptions: toValue(options?.rehypeOptions),\r\n sanitize: toValue(options?.sanitize),\r\n sanitizeOptions: toValue(options?.sanitizeOptions),\r\n })\r\n })\r\n return { processor }\r\n}\r\n\r\nexport function createProcessor(options?: {\r\n prePlugins?: PluggableList\r\n rehypePlugins?: PluggableList\r\n rehypeOptions?: Omit<TRehypeOptions, 'file'>\r\n sanitize?: boolean\r\n sanitizeOptions?: SanitizeOptions\r\n // TODO: fix types\r\n}): Processor<any, any, any, any, any> {\r\n return unified()\r\n .use(options?.prePlugins ?? [])\r\n .use(remarkRehype, {\r\n allowDangerousHtml: true,\r\n ...(options?.rehypeOptions || {}),\r\n })\r\n .use(options?.rehypePlugins ?? [])\r\n .use(\r\n options?.sanitize\r\n ? [\r\n [\r\n rehypeSanitize,\r\n deepmerge(\r\n defaultSchema,\r\n options?.sanitizeOptions?.sanitizeOptions || {},\r\n options?.sanitizeOptions?.mergeOptions || {},\r\n ),\r\n ],\r\n ]\r\n : [],\r\n )\r\n}\r\n"],"names":["
|
|
1
|
+
{"version":3,"file":"x-markdown.cjs5.js","sources":["../src/core/useProcessor.ts"],"sourcesContent":["import type { Root } from 'hast'\r\nimport type { Root as MdastRoot } from 'mdast'\r\nimport type { Options as TRehypeOptions } from 'mdast-util-to-hast'\r\nimport type { PluggableList, Processor } from 'unified'\r\nimport type { ComputedRef, MaybeRefOrGetter } from 'vue'\r\nimport type { SanitizeOptions } from './types'\r\nimport deepmerge from 'deepmerge'\r\nimport rehypeSanitize, { defaultSchema } from 'rehype-sanitize'\r\nimport remarkParse from 'remark-parse'\r\nimport remarkRehype from 'remark-rehype'\r\nimport { unified } from 'unified'\r\nimport { computed, toValue } from 'vue'\r\n\r\nexport interface TUseMarkdownProcessorOptions {\r\n remarkPlugins?: MaybeRefOrGetter<PluggableList>\r\n rehypePlugins?: MaybeRefOrGetter<PluggableList>\r\n rehypeOptions?: MaybeRefOrGetter<Omit<TRehypeOptions, 'file'>>\r\n sanitize?: MaybeRefOrGetter<boolean>\r\n sanitizeOptions?: MaybeRefOrGetter<SanitizeOptions>\r\n}\r\nexport function useMarkdownProcessor(options?: TUseMarkdownProcessorOptions): {\r\n processor: ComputedRef<Processor<MdastRoot, MdastRoot, Root, undefined, undefined>>\r\n} {\r\n const processor = computed(() => {\r\n return createProcessor({\r\n prePlugins: [remarkParse, ...(toValue(options?.remarkPlugins) ?? [])],\r\n rehypePlugins: toValue(options?.rehypePlugins),\r\n rehypeOptions: toValue(options?.rehypeOptions),\r\n sanitize: toValue(options?.sanitize),\r\n sanitizeOptions: toValue(options?.sanitizeOptions),\r\n })\r\n })\r\n return { processor }\r\n}\r\n\r\nexport function createProcessor(options?: {\r\n prePlugins?: PluggableList\r\n rehypePlugins?: PluggableList\r\n rehypeOptions?: Omit<TRehypeOptions, 'file'>\r\n sanitize?: boolean\r\n sanitizeOptions?: SanitizeOptions\r\n // TODO: fix types\r\n}): Processor<any, any, any, any, any> {\r\n return unified()\r\n .use(options?.prePlugins ?? [])\r\n .use(remarkRehype, {\r\n allowDangerousHtml: true,\r\n ...(options?.rehypeOptions || {}),\r\n })\r\n .use(options?.rehypePlugins ?? [])\r\n .use(\r\n options?.sanitize\r\n ? [\r\n [\r\n rehypeSanitize,\r\n deepmerge(\r\n defaultSchema,\r\n options?.sanitizeOptions?.sanitizeOptions || {},\r\n options?.sanitizeOptions?.mergeOptions || {},\r\n ),\r\n ],\r\n ]\r\n : [],\r\n )\r\n}\r\n"],"names":["computed","toValue","unified","defaultSchema"],"mappings":";;;;;;;;;;;AAoBO,SAAS,qBAAqB,OAAA,EAEnC;AACA,EAAA,MAAM,SAAA,GAAYA,aAAS,MAAM;AAC/B,IAAA,OAAO,eAAA,CAAgB;AAAA,MACrB,UAAA,EAAY,CAAC,WAAA,EAAa,GAAIC,YAAQ,OAAA,EAAS,aAAa,CAAA,IAAK,EAAG,CAAA;AAAA,MACpE,aAAA,EAAeA,WAAA,CAAQ,OAAA,EAAS,aAAa,CAAA;AAAA,MAC7C,aAAA,EAAeA,WAAA,CAAQ,OAAA,EAAS,aAAa,CAAA;AAAA,MAC7C,QAAA,EAAUA,WAAA,CAAQ,OAAA,EAAS,QAAQ,CAAA;AAAA,MACnC,eAAA,EAAiBA,WAAA,CAAQ,OAAA,EAAS,eAAe;AAAA,KAClD,CAAA;AAAA,EACH,CAAC,CAAA;AACD,EAAA,OAAO,EAAE,SAAA,EAAU;AACrB;AAEO,SAAS,gBAAgB,OAAA,EAOO;AACrC,EAAA,OAAOC,eAAA,GACJ,GAAA,CAAI,OAAA,EAAS,cAAc,EAAE,CAAA,CAC7B,GAAA,CAAI,YAAA,EAAc;AAAA,IACjB,kBAAA,EAAoB,IAAA;AAAA,IACpB,GAAI,OAAA,EAAS,aAAA,IAAiB;AAAC,GAChC,CAAA,CACA,GAAA,CAAI,SAAS,aAAA,IAAiB,EAAE,CAAA,CAChC,GAAA;AAAA,IACC,SAAS,QAAA,GACL;AAAA,MACE;AAAA,QACE,cAAA;AAAA,QACA,SAAA;AAAA,UACEC,4BAAA;AAAA,UACA,OAAA,EAAS,eAAA,EAAiB,eAAA,IAAmB,EAAC;AAAA,UAC9C,OAAA,EAAS,eAAA,EAAiB,YAAA,IAAgB;AAAC;AAC7C;AACF,QAEF;AAAC,GACP;AACJ;;;;;"}
|
package/dist/x-markdown.cjs6.js
CHANGED
|
@@ -1,2 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
|
|
5
|
+
const vue = require('vue');
|
|
6
|
+
const index_vue_vue_type_script_lang = require('./x-markdown.cjs14.js');
|
|
7
|
+
|
|
8
|
+
function useComponents(props) {
|
|
9
|
+
const components = {
|
|
10
|
+
code: (raw) => vue.h(index_vue_vue_type_script_lang.default, {
|
|
11
|
+
raw,
|
|
12
|
+
codeXRender: props?.codeXRender,
|
|
13
|
+
isDark: props?.isDark,
|
|
14
|
+
shikiTheme: props?.shikiTheme,
|
|
15
|
+
enableAnimate: props?.enableAnimate,
|
|
16
|
+
showCodeBlockHeader: props?.showCodeBlockHeader,
|
|
17
|
+
stickyCodeBlockHeader: props?.stickyCodeBlockHeader,
|
|
18
|
+
codeMaxHeight: props?.codeMaxHeight,
|
|
19
|
+
codeBlockActions: props?.codeBlockActions,
|
|
20
|
+
mermaidActions: props?.mermaidActions,
|
|
21
|
+
mermaidConfig: props?.mermaidConfig
|
|
22
|
+
})
|
|
23
|
+
};
|
|
24
|
+
return components;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
exports.useComponents = useComponents;
|
|
2
28
|
//# sourceMappingURL=x-markdown.cjs6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs6.js","sources":["../src/hooks/useComponents.ts"],"sourcesContent":["import { h } from 'vue'\r\nimport type { CodeBlockAction } from '../components/CodeBlock/types'\r\nimport type { MermaidAction } from '../components/Mermaid/types'\r\nimport CodeX from '../components/CodeX/index.vue'\r\n\r\n// Shiki 主题类型(本地定义,避免直接依赖 shiki)\r\ntype ShikiThemeName =\r\n | 'vitesse-light' | 'vitesse-dark'\r\n | 'github-light' | 'github-dark'\r\n | 'nord' | 'one-dark-pro'\r\n | string // 允许其他自定义主题名称\r\n\r\ninterface UseComponentsOptions {\r\n codeXRender?: Record<string, any>\r\n isDark?: boolean\r\n shikiTheme?: [ShikiThemeName, ShikiThemeName]\r\n enableAnimate?: boolean\r\n showCodeBlockHeader?: boolean\r\n stickyCodeBlockHeader?: boolean\r\n codeMaxHeight?: string\r\n codeBlockActions?: CodeBlockAction[]\r\n mermaidActions?: MermaidAction[]\r\n mermaidConfig?: Record<string, any>\r\n}\r\n\r\nfunction useComponents(props?: UseComponentsOptions) {\r\n const components = {\r\n code: (raw: any) =>\r\n h(CodeX, {\r\n raw,\r\n codeXRender: props?.codeXRender,\r\n isDark: props?.isDark,\r\n shikiTheme: props?.shikiTheme,\r\n enableAnimate: props?.enableAnimate,\r\n showCodeBlockHeader: props?.showCodeBlockHeader,\r\n stickyCodeBlockHeader: props?.stickyCodeBlockHeader,\r\n codeMaxHeight: props?.codeMaxHeight,\r\n codeBlockActions: props?.codeBlockActions,\r\n mermaidActions: props?.mermaidActions,\r\n mermaidConfig: props?.mermaidConfig,\r\n }),\r\n }\r\n return components\r\n}\r\n\r\nexport { useComponents }\r\n"],"names":["
|
|
1
|
+
{"version":3,"file":"x-markdown.cjs6.js","sources":["../src/hooks/useComponents.ts"],"sourcesContent":["import { h } from 'vue'\r\nimport type { CodeBlockAction } from '../components/CodeBlock/types'\r\nimport type { MermaidAction } from '../components/Mermaid/types'\r\nimport CodeX from '../components/CodeX/index.vue'\r\n\r\n// Shiki 主题类型(本地定义,避免直接依赖 shiki)\r\ntype ShikiThemeName =\r\n | 'vitesse-light' | 'vitesse-dark'\r\n | 'github-light' | 'github-dark'\r\n | 'nord' | 'one-dark-pro'\r\n | string // 允许其他自定义主题名称\r\n\r\ninterface UseComponentsOptions {\r\n codeXRender?: Record<string, any>\r\n isDark?: boolean\r\n shikiTheme?: [ShikiThemeName, ShikiThemeName]\r\n enableAnimate?: boolean\r\n showCodeBlockHeader?: boolean\r\n stickyCodeBlockHeader?: boolean\r\n codeMaxHeight?: string\r\n codeBlockActions?: CodeBlockAction[]\r\n mermaidActions?: MermaidAction[]\r\n mermaidConfig?: Record<string, any>\r\n}\r\n\r\nfunction useComponents(props?: UseComponentsOptions) {\r\n const components = {\r\n code: (raw: any) =>\r\n h(CodeX, {\r\n raw,\r\n codeXRender: props?.codeXRender,\r\n isDark: props?.isDark,\r\n shikiTheme: props?.shikiTheme,\r\n enableAnimate: props?.enableAnimate,\r\n showCodeBlockHeader: props?.showCodeBlockHeader,\r\n stickyCodeBlockHeader: props?.stickyCodeBlockHeader,\r\n codeMaxHeight: props?.codeMaxHeight,\r\n codeBlockActions: props?.codeBlockActions,\r\n mermaidActions: props?.mermaidActions,\r\n mermaidConfig: props?.mermaidConfig,\r\n }),\r\n }\r\n return components\r\n}\r\n\r\nexport { useComponents }\r\n"],"names":["h","CodeX"],"mappings":";;;;;;;AAyBA,SAAS,cAAc,KAAA,EAA8B;AACnD,EAAA,MAAM,UAAA,GAAa;AAAA,IACjB,IAAA,EAAM,CAAC,GAAA,KACLA,KAAA,CAAEC,sCAAA,EAAO;AAAA,MACP,GAAA;AAAA,MACA,aAAa,KAAA,EAAO,WAAA;AAAA,MACpB,QAAQ,KAAA,EAAO,MAAA;AAAA,MACf,YAAY,KAAA,EAAO,UAAA;AAAA,MACnB,eAAe,KAAA,EAAO,aAAA;AAAA,MACtB,qBAAqB,KAAA,EAAO,mBAAA;AAAA,MAC5B,uBAAuB,KAAA,EAAO,qBAAA;AAAA,MAC9B,eAAe,KAAA,EAAO,aAAA;AAAA,MACtB,kBAAkB,KAAA,EAAO,gBAAA;AAAA,MACzB,gBAAgB,KAAA,EAAO,cAAA;AAAA,MACvB,eAAe,KAAA,EAAO;AAAA,KACvB;AAAA,GACL;AACA,EAAA,OAAO,UAAA;AACT;;;;"}
|
package/dist/x-markdown.cjs7.js
CHANGED
|
@@ -1,2 +1,311 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
|
|
5
|
+
const vue = require('vue');
|
|
6
|
+
const config = require('./x-markdown.cjs12.js');
|
|
7
|
+
|
|
8
|
+
let hasShownShikiHint = false;
|
|
9
|
+
let hasShownShikiStreamHint = false;
|
|
10
|
+
const highlighterCache = /* @__PURE__ */ new Map();
|
|
11
|
+
const getHighlighterCacheKey = (theme) => `highlighter-${theme}`;
|
|
12
|
+
const tokensToLineTokens = (tokens) => {
|
|
13
|
+
if (!tokens.length) return [[]];
|
|
14
|
+
if (Array.isArray(tokens[0])) {
|
|
15
|
+
return tokens;
|
|
16
|
+
}
|
|
17
|
+
const lines = [[]];
|
|
18
|
+
let currentLine = lines[0];
|
|
19
|
+
const startNewLine = () => {
|
|
20
|
+
currentLine = [];
|
|
21
|
+
lines.push(currentLine);
|
|
22
|
+
};
|
|
23
|
+
tokens.forEach((token) => {
|
|
24
|
+
const content = token.content ?? "";
|
|
25
|
+
if (content === "\n") {
|
|
26
|
+
startNewLine();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (!content.includes("\n")) {
|
|
30
|
+
currentLine.push(token);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const segments = content.split("\n");
|
|
34
|
+
segments.forEach((segment, index) => {
|
|
35
|
+
if (segment) {
|
|
36
|
+
currentLine.push({
|
|
37
|
+
...token,
|
|
38
|
+
content: segment
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (index < segments.length - 1) {
|
|
42
|
+
startNewLine();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
return lines.length === 0 ? [[]] : lines;
|
|
47
|
+
};
|
|
48
|
+
const createPreStyle = (bg, fg) => {
|
|
49
|
+
if (!bg && !fg) return void 0;
|
|
50
|
+
return {
|
|
51
|
+
backgroundColor: bg,
|
|
52
|
+
color: fg
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
function useHighlight(text, options) {
|
|
56
|
+
const config$1 = config.useXMarkdownConfig();
|
|
57
|
+
const streaming = vue.ref();
|
|
58
|
+
const isLoading = vue.ref(false);
|
|
59
|
+
const error = vue.ref(null);
|
|
60
|
+
let tokenizer = null;
|
|
61
|
+
let previousText = "";
|
|
62
|
+
let highlighter = null;
|
|
63
|
+
let currentUsedLang = "";
|
|
64
|
+
let lastRequestedLang = "";
|
|
65
|
+
const effectiveTheme = vue.computed(() => {
|
|
66
|
+
const theme = vue.isRef(options.theme) ? options.theme.value : options.theme;
|
|
67
|
+
return theme || "slack-dark";
|
|
68
|
+
});
|
|
69
|
+
const effectiveLanguage = vue.computed(() => {
|
|
70
|
+
return vue.toValue(options.language) || "text";
|
|
71
|
+
});
|
|
72
|
+
const lines = vue.computed(() => streaming.value?.lines || [[]]);
|
|
73
|
+
const preStyle = vue.computed(() => streaming.value?.preStyle);
|
|
74
|
+
const showConsoleHints = () => config$1.showConsoleHints !== false;
|
|
75
|
+
const showShikiHint = () => {
|
|
76
|
+
if (hasShownShikiHint) return;
|
|
77
|
+
if (!showConsoleHints()) return;
|
|
78
|
+
hasShownShikiHint = true;
|
|
79
|
+
console.log(
|
|
80
|
+
"%c[x-markdown]%c 需配置 shikiLoader: %cpnpm add shiki%c",
|
|
81
|
+
"font-weight: bold; color: #0066cc;",
|
|
82
|
+
"color: #666;",
|
|
83
|
+
"color: #00aa00; font-family: monospace;",
|
|
84
|
+
"color: #999;"
|
|
85
|
+
);
|
|
86
|
+
};
|
|
87
|
+
const showShikiStreamHint = () => {
|
|
88
|
+
if (hasShownShikiStreamHint) return;
|
|
89
|
+
if (!showConsoleHints()) return;
|
|
90
|
+
hasShownShikiStreamHint = true;
|
|
91
|
+
console.log(
|
|
92
|
+
"%c[x-markdown]%c AI 流式可选: %cpnpm add shiki-stream%c (需配置 shikiStreamLoader)",
|
|
93
|
+
"font-weight: bold; color: #0066cc;",
|
|
94
|
+
"color: #666;",
|
|
95
|
+
"color: #00aa00; font-family: monospace;",
|
|
96
|
+
"color: #999;"
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
const loadShiki = async () => {
|
|
100
|
+
if (!config$1.shiki) return null;
|
|
101
|
+
try {
|
|
102
|
+
const mod = await config$1.shiki();
|
|
103
|
+
if (mod && mod.default === null) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
if (!mod || !(mod.createHighlighter || mod.getHighlighter)) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
return mod;
|
|
110
|
+
} catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const loadShikiStream = async () => {
|
|
115
|
+
if (!config$1.shikiStream) return null;
|
|
116
|
+
try {
|
|
117
|
+
const mod = await config$1.shikiStream();
|
|
118
|
+
if (mod && mod.default === null) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
if (!mod || !mod.ShikiStreamTokenizer) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
return mod;
|
|
125
|
+
} catch {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const updateTokens = async (nextText, forceReset = false) => {
|
|
130
|
+
if (tokenizer) {
|
|
131
|
+
if (forceReset) {
|
|
132
|
+
tokenizer.clear();
|
|
133
|
+
previousText = "";
|
|
134
|
+
}
|
|
135
|
+
const canAppend = !forceReset && nextText.startsWith(previousText);
|
|
136
|
+
let chunk = nextText;
|
|
137
|
+
if (canAppend) {
|
|
138
|
+
chunk = nextText.slice(previousText.length);
|
|
139
|
+
} else if (!forceReset) {
|
|
140
|
+
tokenizer.clear();
|
|
141
|
+
}
|
|
142
|
+
previousText = nextText;
|
|
143
|
+
if (!chunk) {
|
|
144
|
+
const mergedTokens = [...tokenizer.tokensStable, ...tokenizer.tokensUnstable];
|
|
145
|
+
streaming.value = {
|
|
146
|
+
colorReplacements: options.colorReplacements,
|
|
147
|
+
lines: mergedTokens.length ? tokensToLineTokens(mergedTokens) : [[]],
|
|
148
|
+
preStyle: streaming.value?.preStyle
|
|
149
|
+
};
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
await tokenizer.enqueue(chunk);
|
|
154
|
+
const mergedTokens = [...tokenizer.tokensStable, ...tokenizer.tokensUnstable];
|
|
155
|
+
streaming.value = {
|
|
156
|
+
colorReplacements: options.colorReplacements,
|
|
157
|
+
lines: tokensToLineTokens(mergedTokens),
|
|
158
|
+
preStyle: streaming.value?.preStyle
|
|
159
|
+
};
|
|
160
|
+
} catch (err) {
|
|
161
|
+
error.value = err;
|
|
162
|
+
}
|
|
163
|
+
} else if (highlighter) {
|
|
164
|
+
try {
|
|
165
|
+
const currentLang = currentUsedLang || "plaintext";
|
|
166
|
+
const currentTheme = effectiveTheme.value;
|
|
167
|
+
const tokens = highlighter.codeToTokens(nextText, {
|
|
168
|
+
lang: currentLang,
|
|
169
|
+
theme: currentTheme
|
|
170
|
+
});
|
|
171
|
+
const tokensArray = tokens.tokens || tokens;
|
|
172
|
+
streaming.value = {
|
|
173
|
+
colorReplacements: options.colorReplacements,
|
|
174
|
+
lines: tokensToLineTokens(tokensArray),
|
|
175
|
+
preStyle: streaming.value?.preStyle
|
|
176
|
+
};
|
|
177
|
+
} catch (err) {
|
|
178
|
+
streaming.value = {
|
|
179
|
+
colorReplacements: options.colorReplacements,
|
|
180
|
+
lines: [[{ content: nextText }]],
|
|
181
|
+
preStyle: streaming.value?.preStyle
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const initHighlighter = async () => {
|
|
187
|
+
isLoading.value = true;
|
|
188
|
+
error.value = null;
|
|
189
|
+
let currentLang = effectiveLanguage.value;
|
|
190
|
+
const currentTheme = effectiveTheme.value;
|
|
191
|
+
const cacheKey = getHighlighterCacheKey(currentTheme);
|
|
192
|
+
try {
|
|
193
|
+
const mod = await loadShiki();
|
|
194
|
+
if (!mod) {
|
|
195
|
+
streaming.value = {
|
|
196
|
+
colorReplacements: options.colorReplacements,
|
|
197
|
+
lines: [[{ content: text.value }]],
|
|
198
|
+
preStyle: void 0
|
|
199
|
+
};
|
|
200
|
+
showShikiHint();
|
|
201
|
+
showShikiStreamHint();
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (!highlighterCache.has(cacheKey)) {
|
|
205
|
+
highlighter = await mod.createHighlighter({
|
|
206
|
+
themes: [currentTheme],
|
|
207
|
+
langs: []
|
|
208
|
+
// 将动态加载语言
|
|
209
|
+
});
|
|
210
|
+
highlighterCache.set(cacheKey, highlighter);
|
|
211
|
+
} else {
|
|
212
|
+
highlighter = highlighterCache.get(cacheKey);
|
|
213
|
+
}
|
|
214
|
+
lastRequestedLang = currentLang;
|
|
215
|
+
try {
|
|
216
|
+
await highlighter.loadLanguage(currentLang);
|
|
217
|
+
currentUsedLang = currentLang;
|
|
218
|
+
} catch {
|
|
219
|
+
currentLang = "plaintext";
|
|
220
|
+
currentUsedLang = "plaintext";
|
|
221
|
+
}
|
|
222
|
+
const shikiStreamMod = await loadShikiStream();
|
|
223
|
+
if (shikiStreamMod) {
|
|
224
|
+
tokenizer = new shikiStreamMod.ShikiStreamTokenizer({
|
|
225
|
+
highlighter,
|
|
226
|
+
lang: currentLang,
|
|
227
|
+
theme: currentTheme
|
|
228
|
+
});
|
|
229
|
+
} else {
|
|
230
|
+
showShikiStreamHint();
|
|
231
|
+
}
|
|
232
|
+
previousText = "";
|
|
233
|
+
const themeInfo = highlighter.getTheme(currentTheme);
|
|
234
|
+
const preStyleValue = createPreStyle(themeInfo?.bg, themeInfo?.fg);
|
|
235
|
+
if (text.value) {
|
|
236
|
+
await updateTokens(text.value, true);
|
|
237
|
+
if (streaming.value) {
|
|
238
|
+
streaming.value.preStyle = preStyleValue;
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
streaming.value = {
|
|
242
|
+
colorReplacements: options.colorReplacements,
|
|
243
|
+
lines: [[]],
|
|
244
|
+
preStyle: preStyleValue
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
} catch (err) {
|
|
248
|
+
streaming.value = {
|
|
249
|
+
colorReplacements: options.colorReplacements,
|
|
250
|
+
lines: [[{ content: text.value }]],
|
|
251
|
+
preStyle: void 0
|
|
252
|
+
};
|
|
253
|
+
} finally {
|
|
254
|
+
isLoading.value = false;
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
vue.watch(
|
|
258
|
+
() => [effectiveLanguage.value, effectiveTheme.value],
|
|
259
|
+
async ([newLang]) => {
|
|
260
|
+
const requestedLang = newLang;
|
|
261
|
+
if (highlighter && currentUsedLang === "plaintext" && requestedLang !== lastRequestedLang && requestedLang !== "plaintext") {
|
|
262
|
+
try {
|
|
263
|
+
await highlighter.loadLanguage(requestedLang);
|
|
264
|
+
initHighlighter();
|
|
265
|
+
return;
|
|
266
|
+
} catch {
|
|
267
|
+
lastRequestedLang = requestedLang;
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
initHighlighter();
|
|
272
|
+
},
|
|
273
|
+
{ immediate: true }
|
|
274
|
+
);
|
|
275
|
+
vue.watch(text, async (newText) => {
|
|
276
|
+
const requestedLang = effectiveLanguage.value;
|
|
277
|
+
if (highlighter && currentUsedLang === "plaintext" && requestedLang !== lastRequestedLang && requestedLang !== "plaintext") {
|
|
278
|
+
try {
|
|
279
|
+
await highlighter.loadLanguage(requestedLang);
|
|
280
|
+
await initHighlighter();
|
|
281
|
+
return;
|
|
282
|
+
} catch {
|
|
283
|
+
lastRequestedLang = requestedLang;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (tokenizer || highlighter) {
|
|
287
|
+
updateTokens(newText);
|
|
288
|
+
} else {
|
|
289
|
+
streaming.value = {
|
|
290
|
+
colorReplacements: options.colorReplacements,
|
|
291
|
+
lines: [[{ content: newText }]],
|
|
292
|
+
preStyle: streaming.value?.preStyle
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
vue.onUnmounted(() => {
|
|
297
|
+
tokenizer?.clear();
|
|
298
|
+
tokenizer = null;
|
|
299
|
+
previousText = "";
|
|
300
|
+
});
|
|
301
|
+
return {
|
|
302
|
+
streaming,
|
|
303
|
+
lines,
|
|
304
|
+
preStyle,
|
|
305
|
+
isLoading,
|
|
306
|
+
error
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
exports.useHighlight = useHighlight;
|
|
2
311
|
//# sourceMappingURL=x-markdown.cjs7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs7.js","sources":["../src/hooks/useHighlight.ts"],"sourcesContent":["import {\r\n ref,\r\n watch,\r\n onUnmounted,\r\n computed,\r\n isRef,\r\n toValue,\r\n type Ref,\r\n type MaybeRefOrGetter,\r\n type CSSProperties,\r\n} from 'vue'\r\n\r\n// 获取是否启用控制台提示的辅助函数\r\nconst consoleHintsEnabled = () => {\r\n if (typeof __X_MARKDOWN_CONSOLE_HINTS_ENABLED__ === 'boolean') {\r\n return __X_MARKDOWN_CONSOLE_HINTS_ENABLED__\r\n }\r\n return true // 默认启用\r\n}\r\n\r\nexport interface HighlightToken {\r\n content?: string\r\n color?: string\r\n fontStyle?: 'italic' | null\r\n fontWeight?: 'normal' | 'bold' | null\r\n htmlStyle?: Record<string, string>\r\n}\r\n\r\ninterface StreamingHighlightResult {\r\n colorReplacements?: Record<string, string>\r\n lines: HighlightToken[][]\r\n preStyle?: CSSProperties\r\n}\r\n\r\ninterface UseHighlightOptions {\r\n language: MaybeRefOrGetter<string>\r\n theme?: string | Ref<string>\r\n colorReplacements?: Record<string, string>\r\n}\r\n\r\nlet shikiModulePromise: Promise<any | null> | null = null\r\nlet shikiStreamModulePromise: Promise<any | null> | null = null\r\nlet hasShownShikiHint = false\r\nlet hasShownShikiStreamHint = false\r\n\r\n// 全局 highlighter 缓存,避免重复创建实例\r\nconst highlighterCache = new Map<string, any>()\r\nconst getHighlighterCacheKey = (theme: string) => `highlighter-${theme}`\r\n\r\nconst showShikiHint = () => {\r\n if (hasShownShikiHint) return\r\n if (!consoleHintsEnabled()) return\r\n\r\n hasShownShikiHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c 需安装 shiki: %cpnpm add shiki%c',\r\n 'font-weight: bold; color: #0066cc;',\r\n 'color: #666;',\r\n 'color: #00aa00; font-family: monospace;',\r\n 'color: #999;',\r\n )\r\n}\r\n\r\nconst showShikiStreamHint = () => {\r\n if (hasShownShikiStreamHint) return\r\n if (!consoleHintsEnabled()) return\r\n\r\n hasShownShikiStreamHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c AI 流式可选: %cpnpm add shiki-stream%c (需先装 shiki)',\r\n 'font-weight: bold; color: #0066cc;',\r\n 'color: #666;',\r\n 'color: #00aa00; font-family: monospace;',\r\n 'color: #999;',\r\n )\r\n}\r\n\r\nconst loadShiki = async () => {\r\n if (!shikiModulePromise) {\r\n shikiModulePromise = (async () => {\r\n try {\r\n const mod = await import('shiki')\r\n // 检查是否是虚拟模块(虚拟模块返回 { default: null })\r\n if (mod && (mod as any).default === null) {\r\n return null\r\n }\r\n // 检查必要的方法是否存在,确保模块可用\r\n if (!mod || !(mod.createHighlighter || (mod as any).getHighlighter)) {\r\n return null\r\n }\r\n return mod\r\n } catch {\r\n // 静默失败,返回 null\r\n return null\r\n }\r\n })()\r\n }\r\n return shikiModulePromise\r\n}\r\n\r\nconst loadShikiStream = async () => {\r\n if (!shikiStreamModulePromise) {\r\n shikiStreamModulePromise = (async () => {\r\n try {\r\n const mod = await import('shiki-stream')\r\n // 检查是否是虚拟模块(虚拟模块返回 { default: null })\r\n if (mod && (mod as any).default === null) {\r\n return null\r\n }\r\n // 检查必要的方法是否存在\r\n if (!mod || !(mod as any).ShikiStreamTokenizer) {\r\n return null\r\n }\r\n return mod\r\n } catch {\r\n // 静默失败,返回 null\r\n return null\r\n }\r\n })()\r\n }\r\n return shikiStreamModulePromise\r\n}\r\n\r\nconst tokensToLineTokens = (tokens: HighlightToken[] | HighlightToken[][]): HighlightToken[][] => {\r\n if (!tokens.length) return [[]]\r\n\r\n // 检查是否已经是二维数组(shiki 3.x codeToTokens 的返回格式)\r\n if (Array.isArray(tokens[0])) {\r\n return tokens as HighlightToken[][]\r\n }\r\n\r\n // 处理一维数组(shiki-stream 的格式)\r\n const lines: HighlightToken[][] = [[]]\r\n let currentLine = lines[0]\r\n\r\n const startNewLine = () => {\r\n currentLine = []\r\n lines.push(currentLine)\r\n }\r\n\r\n ;(tokens as HighlightToken[]).forEach((token) => {\r\n const content = token.content ?? ''\r\n\r\n if (content === '\\n') {\r\n startNewLine()\r\n return\r\n }\r\n\r\n if (!content.includes('\\n')) {\r\n currentLine.push(token)\r\n return\r\n }\r\n\r\n const segments = content.split('\\n')\r\n segments.forEach((segment: string, index: number) => {\r\n if (segment) {\r\n currentLine.push({\r\n ...token,\r\n content: segment,\r\n })\r\n }\r\n\r\n if (index < segments.length - 1) {\r\n startNewLine()\r\n }\r\n })\r\n })\r\n\r\n return lines.length === 0 ? [[]] : lines\r\n}\r\n\r\nconst createPreStyle = (bg?: string, fg?: string): CSSProperties | undefined => {\r\n if (!bg && !fg) return undefined\r\n return {\r\n backgroundColor: bg,\r\n color: fg,\r\n }\r\n}\r\n\r\nexport function useHighlight(text: Ref<string>, options: UseHighlightOptions) {\r\n const streaming = ref<StreamingHighlightResult>()\r\n const isLoading = ref(false)\r\n const error = ref<Error | null>(null)\r\n\r\n let tokenizer: any | null = null\r\n let previousText = ''\r\n let highlighter: any | null = null\r\n let currentUsedLang = ''\r\n let lastRequestedLang = ''\r\n\r\n const effectiveTheme = computed(() => {\r\n const theme = isRef(options.theme) ? options.theme.value : options.theme\r\n return theme || 'slack-dark'\r\n })\r\n\r\n const effectiveLanguage = computed(() => {\r\n return toValue(options.language) || 'text'\r\n })\r\n\r\n const lines = computed(() => streaming.value?.lines || [[]])\r\n const preStyle = computed(() => streaming.value?.preStyle)\r\n\r\n const updateTokens = async (nextText: string, forceReset = false) => {\r\n // 当有 tokenizer 时使用流式处理\r\n if (tokenizer) {\r\n if (forceReset) {\r\n tokenizer.clear()\r\n previousText = ''\r\n }\r\n\r\n const canAppend = !forceReset && nextText.startsWith(previousText)\r\n let chunk = nextText\r\n\r\n if (canAppend) {\r\n chunk = nextText.slice(previousText.length)\r\n } else if (!forceReset) {\r\n tokenizer.clear()\r\n }\r\n\r\n previousText = nextText\r\n\r\n if (!chunk) {\r\n const mergedTokens = [...tokenizer.tokensStable, ...tokenizer.tokensUnstable]\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: mergedTokens.length ? tokensToLineTokens(mergedTokens) : [[]],\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n return\r\n }\r\n\r\n try {\r\n await tokenizer.enqueue(chunk)\r\n\r\n const mergedTokens = [...tokenizer.tokensStable, ...tokenizer.tokensUnstable]\r\n\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: tokensToLineTokens(mergedTokens),\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n } catch (err) {\r\n // 静默失败,降级为纯文本\r\n error.value = err as Error\r\n }\r\n } else if (highlighter) {\r\n // 当没有 tokenizer 但有 highlighter 时,使用非流式方式高亮\r\n // 这发生在 shiki 可用但 shiki-stream 不可用时\r\n try {\r\n const currentLang = currentUsedLang || 'plaintext'\r\n const currentTheme = effectiveTheme.value\r\n const tokens = highlighter.codeToTokens(nextText, {\r\n lang: currentLang,\r\n theme: currentTheme,\r\n })\r\n\r\n // shiki 3.x 的 codeToTokens 返回一个对象,包含 tokens、fg、bg 等属性\r\n // 需要从返回对象中提取 tokens 数组\r\n const tokensArray = (tokens as any).tokens || tokens\r\n\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: tokensToLineTokens(tokensArray),\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n } catch (err) {\r\n // 静默降级为纯文本\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: nextText }]],\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n }\r\n }\r\n }\r\n\r\n const initHighlighter = async () => {\r\n isLoading.value = true\r\n error.value = null\r\n\r\n let currentLang = effectiveLanguage.value\r\n const currentTheme = effectiveTheme.value\r\n const cacheKey = getHighlighterCacheKey(currentTheme)\r\n\r\n try {\r\n const mod = await loadShiki()\r\n if (!mod) {\r\n // shiki 完全不可用,降级为纯文本\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: text.value }]],\r\n preStyle: undefined,\r\n }\r\n showShikiHint()\r\n showShikiStreamHint()\r\n return\r\n }\r\n\r\n // 检查缓存,如果已有相同主题的 highlighter,直接复用\r\n // 这避免了 Shiki 单例警告并提高了性能\r\n if (!highlighterCache.has(cacheKey)) {\r\n highlighter = await mod.createHighlighter({\r\n themes: [currentTheme],\r\n langs: [], // 将动态加载语言\r\n })\r\n highlighterCache.set(cacheKey, highlighter)\r\n } else {\r\n highlighter = highlighterCache.get(cacheKey)\r\n }\r\n\r\n lastRequestedLang = currentLang\r\n\r\n // 尝试加载请求的语言,失败则降级为纯文本\r\n try {\r\n await highlighter.loadLanguage(currentLang as any)\r\n currentUsedLang = currentLang\r\n } catch {\r\n currentLang = 'plaintext'\r\n currentUsedLang = 'plaintext'\r\n }\r\n\r\n // 动态加载 shiki-stream\r\n const shikiStreamMod = await loadShikiStream()\r\n if (shikiStreamMod) {\r\n tokenizer = new shikiStreamMod.ShikiStreamTokenizer({\r\n highlighter: highlighter,\r\n lang: currentLang,\r\n theme: currentTheme,\r\n })\r\n } else {\r\n // shiki 可用但 shiki-stream 不可用\r\n showShikiStreamHint()\r\n }\r\n\r\n previousText = ''\r\n\r\n const themeInfo = highlighter.getTheme(currentTheme)\r\n const preStyleValue = createPreStyle(themeInfo?.bg, themeInfo?.fg)\r\n\r\n if (text.value) {\r\n await updateTokens(text.value, true)\r\n if (streaming.value) {\r\n streaming.value.preStyle = preStyleValue\r\n }\r\n } else {\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[]],\r\n preStyle: preStyleValue,\r\n }\r\n }\r\n } catch (err) {\r\n // 静默降级\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: text.value }]],\r\n preStyle: undefined,\r\n }\r\n } finally {\r\n isLoading.value = false\r\n }\r\n }\r\n\r\n watch(\r\n () => [effectiveLanguage.value, effectiveTheme.value],\r\n async ([newLang]) => {\r\n const requestedLang = newLang as string\r\n\r\n if (\r\n highlighter &&\r\n currentUsedLang === 'plaintext' &&\r\n requestedLang !== lastRequestedLang &&\r\n requestedLang !== 'plaintext'\r\n ) {\r\n try {\r\n await highlighter.loadLanguage(requestedLang as any)\r\n initHighlighter()\r\n return\r\n } catch {\r\n lastRequestedLang = requestedLang\r\n return\r\n }\r\n }\r\n\r\n initHighlighter()\r\n },\r\n { immediate: true },\r\n )\r\n\r\n watch(text, async (newText) => {\r\n const requestedLang = effectiveLanguage.value\r\n if (\r\n highlighter &&\r\n currentUsedLang === 'plaintext' &&\r\n requestedLang !== lastRequestedLang &&\r\n requestedLang !== 'plaintext'\r\n ) {\r\n try {\r\n await highlighter.loadLanguage(requestedLang as any)\r\n await initHighlighter()\r\n return\r\n } catch {\r\n lastRequestedLang = requestedLang\r\n }\r\n }\r\n\r\n if (tokenizer || highlighter) {\r\n // 当有 tokenizer 或 highlighter 时都调用 updateTokens\r\n // updateTokens 内部会处理两种情况\r\n updateTokens(newText)\r\n } else {\r\n // 两者都没有时降级为纯文本\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: newText }]],\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n }\r\n })\r\n\r\n onUnmounted(() => {\r\n tokenizer?.clear()\r\n tokenizer = null\r\n previousText = ''\r\n })\r\n\r\n return {\r\n streaming,\r\n lines,\r\n preStyle,\r\n isLoading,\r\n error,\r\n }\r\n}\r\n"],"names":["consoleHintsEnabled","__X_MARKDOWN_CONSOLE_HINTS_ENABLED__","shikiModulePromise","shikiStreamModulePromise","hasShownShikiHint","hasShownShikiStreamHint","highlighterCache","Map","showShikiStreamHint","console","log","tokensToLineTokens","tokens","length","Array","isArray","lines","currentLine","startNewLine","push","forEach","token","content","includes","segments","split","segment","index","text","options","streaming","ref","isLoading","error","tokenizer","previousText","highlighter","currentUsedLang","lastRequestedLang","effectiveTheme","computed","isRef","theme","value","effectiveLanguage","toValue","language","preStyle","updateTokens","async","nextText","forceReset","clear","canAppend","startsWith","chunk","slice","mergedTokens","tokensStable","tokensUnstable","colorReplacements","enqueue","err","currentLang","currentTheme","codeToTokens","lang","tokensArray","initHighlighter","cacheKey","mod","import","default","createHighlighter","getHighlighter","loadShiki","has","get","themes","langs","set","loadLanguage","shikiStreamMod","ShikiStreamTokenizer","loadShikiStream","themeInfo","getTheme","preStyleValue","bg","fg","backgroundColor","color","createPreStyle","watch","newLang","requestedLang","immediate","newText","onUnmounted"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"x-markdown.cjs7.js","sources":["../src/hooks/useHighlight.ts"],"sourcesContent":["import {\r\n ref,\r\n watch,\r\n onUnmounted,\r\n computed,\r\n isRef,\r\n toValue,\r\n type Ref,\r\n type MaybeRefOrGetter,\r\n type CSSProperties,\r\n} from 'vue'\r\nimport { useXMarkdownConfig } from '../config'\r\n\r\nexport interface HighlightToken {\r\n content?: string\r\n color?: string\r\n fontStyle?: 'italic' | null\r\n fontWeight?: 'normal' | 'bold' | null\r\n htmlStyle?: Record<string, string>\r\n}\r\n\r\ninterface StreamingHighlightResult {\r\n colorReplacements?: Record<string, string>\r\n lines: HighlightToken[][]\r\n preStyle?: CSSProperties\r\n}\r\n\r\ninterface UseHighlightOptions {\r\n language: MaybeRefOrGetter<string>\r\n theme?: string | Ref<string>\r\n colorReplacements?: Record<string, string>\r\n}\r\n\r\nlet hasShownShikiHint = false\r\nlet hasShownShikiStreamHint = false\r\n\r\n// 全局 highlighter 缓存,避免重复创建实例\r\nconst highlighterCache = new Map<string, any>()\r\nconst getHighlighterCacheKey = (theme: string) => `highlighter-${theme}`\r\n\r\nconst tokensToLineTokens = (tokens: HighlightToken[] | HighlightToken[][]): HighlightToken[][] => {\r\n if (!tokens.length) return [[]]\r\n\r\n // 检查是否已经是二维数组(shiki 3.x codeToTokens 的返回格式)\r\n if (Array.isArray(tokens[0])) {\r\n return tokens as HighlightToken[][]\r\n }\r\n\r\n // 处理一维数组(shiki-stream 的格式)\r\n const lines: HighlightToken[][] = [[]]\r\n let currentLine = lines[0]\r\n\r\n const startNewLine = () => {\r\n currentLine = []\r\n lines.push(currentLine)\r\n }\r\n\r\n ;(tokens as HighlightToken[]).forEach((token) => {\r\n const content = token.content ?? ''\r\n\r\n if (content === '\\n') {\r\n startNewLine()\r\n return\r\n }\r\n\r\n if (!content.includes('\\n')) {\r\n currentLine.push(token)\r\n return\r\n }\r\n\r\n const segments = content.split('\\n')\r\n segments.forEach((segment: string, index: number) => {\r\n if (segment) {\r\n currentLine.push({\r\n ...token,\r\n content: segment,\r\n })\r\n }\r\n\r\n if (index < segments.length - 1) {\r\n startNewLine()\r\n }\r\n })\r\n })\r\n\r\n return lines.length === 0 ? [[]] : lines\r\n}\r\n\r\nconst createPreStyle = (bg?: string, fg?: string): CSSProperties | undefined => {\r\n if (!bg && !fg) return undefined\r\n return {\r\n backgroundColor: bg,\r\n color: fg,\r\n }\r\n}\r\n\r\nexport function useHighlight(text: Ref<string>, options: UseHighlightOptions) {\r\n const config = useXMarkdownConfig()\r\n const streaming = ref<StreamingHighlightResult>()\r\n const isLoading = ref(false)\r\n const error = ref<Error | null>(null)\r\n\r\n let tokenizer: any | null = null\r\n let previousText = ''\r\n let highlighter: any | null = null\r\n let currentUsedLang = ''\r\n let lastRequestedLang = ''\r\n\r\n const effectiveTheme = computed(() => {\r\n const theme = isRef(options.theme) ? options.theme.value : options.theme\r\n return theme || 'slack-dark'\r\n })\r\n\r\n const effectiveLanguage = computed(() => {\r\n return toValue(options.language) || 'text'\r\n })\r\n\r\n const lines = computed(() => streaming.value?.lines || [[]])\r\n const preStyle = computed(() => streaming.value?.preStyle)\r\n\r\n const showConsoleHints = () => config.showConsoleHints !== false\r\n\r\n const showShikiHint = () => {\r\n if (hasShownShikiHint) return\r\n if (!showConsoleHints()) return\r\n\r\n hasShownShikiHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c 需配置 shikiLoader: %cpnpm add shiki%c',\r\n 'font-weight: bold; color: #0066cc;',\r\n 'color: #666;',\r\n 'color: #00aa00; font-family: monospace;',\r\n 'color: #999;',\r\n )\r\n }\r\n\r\n const showShikiStreamHint = () => {\r\n if (hasShownShikiStreamHint) return\r\n if (!showConsoleHints()) return\r\n\r\n hasShownShikiStreamHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c AI 流式可选: %cpnpm add shiki-stream%c (需配置 shikiStreamLoader)',\r\n 'font-weight: bold; color: #0066cc;',\r\n 'color: #666;',\r\n 'color: #00aa00; font-family: monospace;',\r\n 'color: #999;',\r\n )\r\n }\r\n\r\n const loadShiki = async () => {\r\n if (!config.shiki) return null\r\n try {\r\n const mod = await config.shiki()\r\n // 检查是否是虚拟模块(虚拟模块返回 { default: null })\r\n if (mod && (mod as any).default === null) {\r\n return null\r\n }\r\n // 检查必要的方法是否存在,确保模块可用\r\n if (!mod || !(mod.createHighlighter || (mod as any).getHighlighter)) {\r\n return null\r\n }\r\n return mod\r\n } catch {\r\n // 静默失败,返回 null\r\n return null\r\n }\r\n }\r\n\r\n const loadShikiStream = async () => {\r\n if (!config.shikiStream) return null\r\n try {\r\n const mod = await config.shikiStream()\r\n // 检查是否是虚拟模块(虚拟模块返回 { default: null })\r\n if (mod && (mod as any).default === null) {\r\n return null\r\n }\r\n // 检查必要的方法是否存在\r\n if (!mod || !(mod as any).ShikiStreamTokenizer) {\r\n return null\r\n }\r\n return mod\r\n } catch {\r\n // 静默失败,返回 null\r\n return null\r\n }\r\n }\r\n\r\n const updateTokens = async (nextText: string, forceReset = false) => {\r\n // 当有 tokenizer 时使用流式处理\r\n if (tokenizer) {\r\n if (forceReset) {\r\n tokenizer.clear()\r\n previousText = ''\r\n }\r\n\r\n const canAppend = !forceReset && nextText.startsWith(previousText)\r\n let chunk = nextText\r\n\r\n if (canAppend) {\r\n chunk = nextText.slice(previousText.length)\r\n } else if (!forceReset) {\r\n tokenizer.clear()\r\n }\r\n\r\n previousText = nextText\r\n\r\n if (!chunk) {\r\n const mergedTokens = [...tokenizer.tokensStable, ...tokenizer.tokensUnstable]\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: mergedTokens.length ? tokensToLineTokens(mergedTokens) : [[]],\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n return\r\n }\r\n\r\n try {\r\n await tokenizer.enqueue(chunk)\r\n\r\n const mergedTokens = [...tokenizer.tokensStable, ...tokenizer.tokensUnstable]\r\n\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: tokensToLineTokens(mergedTokens),\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n } catch (err) {\r\n // 静默失败,降级为纯文本\r\n error.value = err as Error\r\n }\r\n } else if (highlighter) {\r\n // 当没有 tokenizer 但有 highlighter 时,使用非流式方式高亮\r\n // 这发生在 shiki 可用但 shiki-stream 不可用时\r\n try {\r\n const currentLang = currentUsedLang || 'plaintext'\r\n const currentTheme = effectiveTheme.value\r\n const tokens = highlighter.codeToTokens(nextText, {\r\n lang: currentLang,\r\n theme: currentTheme,\r\n })\r\n\r\n // shiki 3.x 的 codeToTokens 返回一个对象,包含 tokens、fg、bg 等属性\r\n // 需要从返回对象中提取 tokens 数组\r\n const tokensArray = (tokens as any).tokens || tokens\r\n\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: tokensToLineTokens(tokensArray),\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n } catch (err) {\r\n // 静默降级为纯文本\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: nextText }]],\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n }\r\n }\r\n }\r\n\r\n const initHighlighter = async () => {\r\n isLoading.value = true\r\n error.value = null\r\n\r\n let currentLang = effectiveLanguage.value\r\n const currentTheme = effectiveTheme.value\r\n const cacheKey = getHighlighterCacheKey(currentTheme)\r\n\r\n try {\r\n const mod = await loadShiki()\r\n if (!mod) {\r\n // shiki 完全不可用,降级为纯文本\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: text.value }]],\r\n preStyle: undefined,\r\n }\r\n showShikiHint()\r\n showShikiStreamHint()\r\n return\r\n }\r\n\r\n // 检查缓存,如果已有相同主题的 highlighter,直接复用\r\n // 这避免了 Shiki 单例警告并提高了性能\r\n if (!highlighterCache.has(cacheKey)) {\r\n highlighter = await mod.createHighlighter({\r\n themes: [currentTheme],\r\n langs: [], // 将动态加载语言\r\n })\r\n highlighterCache.set(cacheKey, highlighter)\r\n } else {\r\n highlighter = highlighterCache.get(cacheKey)\r\n }\r\n\r\n lastRequestedLang = currentLang\r\n\r\n // 尝试加载请求的语言,失败则降级为纯文本\r\n try {\r\n await highlighter.loadLanguage(currentLang as any)\r\n currentUsedLang = currentLang\r\n } catch {\r\n currentLang = 'plaintext'\r\n currentUsedLang = 'plaintext'\r\n }\r\n\r\n // 动态加载 shiki-stream\r\n const shikiStreamMod = await loadShikiStream()\r\n if (shikiStreamMod) {\r\n tokenizer = new shikiStreamMod.ShikiStreamTokenizer({\r\n highlighter: highlighter,\r\n lang: currentLang,\r\n theme: currentTheme,\r\n })\r\n } else {\r\n // shiki 可用但 shiki-stream 不可用\r\n showShikiStreamHint()\r\n }\r\n\r\n previousText = ''\r\n\r\n const themeInfo = highlighter.getTheme(currentTheme)\r\n const preStyleValue = createPreStyle(themeInfo?.bg, themeInfo?.fg)\r\n\r\n if (text.value) {\r\n await updateTokens(text.value, true)\r\n if (streaming.value) {\r\n streaming.value.preStyle = preStyleValue\r\n }\r\n } else {\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[]],\r\n preStyle: preStyleValue,\r\n }\r\n }\r\n } catch (err) {\r\n // 静默降级\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: text.value }]],\r\n preStyle: undefined,\r\n }\r\n } finally {\r\n isLoading.value = false\r\n }\r\n }\r\n\r\n watch(\r\n () => [effectiveLanguage.value, effectiveTheme.value],\r\n async ([newLang]) => {\r\n const requestedLang = newLang as string\r\n\r\n if (\r\n highlighter &&\r\n currentUsedLang === 'plaintext' &&\r\n requestedLang !== lastRequestedLang &&\r\n requestedLang !== 'plaintext'\r\n ) {\r\n try {\r\n await highlighter.loadLanguage(requestedLang as any)\r\n initHighlighter()\r\n return\r\n } catch {\r\n lastRequestedLang = requestedLang\r\n return\r\n }\r\n }\r\n\r\n initHighlighter()\r\n },\r\n { immediate: true },\r\n )\r\n\r\n watch(text, async (newText) => {\r\n const requestedLang = effectiveLanguage.value\r\n if (\r\n highlighter &&\r\n currentUsedLang === 'plaintext' &&\r\n requestedLang !== lastRequestedLang &&\r\n requestedLang !== 'plaintext'\r\n ) {\r\n try {\r\n await highlighter.loadLanguage(requestedLang as any)\r\n await initHighlighter()\r\n return\r\n } catch {\r\n lastRequestedLang = requestedLang\r\n }\r\n }\r\n\r\n if (tokenizer || highlighter) {\r\n // 当有 tokenizer 或 highlighter 时都调用 updateTokens\r\n // updateTokens 内部会处理两种情况\r\n updateTokens(newText)\r\n } else {\r\n // 两者都没有时降级为纯文本\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: newText }]],\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n }\r\n })\r\n\r\n onUnmounted(() => {\r\n tokenizer?.clear()\r\n tokenizer = null\r\n previousText = ''\r\n })\r\n\r\n return {\r\n streaming,\r\n lines,\r\n preStyle,\r\n isLoading,\r\n error,\r\n }\r\n}\r\n"],"names":["config","useXMarkdownConfig","ref","computed","isRef","toValue","watch","onUnmounted"],"mappings":";;;;;;;AAiCA,IAAI,iBAAA,GAAoB,KAAA;AACxB,IAAI,uBAAA,GAA0B,KAAA;AAG9B,MAAM,gBAAA,uBAAuB,GAAA,EAAiB;AAC9C,MAAM,sBAAA,GAAyB,CAAC,KAAA,KAAkB,CAAA,YAAA,EAAe,KAAK,CAAA,CAAA;AAEtE,MAAM,kBAAA,GAAqB,CAAC,MAAA,KAAsE;AAChG,EAAA,IAAI,CAAC,MAAA,CAAO,MAAA,EAAQ,OAAO,CAAC,EAAE,CAAA;AAG9B,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAC,CAAA,EAAG;AAC5B,IAAA,OAAO,MAAA;AAAA,EACT;AAGA,EAAA,MAAM,KAAA,GAA4B,CAAC,EAAE,CAAA;AACrC,EAAA,IAAI,WAAA,GAAc,MAAM,CAAC,CAAA;AAEzB,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,WAAA,GAAc,EAAC;AACf,IAAA,KAAA,CAAM,KAAK,WAAW,CAAA;AAAA,EACxB,CAAA;AAEC,EAAC,MAAA,CAA4B,OAAA,CAAQ,CAAC,KAAA,KAAU;AAC/C,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,IAAW,EAAA;AAEjC,IAAA,IAAI,YAAY,IAAA,EAAM;AACpB,MAAA,YAAA,EAAa;AACb,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAA,EAAG;AAC3B,MAAA,WAAA,CAAY,KAAK,KAAK,CAAA;AACtB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA;AACnC,IAAA,QAAA,CAAS,OAAA,CAAQ,CAAC,OAAA,EAAiB,KAAA,KAAkB;AACnD,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,WAAA,CAAY,IAAA,CAAK;AAAA,UACf,GAAG,KAAA;AAAA,UACH,OAAA,EAAS;AAAA,SACV,CAAA;AAAA,MACH;AAEA,MAAA,IAAI,KAAA,GAAQ,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AAC/B,QAAA,YAAA,EAAa;AAAA,MACf;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AAED,EAAA,OAAO,MAAM,MAAA,KAAW,CAAA,GAAI,CAAC,EAAE,CAAA,GAAI,KAAA;AACrC,CAAA;AAEA,MAAM,cAAA,GAAiB,CAAC,EAAA,EAAa,EAAA,KAA2C;AAC9E,EAAA,IAAI,CAAC,EAAA,IAAM,CAAC,EAAA,EAAI,OAAO,MAAA;AACvB,EAAA,OAAO;AAAA,IACL,eAAA,EAAiB,EAAA;AAAA,IACjB,KAAA,EAAO;AAAA,GACT;AACF,CAAA;AAEO,SAAS,YAAA,CAAa,MAAmB,OAAA,EAA8B;AAC5E,EAAA,MAAMA,WAASC,yBAAA,EAAmB;AAClC,EAAA,MAAM,YAAYC,OAAA,EAA8B;AAChD,EAAA,MAAM,SAAA,GAAYA,QAAI,KAAK,CAAA;AAC3B,EAAA,MAAM,KAAA,GAAQA,QAAkB,IAAI,CAAA;AAEpC,EAAA,IAAI,SAAA,GAAwB,IAAA;AAC5B,EAAA,IAAI,YAAA,GAAe,EAAA;AACnB,EAAA,IAAI,WAAA,GAA0B,IAAA;AAC9B,EAAA,IAAI,eAAA,GAAkB,EAAA;AACtB,EAAA,IAAI,iBAAA,GAAoB,EAAA;AAExB,EAAA,MAAM,cAAA,GAAiBC,aAAS,MAAM;AACpC,IAAA,MAAM,KAAA,GAAQC,UAAM,OAAA,CAAQ,KAAK,IAAI,OAAA,CAAQ,KAAA,CAAM,QAAQ,OAAA,CAAQ,KAAA;AACnE,IAAA,OAAO,KAAA,IAAS,YAAA;AAAA,EAClB,CAAC,CAAA;AAED,EAAA,MAAM,iBAAA,GAAoBD,aAAS,MAAM;AACvC,IAAA,OAAOE,WAAA,CAAQ,OAAA,CAAQ,QAAQ,CAAA,IAAK,MAAA;AAAA,EACtC,CAAC,CAAA;AAED,EAAA,MAAM,KAAA,GAAQF,aAAS,MAAM,SAAA,CAAU,OAAO,KAAA,IAAS,CAAC,EAAE,CAAC,CAAA;AAC3D,EAAA,MAAM,QAAA,GAAWA,YAAA,CAAS,MAAM,SAAA,CAAU,OAAO,QAAQ,CAAA;AAEzD,EAAA,MAAM,gBAAA,GAAmB,MAAMH,QAAA,CAAO,gBAAA,KAAqB,KAAA;AAE3D,EAAA,MAAM,gBAAgB,MAAM;AAC1B,IAAA,IAAI,iBAAA,EAAmB;AACvB,IAAA,IAAI,CAAC,kBAAiB,EAAG;AAEzB,IAAA,iBAAA,GAAoB,IAAA;AAEpB,IAAA,OAAA,CAAQ,GAAA;AAAA,MACN,sDAAA;AAAA,MACA,oCAAA;AAAA,MACA,cAAA;AAAA,MACA,yCAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,sBAAsB,MAAM;AAChC,IAAA,IAAI,uBAAA,EAAyB;AAC7B,IAAA,IAAI,CAAC,kBAAiB,EAAG;AAEzB,IAAA,uBAAA,GAA0B,IAAA;AAE1B,IAAA,OAAA,CAAQ,GAAA;AAAA,MACN,6EAAA;AAAA,MACA,oCAAA;AAAA,MACA,cAAA;AAAA,MACA,yCAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,YAAY,YAAY;AAC5B,IAAA,IAAI,CAACA,QAAA,CAAO,KAAA,EAAO,OAAO,IAAA;AAC1B,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAMA,QAAA,CAAO,KAAA,EAAM;AAE/B,MAAA,IAAI,GAAA,IAAQ,GAAA,CAAY,OAAA,KAAY,IAAA,EAAM;AACxC,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,IAAI,CAAC,GAAA,IAAO,EAAE,GAAA,CAAI,iBAAA,IAAsB,IAAY,cAAA,CAAA,EAAiB;AACnE,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,OAAO,GAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AAEN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,kBAAkB,YAAY;AAClC,IAAA,IAAI,CAACA,QAAA,CAAO,WAAA,EAAa,OAAO,IAAA;AAChC,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAMA,QAAA,CAAO,WAAA,EAAY;AAErC,MAAA,IAAI,GAAA,IAAQ,GAAA,CAAY,OAAA,KAAY,IAAA,EAAM;AACxC,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,IAAI,CAAC,GAAA,IAAO,CAAE,GAAA,CAAY,oBAAA,EAAsB;AAC9C,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,OAAO,GAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AAEN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,YAAA,GAAe,OAAO,QAAA,EAAkB,UAAA,GAAa,KAAA,KAAU;AAEnE,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,SAAA,CAAU,KAAA,EAAM;AAChB,QAAA,YAAA,GAAe,EAAA;AAAA,MACjB;AAEA,MAAA,MAAM,SAAA,GAAY,CAAC,UAAA,IAAc,QAAA,CAAS,WAAW,YAAY,CAAA;AACjE,MAAA,IAAI,KAAA,GAAQ,QAAA;AAEZ,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,YAAA,CAAa,MAAM,CAAA;AAAA,MAC5C,CAAA,MAAA,IAAW,CAAC,UAAA,EAAY;AACtB,QAAA,SAAA,CAAU,KAAA,EAAM;AAAA,MAClB;AAEA,MAAA,YAAA,GAAe,QAAA;AAEf,MAAA,IAAI,CAAC,KAAA,EAAO;AACV,QAAA,MAAM,eAAe,CAAC,GAAG,UAAU,YAAA,EAAc,GAAG,UAAU,cAAc,CAAA;AAC5E,QAAA,SAAA,CAAU,KAAA,GAAQ;AAAA,UAChB,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,UAC3B,KAAA,EAAO,aAAa,MAAA,GAAS,kBAAA,CAAmB,YAAY,CAAA,GAAI,CAAC,EAAE,CAAA;AAAA,UACnE,QAAA,EAAU,UAAU,KAAA,EAAO;AAAA,SAC7B;AACA,QAAA;AAAA,MACF;AAEA,MAAA,IAAI;AACF,QAAA,MAAM,SAAA,CAAU,QAAQ,KAAK,CAAA;AAE7B,QAAA,MAAM,eAAe,CAAC,GAAG,UAAU,YAAA,EAAc,GAAG,UAAU,cAAc,CAAA;AAE5E,QAAA,SAAA,CAAU,KAAA,GAAQ;AAAA,UAChB,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,UAC3B,KAAA,EAAO,mBAAmB,YAAY,CAAA;AAAA,UACtC,QAAA,EAAU,UAAU,KAAA,EAAO;AAAA,SAC7B;AAAA,MACF,SAAS,GAAA,EAAK;AAEZ,QAAA,KAAA,CAAM,KAAA,GAAQ,GAAA;AAAA,MAChB;AAAA,IACF,WAAW,WAAA,EAAa;AAGtB,MAAA,IAAI;AACF,QAAA,MAAM,cAAc,eAAA,IAAmB,WAAA;AACvC,QAAA,MAAM,eAAe,cAAA,CAAe,KAAA;AACpC,QAAA,MAAM,MAAA,GAAS,WAAA,CAAY,YAAA,CAAa,QAAA,EAAU;AAAA,UAChD,IAAA,EAAM,WAAA;AAAA,UACN,KAAA,EAAO;AAAA,SACR,CAAA;AAID,QAAA,MAAM,WAAA,GAAe,OAAe,MAAA,IAAU,MAAA;AAE9C,QAAA,SAAA,CAAU,KAAA,GAAQ;AAAA,UAChB,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,UAC3B,KAAA,EAAO,mBAAmB,WAAW,CAAA;AAAA,UACrC,QAAA,EAAU,UAAU,KAAA,EAAO;AAAA,SAC7B;AAAA,MACF,SAAS,GAAA,EAAK;AAEZ,QAAA,SAAA,CAAU,KAAA,GAAQ;AAAA,UAChB,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,UAC3B,OAAO,CAAC,CAAC,EAAE,OAAA,EAAS,QAAA,EAAU,CAAC,CAAA;AAAA,UAC/B,QAAA,EAAU,UAAU,KAAA,EAAO;AAAA,SAC7B;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,kBAAkB,YAAY;AAClC,IAAA,SAAA,CAAU,KAAA,GAAQ,IAAA;AAClB,IAAA,KAAA,CAAM,KAAA,GAAQ,IAAA;AAEd,IAAA,IAAI,cAAc,iBAAA,CAAkB,KAAA;AACpC,IAAA,MAAM,eAAe,cAAA,CAAe,KAAA;AACpC,IAAA,MAAM,QAAA,GAAW,uBAAuB,YAAY,CAAA;AAEpD,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAM,SAAA,EAAU;AAC5B,MAAA,IAAI,CAAC,GAAA,EAAK;AAER,QAAA,SAAA,CAAU,KAAA,GAAQ;AAAA,UAChB,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,UAC3B,KAAA,EAAO,CAAC,CAAC,EAAE,SAAS,IAAA,CAAK,KAAA,EAAO,CAAC,CAAA;AAAA,UACjC,QAAA,EAAU,KAAA;AAAA,SACZ;AACA,QAAA,aAAA,EAAc;AACd,QAAA,mBAAA,EAAoB;AACpB,QAAA;AAAA,MACF;AAIA,MAAA,IAAI,CAAC,gBAAA,CAAiB,GAAA,CAAI,QAAQ,CAAA,EAAG;AACnC,QAAA,WAAA,GAAc,MAAM,IAAI,iBAAA,CAAkB;AAAA,UACxC,MAAA,EAAQ,CAAC,YAAY,CAAA;AAAA,UACrB,OAAO;AAAC;AAAA,SACT,CAAA;AACD,QAAA,gBAAA,CAAiB,GAAA,CAAI,UAAU,WAAW,CAAA;AAAA,MAC5C,CAAA,MAAO;AACL,QAAA,WAAA,GAAc,gBAAA,CAAiB,IAAI,QAAQ,CAAA;AAAA,MAC7C;AAEA,MAAA,iBAAA,GAAoB,WAAA;AAGpB,MAAA,IAAI;AACF,QAAA,MAAM,WAAA,CAAY,aAAa,WAAkB,CAAA;AACjD,QAAA,eAAA,GAAkB,WAAA;AAAA,MACpB,CAAA,CAAA,MAAQ;AACN,QAAA,WAAA,GAAc,WAAA;AACd,QAAA,eAAA,GAAkB,WAAA;AAAA,MACpB;AAGA,MAAA,MAAM,cAAA,GAAiB,MAAM,eAAA,EAAgB;AAC7C,MAAA,IAAI,cAAA,EAAgB;AAClB,QAAA,SAAA,GAAY,IAAI,eAAe,oBAAA,CAAqB;AAAA,UAClD,WAAA;AAAA,UACA,IAAA,EAAM,WAAA;AAAA,UACN,KAAA,EAAO;AAAA,SACR,CAAA;AAAA,MACH,CAAA,MAAO;AAEL,QAAA,mBAAA,EAAoB;AAAA,MACtB;AAEA,MAAA,YAAA,GAAe,EAAA;AAEf,MAAA,MAAM,SAAA,GAAY,WAAA,CAAY,QAAA,CAAS,YAAY,CAAA;AACnD,MAAA,MAAM,aAAA,GAAgB,cAAA,CAAe,SAAA,EAAW,EAAA,EAAI,WAAW,EAAE,CAAA;AAEjE,MAAA,IAAI,KAAK,KAAA,EAAO;AACd,QAAA,MAAM,YAAA,CAAa,IAAA,CAAK,KAAA,EAAO,IAAI,CAAA;AACnC,QAAA,IAAI,UAAU,KAAA,EAAO;AACnB,UAAA,SAAA,CAAU,MAAM,QAAA,GAAW,aAAA;AAAA,QAC7B;AAAA,MACF,CAAA,MAAO;AACL,QAAA,SAAA,CAAU,KAAA,GAAQ;AAAA,UAChB,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,UAC3B,KAAA,EAAO,CAAC,EAAE,CAAA;AAAA,UACV,QAAA,EAAU;AAAA,SACZ;AAAA,MACF;AAAA,IACF,SAAS,GAAA,EAAK;AAEZ,MAAA,SAAA,CAAU,KAAA,GAAQ;AAAA,QAChB,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,QAC3B,KAAA,EAAO,CAAC,CAAC,EAAE,SAAS,IAAA,CAAK,KAAA,EAAO,CAAC,CAAA;AAAA,QACjC,QAAA,EAAU;AAAA,OACZ;AAAA,IACF,CAAA,SAAE;AACA,MAAA,SAAA,CAAU,KAAA,GAAQ,KAAA;AAAA,IACpB;AAAA,EACF,CAAA;AAEA,EAAAM,SAAA;AAAA,IACE,MAAM,CAAC,iBAAA,CAAkB,KAAA,EAAO,eAAe,KAAK,CAAA;AAAA,IACpD,OAAO,CAAC,OAAO,CAAA,KAAM;AACnB,MAAA,MAAM,aAAA,GAAgB,OAAA;AAEtB,MAAA,IACE,eACA,eAAA,KAAoB,WAAA,IACpB,aAAA,KAAkB,iBAAA,IAClB,kBAAkB,WAAA,EAClB;AACA,QAAA,IAAI;AACF,UAAA,MAAM,WAAA,CAAY,aAAa,aAAoB,CAAA;AACnD,UAAA,eAAA,EAAgB;AAChB,UAAA;AAAA,QACF,CAAA,CAAA,MAAQ;AACN,UAAA,iBAAA,GAAoB,aAAA;AACpB,UAAA;AAAA,QACF;AAAA,MACF;AAEA,MAAA,eAAA,EAAgB;AAAA,IAClB,CAAA;AAAA,IACA,EAAE,WAAW,IAAA;AAAK,GACpB;AAEA,EAAAA,SAAA,CAAM,IAAA,EAAM,OAAO,OAAA,KAAY;AAC7B,IAAA,MAAM,gBAAgB,iBAAA,CAAkB,KAAA;AACxC,IAAA,IACE,eACA,eAAA,KAAoB,WAAA,IACpB,aAAA,KAAkB,iBAAA,IAClB,kBAAkB,WAAA,EAClB;AACA,MAAA,IAAI;AACF,QAAA,MAAM,WAAA,CAAY,aAAa,aAAoB,CAAA;AACnD,QAAA,MAAM,eAAA,EAAgB;AACtB,QAAA;AAAA,MACF,CAAA,CAAA,MAAQ;AACN,QAAA,iBAAA,GAAoB,aAAA;AAAA,MACtB;AAAA,IACF;AAEA,IAAA,IAAI,aAAa,WAAA,EAAa;AAG5B,MAAA,YAAA,CAAa,OAAO,CAAA;AAAA,IACtB,CAAA,MAAO;AAEL,MAAA,SAAA,CAAU,KAAA,GAAQ;AAAA,QAChB,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,QAC3B,OAAO,CAAC,CAAC,EAAE,OAAA,EAAS,OAAA,EAAS,CAAC,CAAA;AAAA,QAC9B,QAAA,EAAU,UAAU,KAAA,EAAO;AAAA,OAC7B;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAED,EAAAC,eAAA,CAAY,MAAM;AAChB,IAAA,SAAA,EAAW,KAAA,EAAM;AACjB,IAAA,SAAA,GAAY,IAAA;AACZ,IAAA,YAAA,GAAe,EAAA;AAAA,EACjB,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,SAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
|
package/dist/x-markdown.cjs8.js
CHANGED
|
@@ -1,2 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
|
|
5
|
+
const lodashEs = require('lodash-es');
|
|
6
|
+
|
|
7
|
+
function useProcessMarkdown(markdown) {
|
|
8
|
+
return preprocessLaTeX(markdown);
|
|
9
|
+
}
|
|
10
|
+
function preprocessLaTeX(markdown) {
|
|
11
|
+
if (typeof markdown !== "string") return markdown;
|
|
12
|
+
const codeBlockRegex = /```[\s\S]*?```/g;
|
|
13
|
+
const codeBlocks = markdown.match(codeBlockRegex) || [];
|
|
14
|
+
const escapeReplacement = (str) => str.replace(/\$/g, "_ELX_DOLLAR_");
|
|
15
|
+
let processedMarkdown = markdown.replace(codeBlockRegex, "ELX_CODE_BLOCK_PLACEHOLDER");
|
|
16
|
+
processedMarkdown = lodashEs.flow([
|
|
17
|
+
(str) => str.replace(/\\\[(.*?)\\\]/g, (_, equation) => `$$${equation}$$`),
|
|
18
|
+
(str) => str.replace(/\\\[([\s\S]*?)\\\]/g, (_, equation) => `$$${equation}$$`),
|
|
19
|
+
(str) => str.replace(/\\\((.*?)\\\)/g, (_, equation) => `$$${equation}$$`),
|
|
20
|
+
(str) => str.replace(/(^|[^\\])\$(.+?)\$/g, (_, prefix, equation) => `${prefix}$${equation}$`)
|
|
21
|
+
])(processedMarkdown);
|
|
22
|
+
codeBlocks.forEach((block) => {
|
|
23
|
+
processedMarkdown = processedMarkdown.replace("ELX_CODE_BLOCK_PLACEHOLDER", escapeReplacement(block));
|
|
24
|
+
});
|
|
25
|
+
processedMarkdown = processedMarkdown.replace(/_ELX_DOLLAR_/g, "$");
|
|
26
|
+
return processedMarkdown;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
exports.preprocessLaTeX = preprocessLaTeX;
|
|
30
|
+
exports.useProcessMarkdown = useProcessMarkdown;
|
|
2
31
|
//# sourceMappingURL=x-markdown.cjs8.js.map
|