@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.es4.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":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"x-markdown.es4.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":[],"mappings":";;;AAMO,SAAS,MAAA,CACd,IAAA,EACA,KAAA,EACA,KAAA,EACA,WAAA,EACO;AACP,EAAA,MAAM,aAAwC,EAAC;AAC/C,EAAA,OAAO,CAAA;AAAA,IACL,KAAA;AAAA,IACA,KAAA;AAAA,IACA,cAAA;AAAA,MACE,IAAA,CAAK,QAAA;AAAA,MACL,EAAE,WAAW,EAAA,EAAI,WAAA,EAAa,OAAO,aAAA,EAAe,EAAA,EAAI,KAAK,KAAA,EAAM;AAAA,MACnE,IAAA;AAAA,MACA,SAAS,EAAC;AAAA,MACV,OAAA,CAAQ,WAAW,CAAA,IAAK,EAAC;AAAA,MACzB;AAAA;AACF,GACF;AACF;AAEO,SAAS,eACd,QAAA,EACA,GAAA,EACA,MAAA,EACA,KAAA,EACA,aACA,UAAA,EACoB;AACpB,EAAA,OAAO,QAAA,CAAS,GAAA,CAAI,CAAC,IAAA,KAAS;AAC5B,IAAA,QAAQ,KAAK,IAAA;AAAM,MACjB,KAAK,MAAA;AACH,QAAA,OAAO,IAAA,CAAK,KAAA;AAAA,MACd,KAAK,KAAA;AACH,QAAA,OAAO,IAAA,CAAK,KAAA;AAAA,MACd,KAAK,MAAA;AACH,QAAA,OAAO,eAAe,IAAA,CAAK,QAAA,EAAU,KAAK,MAAA,EAAQ,KAAA,EAAO,aAAa,UAAU,CAAA;AAAA,MAClF,KAAK,SAAA,EAAW;AACd,QAAA,MAAM,EAAE,KAAA,EAAO,OAAA,EAAS,SAAA,EAAW,UAAA,EAAW,GAAI,aAAA,CAAc,IAAA,EAAM,MAAA,EAAQ,GAAA,EAAK,UAAA,EAAY,WAAW,CAAA;AAC1G,QAAA,KAAA,IAAS,IAAI,SAAA,CAAU,MAAA,GAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAC9C,UAAA,MAAM,UAAA,GAAa,KAAA,CAAM,SAAA,CAAU,CAAC,CAAC,CAAA;AACrC,UAAA,IAAI,OAAO,eAAe,UAAA,EAAY;AACpC,YAAA,OAAO,UAAA,CAAW;AAAA,cAChB,GAAG,UAAA;AAAA,cACH,GAAG,KAAA;AAAA,cACH,QAAA,EAAU,MAAM,cAAA,CAAe,IAAA,CAAK,UAAU,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,WAAA,EAAa,UAAU;AAAA,aAC5F,CAAA;AAAA,UACH;AAAA,QACF;AAEA,QAAA,OAAO,CAAA,CAAE,IAAA,CAAK,OAAA,EAAS,KAAA,EAAO,cAAA,CAAe,IAAA,CAAK,QAAA,EAAU,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,WAAA,EAAa,UAAU,CAAC,CAAA;AAAA,MAC5G;AAAA,MACA;AACE,QAAA,OAAO,IAAA;AAAA;AACX,EACF,CAAC,CAAA;AACH;AAEO,SAAS,aAAA,CACd,IAAA,EACA,MAAA,EACA,OAAA,EACA,YACA,WAAA,EAMA;AACA,EAAA,MAAM,YAAuB,EAAC;AAE9B,EAAA,IAAI,QAAiC,EAAC;AACtC,EAAA,MAAM,aAAkC,EAAC;AACzC,EAAA,MAAM,GAAA,GAAM,EAAE,GAAG,OAAA,EAAQ;AAEzB,EAAA,IAAI,IAAA,CAAK,SAAS,SAAA,EAAW;AAC3B,IAAA,SAAA,CAAU,IAAA,CAAK,KAAK,OAAO,CAAA;AAC3B,IAAA,UAAA,CAAW,IAAA,CAAK,OAAO,CAAA,GAAI,IAAA,CAAK,OAAA,IAAW,aAAa,UAAA,CAAW,IAAA,CAAK,OAAO,CAAA,GAAI,CAAA,GAAI,CAAA;AACvF,IAAA,UAAA,CAAW,GAAA,GAAM,GAAG,IAAA,CAAK,OAAO,IAAI,UAAA,CAAW,IAAA,CAAK,OAAO,CAAC,CAAA,CAAA;AAC5D,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA,CAAK,UAAA,IAAc,EAAC;AAEtC,IAAA,IAAI,IAAA,CAAK,YAAY,KAAA,EAAO;AAC1B,MAAA,GAAA,CAAI,GAAA,GAAM,IAAA;AAAA,IACZ;AAEA,IAAA,KAAA,GAAQ,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,UAAU,CAAA,CAAE,MAAA,CAA4B,CAAC,GAAA,EAAK,CAAC,OAAA,EAAS,KAAK,CAAA,KAAM;AAC7F,MAAA,MAAM,WAAW,IAAA,CAAK,GAAA,CAAI,GAAA,GAAM,GAAA,GAAM,MAAM,OAAO,CAAA;AACnD,MAAA,GAAA,CAAI,QAAA,CAAS,SAAS,CAAA,GAAI,KAAA;AAE1B,MAAA,OAAO,GAAA;AAAA,IACT,CAAA,EAAG,EAAE,CAAA;AAEL,IAAA,QAAQ,KAAK,OAAA;AAAS,MACpB,KAAK,IAAA;AAAA,MACL,KAAK,IAAA;AAAA,MACL,KAAK,IAAA;AAAA,MACL,KAAK,IAAA;AAAA,MACL,KAAK,IAAA;AAAA,MACL,KAAK,IAAA;AACH,QAAA,UAAA,CAAW,QAAQ,MAAA,CAAO,UAAA,CAAW,KAAK,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAC,CAAA;AAC1D,QAAA,SAAA,CAAU,KAAK,SAAS,CAAA;AACxB,QAAA;AAAA,MAEF,KAAK,MAAA;AACH,QAAA,UAAA,CAAW,gBAAA,GAAmB,KAAA,CAAM,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA,GACnD,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,CAAC,GAAA,KAAQ,GAAA,CAAI,UAAA,CAAW,WAAW,CAAC,CAAA,GACrD,EAAA;AACJ,QAAA,UAAA,CAAW,QAAA,GAAW,WAAW,gBAAA,GAAmB,UAAA,CAAW,iBAAiB,OAAA,CAAQ,WAAA,EAAa,EAAE,CAAA,GAAI,EAAA;AAC3G,QAAA,UAAA,CAAW,MAAA,GAAS,SAAA,IAAa,MAAA,IAAU,MAAA,CAAO,OAAA,KAAY,KAAA;AAI9D,QAAA,UAAA,CAAW,OAAA,GAAW,IAAA,CAAK,QAAA,CAAS,CAAC,GAAuB,KAAA,IAAS,EAAA;AAErE,QAAA,SAAA,CAAU,IAAA,CAAK,UAAA,CAAW,MAAA,GAAS,aAAA,GAAgB,YAAY,CAAA;AAC/D,QAAA;AAAA,MACF,KAAK,OAAA;AAAA,MACL,KAAK,OAAA;AACH,QAAA,GAAA,CAAI,iBAAiB,IAAA,CAAK,OAAA;AAC1B,QAAA;AAAA,MACF,KAAK,IAAA;AAAA,MACL,KAAK,IAAA;AAAA,MACL,KAAK,IAAA;AACH,QAAA,UAAA,CAAW,MAAA,GAAS,QAAQ,cAAA,KAAmB,OAAA;AAC/C,QAAA;AAAA,MAEF,KAAK,IAAA;AAAA,MACL,KAAK,IAAA;AACH,QAAA,GAAA,CAAI,SAAA,GAAY,QAAQ,SAAA,GAAY,CAAA;AACpC,QAAA,GAAA,CAAI,WAAA,GAAc,KAAK,OAAA,KAAY,IAAA;AACnC,QAAA,GAAA,CAAI,aAAA,GAAgB,EAAA;AACpB,QAAA,UAAA,CAAW,UAAU,GAAA,CAAI,WAAA;AACzB,QAAA,UAAA,CAAW,QAAQ,GAAA,CAAI,SAAA;AAEvB,QAAA,SAAA,CAAU,KAAK,MAAM,CAAA;AACrB,QAAA;AAAA,MAEF,KAAK,IAAA;AACH,QAAA,GAAA,CAAI,aAAA,EAAA;AAEJ,QAAA,UAAA,CAAW,UAAU,GAAA,CAAI,WAAA;AACzB,QAAA,UAAA,CAAW,QAAQ,GAAA,CAAI,SAAA;AACvB,QAAA,UAAA,CAAW,QAAQ,GAAA,CAAI,aAAA;AACvB,QAAA,SAAA,CAAU,KAAK,WAAW,CAAA;AAE1B,QAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAA,IAAI,OAAO,IAAA,CAAK,UAAA,CAAW,WAAW,MAAM,QAAA,EAAU;AACpD,UAAA,SAAA,CAAU,KAAK,CAAA,EAAG,IAAA,CAAK,UAAA,CAAW,WAAW,CAAC,CAAA,CAAE,CAAA;AAChD,UAAA,OAAO,IAAA,CAAK,WAAW,WAAW,CAAA;AAAA,QACpC;AACA,QAAA;AAEA;AAGJ,IAAA,KAAA,GAAQ,YAAA;AAAA,MACN,IAAA;AAAA,MACA,SAAA;AAAA,MACA,UAAA;AAAA,MACA,EAAE,GAAG,KAAA,EAAM;AAAA;AAAA,MACX;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,OAAA,EAAS,GAAA;AAAA,IACT,SAAA;AAAA,IACA;AAAA,GACF;AACF;AAUA,SAAS,YAAA,CACP,IAAA,EACA,SAAA,EACA,UAAA,EACA,OACA,WAAA,EACyB;AACzB,EAAA,MAAM,MAAA,GAAkC;AAAA,IACtC,GAAG;AAAA,GACL;AACA,EAAA,KAAA,IAAS,IAAI,SAAA,CAAU,MAAA,GAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAC9C,IAAA,MAAM,IAAA,GAAO,UAAU,CAAC,CAAA;AAExB,IAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,MAAA,MAAM,UAAA,GAAa,YAAY,IAAI,CAAA;AACnC,MAAA,OAAO;AAAA,QACL,GAAG,MAAA;AAAA,QACH,GAAI,OAAO,UAAA,KAAe,UAAA,GAAa,UAAA,CAAW,IAAA,EAAM,EAAE,GAAG,KAAA,EAAO,GAAG,UAAA,EAAY,CAAA,GAAI;AAAA,OACzF;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;;;;"}
|
package/dist/x-markdown.es5.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import deepmerge from
|
|
2
|
-
import rehypeSanitize, { defaultSchema } from
|
|
3
|
-
import remarkParse from
|
|
4
|
-
import remarkRehype from
|
|
5
|
-
import { unified } from
|
|
6
|
-
import { computed, toValue } from
|
|
1
|
+
import deepmerge from 'deepmerge';
|
|
2
|
+
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
|
|
3
|
+
import remarkParse from 'remark-parse';
|
|
4
|
+
import remarkRehype from 'remark-rehype';
|
|
5
|
+
import { unified } from 'unified';
|
|
6
|
+
import { computed, toValue } from 'vue';
|
|
7
|
+
|
|
7
8
|
function useMarkdownProcessor(options) {
|
|
8
9
|
const processor = computed(() => {
|
|
9
10
|
return createProcessor({
|
|
@@ -33,8 +34,6 @@ function createProcessor(options) {
|
|
|
33
34
|
] : []
|
|
34
35
|
);
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
useMarkdownProcessor
|
|
39
|
-
};
|
|
37
|
+
|
|
38
|
+
export { createProcessor, useMarkdownProcessor };
|
|
40
39
|
//# sourceMappingURL=x-markdown.es5.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es5.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":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"x-markdown.es5.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":[],"mappings":";;;;;;;AAoBO,SAAS,qBAAqB,OAAA,EAEnC;AACA,EAAA,MAAM,SAAA,GAAY,SAAS,MAAM;AAC/B,IAAA,OAAO,eAAA,CAAgB;AAAA,MACrB,UAAA,EAAY,CAAC,WAAA,EAAa,GAAI,QAAQ,OAAA,EAAS,aAAa,CAAA,IAAK,EAAG,CAAA;AAAA,MACpE,aAAA,EAAe,OAAA,CAAQ,OAAA,EAAS,aAAa,CAAA;AAAA,MAC7C,aAAA,EAAe,OAAA,CAAQ,OAAA,EAAS,aAAa,CAAA;AAAA,MAC7C,QAAA,EAAU,OAAA,CAAQ,OAAA,EAAS,QAAQ,CAAA;AAAA,MACnC,eAAA,EAAiB,OAAA,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,OAAO,OAAA,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,UACE,aAAA;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.es6.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { h } from
|
|
2
|
-
import _sfc_main from
|
|
1
|
+
import { h } from 'vue';
|
|
2
|
+
import _sfc_main from './x-markdown.es14.js';
|
|
3
|
+
|
|
3
4
|
function useComponents(props) {
|
|
4
5
|
const components = {
|
|
5
6
|
code: (raw) => h(_sfc_main, {
|
|
@@ -18,7 +19,6 @@ function useComponents(props) {
|
|
|
18
19
|
};
|
|
19
20
|
return components;
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
};
|
|
22
|
+
|
|
23
|
+
export { useComponents };
|
|
24
24
|
//# sourceMappingURL=x-markdown.es6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es6.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":["CodeX"],"mappings":"
|
|
1
|
+
{"version":3,"file":"x-markdown.es6.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":["CodeX"],"mappings":";;;AAyBA,SAAS,cAAc,KAAA,EAA8B;AACnD,EAAA,MAAM,UAAA,GAAa;AAAA,IACjB,IAAA,EAAM,CAAC,GAAA,KACL,CAAA,CAAEA,SAAA,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.es7.js
CHANGED
|
@@ -1,78 +1,10 @@
|
|
|
1
|
-
import { ref, computed, isRef, toValue, watch, onUnmounted } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
return __X_MARKDOWN_CONSOLE_HINTS_ENABLED__;
|
|
5
|
-
}
|
|
6
|
-
return true;
|
|
7
|
-
};
|
|
8
|
-
let shikiModulePromise = null;
|
|
9
|
-
let shikiStreamModulePromise = null;
|
|
1
|
+
import { ref, computed, isRef, toValue, watch, onUnmounted } from 'vue';
|
|
2
|
+
import { useXMarkdownConfig } from './x-markdown.es12.js';
|
|
3
|
+
|
|
10
4
|
let hasShownShikiHint = false;
|
|
11
5
|
let hasShownShikiStreamHint = false;
|
|
12
6
|
const highlighterCache = /* @__PURE__ */ new Map();
|
|
13
7
|
const getHighlighterCacheKey = (theme) => `highlighter-${theme}`;
|
|
14
|
-
const showShikiHint = () => {
|
|
15
|
-
if (hasShownShikiHint) return;
|
|
16
|
-
if (!consoleHintsEnabled()) return;
|
|
17
|
-
hasShownShikiHint = true;
|
|
18
|
-
console.log(
|
|
19
|
-
"%c[x-markdown]%c 需安装 shiki: %cpnpm add shiki%c",
|
|
20
|
-
"font-weight: bold; color: #0066cc;",
|
|
21
|
-
"color: #666;",
|
|
22
|
-
"color: #00aa00; font-family: monospace;",
|
|
23
|
-
"color: #999;"
|
|
24
|
-
);
|
|
25
|
-
};
|
|
26
|
-
const showShikiStreamHint = () => {
|
|
27
|
-
if (hasShownShikiStreamHint) return;
|
|
28
|
-
if (!consoleHintsEnabled()) return;
|
|
29
|
-
hasShownShikiStreamHint = true;
|
|
30
|
-
console.log(
|
|
31
|
-
"%c[x-markdown]%c AI 流式可选: %cpnpm add shiki-stream%c (需先装 shiki)",
|
|
32
|
-
"font-weight: bold; color: #0066cc;",
|
|
33
|
-
"color: #666;",
|
|
34
|
-
"color: #00aa00; font-family: monospace;",
|
|
35
|
-
"color: #999;"
|
|
36
|
-
);
|
|
37
|
-
};
|
|
38
|
-
const loadShiki = async () => {
|
|
39
|
-
if (!shikiModulePromise) {
|
|
40
|
-
shikiModulePromise = (async () => {
|
|
41
|
-
try {
|
|
42
|
-
const mod = await import("shiki");
|
|
43
|
-
if (mod && mod.default === null) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
if (!mod || !(mod.createHighlighter || mod.getHighlighter)) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
return mod;
|
|
50
|
-
} catch {
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
})();
|
|
54
|
-
}
|
|
55
|
-
return shikiModulePromise;
|
|
56
|
-
};
|
|
57
|
-
const loadShikiStream = async () => {
|
|
58
|
-
if (!shikiStreamModulePromise) {
|
|
59
|
-
shikiStreamModulePromise = (async () => {
|
|
60
|
-
try {
|
|
61
|
-
const mod = await import("shiki-stream");
|
|
62
|
-
if (mod && mod.default === null) {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
if (!mod || !mod.ShikiStreamTokenizer) {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
return mod;
|
|
69
|
-
} catch {
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
})();
|
|
73
|
-
}
|
|
74
|
-
return shikiStreamModulePromise;
|
|
75
|
-
};
|
|
76
8
|
const tokensToLineTokens = (tokens) => {
|
|
77
9
|
if (!tokens.length) return [[]];
|
|
78
10
|
if (Array.isArray(tokens[0])) {
|
|
@@ -117,6 +49,7 @@ const createPreStyle = (bg, fg) => {
|
|
|
117
49
|
};
|
|
118
50
|
};
|
|
119
51
|
function useHighlight(text, options) {
|
|
52
|
+
const config = useXMarkdownConfig();
|
|
120
53
|
const streaming = ref();
|
|
121
54
|
const isLoading = ref(false);
|
|
122
55
|
const error = ref(null);
|
|
@@ -134,6 +67,61 @@ function useHighlight(text, options) {
|
|
|
134
67
|
});
|
|
135
68
|
const lines = computed(() => streaming.value?.lines || [[]]);
|
|
136
69
|
const preStyle = computed(() => streaming.value?.preStyle);
|
|
70
|
+
const showConsoleHints = () => config.showConsoleHints !== false;
|
|
71
|
+
const showShikiHint = () => {
|
|
72
|
+
if (hasShownShikiHint) return;
|
|
73
|
+
if (!showConsoleHints()) return;
|
|
74
|
+
hasShownShikiHint = true;
|
|
75
|
+
console.log(
|
|
76
|
+
"%c[x-markdown]%c 需配置 shikiLoader: %cpnpm add shiki%c",
|
|
77
|
+
"font-weight: bold; color: #0066cc;",
|
|
78
|
+
"color: #666;",
|
|
79
|
+
"color: #00aa00; font-family: monospace;",
|
|
80
|
+
"color: #999;"
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
const showShikiStreamHint = () => {
|
|
84
|
+
if (hasShownShikiStreamHint) return;
|
|
85
|
+
if (!showConsoleHints()) return;
|
|
86
|
+
hasShownShikiStreamHint = true;
|
|
87
|
+
console.log(
|
|
88
|
+
"%c[x-markdown]%c AI 流式可选: %cpnpm add shiki-stream%c (需配置 shikiStreamLoader)",
|
|
89
|
+
"font-weight: bold; color: #0066cc;",
|
|
90
|
+
"color: #666;",
|
|
91
|
+
"color: #00aa00; font-family: monospace;",
|
|
92
|
+
"color: #999;"
|
|
93
|
+
);
|
|
94
|
+
};
|
|
95
|
+
const loadShiki = async () => {
|
|
96
|
+
if (!config.shiki) return null;
|
|
97
|
+
try {
|
|
98
|
+
const mod = await config.shiki();
|
|
99
|
+
if (mod && mod.default === null) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
if (!mod || !(mod.createHighlighter || mod.getHighlighter)) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
return mod;
|
|
106
|
+
} catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const loadShikiStream = async () => {
|
|
111
|
+
if (!config.shikiStream) return null;
|
|
112
|
+
try {
|
|
113
|
+
const mod = await config.shikiStream();
|
|
114
|
+
if (mod && mod.default === null) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
if (!mod || !mod.ShikiStreamTokenizer) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
return mod;
|
|
121
|
+
} catch {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
137
125
|
const updateTokens = async (nextText, forceReset = false) => {
|
|
138
126
|
if (tokenizer) {
|
|
139
127
|
if (forceReset) {
|
|
@@ -314,7 +302,6 @@ function useHighlight(text, options) {
|
|
|
314
302
|
error
|
|
315
303
|
};
|
|
316
304
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
};
|
|
305
|
+
|
|
306
|
+
export { useHighlight };
|
|
320
307
|
//# sourceMappingURL=x-markdown.es7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es7.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":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"x-markdown.es7.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":[],"mappings":"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"}
|
package/dist/x-markdown.es8.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { flow } from
|
|
1
|
+
import { flow } from 'lodash-es';
|
|
2
|
+
|
|
2
3
|
function useProcessMarkdown(markdown) {
|
|
3
4
|
return preprocessLaTeX(markdown);
|
|
4
5
|
}
|
|
@@ -20,8 +21,6 @@ function preprocessLaTeX(markdown) {
|
|
|
20
21
|
processedMarkdown = processedMarkdown.replace(/_ELX_DOLLAR_/g, "$");
|
|
21
22
|
return processedMarkdown;
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
useProcessMarkdown
|
|
26
|
-
};
|
|
24
|
+
|
|
25
|
+
export { preprocessLaTeX, useProcessMarkdown };
|
|
27
26
|
//# sourceMappingURL=x-markdown.es8.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es8.js","sources":["../src/hooks/useMarkdown.ts"],"sourcesContent":["import { flow } from 'lodash-es'\r\n\r\nexport function useProcessMarkdown(markdown: string) {\r\n return preprocessLaTeX(markdown)\r\n}\r\n\r\nexport function preprocessLaTeX(markdown: string) {\r\n if (typeof markdown !== 'string') return markdown\r\n\r\n const codeBlockRegex = /```[\\s\\S]*?```/g\r\n const codeBlocks = markdown.match(codeBlockRegex) || []\r\n const escapeReplacement = (str: string) => str.replace(/\\$/g, '_ELX_DOLLAR_')\r\n let processedMarkdown = markdown.replace(codeBlockRegex, 'ELX_CODE_BLOCK_PLACEHOLDER')\r\n\r\n processedMarkdown = flow([\r\n (str: string) => str.replace(/\\\\\\[(.*?)\\\\\\]/g, (_, equation) => `$$${equation}$$`),\r\n (str: string) => str.replace(/\\\\\\[([\\s\\S]*?)\\\\\\]/g, (_, equation) => `$$${equation}$$`),\r\n (str: string) => str.replace(/\\\\\\((.*?)\\\\\\)/g, (_, equation) => `$$${equation}$$`),\r\n (str: string) => str.replace(/(^|[^\\\\])\\$(.+?)\\$/g, (_, prefix, equation) => `${prefix}$${equation}$`),\r\n ])(processedMarkdown)\r\n\r\n codeBlocks.forEach((block) => {\r\n processedMarkdown = processedMarkdown.replace('ELX_CODE_BLOCK_PLACEHOLDER', escapeReplacement(block))\r\n })\r\n\r\n processedMarkdown = processedMarkdown.replace(/_ELX_DOLLAR_/g, '$')\r\n\r\n return processedMarkdown\r\n}\r\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"x-markdown.es8.js","sources":["../src/hooks/useMarkdown.ts"],"sourcesContent":["import { flow } from 'lodash-es'\r\n\r\nexport function useProcessMarkdown(markdown: string) {\r\n return preprocessLaTeX(markdown)\r\n}\r\n\r\nexport function preprocessLaTeX(markdown: string) {\r\n if (typeof markdown !== 'string') return markdown\r\n\r\n const codeBlockRegex = /```[\\s\\S]*?```/g\r\n const codeBlocks = markdown.match(codeBlockRegex) || []\r\n const escapeReplacement = (str: string) => str.replace(/\\$/g, '_ELX_DOLLAR_')\r\n let processedMarkdown = markdown.replace(codeBlockRegex, 'ELX_CODE_BLOCK_PLACEHOLDER')\r\n\r\n processedMarkdown = flow([\r\n (str: string) => str.replace(/\\\\\\[(.*?)\\\\\\]/g, (_, equation) => `$$${equation}$$`),\r\n (str: string) => str.replace(/\\\\\\[([\\s\\S]*?)\\\\\\]/g, (_, equation) => `$$${equation}$$`),\r\n (str: string) => str.replace(/\\\\\\((.*?)\\\\\\)/g, (_, equation) => `$$${equation}$$`),\r\n (str: string) => str.replace(/(^|[^\\\\])\\$(.+?)\\$/g, (_, prefix, equation) => `${prefix}$${equation}$`),\r\n ])(processedMarkdown)\r\n\r\n codeBlocks.forEach((block) => {\r\n processedMarkdown = processedMarkdown.replace('ELX_CODE_BLOCK_PLACEHOLDER', escapeReplacement(block))\r\n })\r\n\r\n processedMarkdown = processedMarkdown.replace(/_ELX_DOLLAR_/g, '$')\r\n\r\n return processedMarkdown\r\n}\r\n"],"names":[],"mappings":";;AAEO,SAAS,mBAAmB,QAAA,EAAkB;AACnD,EAAA,OAAO,gBAAgB,QAAQ,CAAA;AACjC;AAEO,SAAS,gBAAgB,QAAA,EAAkB;AAChD,EAAA,IAAI,OAAO,QAAA,KAAa,QAAA,EAAU,OAAO,QAAA;AAEzC,EAAA,MAAM,cAAA,GAAiB,iBAAA;AACvB,EAAA,MAAM,UAAA,GAAa,QAAA,CAAS,KAAA,CAAM,cAAc,KAAK,EAAC;AACtD,EAAA,MAAM,oBAAoB,CAAC,GAAA,KAAgB,GAAA,CAAI,OAAA,CAAQ,OAAO,cAAc,CAAA;AAC5E,EAAA,IAAI,iBAAA,GAAoB,QAAA,CAAS,OAAA,CAAQ,cAAA,EAAgB,4BAA4B,CAAA;AAErF,EAAA,iBAAA,GAAoB,IAAA,CAAK;AAAA,IACvB,CAAC,GAAA,KAAgB,GAAA,CAAI,OAAA,CAAQ,gBAAA,EAAkB,CAAC,CAAA,EAAG,QAAA,KAAa,CAAA,EAAA,EAAK,QAAQ,CAAA,EAAA,CAAI,CAAA;AAAA,IACjF,CAAC,GAAA,KAAgB,GAAA,CAAI,OAAA,CAAQ,qBAAA,EAAuB,CAAC,CAAA,EAAG,QAAA,KAAa,CAAA,EAAA,EAAK,QAAQ,CAAA,EAAA,CAAI,CAAA;AAAA,IACtF,CAAC,GAAA,KAAgB,GAAA,CAAI,OAAA,CAAQ,gBAAA,EAAkB,CAAC,CAAA,EAAG,QAAA,KAAa,CAAA,EAAA,EAAK,QAAQ,CAAA,EAAA,CAAI,CAAA;AAAA,IACjF,CAAC,GAAA,KAAgB,GAAA,CAAI,OAAA,CAAQ,qBAAA,EAAuB,CAAC,CAAA,EAAG,MAAA,EAAQ,QAAA,KAAa,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,CAAG;AAAA,GACtG,EAAE,iBAAiB,CAAA;AAEpB,EAAA,UAAA,CAAW,OAAA,CAAQ,CAAC,KAAA,KAAU;AAC5B,IAAA,iBAAA,GAAoB,iBAAA,CAAkB,OAAA,CAAQ,4BAAA,EAA8B,iBAAA,CAAkB,KAAK,CAAC,CAAA;AAAA,EACtG,CAAC,CAAA;AAED,EAAA,iBAAA,GAAoB,iBAAA,CAAkB,OAAA,CAAQ,eAAA,EAAiB,GAAG,CAAA;AAElE,EAAA,OAAO,iBAAA;AACT;;;;"}
|
package/dist/x-markdown.es9.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { throttle } from
|
|
2
|
-
import { computed, ref, watch, onUnmounted } from
|
|
1
|
+
import { throttle } from 'lodash-es';
|
|
2
|
+
import { computed, ref, watch, onUnmounted } from 'vue';
|
|
3
|
+
import { useXMarkdownConfig } from './x-markdown.es12.js';
|
|
4
|
+
|
|
3
5
|
const consoleHintsEnabled = () => {
|
|
4
6
|
if (typeof __X_MARKDOWN_CONSOLE_HINTS_ENABLED__ === "boolean") {
|
|
5
7
|
return __X_MARKDOWN_CONSOLE_HINTS_ENABLED__;
|
|
@@ -76,14 +78,14 @@ const showMermaidHint = () => {
|
|
|
76
78
|
if (!consoleHintsEnabled()) return;
|
|
77
79
|
hasShownMermaidHint = true;
|
|
78
80
|
console.log(
|
|
79
|
-
"%c[x-markdown]%c 图表可选: %cpnpm add mermaid%c",
|
|
81
|
+
"%c[x-markdown]%c 图表可选: %cpnpm add mermaid%c (需配置 mermaidLoader)",
|
|
80
82
|
"font-weight: bold; color: #9333ea;",
|
|
81
83
|
"color: #666;",
|
|
82
84
|
"color: #9333ea; font-family: monospace;",
|
|
83
85
|
"color: #999;"
|
|
84
86
|
);
|
|
85
87
|
};
|
|
86
|
-
async function checkMermaidAvailable() {
|
|
88
|
+
async function checkMermaidAvailable(loader) {
|
|
87
89
|
if (mermaidAvailableCache !== null) {
|
|
88
90
|
return mermaidAvailableCache;
|
|
89
91
|
}
|
|
@@ -92,7 +94,12 @@ async function checkMermaidAvailable() {
|
|
|
92
94
|
}
|
|
93
95
|
mermaidCheckPromise = (async () => {
|
|
94
96
|
try {
|
|
95
|
-
|
|
97
|
+
if (!loader) {
|
|
98
|
+
mermaidAvailableCache = false;
|
|
99
|
+
showMermaidHint();
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
const mod = await loader();
|
|
96
103
|
const mermaidInstance = mod?.default;
|
|
97
104
|
const hasMermaidAPI = mermaidInstance && (typeof mermaidInstance.render === "function" || typeof mermaidInstance.initialize === "function" || typeof mermaidInstance.run === "function");
|
|
98
105
|
mermaidAvailableCache = hasMermaidAPI;
|
|
@@ -108,12 +115,16 @@ async function checkMermaidAvailable() {
|
|
|
108
115
|
})();
|
|
109
116
|
return mermaidCheckPromise;
|
|
110
117
|
}
|
|
111
|
-
async function loadMermaid() {
|
|
118
|
+
async function loadMermaid(loader) {
|
|
112
119
|
if (typeof window === "undefined") return null;
|
|
113
120
|
if (!mermaidPromise) {
|
|
114
121
|
mermaidPromise = (async () => {
|
|
115
122
|
try {
|
|
116
|
-
|
|
123
|
+
if (!loader) {
|
|
124
|
+
showMermaidHint();
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
const mod = await loader();
|
|
117
128
|
if (mod && mod.default === null) {
|
|
118
129
|
showMermaidHint();
|
|
119
130
|
return null;
|
|
@@ -154,6 +165,7 @@ function addToRenderQueue(task) {
|
|
|
154
165
|
processRenderQueue();
|
|
155
166
|
}
|
|
156
167
|
function useMermaid(content, options = {}) {
|
|
168
|
+
const config = useXMarkdownConfig();
|
|
157
169
|
const optionsRef = computed(() => typeof options === "object" && "value" in options ? options.value : options);
|
|
158
170
|
const mermaidConfig = computed(() => ({
|
|
159
171
|
suppressErrorRendering: true,
|
|
@@ -186,7 +198,7 @@ function useMermaid(content, options = {}) {
|
|
|
186
198
|
addToRenderQueue(async () => {
|
|
187
199
|
if (isUnmounted) return;
|
|
188
200
|
try {
|
|
189
|
-
const mermaidInstance = await loadMermaid();
|
|
201
|
+
const mermaidInstance = await loadMermaid(config.mermaid);
|
|
190
202
|
if (!mermaidInstance) {
|
|
191
203
|
data.value = contentValue;
|
|
192
204
|
error.value = null;
|
|
@@ -412,10 +424,6 @@ function useMermaidZoom(options) {
|
|
|
412
424
|
initialize
|
|
413
425
|
};
|
|
414
426
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
downloadSvgAsPng,
|
|
418
|
-
useMermaid,
|
|
419
|
-
useMermaidZoom
|
|
420
|
-
};
|
|
427
|
+
|
|
428
|
+
export { checkMermaidAvailable, downloadSvgAsPng, useMermaid, useMermaidZoom };
|
|
421
429
|
//# sourceMappingURL=x-markdown.es9.js.map
|