@hejiayue/x-markdown-test 0.0.1-beta.132 → 0.0.1-beta.134
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/x-markdown.cjs19.js +1 -1
- package/dist/x-markdown.cjs24.js +1 -1
- package/dist/x-markdown.cjs24.js.map +1 -1
- package/dist/x-markdown.cjs27.js +1 -1
- package/dist/x-markdown.cjs27.js.map +1 -1
- package/dist/x-markdown.cjs29.js +2 -0
- package/dist/x-markdown.cjs29.js.map +1 -0
- package/dist/x-markdown.cjs33.js +1 -1
- package/dist/x-markdown.cjs7.js +1 -1
- package/dist/x-markdown.cjs7.js.map +1 -1
- package/dist/x-markdown.es19.js +1 -1
- package/dist/x-markdown.es24.js +2 -2
- package/dist/x-markdown.es24.js.map +1 -1
- package/dist/x-markdown.es27.js +139 -5
- package/dist/x-markdown.es27.js.map +1 -1
- package/dist/x-markdown.es29.js +8 -0
- package/dist/x-markdown.es29.js.map +1 -0
- package/dist/x-markdown.es33.js +1 -1
- package/dist/x-markdown.es7.js +57 -35
- package/dist/x-markdown.es7.js.map +1 -1
- package/package.json +13 -2
- package/dist/x-markdown.cjs28.js +0 -2
- package/dist/x-markdown.cjs28.js.map +0 -1
- package/dist/x-markdown.es28.js +0 -142
- package/dist/x-markdown.es28.js.map +0 -1
package/dist/x-markdown.cjs19.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),o=require("./x-markdown.cjs26.js"),l=require("./x-markdown.
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),o=require("./x-markdown.cjs26.js"),l=require("./x-markdown.cjs29.js"),a={class:"x-md-code-header"},t={class:"x-md-code-header__left"},c=["title"],n={class:"x-md-code-lang"},d={class:"x-md-code-header__right"},r=["title","disabled","onClick"],s={key:0,class:"x-md-copy-icon",width:"16",height:"16",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 1024 1024"},i={key:1,class:"x-md-copy-icon",width:"16",height:"16",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 1024 1024"},u=e.defineComponent({name:"CodeBlock",__name:"index",props:{code:{},language:{},lightTheme:{default:"vitesse-light"},darkTheme:{default:"vitesse-dark"},isDark:{type:Boolean,default:!1},colorReplacements:{},codeMaxHeight:{},showCodeBlockHeader:{type:Boolean,default:!0},enableAnimate:{type:Boolean,default:!1},codeBlockActions:{default:void 0},stickyCodeBlockHeader:{type:Boolean,default:!0}},setup(u,{expose:m}){const{copy:p,copied:k}=o.useClipboard({copiedDuring:2e3}),h=e.ref(!1),v=e.ref(null),g=()=>{h.value=!h.value},f=u,x=e.computed(()=>f.code.trim()),y=e.computed(()=>f.language||"text"),B=e.computed(()=>f.codeBlockActions||[]),C=e.computed(()=>B.value.filter(e=>!e.show||e.show(b.value))),b=e.computed(()=>({language:y.value,code:x.value,copy:p,copied:k.value,collapsed:h.value,toggleCollapse:g}));function w(o){if(!o.icon)return null;if("string"==typeof o.icon)return e.h("span",{class:"x-md-action-icon",innerHTML:o.icon});if("function"==typeof o.icon){try{const e=o.icon(b.value);if(e&&"object"==typeof e&&"__v_isVNode"in e)return e}catch{}return e.h(o.icon)}return e.h(o.icon)}return m({copy:p,copied:k,collapsed:h,toggleCollapse:g,syntaxCodeBlockRef:v}),(o,m)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["x-md-code-block",{"x-md-code-block--dark":f.isDark}])},[u.showCodeBlockHeader?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["x-md-code-header-wrapper",[{"x-md-code-header-wrapper--sticky":f.stickyCodeBlockHeader},{"x-md-code-header-wrapper--collapsed":h.value}]])},[e.createElementVNode("div",a,[e.renderSlot(o.$slots,"codeHeader",{language:y.value,code:x.value,copy:e.unref(p),copied:e.unref(k),collapsed:h.value,toggleCollapse:g},()=>[e.createElementVNode("div",t,[e.createElementVNode("button",{class:e.normalizeClass(["x-md-collapse-btn",{"x-md-collapse-btn--collapsed":h.value}]),onClick:g,title:h.value?"展开代码":"折叠代码"},[...m[1]||(m[1]=[e.createElementVNode("svg",{class:"x-md-collapse-icon",viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e.createElementVNode("polyline",{points:"6 9 12 15 18 9"})],-1)])],10,c),e.createElementVNode("span",n,e.toDisplayString(y.value),1)]),e.createElementVNode("div",d,[e.renderSlot(o.$slots,"codeActions",{code:x.value,copy:e.unref(p),copied:e.unref(k)},()=>[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(C.value,o=>(e.openBlock(),e.createElementBlock("button",{key:o.key,class:e.normalizeClass(["x-md-action-btn",[o.class,{"x-md-action-btn--disabled":o.disabled}]]),style:e.normalizeStyle(o.style),title:o.title,disabled:o.disabled,onClick:e=>function(e){e.disabled||e.onClick?.(b.value)}(o)},[o.icon?(e.openBlock(),e.createBlock(e.resolveDynamicComponent(w(o)),{key:0})):e.createCommentVNode("",!0)],14,r))),128)),e.createElementVNode("button",{class:e.normalizeClass(["x-md-copy-btn",{"x-md-copy-btn--copied":e.unref(k)}]),onClick:m[0]||(m[0]=o=>e.unref(p)(x.value))},[e.unref(k)?(e.openBlock(),e.createElementBlock("svg",s,[...m[2]||(m[2]=[e.createElementVNode("path",{fill:"currentColor",d:"M406.656 706.944 195.84 496.256a32 32 0 1 0-45.248 45.248l256 256 512-512a32 32 0 0 0-45.248-45.248L406.592 706.944z"},null,-1)])])):(e.openBlock(),e.createElementBlock("svg",i,[...m[3]||(m[3]=[e.createElementVNode("path",{fill:"currentColor",d:"M768 832a128 128 0 0 1-128 128H192A128 128 0 0 1 64 832V384a128 128 0 0 1 128-128v64a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64z"},null,-1),e.createElementVNode("path",{fill:"currentColor",d:"M384 128a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64V192a64 64 0 0 0-64-64zm0-64h448a128 128 0 0 1 128 128v448a128 128 0 0 1-128 128H384a128 128 0 0 1-128-128V192A128 128 0 0 1 384 64"},null,-1)])]))],2)],!0)])],!0)])],2)):e.createCommentVNode("",!0),e.createElementVNode("div",{class:e.normalizeClass(["x-md-code-body",{"x-md-code-body--collapsed":h.value}])},[e.createVNode(l.default,{ref_key:"syntaxCodeBlockRef",ref:v,code:x.value,language:y.value,"light-theme":f.lightTheme,"dark-theme":f.darkTheme,"is-dark":f.isDark,"color-replacements":f.colorReplacements,"code-max-height":f.codeMaxHeight,"enable-animate":f.enableAnimate},null,8,["code","language","light-theme","dark-theme","is-dark","color-replacements","code-max-height","enable-animate"])],2)],2))}});exports.default=u;
|
|
2
2
|
//# sourceMappingURL=x-markdown.cjs19.js.map
|
package/dist/x-markdown.cjs24.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),t=require("./x-markdown.cjs26.js"),o=require("./x-markdown.cjs9.js"),a=require("./x-markdown.
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),t=require("./x-markdown.cjs26.js"),o=require("./x-markdown.cjs9.js"),a=require("./x-markdown.cjs27.js");;/* empty css */const l=require("./x-markdown.cjs17.js"),n={class:"toolbar-container"},r={class:"mermaid-toolbar"},i={class:"toolbar-left"},c={class:"segmented-control"},d={class:"toolbar-right"},s=["title","onClick"],u={key:0,width:"16",height:"16",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 1024 1024"},m={key:1,width:"16",height:"16",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 1024 1024"},v={class:"mermaid-source-code"},h=e.defineComponent({__name:"index",props:{isDark:{type:Boolean,default:!1},shikiTheme:{default:()=>["vitesse-light","vitesse-dark"]},config:{default:()=>({})},mermaidActions:{default:void 0},raw:{default:()=>({})}},setup(h){const k=h,w=e.ref(null),p=e.ref(!1),g=e.ref(!0),f=e.computed(()=>k.raw?.content||""),V=e.computed(()=>`mermaid-${k.raw?.key||"default"}`),C=e.computed(()=>w.value?.isLoading??!0),E=e.computed(()=>w.value?.svg??""),N=e.computed(()=>p.value?"code":"diagram");function y(e){e?.stopPropagation(),e?.preventDefault(),p.value||w.value?.zoomIn()}function b(e){e?.stopPropagation(),e?.preventDefault(),p.value||w.value?.zoomOut()}function B(e){e?.stopPropagation(),e?.preventDefault(),p.value||w.value?.reset()}function x(){p.value||w.value?.fullscreen()}function z(){p.value=!p.value}const{copy:L,copied:M}=t.useClipboard({copiedDuring:1500});function j(e){"code"!==e||p.value?"diagram"===e&&p.value&&(p.value=!1):p.value=!0}async function D(e){e?.stopPropagation(),e?.preventDefault(),M.value||k.raw.content&&await L(k.raw.content)}function P(){w.value?.download()}const S=e.computed(()=>k.mermaidActions||[]),_=e.computed(()=>S.value.filter(e=>!e.show||e.show(H.value))),H=e.computed(()=>({showSourceCode:p.value,svg:E.value,rawContent:k.raw.content||"",isLoading:C.value,copied:M.value,zoomIn:y,zoomOut:b,reset:B,fullscreen:x,toggleCode:z,copyCode:D,download:P,raw:k.raw}));function T(t){if(!t.icon)return null;if("string"==typeof t.icon)return e.h("span",{class:"mermaid-action-icon",innerHTML:t.icon});if("function"==typeof t.icon){try{const e=t.icon(H.value);if(e&&"object"==typeof e&&"__v_isVNode"in e)return e}catch{}return e.h(t.icon)}return e.h(t.icon)}const q=e.computed(()=>({showSourceCode:p.value,svg:E.value,rawContent:k.raw.content||"",isLoading:C.value,copied:M.value,zoomIn:y,zoomOut:b,reset:B,fullscreen:x,toggleCode:z,copyCode:D,download:P,raw:k.raw}));return e.onMounted(async()=>{const e=await o.checkMermaidAvailable();g.value=!e}),(t,o)=>g.value?(e.openBlock(),e.createBlock(l.default,{key:0,code:k.raw?.content||"",language:"mermaid","is-dark":k.isDark,"light-theme":k.shikiTheme[0],"dark-theme":k.shikiTheme[1]},null,8,["code","is-dark","light-theme","dark-theme"])):(e.openBlock(),e.createElementBlock("div",{key:k.raw.key,class:e.normalizeClass(["markdown-mermaid",{"markdown-mermaid--dark":k.isDark}])},[e.createVNode(e.Transition,{name:"toolbar",appear:""},{default:e.withCtx(()=>[e.createElementVNode("div",n,[e.renderSlot(t.$slots,"mermaidHeader",e.normalizeProps(e.guardReactiveProps(q.value)),()=>[e.createElementVNode("div",r,[e.createElementVNode("div",i,[e.createElementVNode("div",c,[e.createElementVNode("div",{class:e.normalizeClass(["segmented-slider",{"slide-right":"code"===N.value}])},null,2),e.createElementVNode("div",{class:e.normalizeClass(["segment-item",{active:"diagram"===N.value}]),onClick:o[0]||(o[0]=e=>j("diagram"))},[...o[6]||(o[6]=[e.createElementVNode("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[e.createElementVNode("path",{d:"M12 2L2 7L12 12L22 7L12 2Z",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"}),e.createElementVNode("path",{d:"M2 17L12 22L22 17",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"}),e.createElementVNode("path",{d:"M2 12L12 17L22 12",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"})],-1),e.createElementVNode("span",null,"预览",-1)])],2),e.createElementVNode("div",{class:e.normalizeClass(["segment-item",{active:"code"===N.value}]),onClick:o[1]||(o[1]=e=>j("code"))},[...o[7]||(o[7]=[e.createElementVNode("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[e.createElementVNode("path",{d:"M16 18L22 12L16 6",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"}),e.createElementVNode("path",{d:"M8 6L2 12L8 18",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"})],-1),e.createElementVNode("span",null,"代码",-1)])],2)])]),e.createElementVNode("div",d,[e.renderSlot(t.$slots,"mermaidActions",e.normalizeProps(e.guardReactiveProps(q.value)),()=>[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(_.value,t=>(e.openBlock(),e.createElementBlock("div",{key:t.key,class:e.normalizeClass(["toolbar-action-btn",[t.class,{"toolbar-action-btn--disabled":t.disabled}]]),style:e.normalizeStyle(t.style),title:t.title,onClick:e=>function(e){e.disabled||e.onClick?.(H.value)}(t)},[t.icon?(e.openBlock(),e.createBlock(e.resolveDynamicComponent(T(t)),{key:0})):e.createCommentVNode("",!0)],14,s))),128)),p.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["toolbar-action-btn",{"copy-success":e.unref(M)}]),title:"复制代码",onClick:o[2]||(o[2]=e=>D(e))},[e.unref(M)?(e.openBlock(),e.createElementBlock("svg",u,[...o[8]||(o[8]=[e.createElementVNode("path",{fill:"currentColor",d:"M406.656 706.944 195.84 496.256a32 32 0 1 0-45.248 45.248l256 256 512-512a32 32 0 0 0-45.248-45.248L406.592 706.944z"},null,-1)])])):(e.openBlock(),e.createElementBlock("svg",m,[...o[9]||(o[9]=[e.createElementVNode("path",{fill:"currentColor",d:"M768 832a128 128 0 0 1-128 128H192A128 128 0 0 1 64 832V384a128 128 0 0 1 128-128v64a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64z"},null,-1),e.createElementVNode("path",{fill:"currentColor",d:"M384 128a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64V192a64 64 0 0 0-64-64zm0-64h448a128 128 0 0 1 128 128v448a128 128 0 0 1-128 128H384a128 128 0 0 1-128-128V192A128 128 0 0 1 384 64"},null,-1)])]))],2)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createElementVNode("div",{class:"toolbar-action-btn",title:"缩小",onClick:o[3]||(o[3]=e=>b(e))},[...o[10]||(o[10]=[e.createElementVNode("svg",{width:"16",height:"16",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 1024 1024"},[e.createElementVNode("path",{fill:"currentColor",d:"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704M352 448h256a32 32 0 0 1 0 64H352a32 32 0 0 1 0-64"})],-1)])]),e.createElementVNode("div",{class:"toolbar-action-btn",title:"放大",onClick:o[4]||(o[4]=e=>y(e))},[...o[11]||(o[11]=[e.createElementVNode("svg",{width:"16",height:"16",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 1024 1024"},[e.createElementVNode("path",{fill:"currentColor",d:"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704m-32-384v-96a32 32 0 0 1 64 0v96h96a32 32 0 0 1 0 64h-96v96a32 32 0 0 1-64 0v-96h-96a32 32 0 0 1 0-64z"})],-1)])]),e.createElementVNode("div",{class:"toolbar-action-btn",title:"重置",onClick:o[5]||(o[5]=e=>B(e))},[...o[12]||(o[12]=[e.createElementVNode("svg",{width:"16",height:"16",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 1024 1024"},[e.createElementVNode("path",{fill:"currentColor",d:"M512 896a384 384 0 1 0 0-768 384 384 0 0 0 0 768m0 64a448 448 0 1 1 0-896 448 448 0 0 1 0 896"}),e.createElementVNode("path",{fill:"currentColor",d:"M512 96a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V128a32 32 0 0 1 32-32m0 576a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V704a32 32 0 0 1 32-32M96 512a32 32 0 0 1 32-32h192a32 32 0 0 1 0 64H128a32 32 0 0 1-32-32m576 0a32 32 0 0 1 32-32h192a32 32 0 1 1 0 64H704a32 32 0 0 1-32-32"})],-1)])]),e.createElementVNode("div",{class:"toolbar-action-btn",title:"下载",onClick:P},[...o[13]||(o[13]=[e.createElementVNode("svg",{width:"16",height:"16",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 1024 1024"},[e.createElementVNode("path",{fill:"currentColor",d:"M160 832h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64m384-253.696 236.288-236.352 45.248 45.248L508.8 704 192 387.2l45.248-45.248L480 584.704V128h64z"})],-1)])])],64))])])])])])]),_:3}),e.withDirectives(e.createElementVNode("div",v,[e.createVNode(l.default,{code:k.raw?.content||"",language:"mermaid","is-dark":k.isDark,"light-theme":k.shikiTheme[0],"dark-theme":k.shikiTheme[1],"show-code-block-header":!1,"sticky-code-block-header":!1},null,8,["code","is-dark","light-theme","dark-theme"])],512),[[e.vShow,p.value]]),e.withDirectives(e.createVNode(a.default,{ref_key:"syntaxMermaidRef",ref:w,content:f.value,id:V.value,"is-dark":k.isDark,config:k.config},null,8,["content","id","is-dark","config"]),[[e.vShow,!p.value]])],2))}});exports.default=h;
|
|
2
2
|
//# sourceMappingURL=x-markdown.cjs24.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs24.js","sources":["../src/components/Mermaid/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport type { MdComponent, MermaidExposeProps, MermaidAction, MermaidSlotProps } from './types'\r\nimport type { VNode } from 'vue'\r\nimport { computed, ref, h, onMounted } from 'vue'\r\nimport { useClipboard } from '@vueuse/core'\r\n// 使用运行时检测\r\nimport { checkMermaidAvailable } from '../../hooks/useMermaid'\r\nimport SyntaxMermaid from './SyntaxMermaid.vue'\r\nimport CodeBlock from '../CodeBlock/index.vue'\r\n\r\ninterface MermaidProps extends MdComponent {\r\n isDark?: boolean\r\n shikiTheme?: [string, string]\r\n config?: Record<string, any>\r\n mermaidActions?: MermaidAction[]\r\n}\r\n\r\nconst props = withDefaults(defineProps<MermaidProps>(), {\r\n raw: () => ({}),\r\n isDark: false,\r\n shikiTheme: () => ['vitesse-light', 'vitesse-dark'],\r\n config: () => ({}),\r\n mermaidActions: undefined,\r\n})\r\n\r\nconst syntaxMermaidRef = ref<InstanceType<typeof SyntaxMermaid> | null>(null)\r\nconst showSourceCode = ref(false)\r\n// 运行时检测 mermaid 是否可用\r\nconst isDegraded = ref(false)\r\nconst mermaidContent = computed(() => props.raw?.content || '')\r\nconst mermaidId = computed(() => `mermaid-${props.raw?.key || 'default'}`)\r\nconst isLoading = computed(() => syntaxMermaidRef.value?.isLoading ?? true)\r\nconst svg = computed(() => syntaxMermaidRef.value?.svg ?? '')\r\nconst activeTab = computed(() => (showSourceCode.value ? 'code' : 'diagram'))\r\n\r\nfunction handleZoomIn(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.zoomIn()\r\n }\r\n}\r\n\r\nfunction handleZoomOut(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.zoomOut()\r\n }\r\n}\r\n\r\nfunction handleReset(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.reset()\r\n }\r\n}\r\n\r\nfunction handleFullscreen() {\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.fullscreen()\r\n }\r\n}\r\n\r\nfunction handleToggleCode() {\r\n showSourceCode.value = !showSourceCode.value\r\n}\r\n\r\nconst { copy: copyCode, copied } = useClipboard({ copiedDuring: 1500 })\r\n\r\nfunction handleTabClick(tabName: string) {\r\n if (tabName === 'code' && !showSourceCode.value) {\r\n showSourceCode.value = true\r\n } else if (tabName === 'diagram' && showSourceCode.value) {\r\n showSourceCode.value = false\r\n }\r\n}\r\n\r\nasync function handleCopyCode(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n\r\n if (copied.value) {\r\n return\r\n }\r\n\r\n if (!props.raw.content) {\r\n return\r\n }\r\n await copyCode(props.raw.content)\r\n}\r\n\r\nfunction handleDownload() {\r\n syntaxMermaidRef.value?.download()\r\n}\r\n\r\nconst normalizedActions = computed<MermaidAction[]>(() => {\r\n return props.mermaidActions || []\r\n})\r\n\r\nconst filteredActions = computed<MermaidAction[]>(() => {\r\n return normalizedActions.value.filter((action) => {\r\n if (!action.show) return true\r\n return action.show(slotProps.value)\r\n })\r\n})\r\n\r\nconst slotProps = computed<MermaidSlotProps>(() => ({\r\n showSourceCode: showSourceCode.value,\r\n svg: svg.value,\r\n rawContent: props.raw.content || '',\r\n isLoading: isLoading.value,\r\n copied: copied.value,\r\n zoomIn: handleZoomIn,\r\n zoomOut: handleZoomOut,\r\n reset: handleReset,\r\n fullscreen: handleFullscreen,\r\n toggleCode: handleToggleCode,\r\n copyCode: handleCopyCode,\r\n download: handleDownload,\r\n raw: props.raw,\r\n}))\r\n\r\nfunction renderActionIcon(action: MermaidAction): VNode | null {\r\n if (!action.icon) return null\r\n\r\n if (typeof action.icon === 'string') {\r\n return h('span', {\r\n class: 'mermaid-action-icon',\r\n innerHTML: action.icon,\r\n })\r\n }\r\n\r\n if (typeof action.icon === 'function') {\r\n try {\r\n const result = (action.icon as (props: MermaidSlotProps) => VNode)(slotProps.value)\r\n if (result && typeof result === 'object' && '__v_isVNode' in result) {\r\n return result\r\n }\r\n } catch {}\r\n return h(action.icon as any)\r\n }\r\n\r\n return h(action.icon as any)\r\n}\r\n\r\nfunction handleActionClick(action: MermaidAction) {\r\n if (action.disabled) return\r\n action.onClick?.(slotProps.value)\r\n}\r\n\r\nconst exposedMethods = computed(\r\n () =>\r\n ({\r\n showSourceCode: showSourceCode.value,\r\n svg: svg.value,\r\n rawContent: props.raw.content || '',\r\n isLoading: isLoading.value,\r\n copied: copied.value,\r\n zoomIn: handleZoomIn,\r\n zoomOut: handleZoomOut,\r\n reset: handleReset,\r\n fullscreen: handleFullscreen,\r\n toggleCode: handleToggleCode,\r\n copyCode: handleCopyCode,\r\n download: handleDownload,\r\n raw: props.raw,\r\n }) satisfies MermaidExposeProps,\r\n)\r\n\r\n// 组件挂载时检测 mermaid 是否可用\r\nonMounted(async () => {\r\n const hasMermaid = await checkMermaidAvailable()\r\n isDegraded.value = !hasMermaid\r\n})\r\n</script>\r\n\r\n<template>\r\n <!-- 当 Mermaid 不可用时(降级),渲染 CodeBlock -->\r\n <CodeBlock\r\n v-if=\"isDegraded\"\r\n :code=\"props.raw?.content || ''\"\r\n language=\"mermaid\"\r\n :is-dark=\"props.isDark\"\r\n :light-theme=\"props.shikiTheme[0]\"\r\n :dark-theme=\"props.shikiTheme[1]\"\r\n />\r\n\r\n <!-- 当 Mermaid 可用时,渲染完整的 Mermaid 组件 -->\r\n <div v-else :key=\"props.raw.key\" class=\"markdown-mermaid\" :class=\"{ 'markdown-mermaid--dark': props.isDark }\">\r\n <Transition name=\"toolbar\" appear>\r\n <div class=\"toolbar-container\">\r\n <slot name=\"mermaidHeader\" v-bind=\"exposedMethods\">\r\n <div class=\"mermaid-toolbar\">\r\n <div class=\"toolbar-left\">\r\n <div class=\"segmented-control\">\r\n <div class=\"segmented-slider\" :class=\"{ 'slide-right': activeTab === 'code' }\" />\r\n <div\r\n class=\"segment-item\"\r\n :class=\"{ active: activeTab === 'diagram' }\"\r\n @click=\"handleTabClick('diagram')\"\r\n >\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M12 2L2 7L12 12L22 7L12 2Z\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M2 17L12 22L22 17\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M2 12L12 17L22 12\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span>预览</span>\r\n </div>\r\n <div class=\"segment-item\" :class=\"{ active: activeTab === 'code' }\" @click=\"handleTabClick('code')\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M16 18L22 12L16 6\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M8 6L2 12L8 18\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span>代码</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"toolbar-right\">\r\n <slot name=\"mermaidActions\" v-bind=\"exposedMethods\">\r\n <div\r\n v-for=\"action in filteredActions\"\r\n :key=\"action.key\"\r\n class=\"toolbar-action-btn\"\r\n :class=\"[action.class, { 'toolbar-action-btn--disabled': action.disabled }]\"\r\n :style=\"action.style\"\r\n :title=\"action.title\"\r\n @click=\"handleActionClick(action)\"\r\n >\r\n <component :is=\"renderActionIcon(action)\" v-if=\"action.icon\" />\r\n </div>\r\n\r\n <template v-if=\"showSourceCode\">\r\n <div\r\n class=\"toolbar-action-btn\"\r\n :class=\"{ 'copy-success': copied }\"\r\n title=\"复制代码\"\r\n @click=\"handleCopyCode($event)\"\r\n >\r\n <svg\r\n v-if=\"copied\"\r\n width=\"16\"\r\n height=\"16\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 1024 1024\"\r\n >\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M406.656 706.944 195.84 496.256a32 32 0 1 0-45.248 45.248l256 256 512-512a32 32 0 0 0-45.248-45.248L406.592 706.944z\"\r\n />\r\n </svg>\r\n <svg v-else width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M768 832a128 128 0 0 1-128 128H192A128 128 0 0 1 64 832V384a128 128 0 0 1 128-128v64a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64z\"\r\n />\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M384 128a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64V192a64 64 0 0 0-64-64zm0-64h448a128 128 0 0 1 128 128v448a128 128 0 0 1-128 128H384a128 128 0 0 1-128-128V192A128 128 0 0 1 384 64\"\r\n />\r\n </svg>\r\n </div>\r\n </template>\r\n\r\n <template v-else>\r\n <div class=\"toolbar-action-btn\" title=\"缩小\" @click=\"handleZoomOut($event)\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704M352 448h256a32 32 0 0 1 0 64H352a32 32 0 0 1 0-64\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"toolbar-action-btn\" title=\"放大\" @click=\"handleZoomIn($event)\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704m-32-384v-96a32 32 0 0 1 64 0v96h96a32 32 0 0 1 0 64h-96v96a32 32 0 0 1-64 0v-96h-96a32 32 0 0 1 0-64z\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"toolbar-action-btn\" title=\"重置\" @click=\"handleReset($event)\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M512 896a384 384 0 1 0 0-768 384 384 0 0 0 0 768m0 64a448 448 0 1 1 0-896 448 448 0 0 1 0 896\"\r\n />\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M512 96a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V128a32 32 0 0 1 32-32m0 576a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V704a32 32 0 0 1 32-32M96 512a32 32 0 0 1 32-32h192a32 32 0 0 1 0 64H128a32 32 0 0 1-32-32m576 0a32 32 0 0 1 32-32h192a32 32 0 1 1 0 64H704a32 32 0 0 1-32-32\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"toolbar-action-btn\" title=\"下载\" @click=\"handleDownload\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M160 832h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64m384-253.696 236.288-236.352 45.248 45.248L508.8 704 192 387.2l45.248-45.248L480 584.704V128h64z\"\r\n />\r\n </svg>\r\n </div>\r\n </template>\r\n </slot>\r\n </div>\r\n </div>\r\n </slot>\r\n </div>\r\n </Transition>\r\n\r\n <div v-show=\"showSourceCode\" class=\"mermaid-source-code\">\r\n <CodeBlock\r\n :code=\"props.raw?.content || ''\"\r\n language=\"mermaid\"\r\n :is-dark=\"props.isDark\"\r\n :light-theme=\"props.shikiTheme[0]\"\r\n :dark-theme=\"props.shikiTheme[1]\"\r\n :show-code-block-header=\"false\"\r\n :sticky-code-block-header=\"false\"\r\n />\r\n </div>\r\n\r\n <SyntaxMermaid\r\n v-show=\"!showSourceCode\"\r\n ref=\"syntaxMermaidRef\"\r\n :content=\"mermaidContent\"\r\n :id=\"mermaidId\"\r\n :is-dark=\"props.isDark\"\r\n :config=\"props.config\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<style>\r\n.markdown-mermaid {\r\n border-radius: 8px;\r\n overflow: hidden;\r\n font-size: 0;\r\n background: rgba(0, 0, 0, 0.03);\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark {\r\n background: rgba(255, 255, 255, 0.13);\r\n}\r\n\r\n.markdown-mermaid .toolbar-container {\r\n position: relative;\r\n z-index: 10;\r\n flex-shrink: 0;\r\n background: rgba(0, 0, 0, 0.05);\r\n color: #333;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .toolbar-container {\r\n background: rgba(0, 0, 0, 0.25);\r\n color: #fff;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 8px 16px;\r\n background: transparent;\r\n color: inherit;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-left {\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segmented-control {\r\n display: flex;\r\n align-items: center;\r\n position: relative;\r\n background: rgba(0, 0, 0, 0.06);\r\n border-radius: 6px;\r\n padding: 3px;\r\n gap: 2px;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .segmented-control {\r\n background: rgba(255, 255, 255, 0.08);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segmented-slider {\r\n position: absolute;\r\n top: 3px;\r\n left: 3px;\r\n width: calc(50% - 4px);\r\n height: calc(100% - 6px);\r\n background: #fff;\r\n border-radius: 4px;\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\r\n transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\r\n z-index: 0;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .segmented-slider {\r\n background: rgba(255, 255, 255, 0.15);\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segmented-slider.slide-right {\r\n transform: translateX(calc(100% + 2px));\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n font-size: 12px;\r\n border: none;\r\n color: inherit;\r\n min-width: 60px;\r\n text-align: center;\r\n box-sizing: border-box;\r\n font-weight: 500;\r\n cursor: pointer;\r\n border-radius: 4px;\r\n padding: 5px 12px;\r\n transition: all 0.2s ease;\r\n background: transparent;\r\n opacity: 0.6;\r\n user-select: none;\r\n position: relative;\r\n z-index: 1;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item.active {\r\n opacity: 1;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .segment-item.active {\r\n color: #fff;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item:hover {\r\n opacity: 1;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item svg {\r\n flex-shrink: 0;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-right {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 28px;\r\n height: 28px;\r\n padding: 0;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: inherit;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n opacity: 0.7;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn:hover {\r\n opacity: 1;\r\n background: rgba(0, 0, 0, 0.08);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn.copy-success {\r\n opacity: 1;\r\n color: #22c55e;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .toolbar-action-btn:hover {\r\n background: rgba(255, 255, 255, 0.1);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn.toolbar-action-btn--disabled {\r\n opacity: 0.3;\r\n cursor: not-allowed;\r\n pointer-events: none;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .mermaid-action-icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .mermaid-action-icon :deep(svg) {\r\n width: 16px;\r\n height: 16px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.markdown-mermaid .mermaid-source-code {\r\n position: relative;\r\n z-index: 1;\r\n flex: 1;\r\n width: 100%;\r\n overflow: auto;\r\n box-sizing: border-box;\r\n}\r\n\r\n.toolbar-enter-active,\r\n.toolbar-leave-active {\r\n transition: opacity 0.3s ease;\r\n}\r\n\r\n.toolbar-enter-from,\r\n.toolbar-leave-to {\r\n opacity: 0;\r\n}\r\n</style>\r\n"],"names":["props","__props","syntaxMermaidRef","ref","showSourceCode","isDegraded","mermaidContent","computed","raw","content","mermaidId","key","isLoading","value","svg","activeTab","handleZoomIn","event","stopPropagation","preventDefault","zoomIn","handleZoomOut","zoomOut","handleReset","reset","handleFullscreen","fullscreen","handleToggleCode","copy","copyCode","copied","useClipboard","copiedDuring","handleTabClick","tabName","async","handleCopyCode","handleDownload","download","normalizedActions","mermaidActions","filteredActions","filter","action","show","slotProps","rawContent","toggleCode","renderActionIcon","icon","h","class","innerHTML","result","exposedMethods","onMounted","hasMermaid","checkMermaidAvailable","_createBlock","CodeBlock","code","language","isDark","shikiTheme","_createElementBlock","_normalizeClass","_createVNode","_Transition","name","appear","_createElementVNode","_hoisted_1","_renderSlot","_ctx","$slots","_normalizeProps","_guardReactiveProps","_hoisted_2","_hoisted_3","_hoisted_4","active","onClick","width","height","viewBox","fill","xmlns","d","stroke","_hoisted_5","_Fragment","_renderList","disabled","style","_normalizeStyle","title","$event","handleActionClick","_resolveDynamicComponent","_unref","_cache","_openBlock","_hoisted_7","_hoisted_8","_withDirectives","_hoisted_9","SyntaxMermaid","id","config"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"x-markdown.cjs24.js","sources":["../src/components/Mermaid/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport type { MdComponent, MermaidExposeProps, MermaidAction, MermaidSlotProps } from './types'\r\nimport type { VNode } from 'vue'\r\nimport { computed, ref, h, onMounted } from 'vue'\r\nimport { useClipboard } from '@vueuse/core'\r\n// 使用运行时检测\r\nimport { checkMermaidAvailable } from '../../hooks/useMermaid'\r\nimport SyntaxMermaid from './SyntaxMermaid.vue'\r\nimport CodeBlock from '../CodeBlock/index.vue'\r\n\r\ninterface MermaidProps extends MdComponent {\r\n isDark?: boolean\r\n shikiTheme?: [string, string]\r\n config?: Record<string, any>\r\n mermaidActions?: MermaidAction[]\r\n}\r\n\r\nconst props = withDefaults(defineProps<MermaidProps>(), {\r\n raw: () => ({}),\r\n isDark: false,\r\n shikiTheme: () => ['vitesse-light', 'vitesse-dark'],\r\n config: () => ({}),\r\n mermaidActions: undefined,\r\n})\r\n\r\nconst syntaxMermaidRef = ref<InstanceType<typeof SyntaxMermaid> | null>(null)\r\nconst showSourceCode = ref(false)\r\n// 运行时检测 mermaid 是否可用\r\n// 默认为 true(降级模式),检测到可用后才切换到正常模式\r\n// 这样可以避免首次渲染时的闪烁问题\r\nconst isDegraded = ref(true)\r\nconst mermaidContent = computed(() => props.raw?.content || '')\r\nconst mermaidId = computed(() => `mermaid-${props.raw?.key || 'default'}`)\r\nconst isLoading = computed(() => syntaxMermaidRef.value?.isLoading ?? true)\r\nconst svg = computed(() => syntaxMermaidRef.value?.svg ?? '')\r\nconst activeTab = computed(() => (showSourceCode.value ? 'code' : 'diagram'))\r\n\r\nfunction handleZoomIn(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.zoomIn()\r\n }\r\n}\r\n\r\nfunction handleZoomOut(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.zoomOut()\r\n }\r\n}\r\n\r\nfunction handleReset(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.reset()\r\n }\r\n}\r\n\r\nfunction handleFullscreen() {\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.fullscreen()\r\n }\r\n}\r\n\r\nfunction handleToggleCode() {\r\n showSourceCode.value = !showSourceCode.value\r\n}\r\n\r\nconst { copy: copyCode, copied } = useClipboard({ copiedDuring: 1500 })\r\n\r\nfunction handleTabClick(tabName: string) {\r\n if (tabName === 'code' && !showSourceCode.value) {\r\n showSourceCode.value = true\r\n } else if (tabName === 'diagram' && showSourceCode.value) {\r\n showSourceCode.value = false\r\n }\r\n}\r\n\r\nasync function handleCopyCode(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n\r\n if (copied.value) {\r\n return\r\n }\r\n\r\n if (!props.raw.content) {\r\n return\r\n }\r\n await copyCode(props.raw.content)\r\n}\r\n\r\nfunction handleDownload() {\r\n syntaxMermaidRef.value?.download()\r\n}\r\n\r\nconst normalizedActions = computed<MermaidAction[]>(() => {\r\n return props.mermaidActions || []\r\n})\r\n\r\nconst filteredActions = computed<MermaidAction[]>(() => {\r\n return normalizedActions.value.filter((action) => {\r\n if (!action.show) return true\r\n return action.show(slotProps.value)\r\n })\r\n})\r\n\r\nconst slotProps = computed<MermaidSlotProps>(() => ({\r\n showSourceCode: showSourceCode.value,\r\n svg: svg.value,\r\n rawContent: props.raw.content || '',\r\n isLoading: isLoading.value,\r\n copied: copied.value,\r\n zoomIn: handleZoomIn,\r\n zoomOut: handleZoomOut,\r\n reset: handleReset,\r\n fullscreen: handleFullscreen,\r\n toggleCode: handleToggleCode,\r\n copyCode: handleCopyCode,\r\n download: handleDownload,\r\n raw: props.raw,\r\n}))\r\n\r\nfunction renderActionIcon(action: MermaidAction): VNode | null {\r\n if (!action.icon) return null\r\n\r\n if (typeof action.icon === 'string') {\r\n return h('span', {\r\n class: 'mermaid-action-icon',\r\n innerHTML: action.icon,\r\n })\r\n }\r\n\r\n if (typeof action.icon === 'function') {\r\n try {\r\n const result = (action.icon as (props: MermaidSlotProps) => VNode)(slotProps.value)\r\n if (result && typeof result === 'object' && '__v_isVNode' in result) {\r\n return result\r\n }\r\n } catch {}\r\n return h(action.icon as any)\r\n }\r\n\r\n return h(action.icon as any)\r\n}\r\n\r\nfunction handleActionClick(action: MermaidAction) {\r\n if (action.disabled) return\r\n action.onClick?.(slotProps.value)\r\n}\r\n\r\nconst exposedMethods = computed(\r\n () =>\r\n ({\r\n showSourceCode: showSourceCode.value,\r\n svg: svg.value,\r\n rawContent: props.raw.content || '',\r\n isLoading: isLoading.value,\r\n copied: copied.value,\r\n zoomIn: handleZoomIn,\r\n zoomOut: handleZoomOut,\r\n reset: handleReset,\r\n fullscreen: handleFullscreen,\r\n toggleCode: handleToggleCode,\r\n copyCode: handleCopyCode,\r\n download: handleDownload,\r\n raw: props.raw,\r\n }) satisfies MermaidExposeProps,\r\n)\r\n\r\n// 组件挂载时检测 mermaid 是否可用\r\nonMounted(async () => {\r\n const hasMermaid = await checkMermaidAvailable()\r\n isDegraded.value = !hasMermaid\r\n})\r\n</script>\r\n\r\n<template>\r\n <!-- 当 Mermaid 不可用时(降级),渲染 CodeBlock -->\r\n <CodeBlock\r\n v-if=\"isDegraded\"\r\n :code=\"props.raw?.content || ''\"\r\n language=\"mermaid\"\r\n :is-dark=\"props.isDark\"\r\n :light-theme=\"props.shikiTheme[0]\"\r\n :dark-theme=\"props.shikiTheme[1]\"\r\n />\r\n\r\n <!-- 当 Mermaid 可用时,渲染完整的 Mermaid 组件 -->\r\n <div v-else :key=\"props.raw.key\" class=\"markdown-mermaid\" :class=\"{ 'markdown-mermaid--dark': props.isDark }\">\r\n <Transition name=\"toolbar\" appear>\r\n <div class=\"toolbar-container\">\r\n <slot name=\"mermaidHeader\" v-bind=\"exposedMethods\">\r\n <div class=\"mermaid-toolbar\">\r\n <div class=\"toolbar-left\">\r\n <div class=\"segmented-control\">\r\n <div class=\"segmented-slider\" :class=\"{ 'slide-right': activeTab === 'code' }\" />\r\n <div\r\n class=\"segment-item\"\r\n :class=\"{ active: activeTab === 'diagram' }\"\r\n @click=\"handleTabClick('diagram')\"\r\n >\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M12 2L2 7L12 12L22 7L12 2Z\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M2 17L12 22L22 17\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M2 12L12 17L22 12\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span>预览</span>\r\n </div>\r\n <div class=\"segment-item\" :class=\"{ active: activeTab === 'code' }\" @click=\"handleTabClick('code')\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M16 18L22 12L16 6\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M8 6L2 12L8 18\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span>代码</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"toolbar-right\">\r\n <slot name=\"mermaidActions\" v-bind=\"exposedMethods\">\r\n <div\r\n v-for=\"action in filteredActions\"\r\n :key=\"action.key\"\r\n class=\"toolbar-action-btn\"\r\n :class=\"[action.class, { 'toolbar-action-btn--disabled': action.disabled }]\"\r\n :style=\"action.style\"\r\n :title=\"action.title\"\r\n @click=\"handleActionClick(action)\"\r\n >\r\n <component :is=\"renderActionIcon(action)\" v-if=\"action.icon\" />\r\n </div>\r\n\r\n <template v-if=\"showSourceCode\">\r\n <div\r\n class=\"toolbar-action-btn\"\r\n :class=\"{ 'copy-success': copied }\"\r\n title=\"复制代码\"\r\n @click=\"handleCopyCode($event)\"\r\n >\r\n <svg\r\n v-if=\"copied\"\r\n width=\"16\"\r\n height=\"16\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 1024 1024\"\r\n >\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M406.656 706.944 195.84 496.256a32 32 0 1 0-45.248 45.248l256 256 512-512a32 32 0 0 0-45.248-45.248L406.592 706.944z\"\r\n />\r\n </svg>\r\n <svg v-else width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M768 832a128 128 0 0 1-128 128H192A128 128 0 0 1 64 832V384a128 128 0 0 1 128-128v64a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64z\"\r\n />\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M384 128a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64V192a64 64 0 0 0-64-64zm0-64h448a128 128 0 0 1 128 128v448a128 128 0 0 1-128 128H384a128 128 0 0 1-128-128V192A128 128 0 0 1 384 64\"\r\n />\r\n </svg>\r\n </div>\r\n </template>\r\n\r\n <template v-else>\r\n <div class=\"toolbar-action-btn\" title=\"缩小\" @click=\"handleZoomOut($event)\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704M352 448h256a32 32 0 0 1 0 64H352a32 32 0 0 1 0-64\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"toolbar-action-btn\" title=\"放大\" @click=\"handleZoomIn($event)\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704m-32-384v-96a32 32 0 0 1 64 0v96h96a32 32 0 0 1 0 64h-96v96a32 32 0 0 1-64 0v-96h-96a32 32 0 0 1 0-64z\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"toolbar-action-btn\" title=\"重置\" @click=\"handleReset($event)\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M512 896a384 384 0 1 0 0-768 384 384 0 0 0 0 768m0 64a448 448 0 1 1 0-896 448 448 0 0 1 0 896\"\r\n />\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M512 96a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V128a32 32 0 0 1 32-32m0 576a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V704a32 32 0 0 1 32-32M96 512a32 32 0 0 1 32-32h192a32 32 0 0 1 0 64H128a32 32 0 0 1-32-32m576 0a32 32 0 0 1 32-32h192a32 32 0 1 1 0 64H704a32 32 0 0 1-32-32\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"toolbar-action-btn\" title=\"下载\" @click=\"handleDownload\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M160 832h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64m384-253.696 236.288-236.352 45.248 45.248L508.8 704 192 387.2l45.248-45.248L480 584.704V128h64z\"\r\n />\r\n </svg>\r\n </div>\r\n </template>\r\n </slot>\r\n </div>\r\n </div>\r\n </slot>\r\n </div>\r\n </Transition>\r\n\r\n <div v-show=\"showSourceCode\" class=\"mermaid-source-code\">\r\n <CodeBlock\r\n :code=\"props.raw?.content || ''\"\r\n language=\"mermaid\"\r\n :is-dark=\"props.isDark\"\r\n :light-theme=\"props.shikiTheme[0]\"\r\n :dark-theme=\"props.shikiTheme[1]\"\r\n :show-code-block-header=\"false\"\r\n :sticky-code-block-header=\"false\"\r\n />\r\n </div>\r\n\r\n <SyntaxMermaid\r\n v-show=\"!showSourceCode\"\r\n ref=\"syntaxMermaidRef\"\r\n :content=\"mermaidContent\"\r\n :id=\"mermaidId\"\r\n :is-dark=\"props.isDark\"\r\n :config=\"props.config\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<style>\r\n.markdown-mermaid {\r\n border-radius: 8px;\r\n overflow: hidden;\r\n font-size: 0;\r\n background: rgba(0, 0, 0, 0.03);\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark {\r\n background: rgba(255, 255, 255, 0.13);\r\n}\r\n\r\n.markdown-mermaid .toolbar-container {\r\n position: relative;\r\n z-index: 10;\r\n flex-shrink: 0;\r\n background: rgba(0, 0, 0, 0.05);\r\n color: #333;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .toolbar-container {\r\n background: rgba(0, 0, 0, 0.25);\r\n color: #fff;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 8px 16px;\r\n background: transparent;\r\n color: inherit;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-left {\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segmented-control {\r\n display: flex;\r\n align-items: center;\r\n position: relative;\r\n background: rgba(0, 0, 0, 0.06);\r\n border-radius: 6px;\r\n padding: 3px;\r\n gap: 2px;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .segmented-control {\r\n background: rgba(255, 255, 255, 0.08);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segmented-slider {\r\n position: absolute;\r\n top: 3px;\r\n left: 3px;\r\n width: calc(50% - 4px);\r\n height: calc(100% - 6px);\r\n background: #fff;\r\n border-radius: 4px;\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\r\n transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\r\n z-index: 0;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .segmented-slider {\r\n background: rgba(255, 255, 255, 0.15);\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segmented-slider.slide-right {\r\n transform: translateX(calc(100% + 2px));\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n font-size: 12px;\r\n border: none;\r\n color: inherit;\r\n min-width: 60px;\r\n text-align: center;\r\n box-sizing: border-box;\r\n font-weight: 500;\r\n cursor: pointer;\r\n border-radius: 4px;\r\n padding: 5px 12px;\r\n transition: all 0.2s ease;\r\n background: transparent;\r\n opacity: 0.6;\r\n user-select: none;\r\n position: relative;\r\n z-index: 1;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item.active {\r\n opacity: 1;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .segment-item.active {\r\n color: #fff;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item:hover {\r\n opacity: 1;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item svg {\r\n flex-shrink: 0;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-right {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 28px;\r\n height: 28px;\r\n padding: 0;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: inherit;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n opacity: 0.7;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn:hover {\r\n opacity: 1;\r\n background: rgba(0, 0, 0, 0.08);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn.copy-success {\r\n opacity: 1;\r\n color: #22c55e;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .toolbar-action-btn:hover {\r\n background: rgba(255, 255, 255, 0.1);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn.toolbar-action-btn--disabled {\r\n opacity: 0.3;\r\n cursor: not-allowed;\r\n pointer-events: none;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .mermaid-action-icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .mermaid-action-icon :deep(svg) {\r\n width: 16px;\r\n height: 16px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.markdown-mermaid .mermaid-source-code {\r\n position: relative;\r\n z-index: 1;\r\n flex: 1;\r\n width: 100%;\r\n overflow: auto;\r\n box-sizing: border-box;\r\n}\r\n\r\n.toolbar-enter-active,\r\n.toolbar-leave-active {\r\n transition: opacity 0.3s ease;\r\n}\r\n\r\n.toolbar-enter-from,\r\n.toolbar-leave-to {\r\n opacity: 0;\r\n}\r\n</style>\r\n"],"names":["props","__props","syntaxMermaidRef","ref","showSourceCode","isDegraded","mermaidContent","computed","raw","content","mermaidId","key","isLoading","value","svg","activeTab","handleZoomIn","event","stopPropagation","preventDefault","zoomIn","handleZoomOut","zoomOut","handleReset","reset","handleFullscreen","fullscreen","handleToggleCode","copy","copyCode","copied","useClipboard","copiedDuring","handleTabClick","tabName","async","handleCopyCode","handleDownload","download","normalizedActions","mermaidActions","filteredActions","filter","action","show","slotProps","rawContent","toggleCode","renderActionIcon","icon","h","class","innerHTML","result","exposedMethods","onMounted","hasMermaid","checkMermaidAvailable","_createBlock","CodeBlock","code","language","isDark","shikiTheme","_createElementBlock","_normalizeClass","_createVNode","_Transition","name","appear","_createElementVNode","_hoisted_1","_renderSlot","_ctx","$slots","_normalizeProps","_guardReactiveProps","_hoisted_2","_hoisted_3","_hoisted_4","active","onClick","width","height","viewBox","fill","xmlns","d","stroke","_hoisted_5","_Fragment","_renderList","disabled","style","_normalizeStyle","title","$event","handleActionClick","_resolveDynamicComponent","_unref","_cache","_openBlock","_hoisted_7","_hoisted_8","_withDirectives","_hoisted_9","SyntaxMermaid","id","config"],"mappings":"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"}
|
package/dist/x-markdown.cjs27.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./x-markdown.
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),a=require("lodash-es"),n=require("./x-markdown.cjs9.js"),t={key:0,class:"syntax-mermaid__loading"},r=["innerHTML"],i=e.defineComponent({__name:"SyntaxMermaid",props:{content:{default:""},id:{default:"mermaid-default"},isDark:{type:Boolean,default:!1},config:{default:()=>({})}},emits:["degraded","ready"],setup(i,{expose:o,emit:d}){const l=i,s=d,u=e.ref(null),c=e.computed(()=>l.content),m=e.computed(()=>({id:l.id,theme:l.isDark?"dark":"default",config:l.config,container:u.value})),v=n.useMermaid(c,m),f=e.ref(""),g=e.computed(()=>v.isLoading.value),y=e.computed(()=>v.error.value),p=e.ref(null),k=n.useMermaidZoom({container:p}),x=a.debounce(function(){e.nextTick(()=>{p.value&&k.initialize()})},500);return e.watch(()=>v.data.value,(e,a)=>{console.log("[SyntaxMermaid] mermaidResult.data.value changed:",{oldSvg:a,newSvg:e,isNewSvg:!!e,startsWithSvg:e?.trim().startsWith("<svg"),preview:e?.substring(0,50)}),e&&(f.value=e,x(),e.trim().startsWith("<svg")?(console.log("[SyntaxMermaid] Emitting ready event - Mermaid is available"),s("ready")):(console.log("[SyntaxMermaid] Emitting degraded event - Mermaid not available"),s("degraded")))},{immediate:!0}),e.watch(f,e=>{e&&x()}),e.onMounted(()=>{f.value&&x()}),o({svg:f,isLoading:g,error:y,containerRef:p,zoomIn:function(){k?.zoomIn()},zoomOut:function(){k?.zoomOut()},reset:function(){k?.reset()},fullscreen:function(){k?.fullscreen(),k?.reset()},download:function(){n.downloadSvgAsPng(f.value)},getSvg:function(){return f.value},reinitialize:function(){x()}}),(a,n)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"containerRef",ref:p,class:e.normalizeClass(["syntax-mermaid",{"syntax-mermaid--dark":l.isDark}])},[e.createElementVNode("div",{ref_key:"renderContainerRef",ref:u,class:"syntax-mermaid__render-container","aria-hidden":"true"},null,512),g.value?(e.openBlock(),e.createElementBlock("div",t,[e.renderSlot(a.$slots,"loading",{},()=>[n[0]||(n[0]=e.createElementVNode("span",{class:"syntax-mermaid__loading-text"},"加载中...",-1))])])):(e.openBlock(),e.createElementBlock("div",{key:1,class:"syntax-mermaid__content",innerHTML:f.value},null,8,r))],2))}});exports.default=i;
|
|
2
2
|
//# sourceMappingURL=x-markdown.cjs27.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs27.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"x-markdown.cjs27.js","sources":["../src/components/Mermaid/SyntaxMermaid.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed, nextTick, ref, watch, onMounted } from 'vue'\r\nimport { debounce } from 'lodash-es'\r\nimport { useMermaid, useMermaidZoom, downloadSvgAsPng } from '../../hooks'\r\n\r\ninterface SyntaxMermaidProps {\r\n content: string\r\n id?: string\r\n isDark?: boolean\r\n config?: Record<string, any>\r\n}\r\n\r\nconst props = withDefaults(defineProps<SyntaxMermaidProps>(), {\r\n content: '',\r\n id: 'mermaid-default',\r\n isDark: false,\r\n config: () => ({}),\r\n})\r\n\r\nconst emit = defineEmits<{\r\n degraded: []\r\n ready: []\r\n}>()\r\n\r\nconst renderContainerRef = ref<HTMLElement | null>(null)\r\n\r\nconst mermaidContent = computed(() => props.content)\r\nconst mermaidOptions = computed(() => ({\r\n id: props.id,\r\n theme: props.isDark ? 'dark' : 'default',\r\n config: props.config,\r\n container: renderContainerRef.value,\r\n}))\r\nconst mermaidResult = useMermaid(mermaidContent, mermaidOptions)\r\n\r\nconst svg = ref('')\r\nconst isLoading = computed(() => mermaidResult.isLoading.value)\r\nconst error = computed(() => mermaidResult.error.value)\r\n\r\nconst containerRef = ref<HTMLElement | null>(null)\r\n\r\nconst zoomControls = useMermaidZoom({\r\n container: containerRef,\r\n scaleStep: 0.2,\r\n minScale: 0.1,\r\n maxScale: 5,\r\n})\r\n\r\nconst debouncedInitialize = debounce(initializeZoom, 500)\r\n\r\nfunction initializeZoom() {\r\n nextTick(() => {\r\n if (containerRef.value) {\r\n zoomControls.initialize()\r\n }\r\n })\r\n}\r\n\r\nwatch(\r\n () => mermaidResult.data.value,\r\n (newSvg, oldSvg) => {\r\n console.log('[SyntaxMermaid] mermaidResult.data.value changed:', {\r\n oldSvg,\r\n newSvg,\r\n isNewSvg: !!newSvg,\r\n startsWithSvg: newSvg?.trim().startsWith('<svg'),\r\n preview: newSvg?.substring(0, 50)\r\n })\r\n\r\n if (newSvg) {\r\n svg.value = newSvg\r\n debouncedInitialize()\r\n\r\n // 检测是否成功渲染了 SVG(以 <svg 开头)\r\n if (newSvg.trim().startsWith('<svg')) {\r\n console.log('[SyntaxMermaid] Emitting ready event - Mermaid is available')\r\n emit('ready')\r\n } else {\r\n console.log('[SyntaxMermaid] Emitting degraded event - Mermaid not available')\r\n emit('degraded')\r\n }\r\n }\r\n },\r\n { immediate: true },\r\n)\r\n\r\nwatch(svg, (newSvg) => {\r\n if (newSvg) {\r\n debouncedInitialize()\r\n }\r\n})\r\n\r\nfunction zoomIn() {\r\n zoomControls?.zoomIn()\r\n}\r\n\r\nfunction zoomOut() {\r\n zoomControls?.zoomOut()\r\n}\r\n\r\nfunction reset() {\r\n zoomControls?.reset()\r\n}\r\n\r\nfunction fullscreen() {\r\n zoomControls?.fullscreen()\r\n zoomControls?.reset()\r\n}\r\n\r\nfunction download() {\r\n downloadSvgAsPng(svg.value)\r\n}\r\n\r\nfunction getSvg() {\r\n return svg.value\r\n}\r\n\r\nfunction reinitialize() {\r\n debouncedInitialize()\r\n}\r\n\r\nonMounted(() => {\r\n if (svg.value) {\r\n debouncedInitialize()\r\n }\r\n})\r\n\r\ndefineExpose({\r\n svg,\r\n isLoading,\r\n error,\r\n containerRef,\r\n zoomIn,\r\n zoomOut,\r\n reset,\r\n fullscreen,\r\n download,\r\n getSvg,\r\n reinitialize,\r\n})\r\n</script>\r\n\r\n<template>\r\n <div ref=\"containerRef\" class=\"syntax-mermaid\" :class=\"{ 'syntax-mermaid--dark': props.isDark }\">\r\n <div ref=\"renderContainerRef\" class=\"syntax-mermaid__render-container\" aria-hidden=\"true\" />\r\n\r\n <div v-if=\"isLoading\" class=\"syntax-mermaid__loading\">\r\n <slot name=\"loading\">\r\n <span class=\"syntax-mermaid__loading-text\">加载中...</span>\r\n </slot>\r\n </div>\r\n <div v-else class=\"syntax-mermaid__content\" v-html=\"svg\" />\r\n </div>\r\n</template>\r\n\r\n<style>\r\n.syntax-mermaid {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n min-height: 200px;\r\n overflow: hidden;\r\n cursor: grab;\r\n position: relative;\r\n}\r\n\r\n.syntax-mermaid__render-container {\r\n position: absolute;\r\n max-height: 0;\r\n opacity: 0;\r\n overflow: hidden;\r\n pointer-events: none;\r\n}\r\n\r\n.syntax-mermaid:active {\r\n cursor: grabbing;\r\n}\r\n\r\n.syntax-mermaid__content {\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.syntax-mermaid__content svg {\r\n transform-origin: center center;\r\n max-width: 100%;\r\n max-height: 100%;\r\n}\r\n\r\n.syntax-mermaid:fullscreen {\r\n max-height: 100vh;\r\n}\r\n\r\n.syntax-mermaid:fullscreen .syntax-mermaid__content {\r\n justify-content: center;\r\n}\r\n\r\n.syntax-mermaid__loading {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 100%;\r\n height: 100%;\r\n min-height: 200px;\r\n}\r\n\r\n.syntax-mermaid__loading-text {\r\n color: #666;\r\n font-size: 14px;\r\n}\r\n\r\n.syntax-mermaid--dark .syntax-mermaid__loading-text {\r\n color: #999;\r\n}\r\n</style>\r\n"],"names":["props","__props","emit","__emit","renderContainerRef","ref","mermaidContent","computed","content","mermaidOptions","id","theme","isDark","config","container","value","mermaidResult","useMermaid","svg","isLoading","error","containerRef","zoomControls","useMermaidZoom","debouncedInitialize","debounce","nextTick","initialize","watch","data","newSvg","oldSvg","console","log","isNewSvg","startsWithSvg","trim","startsWith","preview","substring","immediate","onMounted","__expose","zoomIn","zoomOut","reset","fullscreen","download","downloadSvgAsPng","getSvg","reinitialize","_createElementBlock","class","_normalizeClass","_createElementVNode","_openBlock","_hoisted_1","_renderSlot","_ctx","_cache","innerHTML"],"mappings":"+cAYA,MAAMA,EAAQC,EAORC,EAAOC,EAKPC,EAAqBC,EAAAA,IAAwB,MAE7CC,EAAiBC,EAAAA,SAAS,IAAMP,EAAMQ,SACtCC,EAAiBF,EAAAA,SAAS,KAAA,CAC9BG,GAAIV,EAAMU,GACVC,MAAOX,EAAMY,OAAS,OAAS,UAC/BC,OAAQb,EAAMa,OACdC,UAAWV,EAAmBW,SAE1BC,EAAgBC,EAAAA,WAAWX,EAAgBG,GAE3CS,EAAMb,EAAAA,IAAI,IACVc,EAAYZ,EAAAA,SAAS,IAAMS,EAAcG,UAAUJ,OACnDK,EAAQb,EAAAA,SAAS,IAAMS,EAAcI,MAAML,OAE3CM,EAAehB,EAAAA,IAAwB,MAEvCiB,EAAeC,EAAAA,eAAe,CAClCT,UAAWO,IAMPG,EAAsBC,EAAAA,SAE5B,WACEC,EAAAA,SAAS,KACHL,EAAaN,OACfO,EAAaK,cAGnB,EARqD,YAUrDC,EAAAA,MACE,IAAMZ,EAAca,KAAKd,MACzB,CAACe,EAAQC,KACPC,QAAQC,IAAI,oDAAqD,CAC/DF,SACAD,SACAI,WAAYJ,EACZK,cAAeL,GAAQM,OAAOC,WAAW,QACzCC,QAASR,GAAQS,UAAU,EAAG,MAG5BT,IACFZ,EAAIH,MAAQe,EACZN,IAGIM,EAAOM,OAAOC,WAAW,SAC3BL,QAAQC,IAAI,+DACZ/B,EAAK,WAEL8B,QAAQC,IAAI,mEACZ/B,EAAK,eAIX,CAAEsC,WAAW,IAGfZ,QAAMV,EAAMY,IACNA,GACFN,MAiCJiB,EAAAA,UAAU,KACJvB,EAAIH,OACNS,MAIJkB,EAAa,CACXxB,MACAC,YACAC,QACAC,eACAsB,OAxCF,WACErB,GAAcqB,QAChB,EAuCEC,QArCF,WACEtB,GAAcsB,SAChB,EAoCEC,MAlCF,WACEvB,GAAcuB,OAChB,EAiCEC,WA/BF,WACExB,GAAcwB,aACdxB,GAAcuB,OAChB,EA6BEE,SA3BF,WACEC,EAAAA,iBAAiB9B,EAAIH,MACvB,EA0BEkC,OAxBF,WACE,OAAO/B,EAAIH,KACb,EAuBEmC,aArBF,WACE1B,GACF,0BAwBE2B,EAAAA,mBASM,MAAA,SATG,eAAJ9C,IAAIgB,EAAe+B,MAAKC,EAAAA,eAAA,CAAC,iBAAgB,CAAA,uBAAmCrD,EAAMY,YACrF0C,EAAAA,mBAA4F,MAAA,SAAnF,qBAAJjD,IAAID,EAAqBgD,MAAM,mCAAmC,cAAY,kBAExEjC,EAAAJ,OAAXwC,EAAAA,YAAAJ,EAAAA,mBAIM,MAJNK,EAIM,CAHJC,EAAAA,WAEOC,sBAFP,IAEO,CADLC,EAAA,KAAAA,EAAA,GAAAL,EAAAA,mBAAwD,OAAA,CAAlDF,MAAM,gCAA+B,UAAM,wBAGrDD,EAAAA,mBAA2D,MAAA,OAA/CC,MAAM,0BAA0BQ,UAAQ1C,EAAAH"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./x-markdown.cjs31.js");;/* empty css */const r=require("./x-markdown.cjs21.js").default(e.default,[["__scopeId","data-v-ddb364e9"]]);exports.default=r;
|
|
2
|
+
//# sourceMappingURL=x-markdown.cjs29.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"x-markdown.cjs29.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/dist/x-markdown.cjs33.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./x-markdown.
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./x-markdown.cjs27.js");,/* empty css */exports.default=e.default;
|
|
2
2
|
//# sourceMappingURL=x-markdown.cjs33.js.map
|
package/dist/x-markdown.cjs7.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.create,Object.defineProperty,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.prototype.hasOwnProperty,Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue");let t=null,l=null,n=!1;const
|
|
1
|
+
"use strict";Object.create,Object.defineProperty,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.prototype.hasOwnProperty,Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue");let t=null,l=null,n=!1;const o=e=>{if(!e.length)return[[]];const t=[[]];let l=t[0];const n=()=>{l=[],t.push(l)};return e.forEach(e=>{const t=e.content??"";if("\n"===t)return void n();if(!t.includes("\n"))return void l.push(e);const o=t.split("\n");o.forEach((t,a)=>{t&&l.push({...e,content:t}),a<o.length-1&&n()})}),0===t.length?[[]]:t};exports.useHighlight=function(a,r){const c=e.ref(),i=e.ref(!1),s=e.ref(null);let u=null,p="",h=null,g="",m="";const v=e.computed(()=>(e.isRef(r.theme)?r.theme.value:r.theme)||"slack-dark"),y=e.computed(()=>e.toValue(r.language)||"text"),d=e.computed(()=>c.value?.lines||[[]]),f=e.computed(()=>c.value?.preStyle),S=async(e,t=!1)=>{if(u){t&&(u.clear(),p="");const n=!t&&e.startsWith(p);let a=e;if(n?a=e.slice(p.length):t||u.clear(),p=e,!a){const e=[...u.tokensStable,...u.tokensUnstable];return void(c.value={colorReplacements:r.colorReplacements,lines:e.length?o(e):[[]],preStyle:c.value?.preStyle})}try{await u.enqueue(a);const e=[...u.tokensStable,...u.tokensUnstable];c.value={colorReplacements:r.colorReplacements,lines:o(e),preStyle:c.value?.preStyle}}catch(l){console.error("[x-markdown] Streaming highlighting failed:",l),s.value=l}}else if(h)try{const t=g||"plaintext",l=v.value,n=h.codeToTokens(e,{lang:t,theme:l});c.value={colorReplacements:r.colorReplacements,lines:o(n),preStyle:c.value?.preStyle}}catch(l){console.error("[x-markdown] Direct highlighting failed:",l),c.value={colorReplacements:r.colorReplacements,lines:[[{content:e}]],preStyle:c.value?.preStyle}}},w=async()=>{i.value=!0,s.value=null;let e=y.value;const o=v.value;try{const i=await(async()=>(t||(t=(async()=>{try{return await import("shiki")}catch{return null}})()),t))();if(!i)return c.value={colorReplacements:r.colorReplacements,lines:[[{content:a.value}]],preStyle:void 0},void(n||(n=!0,console.log("%c[x-markdown]%c 代码高亮功能已降级为纯文本模式","font-weight: bold; color: #0066cc;","color: #666;"),console.log("%c如需语法高亮功能,请安装以下依赖:","color: #666; font-weight: bold;"),console.log("%c pnpm add shiki shiki-stream","color: #00aa00; font-family: monospace;"),console.log("%c安装后请重启开发服务器","color: #999; font-size: 12px;")));h=await i.createHighlighter({themes:[o],langs:[]}),m=e;try{await h.loadLanguage(e),g=e}catch{e="plaintext",g="plaintext"}const s=await(async()=>(l||(l=(async()=>{try{return await import("shiki-stream")}catch{return null}})()),l))();s&&(u=new s.ShikiStreamTokenizer({highlighter:h,lang:e,theme:o})),p="";const v=h.getTheme(o),y=((e,t)=>{if(e||t)return{backgroundColor:e,color:t}})(v?.bg,v?.fg);a.value?(await S(a.value,!0),c.value&&(c.value.preStyle=y)):c.value={colorReplacements:r.colorReplacements,lines:[[]],preStyle:y}}catch(d){c.value={colorReplacements:r.colorReplacements,lines:[[{content:a.value}]],preStyle:void 0}}finally{i.value=!1}};return e.watch(()=>[y.value,v.value],async([e])=>{const t=e;if(h&&"plaintext"===g&&t!==m&&"plaintext"!==t)try{return await h.loadLanguage(t),void w()}catch{return void(m=t)}w()},{immediate:!0}),e.watch(a,async e=>{const t=y.value;if(h&&"plaintext"===g&&t!==m&&"plaintext"!==t)try{return await h.loadLanguage(t),void(await w())}catch{m=t}u||h?S(e):c.value={colorReplacements:r.colorReplacements,lines:[[{content:e}]],preStyle:c.value?.preStyle}}),e.onUnmounted(()=>{u?.clear(),u=null,p=""}),{streaming:c,lines:d,preStyle:f,isLoading:i,error:s}};
|
|
2
2
|
//# sourceMappingURL=x-markdown.cjs7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs7.js","sources":["../src/hooks/useHighlight.ts"],"sourcesContent":["import { ref, watch, onUnmounted, computed, isRef, toValue, type Ref, type MaybeRef, type CSSProperties } from 'vue'\r\n\r\ninterface 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: MaybeRef<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 hasShownDependencyHint = false\r\n\r\n\r\nconst showDependencyHint = () => {\r\n if (hasShownDependencyHint) return\r\n hasShownDependencyHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c 代码高亮功能已降级为纯文本模式',\r\n 'font-weight: bold; color: #0066cc;',\r\n 'color: #666;'\r\n )\r\n console.log(\r\n '%c如需语法高亮功能,请安装以下依赖:',\r\n 'color: #666; font-weight: bold;'\r\n )\r\n console.log(\r\n '%c pnpm add shiki shiki-stream',\r\n 'color: #00aa00; font-family: monospace;'\r\n )\r\n console.log(\r\n '%c安装后请重启开发服务器',\r\n 'color: #999; font-size: 12px;'\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 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 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[][] => {\r\n if (!tokens.length) return [[]]\r\n\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.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, index) => {\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 if (!tokenizer) return\r\n\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 console.error('[x-markdown] Streaming highlighting failed:', err)\r\n error.value = err as Error\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\r\n try {\r\n const mod = await loadShiki()\r\n if (!mod) {\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 showDependencyHint()\r\n return\r\n }\r\n\r\n // shiki 3.x API\r\n highlighter = await mod.createHighlighter({\r\n themes: [currentTheme],\r\n langs: [], // 将动态加载语言\r\n })\r\n\r\n lastRequestedLang = currentLang\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 }\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) {\r\n updateTokens(newText)\r\n } else if (!highlighter) {\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":["shikiModulePromise","shikiStreamModulePromise","hasShownDependencyHint","tokensToLineTokens","tokens","length","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","console","initHighlighter","currentLang","currentTheme","mod","import","loadShiki","log","createHighlighter","themes","langs","loadLanguage","shikiStreamMod","loadShikiStream","ShikiStreamTokenizer","lang","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 { ref, watch, onUnmounted, computed, isRef, toValue, type Ref, type MaybeRef, type CSSProperties } from 'vue'\r\n\r\ninterface 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: MaybeRef<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 hasShownDependencyHint = false\r\n\r\n\r\nconst showDependencyHint = () => {\r\n if (hasShownDependencyHint) return\r\n hasShownDependencyHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c 代码高亮功能已降级为纯文本模式',\r\n 'font-weight: bold; color: #0066cc;',\r\n 'color: #666;'\r\n )\r\n console.log(\r\n '%c如需语法高亮功能,请安装以下依赖:',\r\n 'color: #666; font-weight: bold;'\r\n )\r\n console.log(\r\n '%c pnpm add shiki shiki-stream',\r\n 'color: #00aa00; font-family: monospace;'\r\n )\r\n console.log(\r\n '%c安装后请重启开发服务器',\r\n 'color: #999; font-size: 12px;'\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 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 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[][] => {\r\n if (!tokens.length) return [[]]\r\n\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.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, index) => {\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 console.error('[x-markdown] Streaming highlighting failed:', err)\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 streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: tokensToLineTokens(tokens),\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n } catch (err) {\r\n console.error('[x-markdown] Direct highlighting failed:', 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\r\n try {\r\n const mod = await loadShiki()\r\n if (!mod) {\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 showDependencyHint()\r\n return\r\n }\r\n\r\n // shiki 3.x API\r\n highlighter = await mod.createHighlighter({\r\n themes: [currentTheme],\r\n langs: [], // 将动态加载语言\r\n })\r\n\r\n lastRequestedLang = currentLang\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 }\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":["shikiModulePromise","shikiStreamModulePromise","hasShownDependencyHint","tokensToLineTokens","tokens","length","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","console","currentLang","currentTheme","codeToTokens","lang","initHighlighter","mod","import","loadShiki","log","createHighlighter","themes","langs","loadLanguage","shikiStreamMod","loadShikiStream","ShikiStreamTokenizer","themeInfo","getTheme","preStyleValue","bg","fg","backgroundColor","color","createPreStyle","watch","newLang","requestedLang","immediate","newText","onUnmounted"],"mappings":"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"}
|
package/dist/x-markdown.es19.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineComponent, ref, computed, createElementBlock, openBlock, normalizeClass, createCommentVNode, createElementVNode, renderSlot, unref, toDisplayString, Fragment, renderList, normalizeStyle, createBlock, resolveDynamicComponent, createVNode, h } from "vue";
|
|
2
2
|
import { useClipboard } from "./x-markdown.es26.js";
|
|
3
|
-
import SyntaxCodeBlock from "./x-markdown.
|
|
3
|
+
import SyntaxCodeBlock from "./x-markdown.es29.js";
|
|
4
4
|
const _hoisted_1 = { class: "x-md-code-header" };
|
|
5
5
|
const _hoisted_2 = { class: "x-md-code-header__left" };
|
|
6
6
|
const _hoisted_3 = ["title"];
|
package/dist/x-markdown.es24.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineComponent, ref, computed, onMounted, createBlock, createElementBlock, openBlock, normalizeClass, createVNode, withDirectives, Transition, withCtx, createElementVNode, renderSlot, normalizeProps, guardReactiveProps, Fragment, renderList, normalizeStyle, createCommentVNode, resolveDynamicComponent, unref, vShow, h } from "vue";
|
|
2
2
|
import { useClipboard } from "./x-markdown.es26.js";
|
|
3
3
|
import { checkMermaidAvailable } from "./x-markdown.es9.js";
|
|
4
|
-
import _sfc_main$1 from "./x-markdown.
|
|
4
|
+
import _sfc_main$1 from "./x-markdown.es27.js";
|
|
5
5
|
/* empty css */
|
|
6
6
|
import CodeBlock from "./x-markdown.es17.js";
|
|
7
7
|
const _hoisted_1 = { class: "toolbar-container" };
|
|
@@ -38,7 +38,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
38
38
|
const props = __props;
|
|
39
39
|
const syntaxMermaidRef = ref(null);
|
|
40
40
|
const showSourceCode = ref(false);
|
|
41
|
-
const isDegraded = ref(
|
|
41
|
+
const isDegraded = ref(true);
|
|
42
42
|
const mermaidContent = computed(() => props.raw?.content || "");
|
|
43
43
|
const mermaidId = computed(() => `mermaid-${props.raw?.key || "default"}`);
|
|
44
44
|
const isLoading = computed(() => syntaxMermaidRef.value?.isLoading ?? true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es24.js","sources":["../src/components/Mermaid/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport type { MdComponent, MermaidExposeProps, MermaidAction, MermaidSlotProps } from './types'\r\nimport type { VNode } from 'vue'\r\nimport { computed, ref, h, onMounted } from 'vue'\r\nimport { useClipboard } from '@vueuse/core'\r\n// 使用运行时检测\r\nimport { checkMermaidAvailable } from '../../hooks/useMermaid'\r\nimport SyntaxMermaid from './SyntaxMermaid.vue'\r\nimport CodeBlock from '../CodeBlock/index.vue'\r\n\r\ninterface MermaidProps extends MdComponent {\r\n isDark?: boolean\r\n shikiTheme?: [string, string]\r\n config?: Record<string, any>\r\n mermaidActions?: MermaidAction[]\r\n}\r\n\r\nconst props = withDefaults(defineProps<MermaidProps>(), {\r\n raw: () => ({}),\r\n isDark: false,\r\n shikiTheme: () => ['vitesse-light', 'vitesse-dark'],\r\n config: () => ({}),\r\n mermaidActions: undefined,\r\n})\r\n\r\nconst syntaxMermaidRef = ref<InstanceType<typeof SyntaxMermaid> | null>(null)\r\nconst showSourceCode = ref(false)\r\n// 运行时检测 mermaid 是否可用\r\nconst isDegraded = ref(false)\r\nconst mermaidContent = computed(() => props.raw?.content || '')\r\nconst mermaidId = computed(() => `mermaid-${props.raw?.key || 'default'}`)\r\nconst isLoading = computed(() => syntaxMermaidRef.value?.isLoading ?? true)\r\nconst svg = computed(() => syntaxMermaidRef.value?.svg ?? '')\r\nconst activeTab = computed(() => (showSourceCode.value ? 'code' : 'diagram'))\r\n\r\nfunction handleZoomIn(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.zoomIn()\r\n }\r\n}\r\n\r\nfunction handleZoomOut(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.zoomOut()\r\n }\r\n}\r\n\r\nfunction handleReset(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.reset()\r\n }\r\n}\r\n\r\nfunction handleFullscreen() {\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.fullscreen()\r\n }\r\n}\r\n\r\nfunction handleToggleCode() {\r\n showSourceCode.value = !showSourceCode.value\r\n}\r\n\r\nconst { copy: copyCode, copied } = useClipboard({ copiedDuring: 1500 })\r\n\r\nfunction handleTabClick(tabName: string) {\r\n if (tabName === 'code' && !showSourceCode.value) {\r\n showSourceCode.value = true\r\n } else if (tabName === 'diagram' && showSourceCode.value) {\r\n showSourceCode.value = false\r\n }\r\n}\r\n\r\nasync function handleCopyCode(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n\r\n if (copied.value) {\r\n return\r\n }\r\n\r\n if (!props.raw.content) {\r\n return\r\n }\r\n await copyCode(props.raw.content)\r\n}\r\n\r\nfunction handleDownload() {\r\n syntaxMermaidRef.value?.download()\r\n}\r\n\r\nconst normalizedActions = computed<MermaidAction[]>(() => {\r\n return props.mermaidActions || []\r\n})\r\n\r\nconst filteredActions = computed<MermaidAction[]>(() => {\r\n return normalizedActions.value.filter((action) => {\r\n if (!action.show) return true\r\n return action.show(slotProps.value)\r\n })\r\n})\r\n\r\nconst slotProps = computed<MermaidSlotProps>(() => ({\r\n showSourceCode: showSourceCode.value,\r\n svg: svg.value,\r\n rawContent: props.raw.content || '',\r\n isLoading: isLoading.value,\r\n copied: copied.value,\r\n zoomIn: handleZoomIn,\r\n zoomOut: handleZoomOut,\r\n reset: handleReset,\r\n fullscreen: handleFullscreen,\r\n toggleCode: handleToggleCode,\r\n copyCode: handleCopyCode,\r\n download: handleDownload,\r\n raw: props.raw,\r\n}))\r\n\r\nfunction renderActionIcon(action: MermaidAction): VNode | null {\r\n if (!action.icon) return null\r\n\r\n if (typeof action.icon === 'string') {\r\n return h('span', {\r\n class: 'mermaid-action-icon',\r\n innerHTML: action.icon,\r\n })\r\n }\r\n\r\n if (typeof action.icon === 'function') {\r\n try {\r\n const result = (action.icon as (props: MermaidSlotProps) => VNode)(slotProps.value)\r\n if (result && typeof result === 'object' && '__v_isVNode' in result) {\r\n return result\r\n }\r\n } catch {}\r\n return h(action.icon as any)\r\n }\r\n\r\n return h(action.icon as any)\r\n}\r\n\r\nfunction handleActionClick(action: MermaidAction) {\r\n if (action.disabled) return\r\n action.onClick?.(slotProps.value)\r\n}\r\n\r\nconst exposedMethods = computed(\r\n () =>\r\n ({\r\n showSourceCode: showSourceCode.value,\r\n svg: svg.value,\r\n rawContent: props.raw.content || '',\r\n isLoading: isLoading.value,\r\n copied: copied.value,\r\n zoomIn: handleZoomIn,\r\n zoomOut: handleZoomOut,\r\n reset: handleReset,\r\n fullscreen: handleFullscreen,\r\n toggleCode: handleToggleCode,\r\n copyCode: handleCopyCode,\r\n download: handleDownload,\r\n raw: props.raw,\r\n }) satisfies MermaidExposeProps,\r\n)\r\n\r\n// 组件挂载时检测 mermaid 是否可用\r\nonMounted(async () => {\r\n const hasMermaid = await checkMermaidAvailable()\r\n isDegraded.value = !hasMermaid\r\n})\r\n</script>\r\n\r\n<template>\r\n <!-- 当 Mermaid 不可用时(降级),渲染 CodeBlock -->\r\n <CodeBlock\r\n v-if=\"isDegraded\"\r\n :code=\"props.raw?.content || ''\"\r\n language=\"mermaid\"\r\n :is-dark=\"props.isDark\"\r\n :light-theme=\"props.shikiTheme[0]\"\r\n :dark-theme=\"props.shikiTheme[1]\"\r\n />\r\n\r\n <!-- 当 Mermaid 可用时,渲染完整的 Mermaid 组件 -->\r\n <div v-else :key=\"props.raw.key\" class=\"markdown-mermaid\" :class=\"{ 'markdown-mermaid--dark': props.isDark }\">\r\n <Transition name=\"toolbar\" appear>\r\n <div class=\"toolbar-container\">\r\n <slot name=\"mermaidHeader\" v-bind=\"exposedMethods\">\r\n <div class=\"mermaid-toolbar\">\r\n <div class=\"toolbar-left\">\r\n <div class=\"segmented-control\">\r\n <div class=\"segmented-slider\" :class=\"{ 'slide-right': activeTab === 'code' }\" />\r\n <div\r\n class=\"segment-item\"\r\n :class=\"{ active: activeTab === 'diagram' }\"\r\n @click=\"handleTabClick('diagram')\"\r\n >\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M12 2L2 7L12 12L22 7L12 2Z\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M2 17L12 22L22 17\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M2 12L12 17L22 12\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span>预览</span>\r\n </div>\r\n <div class=\"segment-item\" :class=\"{ active: activeTab === 'code' }\" @click=\"handleTabClick('code')\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M16 18L22 12L16 6\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M8 6L2 12L8 18\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span>代码</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"toolbar-right\">\r\n <slot name=\"mermaidActions\" v-bind=\"exposedMethods\">\r\n <div\r\n v-for=\"action in filteredActions\"\r\n :key=\"action.key\"\r\n class=\"toolbar-action-btn\"\r\n :class=\"[action.class, { 'toolbar-action-btn--disabled': action.disabled }]\"\r\n :style=\"action.style\"\r\n :title=\"action.title\"\r\n @click=\"handleActionClick(action)\"\r\n >\r\n <component :is=\"renderActionIcon(action)\" v-if=\"action.icon\" />\r\n </div>\r\n\r\n <template v-if=\"showSourceCode\">\r\n <div\r\n class=\"toolbar-action-btn\"\r\n :class=\"{ 'copy-success': copied }\"\r\n title=\"复制代码\"\r\n @click=\"handleCopyCode($event)\"\r\n >\r\n <svg\r\n v-if=\"copied\"\r\n width=\"16\"\r\n height=\"16\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 1024 1024\"\r\n >\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M406.656 706.944 195.84 496.256a32 32 0 1 0-45.248 45.248l256 256 512-512a32 32 0 0 0-45.248-45.248L406.592 706.944z\"\r\n />\r\n </svg>\r\n <svg v-else width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M768 832a128 128 0 0 1-128 128H192A128 128 0 0 1 64 832V384a128 128 0 0 1 128-128v64a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64z\"\r\n />\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M384 128a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64V192a64 64 0 0 0-64-64zm0-64h448a128 128 0 0 1 128 128v448a128 128 0 0 1-128 128H384a128 128 0 0 1-128-128V192A128 128 0 0 1 384 64\"\r\n />\r\n </svg>\r\n </div>\r\n </template>\r\n\r\n <template v-else>\r\n <div class=\"toolbar-action-btn\" title=\"缩小\" @click=\"handleZoomOut($event)\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704M352 448h256a32 32 0 0 1 0 64H352a32 32 0 0 1 0-64\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"toolbar-action-btn\" title=\"放大\" @click=\"handleZoomIn($event)\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704m-32-384v-96a32 32 0 0 1 64 0v96h96a32 32 0 0 1 0 64h-96v96a32 32 0 0 1-64 0v-96h-96a32 32 0 0 1 0-64z\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"toolbar-action-btn\" title=\"重置\" @click=\"handleReset($event)\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M512 896a384 384 0 1 0 0-768 384 384 0 0 0 0 768m0 64a448 448 0 1 1 0-896 448 448 0 0 1 0 896\"\r\n />\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M512 96a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V128a32 32 0 0 1 32-32m0 576a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V704a32 32 0 0 1 32-32M96 512a32 32 0 0 1 32-32h192a32 32 0 0 1 0 64H128a32 32 0 0 1-32-32m576 0a32 32 0 0 1 32-32h192a32 32 0 1 1 0 64H704a32 32 0 0 1-32-32\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"toolbar-action-btn\" title=\"下载\" @click=\"handleDownload\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M160 832h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64m384-253.696 236.288-236.352 45.248 45.248L508.8 704 192 387.2l45.248-45.248L480 584.704V128h64z\"\r\n />\r\n </svg>\r\n </div>\r\n </template>\r\n </slot>\r\n </div>\r\n </div>\r\n </slot>\r\n </div>\r\n </Transition>\r\n\r\n <div v-show=\"showSourceCode\" class=\"mermaid-source-code\">\r\n <CodeBlock\r\n :code=\"props.raw?.content || ''\"\r\n language=\"mermaid\"\r\n :is-dark=\"props.isDark\"\r\n :light-theme=\"props.shikiTheme[0]\"\r\n :dark-theme=\"props.shikiTheme[1]\"\r\n :show-code-block-header=\"false\"\r\n :sticky-code-block-header=\"false\"\r\n />\r\n </div>\r\n\r\n <SyntaxMermaid\r\n v-show=\"!showSourceCode\"\r\n ref=\"syntaxMermaidRef\"\r\n :content=\"mermaidContent\"\r\n :id=\"mermaidId\"\r\n :is-dark=\"props.isDark\"\r\n :config=\"props.config\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<style>\r\n.markdown-mermaid {\r\n border-radius: 8px;\r\n overflow: hidden;\r\n font-size: 0;\r\n background: rgba(0, 0, 0, 0.03);\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark {\r\n background: rgba(255, 255, 255, 0.13);\r\n}\r\n\r\n.markdown-mermaid .toolbar-container {\r\n position: relative;\r\n z-index: 10;\r\n flex-shrink: 0;\r\n background: rgba(0, 0, 0, 0.05);\r\n color: #333;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .toolbar-container {\r\n background: rgba(0, 0, 0, 0.25);\r\n color: #fff;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 8px 16px;\r\n background: transparent;\r\n color: inherit;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-left {\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segmented-control {\r\n display: flex;\r\n align-items: center;\r\n position: relative;\r\n background: rgba(0, 0, 0, 0.06);\r\n border-radius: 6px;\r\n padding: 3px;\r\n gap: 2px;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .segmented-control {\r\n background: rgba(255, 255, 255, 0.08);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segmented-slider {\r\n position: absolute;\r\n top: 3px;\r\n left: 3px;\r\n width: calc(50% - 4px);\r\n height: calc(100% - 6px);\r\n background: #fff;\r\n border-radius: 4px;\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\r\n transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\r\n z-index: 0;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .segmented-slider {\r\n background: rgba(255, 255, 255, 0.15);\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segmented-slider.slide-right {\r\n transform: translateX(calc(100% + 2px));\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n font-size: 12px;\r\n border: none;\r\n color: inherit;\r\n min-width: 60px;\r\n text-align: center;\r\n box-sizing: border-box;\r\n font-weight: 500;\r\n cursor: pointer;\r\n border-radius: 4px;\r\n padding: 5px 12px;\r\n transition: all 0.2s ease;\r\n background: transparent;\r\n opacity: 0.6;\r\n user-select: none;\r\n position: relative;\r\n z-index: 1;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item.active {\r\n opacity: 1;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .segment-item.active {\r\n color: #fff;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item:hover {\r\n opacity: 1;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item svg {\r\n flex-shrink: 0;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-right {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 28px;\r\n height: 28px;\r\n padding: 0;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: inherit;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n opacity: 0.7;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn:hover {\r\n opacity: 1;\r\n background: rgba(0, 0, 0, 0.08);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn.copy-success {\r\n opacity: 1;\r\n color: #22c55e;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .toolbar-action-btn:hover {\r\n background: rgba(255, 255, 255, 0.1);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn.toolbar-action-btn--disabled {\r\n opacity: 0.3;\r\n cursor: not-allowed;\r\n pointer-events: none;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .mermaid-action-icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .mermaid-action-icon :deep(svg) {\r\n width: 16px;\r\n height: 16px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.markdown-mermaid .mermaid-source-code {\r\n position: relative;\r\n z-index: 1;\r\n flex: 1;\r\n width: 100%;\r\n overflow: auto;\r\n box-sizing: border-box;\r\n}\r\n\r\n.toolbar-enter-active,\r\n.toolbar-leave-active {\r\n transition: opacity 0.3s ease;\r\n}\r\n\r\n.toolbar-enter-from,\r\n.toolbar-leave-to {\r\n opacity: 0;\r\n}\r\n</style>\r\n"],"names":["_createBlock","_createElementBlock","_normalizeClass","_createVNode","_Transition","_createElementVNode","_renderSlot","_normalizeProps","_guardReactiveProps","_Fragment","_renderList","_normalizeStyle","_resolveDynamicComponent","_unref","_openBlock","_withDirectives","SyntaxMermaid"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"x-markdown.es24.js","sources":["../src/components/Mermaid/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport type { MdComponent, MermaidExposeProps, MermaidAction, MermaidSlotProps } from './types'\r\nimport type { VNode } from 'vue'\r\nimport { computed, ref, h, onMounted } from 'vue'\r\nimport { useClipboard } from '@vueuse/core'\r\n// 使用运行时检测\r\nimport { checkMermaidAvailable } from '../../hooks/useMermaid'\r\nimport SyntaxMermaid from './SyntaxMermaid.vue'\r\nimport CodeBlock from '../CodeBlock/index.vue'\r\n\r\ninterface MermaidProps extends MdComponent {\r\n isDark?: boolean\r\n shikiTheme?: [string, string]\r\n config?: Record<string, any>\r\n mermaidActions?: MermaidAction[]\r\n}\r\n\r\nconst props = withDefaults(defineProps<MermaidProps>(), {\r\n raw: () => ({}),\r\n isDark: false,\r\n shikiTheme: () => ['vitesse-light', 'vitesse-dark'],\r\n config: () => ({}),\r\n mermaidActions: undefined,\r\n})\r\n\r\nconst syntaxMermaidRef = ref<InstanceType<typeof SyntaxMermaid> | null>(null)\r\nconst showSourceCode = ref(false)\r\n// 运行时检测 mermaid 是否可用\r\n// 默认为 true(降级模式),检测到可用后才切换到正常模式\r\n// 这样可以避免首次渲染时的闪烁问题\r\nconst isDegraded = ref(true)\r\nconst mermaidContent = computed(() => props.raw?.content || '')\r\nconst mermaidId = computed(() => `mermaid-${props.raw?.key || 'default'}`)\r\nconst isLoading = computed(() => syntaxMermaidRef.value?.isLoading ?? true)\r\nconst svg = computed(() => syntaxMermaidRef.value?.svg ?? '')\r\nconst activeTab = computed(() => (showSourceCode.value ? 'code' : 'diagram'))\r\n\r\nfunction handleZoomIn(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.zoomIn()\r\n }\r\n}\r\n\r\nfunction handleZoomOut(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.zoomOut()\r\n }\r\n}\r\n\r\nfunction handleReset(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.reset()\r\n }\r\n}\r\n\r\nfunction handleFullscreen() {\r\n if (!showSourceCode.value) {\r\n syntaxMermaidRef.value?.fullscreen()\r\n }\r\n}\r\n\r\nfunction handleToggleCode() {\r\n showSourceCode.value = !showSourceCode.value\r\n}\r\n\r\nconst { copy: copyCode, copied } = useClipboard({ copiedDuring: 1500 })\r\n\r\nfunction handleTabClick(tabName: string) {\r\n if (tabName === 'code' && !showSourceCode.value) {\r\n showSourceCode.value = true\r\n } else if (tabName === 'diagram' && showSourceCode.value) {\r\n showSourceCode.value = false\r\n }\r\n}\r\n\r\nasync function handleCopyCode(event?: Event) {\r\n event?.stopPropagation()\r\n event?.preventDefault()\r\n\r\n if (copied.value) {\r\n return\r\n }\r\n\r\n if (!props.raw.content) {\r\n return\r\n }\r\n await copyCode(props.raw.content)\r\n}\r\n\r\nfunction handleDownload() {\r\n syntaxMermaidRef.value?.download()\r\n}\r\n\r\nconst normalizedActions = computed<MermaidAction[]>(() => {\r\n return props.mermaidActions || []\r\n})\r\n\r\nconst filteredActions = computed<MermaidAction[]>(() => {\r\n return normalizedActions.value.filter((action) => {\r\n if (!action.show) return true\r\n return action.show(slotProps.value)\r\n })\r\n})\r\n\r\nconst slotProps = computed<MermaidSlotProps>(() => ({\r\n showSourceCode: showSourceCode.value,\r\n svg: svg.value,\r\n rawContent: props.raw.content || '',\r\n isLoading: isLoading.value,\r\n copied: copied.value,\r\n zoomIn: handleZoomIn,\r\n zoomOut: handleZoomOut,\r\n reset: handleReset,\r\n fullscreen: handleFullscreen,\r\n toggleCode: handleToggleCode,\r\n copyCode: handleCopyCode,\r\n download: handleDownload,\r\n raw: props.raw,\r\n}))\r\n\r\nfunction renderActionIcon(action: MermaidAction): VNode | null {\r\n if (!action.icon) return null\r\n\r\n if (typeof action.icon === 'string') {\r\n return h('span', {\r\n class: 'mermaid-action-icon',\r\n innerHTML: action.icon,\r\n })\r\n }\r\n\r\n if (typeof action.icon === 'function') {\r\n try {\r\n const result = (action.icon as (props: MermaidSlotProps) => VNode)(slotProps.value)\r\n if (result && typeof result === 'object' && '__v_isVNode' in result) {\r\n return result\r\n }\r\n } catch {}\r\n return h(action.icon as any)\r\n }\r\n\r\n return h(action.icon as any)\r\n}\r\n\r\nfunction handleActionClick(action: MermaidAction) {\r\n if (action.disabled) return\r\n action.onClick?.(slotProps.value)\r\n}\r\n\r\nconst exposedMethods = computed(\r\n () =>\r\n ({\r\n showSourceCode: showSourceCode.value,\r\n svg: svg.value,\r\n rawContent: props.raw.content || '',\r\n isLoading: isLoading.value,\r\n copied: copied.value,\r\n zoomIn: handleZoomIn,\r\n zoomOut: handleZoomOut,\r\n reset: handleReset,\r\n fullscreen: handleFullscreen,\r\n toggleCode: handleToggleCode,\r\n copyCode: handleCopyCode,\r\n download: handleDownload,\r\n raw: props.raw,\r\n }) satisfies MermaidExposeProps,\r\n)\r\n\r\n// 组件挂载时检测 mermaid 是否可用\r\nonMounted(async () => {\r\n const hasMermaid = await checkMermaidAvailable()\r\n isDegraded.value = !hasMermaid\r\n})\r\n</script>\r\n\r\n<template>\r\n <!-- 当 Mermaid 不可用时(降级),渲染 CodeBlock -->\r\n <CodeBlock\r\n v-if=\"isDegraded\"\r\n :code=\"props.raw?.content || ''\"\r\n language=\"mermaid\"\r\n :is-dark=\"props.isDark\"\r\n :light-theme=\"props.shikiTheme[0]\"\r\n :dark-theme=\"props.shikiTheme[1]\"\r\n />\r\n\r\n <!-- 当 Mermaid 可用时,渲染完整的 Mermaid 组件 -->\r\n <div v-else :key=\"props.raw.key\" class=\"markdown-mermaid\" :class=\"{ 'markdown-mermaid--dark': props.isDark }\">\r\n <Transition name=\"toolbar\" appear>\r\n <div class=\"toolbar-container\">\r\n <slot name=\"mermaidHeader\" v-bind=\"exposedMethods\">\r\n <div class=\"mermaid-toolbar\">\r\n <div class=\"toolbar-left\">\r\n <div class=\"segmented-control\">\r\n <div class=\"segmented-slider\" :class=\"{ 'slide-right': activeTab === 'code' }\" />\r\n <div\r\n class=\"segment-item\"\r\n :class=\"{ active: activeTab === 'diagram' }\"\r\n @click=\"handleTabClick('diagram')\"\r\n >\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M12 2L2 7L12 12L22 7L12 2Z\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M2 17L12 22L22 17\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M2 12L12 17L22 12\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span>预览</span>\r\n </div>\r\n <div class=\"segment-item\" :class=\"{ active: activeTab === 'code' }\" @click=\"handleTabClick('code')\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M16 18L22 12L16 6\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M8 6L2 12L8 18\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span>代码</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"toolbar-right\">\r\n <slot name=\"mermaidActions\" v-bind=\"exposedMethods\">\r\n <div\r\n v-for=\"action in filteredActions\"\r\n :key=\"action.key\"\r\n class=\"toolbar-action-btn\"\r\n :class=\"[action.class, { 'toolbar-action-btn--disabled': action.disabled }]\"\r\n :style=\"action.style\"\r\n :title=\"action.title\"\r\n @click=\"handleActionClick(action)\"\r\n >\r\n <component :is=\"renderActionIcon(action)\" v-if=\"action.icon\" />\r\n </div>\r\n\r\n <template v-if=\"showSourceCode\">\r\n <div\r\n class=\"toolbar-action-btn\"\r\n :class=\"{ 'copy-success': copied }\"\r\n title=\"复制代码\"\r\n @click=\"handleCopyCode($event)\"\r\n >\r\n <svg\r\n v-if=\"copied\"\r\n width=\"16\"\r\n height=\"16\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 1024 1024\"\r\n >\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M406.656 706.944 195.84 496.256a32 32 0 1 0-45.248 45.248l256 256 512-512a32 32 0 0 0-45.248-45.248L406.592 706.944z\"\r\n />\r\n </svg>\r\n <svg v-else width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M768 832a128 128 0 0 1-128 128H192A128 128 0 0 1 64 832V384a128 128 0 0 1 128-128v64a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64z\"\r\n />\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M384 128a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64V192a64 64 0 0 0-64-64zm0-64h448a128 128 0 0 1 128 128v448a128 128 0 0 1-128 128H384a128 128 0 0 1-128-128V192A128 128 0 0 1 384 64\"\r\n />\r\n </svg>\r\n </div>\r\n </template>\r\n\r\n <template v-else>\r\n <div class=\"toolbar-action-btn\" title=\"缩小\" @click=\"handleZoomOut($event)\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704M352 448h256a32 32 0 0 1 0 64H352a32 32 0 0 1 0-64\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"toolbar-action-btn\" title=\"放大\" @click=\"handleZoomIn($event)\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704m-32-384v-96a32 32 0 0 1 64 0v96h96a32 32 0 0 1 0 64h-96v96a32 32 0 0 1-64 0v-96h-96a32 32 0 0 1 0-64z\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"toolbar-action-btn\" title=\"重置\" @click=\"handleReset($event)\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M512 896a384 384 0 1 0 0-768 384 384 0 0 0 0 768m0 64a448 448 0 1 1 0-896 448 448 0 0 1 0 896\"\r\n />\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M512 96a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V128a32 32 0 0 1 32-32m0 576a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V704a32 32 0 0 1 32-32M96 512a32 32 0 0 1 32-32h192a32 32 0 0 1 0 64H128a32 32 0 0 1-32-32m576 0a32 32 0 0 1 32-32h192a32 32 0 1 1 0 64H704a32 32 0 0 1-32-32\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <div class=\"toolbar-action-btn\" title=\"下载\" @click=\"handleDownload\">\r\n <svg width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 1024\">\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M160 832h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64m384-253.696 236.288-236.352 45.248 45.248L508.8 704 192 387.2l45.248-45.248L480 584.704V128h64z\"\r\n />\r\n </svg>\r\n </div>\r\n </template>\r\n </slot>\r\n </div>\r\n </div>\r\n </slot>\r\n </div>\r\n </Transition>\r\n\r\n <div v-show=\"showSourceCode\" class=\"mermaid-source-code\">\r\n <CodeBlock\r\n :code=\"props.raw?.content || ''\"\r\n language=\"mermaid\"\r\n :is-dark=\"props.isDark\"\r\n :light-theme=\"props.shikiTheme[0]\"\r\n :dark-theme=\"props.shikiTheme[1]\"\r\n :show-code-block-header=\"false\"\r\n :sticky-code-block-header=\"false\"\r\n />\r\n </div>\r\n\r\n <SyntaxMermaid\r\n v-show=\"!showSourceCode\"\r\n ref=\"syntaxMermaidRef\"\r\n :content=\"mermaidContent\"\r\n :id=\"mermaidId\"\r\n :is-dark=\"props.isDark\"\r\n :config=\"props.config\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<style>\r\n.markdown-mermaid {\r\n border-radius: 8px;\r\n overflow: hidden;\r\n font-size: 0;\r\n background: rgba(0, 0, 0, 0.03);\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark {\r\n background: rgba(255, 255, 255, 0.13);\r\n}\r\n\r\n.markdown-mermaid .toolbar-container {\r\n position: relative;\r\n z-index: 10;\r\n flex-shrink: 0;\r\n background: rgba(0, 0, 0, 0.05);\r\n color: #333;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .toolbar-container {\r\n background: rgba(0, 0, 0, 0.25);\r\n color: #fff;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 8px 16px;\r\n background: transparent;\r\n color: inherit;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-left {\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segmented-control {\r\n display: flex;\r\n align-items: center;\r\n position: relative;\r\n background: rgba(0, 0, 0, 0.06);\r\n border-radius: 6px;\r\n padding: 3px;\r\n gap: 2px;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .segmented-control {\r\n background: rgba(255, 255, 255, 0.08);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segmented-slider {\r\n position: absolute;\r\n top: 3px;\r\n left: 3px;\r\n width: calc(50% - 4px);\r\n height: calc(100% - 6px);\r\n background: #fff;\r\n border-radius: 4px;\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\r\n transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\r\n z-index: 0;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .segmented-slider {\r\n background: rgba(255, 255, 255, 0.15);\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segmented-slider.slide-right {\r\n transform: translateX(calc(100% + 2px));\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n font-size: 12px;\r\n border: none;\r\n color: inherit;\r\n min-width: 60px;\r\n text-align: center;\r\n box-sizing: border-box;\r\n font-weight: 500;\r\n cursor: pointer;\r\n border-radius: 4px;\r\n padding: 5px 12px;\r\n transition: all 0.2s ease;\r\n background: transparent;\r\n opacity: 0.6;\r\n user-select: none;\r\n position: relative;\r\n z-index: 1;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item.active {\r\n opacity: 1;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .segment-item.active {\r\n color: #fff;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item:hover {\r\n opacity: 1;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .segment-item svg {\r\n flex-shrink: 0;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-right {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 28px;\r\n height: 28px;\r\n padding: 0;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: inherit;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n opacity: 0.7;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn:hover {\r\n opacity: 1;\r\n background: rgba(0, 0, 0, 0.08);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn.copy-success {\r\n opacity: 1;\r\n color: #22c55e;\r\n}\r\n\r\n.markdown-mermaid.markdown-mermaid--dark .mermaid-toolbar .toolbar-action-btn:hover {\r\n background: rgba(255, 255, 255, 0.1);\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .toolbar-action-btn.toolbar-action-btn--disabled {\r\n opacity: 0.3;\r\n cursor: not-allowed;\r\n pointer-events: none;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .mermaid-action-icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.markdown-mermaid .mermaid-toolbar .mermaid-action-icon :deep(svg) {\r\n width: 16px;\r\n height: 16px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.markdown-mermaid .mermaid-source-code {\r\n position: relative;\r\n z-index: 1;\r\n flex: 1;\r\n width: 100%;\r\n overflow: auto;\r\n box-sizing: border-box;\r\n}\r\n\r\n.toolbar-enter-active,\r\n.toolbar-leave-active {\r\n transition: opacity 0.3s ease;\r\n}\r\n\r\n.toolbar-enter-from,\r\n.toolbar-leave-to {\r\n opacity: 0;\r\n}\r\n</style>\r\n"],"names":["_createBlock","_createElementBlock","_normalizeClass","_createVNode","_Transition","_createElementVNode","_renderSlot","_normalizeProps","_guardReactiveProps","_Fragment","_renderList","_normalizeStyle","_resolveDynamicComponent","_unref","_openBlock","_withDirectives","SyntaxMermaid"],"mappings":"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"}
|
package/dist/x-markdown.es27.js
CHANGED
|
@@ -1,8 +1,142 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
const
|
|
1
|
+
import { defineComponent, ref, computed, nextTick, watch, onMounted, createElementBlock, openBlock, normalizeClass, createElementVNode, renderSlot } from "vue";
|
|
2
|
+
import { debounce } from "lodash-es";
|
|
3
|
+
import { useMermaid, useMermaidZoom, downloadSvgAsPng } from "./x-markdown.es9.js";
|
|
4
|
+
const _hoisted_1 = {
|
|
5
|
+
key: 0,
|
|
6
|
+
class: "syntax-mermaid__loading"
|
|
7
|
+
};
|
|
8
|
+
const _hoisted_2 = ["innerHTML"];
|
|
9
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
10
|
+
__name: "SyntaxMermaid",
|
|
11
|
+
props: {
|
|
12
|
+
content: { default: "" },
|
|
13
|
+
id: { default: "mermaid-default" },
|
|
14
|
+
isDark: { type: Boolean, default: false },
|
|
15
|
+
config: { default: () => ({}) }
|
|
16
|
+
},
|
|
17
|
+
emits: ["degraded", "ready"],
|
|
18
|
+
setup(__props, { expose: __expose, emit: __emit }) {
|
|
19
|
+
const props = __props;
|
|
20
|
+
const emit = __emit;
|
|
21
|
+
const renderContainerRef = ref(null);
|
|
22
|
+
const mermaidContent = computed(() => props.content);
|
|
23
|
+
const mermaidOptions = computed(() => ({
|
|
24
|
+
id: props.id,
|
|
25
|
+
theme: props.isDark ? "dark" : "default",
|
|
26
|
+
config: props.config,
|
|
27
|
+
container: renderContainerRef.value
|
|
28
|
+
}));
|
|
29
|
+
const mermaidResult = useMermaid(mermaidContent, mermaidOptions);
|
|
30
|
+
const svg = ref("");
|
|
31
|
+
const isLoading = computed(() => mermaidResult.isLoading.value);
|
|
32
|
+
const error = computed(() => mermaidResult.error.value);
|
|
33
|
+
const containerRef = ref(null);
|
|
34
|
+
const zoomControls = useMermaidZoom({
|
|
35
|
+
container: containerRef
|
|
36
|
+
});
|
|
37
|
+
const debouncedInitialize = debounce(initializeZoom, 500);
|
|
38
|
+
function initializeZoom() {
|
|
39
|
+
nextTick(() => {
|
|
40
|
+
if (containerRef.value) {
|
|
41
|
+
zoomControls.initialize();
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
watch(
|
|
46
|
+
() => mermaidResult.data.value,
|
|
47
|
+
(newSvg, oldSvg) => {
|
|
48
|
+
console.log("[SyntaxMermaid] mermaidResult.data.value changed:", {
|
|
49
|
+
oldSvg,
|
|
50
|
+
newSvg,
|
|
51
|
+
isNewSvg: !!newSvg,
|
|
52
|
+
startsWithSvg: newSvg?.trim().startsWith("<svg"),
|
|
53
|
+
preview: newSvg?.substring(0, 50)
|
|
54
|
+
});
|
|
55
|
+
if (newSvg) {
|
|
56
|
+
svg.value = newSvg;
|
|
57
|
+
debouncedInitialize();
|
|
58
|
+
if (newSvg.trim().startsWith("<svg")) {
|
|
59
|
+
console.log("[SyntaxMermaid] Emitting ready event - Mermaid is available");
|
|
60
|
+
emit("ready");
|
|
61
|
+
} else {
|
|
62
|
+
console.log("[SyntaxMermaid] Emitting degraded event - Mermaid not available");
|
|
63
|
+
emit("degraded");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{ immediate: true }
|
|
68
|
+
);
|
|
69
|
+
watch(svg, (newSvg) => {
|
|
70
|
+
if (newSvg) {
|
|
71
|
+
debouncedInitialize();
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
function zoomIn() {
|
|
75
|
+
zoomControls?.zoomIn();
|
|
76
|
+
}
|
|
77
|
+
function zoomOut() {
|
|
78
|
+
zoomControls?.zoomOut();
|
|
79
|
+
}
|
|
80
|
+
function reset() {
|
|
81
|
+
zoomControls?.reset();
|
|
82
|
+
}
|
|
83
|
+
function fullscreen() {
|
|
84
|
+
zoomControls?.fullscreen();
|
|
85
|
+
zoomControls?.reset();
|
|
86
|
+
}
|
|
87
|
+
function download() {
|
|
88
|
+
downloadSvgAsPng(svg.value);
|
|
89
|
+
}
|
|
90
|
+
function getSvg() {
|
|
91
|
+
return svg.value;
|
|
92
|
+
}
|
|
93
|
+
function reinitialize() {
|
|
94
|
+
debouncedInitialize();
|
|
95
|
+
}
|
|
96
|
+
onMounted(() => {
|
|
97
|
+
if (svg.value) {
|
|
98
|
+
debouncedInitialize();
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
__expose({
|
|
102
|
+
svg,
|
|
103
|
+
isLoading,
|
|
104
|
+
error,
|
|
105
|
+
containerRef,
|
|
106
|
+
zoomIn,
|
|
107
|
+
zoomOut,
|
|
108
|
+
reset,
|
|
109
|
+
fullscreen,
|
|
110
|
+
download,
|
|
111
|
+
getSvg,
|
|
112
|
+
reinitialize
|
|
113
|
+
});
|
|
114
|
+
return (_ctx, _cache) => {
|
|
115
|
+
return openBlock(), createElementBlock("div", {
|
|
116
|
+
ref_key: "containerRef",
|
|
117
|
+
ref: containerRef,
|
|
118
|
+
class: normalizeClass(["syntax-mermaid", { "syntax-mermaid--dark": props.isDark }])
|
|
119
|
+
}, [
|
|
120
|
+
createElementVNode("div", {
|
|
121
|
+
ref_key: "renderContainerRef",
|
|
122
|
+
ref: renderContainerRef,
|
|
123
|
+
class: "syntax-mermaid__render-container",
|
|
124
|
+
"aria-hidden": "true"
|
|
125
|
+
}, null, 512),
|
|
126
|
+
isLoading.value ? (openBlock(), createElementBlock("div", _hoisted_1, [
|
|
127
|
+
renderSlot(_ctx.$slots, "loading", {}, () => [
|
|
128
|
+
_cache[0] || (_cache[0] = createElementVNode("span", { class: "syntax-mermaid__loading-text" }, "加载中...", -1))
|
|
129
|
+
])
|
|
130
|
+
])) : (openBlock(), createElementBlock("div", {
|
|
131
|
+
key: 1,
|
|
132
|
+
class: "syntax-mermaid__content",
|
|
133
|
+
innerHTML: svg.value
|
|
134
|
+
}, null, 8, _hoisted_2))
|
|
135
|
+
], 2);
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
});
|
|
5
139
|
export {
|
|
6
|
-
|
|
140
|
+
_sfc_main as default
|
|
7
141
|
};
|
|
8
142
|
//# sourceMappingURL=x-markdown.es27.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es27.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"x-markdown.es27.js","sources":["../src/components/Mermaid/SyntaxMermaid.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed, nextTick, ref, watch, onMounted } from 'vue'\r\nimport { debounce } from 'lodash-es'\r\nimport { useMermaid, useMermaidZoom, downloadSvgAsPng } from '../../hooks'\r\n\r\ninterface SyntaxMermaidProps {\r\n content: string\r\n id?: string\r\n isDark?: boolean\r\n config?: Record<string, any>\r\n}\r\n\r\nconst props = withDefaults(defineProps<SyntaxMermaidProps>(), {\r\n content: '',\r\n id: 'mermaid-default',\r\n isDark: false,\r\n config: () => ({}),\r\n})\r\n\r\nconst emit = defineEmits<{\r\n degraded: []\r\n ready: []\r\n}>()\r\n\r\nconst renderContainerRef = ref<HTMLElement | null>(null)\r\n\r\nconst mermaidContent = computed(() => props.content)\r\nconst mermaidOptions = computed(() => ({\r\n id: props.id,\r\n theme: props.isDark ? 'dark' : 'default',\r\n config: props.config,\r\n container: renderContainerRef.value,\r\n}))\r\nconst mermaidResult = useMermaid(mermaidContent, mermaidOptions)\r\n\r\nconst svg = ref('')\r\nconst isLoading = computed(() => mermaidResult.isLoading.value)\r\nconst error = computed(() => mermaidResult.error.value)\r\n\r\nconst containerRef = ref<HTMLElement | null>(null)\r\n\r\nconst zoomControls = useMermaidZoom({\r\n container: containerRef,\r\n scaleStep: 0.2,\r\n minScale: 0.1,\r\n maxScale: 5,\r\n})\r\n\r\nconst debouncedInitialize = debounce(initializeZoom, 500)\r\n\r\nfunction initializeZoom() {\r\n nextTick(() => {\r\n if (containerRef.value) {\r\n zoomControls.initialize()\r\n }\r\n })\r\n}\r\n\r\nwatch(\r\n () => mermaidResult.data.value,\r\n (newSvg, oldSvg) => {\r\n console.log('[SyntaxMermaid] mermaidResult.data.value changed:', {\r\n oldSvg,\r\n newSvg,\r\n isNewSvg: !!newSvg,\r\n startsWithSvg: newSvg?.trim().startsWith('<svg'),\r\n preview: newSvg?.substring(0, 50)\r\n })\r\n\r\n if (newSvg) {\r\n svg.value = newSvg\r\n debouncedInitialize()\r\n\r\n // 检测是否成功渲染了 SVG(以 <svg 开头)\r\n if (newSvg.trim().startsWith('<svg')) {\r\n console.log('[SyntaxMermaid] Emitting ready event - Mermaid is available')\r\n emit('ready')\r\n } else {\r\n console.log('[SyntaxMermaid] Emitting degraded event - Mermaid not available')\r\n emit('degraded')\r\n }\r\n }\r\n },\r\n { immediate: true },\r\n)\r\n\r\nwatch(svg, (newSvg) => {\r\n if (newSvg) {\r\n debouncedInitialize()\r\n }\r\n})\r\n\r\nfunction zoomIn() {\r\n zoomControls?.zoomIn()\r\n}\r\n\r\nfunction zoomOut() {\r\n zoomControls?.zoomOut()\r\n}\r\n\r\nfunction reset() {\r\n zoomControls?.reset()\r\n}\r\n\r\nfunction fullscreen() {\r\n zoomControls?.fullscreen()\r\n zoomControls?.reset()\r\n}\r\n\r\nfunction download() {\r\n downloadSvgAsPng(svg.value)\r\n}\r\n\r\nfunction getSvg() {\r\n return svg.value\r\n}\r\n\r\nfunction reinitialize() {\r\n debouncedInitialize()\r\n}\r\n\r\nonMounted(() => {\r\n if (svg.value) {\r\n debouncedInitialize()\r\n }\r\n})\r\n\r\ndefineExpose({\r\n svg,\r\n isLoading,\r\n error,\r\n containerRef,\r\n zoomIn,\r\n zoomOut,\r\n reset,\r\n fullscreen,\r\n download,\r\n getSvg,\r\n reinitialize,\r\n})\r\n</script>\r\n\r\n<template>\r\n <div ref=\"containerRef\" class=\"syntax-mermaid\" :class=\"{ 'syntax-mermaid--dark': props.isDark }\">\r\n <div ref=\"renderContainerRef\" class=\"syntax-mermaid__render-container\" aria-hidden=\"true\" />\r\n\r\n <div v-if=\"isLoading\" class=\"syntax-mermaid__loading\">\r\n <slot name=\"loading\">\r\n <span class=\"syntax-mermaid__loading-text\">加载中...</span>\r\n </slot>\r\n </div>\r\n <div v-else class=\"syntax-mermaid__content\" v-html=\"svg\" />\r\n </div>\r\n</template>\r\n\r\n<style>\r\n.syntax-mermaid {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n min-height: 200px;\r\n overflow: hidden;\r\n cursor: grab;\r\n position: relative;\r\n}\r\n\r\n.syntax-mermaid__render-container {\r\n position: absolute;\r\n max-height: 0;\r\n opacity: 0;\r\n overflow: hidden;\r\n pointer-events: none;\r\n}\r\n\r\n.syntax-mermaid:active {\r\n cursor: grabbing;\r\n}\r\n\r\n.syntax-mermaid__content {\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.syntax-mermaid__content svg {\r\n transform-origin: center center;\r\n max-width: 100%;\r\n max-height: 100%;\r\n}\r\n\r\n.syntax-mermaid:fullscreen {\r\n max-height: 100vh;\r\n}\r\n\r\n.syntax-mermaid:fullscreen .syntax-mermaid__content {\r\n justify-content: center;\r\n}\r\n\r\n.syntax-mermaid__loading {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 100%;\r\n height: 100%;\r\n min-height: 200px;\r\n}\r\n\r\n.syntax-mermaid__loading-text {\r\n color: #666;\r\n font-size: 14px;\r\n}\r\n\r\n.syntax-mermaid--dark .syntax-mermaid__loading-text {\r\n color: #999;\r\n}\r\n</style>\r\n"],"names":["_createElementBlock","_normalizeClass","_createElementVNode","_openBlock","_renderSlot"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import _sfc_main from "./x-markdown.es31.js";
|
|
2
|
+
/* empty css */
|
|
3
|
+
import _export_sfc from "./x-markdown.es21.js";
|
|
4
|
+
const SyntaxCodeBlock = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-ddb364e9"]]);
|
|
5
|
+
export {
|
|
6
|
+
SyntaxCodeBlock as default
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=x-markdown.es29.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"x-markdown.es29.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
package/dist/x-markdown.es33.js
CHANGED
package/dist/x-markdown.es7.js
CHANGED
|
@@ -108,39 +108,61 @@ function useHighlight(text, options) {
|
|
|
108
108
|
const lines = computed(() => streaming.value?.lines || [[]]);
|
|
109
109
|
const preStyle = computed(() => streaming.value?.preStyle);
|
|
110
110
|
const updateTokens = async (nextText, forceReset = false) => {
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
111
|
+
if (tokenizer) {
|
|
112
|
+
if (forceReset) {
|
|
113
|
+
tokenizer.clear();
|
|
114
|
+
previousText = "";
|
|
115
|
+
}
|
|
116
|
+
const canAppend = !forceReset && nextText.startsWith(previousText);
|
|
117
|
+
let chunk = nextText;
|
|
118
|
+
if (canAppend) {
|
|
119
|
+
chunk = nextText.slice(previousText.length);
|
|
120
|
+
} else if (!forceReset) {
|
|
121
|
+
tokenizer.clear();
|
|
122
|
+
}
|
|
123
|
+
previousText = nextText;
|
|
124
|
+
if (!chunk) {
|
|
125
|
+
const mergedTokens = [...tokenizer.tokensStable, ...tokenizer.tokensUnstable];
|
|
126
|
+
streaming.value = {
|
|
127
|
+
colorReplacements: options.colorReplacements,
|
|
128
|
+
lines: mergedTokens.length ? tokensToLineTokens(mergedTokens) : [[]],
|
|
129
|
+
preStyle: streaming.value?.preStyle
|
|
130
|
+
};
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
await tokenizer.enqueue(chunk);
|
|
135
|
+
const mergedTokens = [...tokenizer.tokensStable, ...tokenizer.tokensUnstable];
|
|
136
|
+
streaming.value = {
|
|
137
|
+
colorReplacements: options.colorReplacements,
|
|
138
|
+
lines: tokensToLineTokens(mergedTokens),
|
|
139
|
+
preStyle: streaming.value?.preStyle
|
|
140
|
+
};
|
|
141
|
+
} catch (err) {
|
|
142
|
+
console.error("[x-markdown] Streaming highlighting failed:", err);
|
|
143
|
+
error.value = err;
|
|
144
|
+
}
|
|
145
|
+
} else if (highlighter) {
|
|
146
|
+
try {
|
|
147
|
+
const currentLang = currentUsedLang || "plaintext";
|
|
148
|
+
const currentTheme = effectiveTheme.value;
|
|
149
|
+
const tokens = highlighter.codeToTokens(nextText, {
|
|
150
|
+
lang: currentLang,
|
|
151
|
+
theme: currentTheme
|
|
152
|
+
});
|
|
153
|
+
streaming.value = {
|
|
154
|
+
colorReplacements: options.colorReplacements,
|
|
155
|
+
lines: tokensToLineTokens(tokens),
|
|
156
|
+
preStyle: streaming.value?.preStyle
|
|
157
|
+
};
|
|
158
|
+
} catch (err) {
|
|
159
|
+
console.error("[x-markdown] Direct highlighting failed:", err);
|
|
160
|
+
streaming.value = {
|
|
161
|
+
colorReplacements: options.colorReplacements,
|
|
162
|
+
lines: [[{ content: nextText }]],
|
|
163
|
+
preStyle: streaming.value?.preStyle
|
|
164
|
+
};
|
|
165
|
+
}
|
|
144
166
|
}
|
|
145
167
|
};
|
|
146
168
|
const initHighlighter = async () => {
|
|
@@ -234,9 +256,9 @@ function useHighlight(text, options) {
|
|
|
234
256
|
lastRequestedLang = requestedLang;
|
|
235
257
|
}
|
|
236
258
|
}
|
|
237
|
-
if (tokenizer) {
|
|
259
|
+
if (tokenizer || highlighter) {
|
|
238
260
|
updateTokens(newText);
|
|
239
|
-
} else
|
|
261
|
+
} else {
|
|
240
262
|
streaming.value = {
|
|
241
263
|
colorReplacements: options.colorReplacements,
|
|
242
264
|
lines: [[{ content: newText }]],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es7.js","sources":["../src/hooks/useHighlight.ts"],"sourcesContent":["import { ref, watch, onUnmounted, computed, isRef, toValue, type Ref, type MaybeRef, type CSSProperties } from 'vue'\r\n\r\ninterface 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: MaybeRef<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 hasShownDependencyHint = false\r\n\r\n\r\nconst showDependencyHint = () => {\r\n if (hasShownDependencyHint) return\r\n hasShownDependencyHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c 代码高亮功能已降级为纯文本模式',\r\n 'font-weight: bold; color: #0066cc;',\r\n 'color: #666;'\r\n )\r\n console.log(\r\n '%c如需语法高亮功能,请安装以下依赖:',\r\n 'color: #666; font-weight: bold;'\r\n )\r\n console.log(\r\n '%c pnpm add shiki shiki-stream',\r\n 'color: #00aa00; font-family: monospace;'\r\n )\r\n console.log(\r\n '%c安装后请重启开发服务器',\r\n 'color: #999; font-size: 12px;'\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 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 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[][] => {\r\n if (!tokens.length) return [[]]\r\n\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.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, index) => {\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 if (!tokenizer) return\r\n\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 console.error('[x-markdown] Streaming highlighting failed:', err)\r\n error.value = err as Error\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\r\n try {\r\n const mod = await loadShiki()\r\n if (!mod) {\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 showDependencyHint()\r\n return\r\n }\r\n\r\n // shiki 3.x API\r\n highlighter = await mod.createHighlighter({\r\n themes: [currentTheme],\r\n langs: [], // 将动态加载语言\r\n })\r\n\r\n lastRequestedLang = currentLang\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 }\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) {\r\n updateTokens(newText)\r\n } else if (!highlighter) {\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 { ref, watch, onUnmounted, computed, isRef, toValue, type Ref, type MaybeRef, type CSSProperties } from 'vue'\r\n\r\ninterface 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: MaybeRef<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 hasShownDependencyHint = false\r\n\r\n\r\nconst showDependencyHint = () => {\r\n if (hasShownDependencyHint) return\r\n hasShownDependencyHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c 代码高亮功能已降级为纯文本模式',\r\n 'font-weight: bold; color: #0066cc;',\r\n 'color: #666;'\r\n )\r\n console.log(\r\n '%c如需语法高亮功能,请安装以下依赖:',\r\n 'color: #666; font-weight: bold;'\r\n )\r\n console.log(\r\n '%c pnpm add shiki shiki-stream',\r\n 'color: #00aa00; font-family: monospace;'\r\n )\r\n console.log(\r\n '%c安装后请重启开发服务器',\r\n 'color: #999; font-size: 12px;'\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 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 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[][] => {\r\n if (!tokens.length) return [[]]\r\n\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.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, index) => {\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 console.error('[x-markdown] Streaming highlighting failed:', err)\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 streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: tokensToLineTokens(tokens),\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n } catch (err) {\r\n console.error('[x-markdown] Direct highlighting failed:', 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\r\n try {\r\n const mod = await loadShiki()\r\n if (!mod) {\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 showDependencyHint()\r\n return\r\n }\r\n\r\n // shiki 3.x API\r\n highlighter = await mod.createHighlighter({\r\n themes: [currentTheme],\r\n langs: [], // 将动态加载语言\r\n })\r\n\r\n lastRequestedLang = currentLang\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 }\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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hejiayue/x-markdown-test",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.134",
|
|
4
4
|
"description": "A markdown component library for Vue",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/x-markdown.cjs.js",
|
|
@@ -67,7 +67,18 @@
|
|
|
67
67
|
"vue": "^3.3.0",
|
|
68
68
|
"shiki": "^1.0.0 || ^3.0.0",
|
|
69
69
|
"shiki-stream": "^0.1.4",
|
|
70
|
-
"mermaid": "^10.0.0"
|
|
70
|
+
"mermaid": "^10.0.0 || ^11.0.0"
|
|
71
|
+
},
|
|
72
|
+
"peerDependenciesMeta": {
|
|
73
|
+
"shiki": {
|
|
74
|
+
"optional": true
|
|
75
|
+
},
|
|
76
|
+
"shiki-stream": {
|
|
77
|
+
"optional": true
|
|
78
|
+
},
|
|
79
|
+
"mermaid": {
|
|
80
|
+
"optional": true
|
|
81
|
+
}
|
|
71
82
|
},
|
|
72
83
|
"devDependencies": {
|
|
73
84
|
"@types/dompurify": "^3.0.0",
|
package/dist/x-markdown.cjs28.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),a=require("lodash-es"),n=require("./x-markdown.cjs9.js"),t={key:0,class:"syntax-mermaid__loading"},r=["innerHTML"],i=e.defineComponent({__name:"SyntaxMermaid",props:{content:{default:""},id:{default:"mermaid-default"},isDark:{type:Boolean,default:!1},config:{default:()=>({})}},emits:["degraded","ready"],setup(i,{expose:o,emit:d}){const l=i,s=d,u=e.ref(null),c=e.computed(()=>l.content),m=e.computed(()=>({id:l.id,theme:l.isDark?"dark":"default",config:l.config,container:u.value})),v=n.useMermaid(c,m),f=e.ref(""),g=e.computed(()=>v.isLoading.value),y=e.computed(()=>v.error.value),p=e.ref(null),k=n.useMermaidZoom({container:p}),x=a.debounce(function(){e.nextTick(()=>{p.value&&k.initialize()})},500);return e.watch(()=>v.data.value,(e,a)=>{console.log("[SyntaxMermaid] mermaidResult.data.value changed:",{oldSvg:a,newSvg:e,isNewSvg:!!e,startsWithSvg:e?.trim().startsWith("<svg"),preview:e?.substring(0,50)}),e&&(f.value=e,x(),e.trim().startsWith("<svg")?(console.log("[SyntaxMermaid] Emitting ready event - Mermaid is available"),s("ready")):(console.log("[SyntaxMermaid] Emitting degraded event - Mermaid not available"),s("degraded")))},{immediate:!0}),e.watch(f,e=>{e&&x()}),e.onMounted(()=>{f.value&&x()}),o({svg:f,isLoading:g,error:y,containerRef:p,zoomIn:function(){k?.zoomIn()},zoomOut:function(){k?.zoomOut()},reset:function(){k?.reset()},fullscreen:function(){k?.fullscreen(),k?.reset()},download:function(){n.downloadSvgAsPng(f.value)},getSvg:function(){return f.value},reinitialize:function(){x()}}),(a,n)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"containerRef",ref:p,class:e.normalizeClass(["syntax-mermaid",{"syntax-mermaid--dark":l.isDark}])},[e.createElementVNode("div",{ref_key:"renderContainerRef",ref:u,class:"syntax-mermaid__render-container","aria-hidden":"true"},null,512),g.value?(e.openBlock(),e.createElementBlock("div",t,[e.renderSlot(a.$slots,"loading",{},()=>[n[0]||(n[0]=e.createElementVNode("span",{class:"syntax-mermaid__loading-text"},"加载中...",-1))])])):(e.openBlock(),e.createElementBlock("div",{key:1,class:"syntax-mermaid__content",innerHTML:f.value},null,8,r))],2))}});exports.default=i;
|
|
2
|
-
//# sourceMappingURL=x-markdown.cjs28.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs28.js","sources":["../src/components/Mermaid/SyntaxMermaid.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed, nextTick, ref, watch, onMounted } from 'vue'\r\nimport { debounce } from 'lodash-es'\r\nimport { useMermaid, useMermaidZoom, downloadSvgAsPng } from '../../hooks'\r\n\r\ninterface SyntaxMermaidProps {\r\n content: string\r\n id?: string\r\n isDark?: boolean\r\n config?: Record<string, any>\r\n}\r\n\r\nconst props = withDefaults(defineProps<SyntaxMermaidProps>(), {\r\n content: '',\r\n id: 'mermaid-default',\r\n isDark: false,\r\n config: () => ({}),\r\n})\r\n\r\nconst emit = defineEmits<{\r\n degraded: []\r\n ready: []\r\n}>()\r\n\r\nconst renderContainerRef = ref<HTMLElement | null>(null)\r\n\r\nconst mermaidContent = computed(() => props.content)\r\nconst mermaidOptions = computed(() => ({\r\n id: props.id,\r\n theme: props.isDark ? 'dark' : 'default',\r\n config: props.config,\r\n container: renderContainerRef.value,\r\n}))\r\nconst mermaidResult = useMermaid(mermaidContent, mermaidOptions)\r\n\r\nconst svg = ref('')\r\nconst isLoading = computed(() => mermaidResult.isLoading.value)\r\nconst error = computed(() => mermaidResult.error.value)\r\n\r\nconst containerRef = ref<HTMLElement | null>(null)\r\n\r\nconst zoomControls = useMermaidZoom({\r\n container: containerRef,\r\n scaleStep: 0.2,\r\n minScale: 0.1,\r\n maxScale: 5,\r\n})\r\n\r\nconst debouncedInitialize = debounce(initializeZoom, 500)\r\n\r\nfunction initializeZoom() {\r\n nextTick(() => {\r\n if (containerRef.value) {\r\n zoomControls.initialize()\r\n }\r\n })\r\n}\r\n\r\nwatch(\r\n () => mermaidResult.data.value,\r\n (newSvg, oldSvg) => {\r\n console.log('[SyntaxMermaid] mermaidResult.data.value changed:', {\r\n oldSvg,\r\n newSvg,\r\n isNewSvg: !!newSvg,\r\n startsWithSvg: newSvg?.trim().startsWith('<svg'),\r\n preview: newSvg?.substring(0, 50)\r\n })\r\n\r\n if (newSvg) {\r\n svg.value = newSvg\r\n debouncedInitialize()\r\n\r\n // 检测是否成功渲染了 SVG(以 <svg 开头)\r\n if (newSvg.trim().startsWith('<svg')) {\r\n console.log('[SyntaxMermaid] Emitting ready event - Mermaid is available')\r\n emit('ready')\r\n } else {\r\n console.log('[SyntaxMermaid] Emitting degraded event - Mermaid not available')\r\n emit('degraded')\r\n }\r\n }\r\n },\r\n { immediate: true },\r\n)\r\n\r\nwatch(svg, (newSvg) => {\r\n if (newSvg) {\r\n debouncedInitialize()\r\n }\r\n})\r\n\r\nfunction zoomIn() {\r\n zoomControls?.zoomIn()\r\n}\r\n\r\nfunction zoomOut() {\r\n zoomControls?.zoomOut()\r\n}\r\n\r\nfunction reset() {\r\n zoomControls?.reset()\r\n}\r\n\r\nfunction fullscreen() {\r\n zoomControls?.fullscreen()\r\n zoomControls?.reset()\r\n}\r\n\r\nfunction download() {\r\n downloadSvgAsPng(svg.value)\r\n}\r\n\r\nfunction getSvg() {\r\n return svg.value\r\n}\r\n\r\nfunction reinitialize() {\r\n debouncedInitialize()\r\n}\r\n\r\nonMounted(() => {\r\n if (svg.value) {\r\n debouncedInitialize()\r\n }\r\n})\r\n\r\ndefineExpose({\r\n svg,\r\n isLoading,\r\n error,\r\n containerRef,\r\n zoomIn,\r\n zoomOut,\r\n reset,\r\n fullscreen,\r\n download,\r\n getSvg,\r\n reinitialize,\r\n})\r\n</script>\r\n\r\n<template>\r\n <div ref=\"containerRef\" class=\"syntax-mermaid\" :class=\"{ 'syntax-mermaid--dark': props.isDark }\">\r\n <div ref=\"renderContainerRef\" class=\"syntax-mermaid__render-container\" aria-hidden=\"true\" />\r\n\r\n <div v-if=\"isLoading\" class=\"syntax-mermaid__loading\">\r\n <slot name=\"loading\">\r\n <span class=\"syntax-mermaid__loading-text\">加载中...</span>\r\n </slot>\r\n </div>\r\n <div v-else class=\"syntax-mermaid__content\" v-html=\"svg\" />\r\n </div>\r\n</template>\r\n\r\n<style>\r\n.syntax-mermaid {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n min-height: 200px;\r\n overflow: hidden;\r\n cursor: grab;\r\n position: relative;\r\n}\r\n\r\n.syntax-mermaid__render-container {\r\n position: absolute;\r\n max-height: 0;\r\n opacity: 0;\r\n overflow: hidden;\r\n pointer-events: none;\r\n}\r\n\r\n.syntax-mermaid:active {\r\n cursor: grabbing;\r\n}\r\n\r\n.syntax-mermaid__content {\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.syntax-mermaid__content svg {\r\n transform-origin: center center;\r\n max-width: 100%;\r\n max-height: 100%;\r\n}\r\n\r\n.syntax-mermaid:fullscreen {\r\n max-height: 100vh;\r\n}\r\n\r\n.syntax-mermaid:fullscreen .syntax-mermaid__content {\r\n justify-content: center;\r\n}\r\n\r\n.syntax-mermaid__loading {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 100%;\r\n height: 100%;\r\n min-height: 200px;\r\n}\r\n\r\n.syntax-mermaid__loading-text {\r\n color: #666;\r\n font-size: 14px;\r\n}\r\n\r\n.syntax-mermaid--dark .syntax-mermaid__loading-text {\r\n color: #999;\r\n}\r\n</style>\r\n"],"names":["props","__props","emit","__emit","renderContainerRef","ref","mermaidContent","computed","content","mermaidOptions","id","theme","isDark","config","container","value","mermaidResult","useMermaid","svg","isLoading","error","containerRef","zoomControls","useMermaidZoom","debouncedInitialize","debounce","nextTick","initialize","watch","data","newSvg","oldSvg","console","log","isNewSvg","startsWithSvg","trim","startsWith","preview","substring","immediate","onMounted","__expose","zoomIn","zoomOut","reset","fullscreen","download","downloadSvgAsPng","getSvg","reinitialize","_createElementBlock","class","_normalizeClass","_createElementVNode","_openBlock","_hoisted_1","_renderSlot","_ctx","_cache","innerHTML"],"mappings":"+cAYA,MAAMA,EAAQC,EAORC,EAAOC,EAKPC,EAAqBC,EAAAA,IAAwB,MAE7CC,EAAiBC,EAAAA,SAAS,IAAMP,EAAMQ,SACtCC,EAAiBF,EAAAA,SAAS,KAAA,CAC9BG,GAAIV,EAAMU,GACVC,MAAOX,EAAMY,OAAS,OAAS,UAC/BC,OAAQb,EAAMa,OACdC,UAAWV,EAAmBW,SAE1BC,EAAgBC,EAAAA,WAAWX,EAAgBG,GAE3CS,EAAMb,EAAAA,IAAI,IACVc,EAAYZ,EAAAA,SAAS,IAAMS,EAAcG,UAAUJ,OACnDK,EAAQb,EAAAA,SAAS,IAAMS,EAAcI,MAAML,OAE3CM,EAAehB,EAAAA,IAAwB,MAEvCiB,EAAeC,EAAAA,eAAe,CAClCT,UAAWO,IAMPG,EAAsBC,EAAAA,SAE5B,WACEC,EAAAA,SAAS,KACHL,EAAaN,OACfO,EAAaK,cAGnB,EARqD,YAUrDC,EAAAA,MACE,IAAMZ,EAAca,KAAKd,MACzB,CAACe,EAAQC,KACPC,QAAQC,IAAI,oDAAqD,CAC/DF,SACAD,SACAI,WAAYJ,EACZK,cAAeL,GAAQM,OAAOC,WAAW,QACzCC,QAASR,GAAQS,UAAU,EAAG,MAG5BT,IACFZ,EAAIH,MAAQe,EACZN,IAGIM,EAAOM,OAAOC,WAAW,SAC3BL,QAAQC,IAAI,+DACZ/B,EAAK,WAEL8B,QAAQC,IAAI,mEACZ/B,EAAK,eAIX,CAAEsC,WAAW,IAGfZ,QAAMV,EAAMY,IACNA,GACFN,MAiCJiB,EAAAA,UAAU,KACJvB,EAAIH,OACNS,MAIJkB,EAAa,CACXxB,MACAC,YACAC,QACAC,eACAsB,OAxCF,WACErB,GAAcqB,QAChB,EAuCEC,QArCF,WACEtB,GAAcsB,SAChB,EAoCEC,MAlCF,WACEvB,GAAcuB,OAChB,EAiCEC,WA/BF,WACExB,GAAcwB,aACdxB,GAAcuB,OAChB,EA6BEE,SA3BF,WACEC,EAAAA,iBAAiB9B,EAAIH,MACvB,EA0BEkC,OAxBF,WACE,OAAO/B,EAAIH,KACb,EAuBEmC,aArBF,WACE1B,GACF,0BAwBE2B,EAAAA,mBASM,MAAA,SATG,eAAJ9C,IAAIgB,EAAe+B,MAAKC,EAAAA,eAAA,CAAC,iBAAgB,CAAA,uBAAmCrD,EAAMY,YACrF0C,EAAAA,mBAA4F,MAAA,SAAnF,qBAAJjD,IAAID,EAAqBgD,MAAM,mCAAmC,cAAY,kBAExEjC,EAAAJ,OAAXwC,EAAAA,YAAAJ,EAAAA,mBAIM,MAJNK,EAIM,CAHJC,EAAAA,WAEOC,sBAFP,IAEO,CADLC,EAAA,KAAAA,EAAA,GAAAL,EAAAA,mBAAwD,OAAA,CAAlDF,MAAM,gCAA+B,UAAM,wBAGrDD,EAAAA,mBAA2D,MAAA,OAA/CC,MAAM,0BAA0BQ,UAAQ1C,EAAAH"}
|
package/dist/x-markdown.es28.js
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { defineComponent, ref, computed, nextTick, watch, onMounted, createElementBlock, openBlock, normalizeClass, createElementVNode, renderSlot } from "vue";
|
|
2
|
-
import { debounce } from "lodash-es";
|
|
3
|
-
import { useMermaid, useMermaidZoom, downloadSvgAsPng } from "./x-markdown.es9.js";
|
|
4
|
-
const _hoisted_1 = {
|
|
5
|
-
key: 0,
|
|
6
|
-
class: "syntax-mermaid__loading"
|
|
7
|
-
};
|
|
8
|
-
const _hoisted_2 = ["innerHTML"];
|
|
9
|
-
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
10
|
-
__name: "SyntaxMermaid",
|
|
11
|
-
props: {
|
|
12
|
-
content: { default: "" },
|
|
13
|
-
id: { default: "mermaid-default" },
|
|
14
|
-
isDark: { type: Boolean, default: false },
|
|
15
|
-
config: { default: () => ({}) }
|
|
16
|
-
},
|
|
17
|
-
emits: ["degraded", "ready"],
|
|
18
|
-
setup(__props, { expose: __expose, emit: __emit }) {
|
|
19
|
-
const props = __props;
|
|
20
|
-
const emit = __emit;
|
|
21
|
-
const renderContainerRef = ref(null);
|
|
22
|
-
const mermaidContent = computed(() => props.content);
|
|
23
|
-
const mermaidOptions = computed(() => ({
|
|
24
|
-
id: props.id,
|
|
25
|
-
theme: props.isDark ? "dark" : "default",
|
|
26
|
-
config: props.config,
|
|
27
|
-
container: renderContainerRef.value
|
|
28
|
-
}));
|
|
29
|
-
const mermaidResult = useMermaid(mermaidContent, mermaidOptions);
|
|
30
|
-
const svg = ref("");
|
|
31
|
-
const isLoading = computed(() => mermaidResult.isLoading.value);
|
|
32
|
-
const error = computed(() => mermaidResult.error.value);
|
|
33
|
-
const containerRef = ref(null);
|
|
34
|
-
const zoomControls = useMermaidZoom({
|
|
35
|
-
container: containerRef
|
|
36
|
-
});
|
|
37
|
-
const debouncedInitialize = debounce(initializeZoom, 500);
|
|
38
|
-
function initializeZoom() {
|
|
39
|
-
nextTick(() => {
|
|
40
|
-
if (containerRef.value) {
|
|
41
|
-
zoomControls.initialize();
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
watch(
|
|
46
|
-
() => mermaidResult.data.value,
|
|
47
|
-
(newSvg, oldSvg) => {
|
|
48
|
-
console.log("[SyntaxMermaid] mermaidResult.data.value changed:", {
|
|
49
|
-
oldSvg,
|
|
50
|
-
newSvg,
|
|
51
|
-
isNewSvg: !!newSvg,
|
|
52
|
-
startsWithSvg: newSvg?.trim().startsWith("<svg"),
|
|
53
|
-
preview: newSvg?.substring(0, 50)
|
|
54
|
-
});
|
|
55
|
-
if (newSvg) {
|
|
56
|
-
svg.value = newSvg;
|
|
57
|
-
debouncedInitialize();
|
|
58
|
-
if (newSvg.trim().startsWith("<svg")) {
|
|
59
|
-
console.log("[SyntaxMermaid] Emitting ready event - Mermaid is available");
|
|
60
|
-
emit("ready");
|
|
61
|
-
} else {
|
|
62
|
-
console.log("[SyntaxMermaid] Emitting degraded event - Mermaid not available");
|
|
63
|
-
emit("degraded");
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
{ immediate: true }
|
|
68
|
-
);
|
|
69
|
-
watch(svg, (newSvg) => {
|
|
70
|
-
if (newSvg) {
|
|
71
|
-
debouncedInitialize();
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
function zoomIn() {
|
|
75
|
-
zoomControls?.zoomIn();
|
|
76
|
-
}
|
|
77
|
-
function zoomOut() {
|
|
78
|
-
zoomControls?.zoomOut();
|
|
79
|
-
}
|
|
80
|
-
function reset() {
|
|
81
|
-
zoomControls?.reset();
|
|
82
|
-
}
|
|
83
|
-
function fullscreen() {
|
|
84
|
-
zoomControls?.fullscreen();
|
|
85
|
-
zoomControls?.reset();
|
|
86
|
-
}
|
|
87
|
-
function download() {
|
|
88
|
-
downloadSvgAsPng(svg.value);
|
|
89
|
-
}
|
|
90
|
-
function getSvg() {
|
|
91
|
-
return svg.value;
|
|
92
|
-
}
|
|
93
|
-
function reinitialize() {
|
|
94
|
-
debouncedInitialize();
|
|
95
|
-
}
|
|
96
|
-
onMounted(() => {
|
|
97
|
-
if (svg.value) {
|
|
98
|
-
debouncedInitialize();
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
__expose({
|
|
102
|
-
svg,
|
|
103
|
-
isLoading,
|
|
104
|
-
error,
|
|
105
|
-
containerRef,
|
|
106
|
-
zoomIn,
|
|
107
|
-
zoomOut,
|
|
108
|
-
reset,
|
|
109
|
-
fullscreen,
|
|
110
|
-
download,
|
|
111
|
-
getSvg,
|
|
112
|
-
reinitialize
|
|
113
|
-
});
|
|
114
|
-
return (_ctx, _cache) => {
|
|
115
|
-
return openBlock(), createElementBlock("div", {
|
|
116
|
-
ref_key: "containerRef",
|
|
117
|
-
ref: containerRef,
|
|
118
|
-
class: normalizeClass(["syntax-mermaid", { "syntax-mermaid--dark": props.isDark }])
|
|
119
|
-
}, [
|
|
120
|
-
createElementVNode("div", {
|
|
121
|
-
ref_key: "renderContainerRef",
|
|
122
|
-
ref: renderContainerRef,
|
|
123
|
-
class: "syntax-mermaid__render-container",
|
|
124
|
-
"aria-hidden": "true"
|
|
125
|
-
}, null, 512),
|
|
126
|
-
isLoading.value ? (openBlock(), createElementBlock("div", _hoisted_1, [
|
|
127
|
-
renderSlot(_ctx.$slots, "loading", {}, () => [
|
|
128
|
-
_cache[0] || (_cache[0] = createElementVNode("span", { class: "syntax-mermaid__loading-text" }, "加载中...", -1))
|
|
129
|
-
])
|
|
130
|
-
])) : (openBlock(), createElementBlock("div", {
|
|
131
|
-
key: 1,
|
|
132
|
-
class: "syntax-mermaid__content",
|
|
133
|
-
innerHTML: svg.value
|
|
134
|
-
}, null, 8, _hoisted_2))
|
|
135
|
-
], 2);
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
export {
|
|
140
|
-
_sfc_main as default
|
|
141
|
-
};
|
|
142
|
-
//# sourceMappingURL=x-markdown.es28.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es28.js","sources":["../src/components/Mermaid/SyntaxMermaid.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed, nextTick, ref, watch, onMounted } from 'vue'\r\nimport { debounce } from 'lodash-es'\r\nimport { useMermaid, useMermaidZoom, downloadSvgAsPng } from '../../hooks'\r\n\r\ninterface SyntaxMermaidProps {\r\n content: string\r\n id?: string\r\n isDark?: boolean\r\n config?: Record<string, any>\r\n}\r\n\r\nconst props = withDefaults(defineProps<SyntaxMermaidProps>(), {\r\n content: '',\r\n id: 'mermaid-default',\r\n isDark: false,\r\n config: () => ({}),\r\n})\r\n\r\nconst emit = defineEmits<{\r\n degraded: []\r\n ready: []\r\n}>()\r\n\r\nconst renderContainerRef = ref<HTMLElement | null>(null)\r\n\r\nconst mermaidContent = computed(() => props.content)\r\nconst mermaidOptions = computed(() => ({\r\n id: props.id,\r\n theme: props.isDark ? 'dark' : 'default',\r\n config: props.config,\r\n container: renderContainerRef.value,\r\n}))\r\nconst mermaidResult = useMermaid(mermaidContent, mermaidOptions)\r\n\r\nconst svg = ref('')\r\nconst isLoading = computed(() => mermaidResult.isLoading.value)\r\nconst error = computed(() => mermaidResult.error.value)\r\n\r\nconst containerRef = ref<HTMLElement | null>(null)\r\n\r\nconst zoomControls = useMermaidZoom({\r\n container: containerRef,\r\n scaleStep: 0.2,\r\n minScale: 0.1,\r\n maxScale: 5,\r\n})\r\n\r\nconst debouncedInitialize = debounce(initializeZoom, 500)\r\n\r\nfunction initializeZoom() {\r\n nextTick(() => {\r\n if (containerRef.value) {\r\n zoomControls.initialize()\r\n }\r\n })\r\n}\r\n\r\nwatch(\r\n () => mermaidResult.data.value,\r\n (newSvg, oldSvg) => {\r\n console.log('[SyntaxMermaid] mermaidResult.data.value changed:', {\r\n oldSvg,\r\n newSvg,\r\n isNewSvg: !!newSvg,\r\n startsWithSvg: newSvg?.trim().startsWith('<svg'),\r\n preview: newSvg?.substring(0, 50)\r\n })\r\n\r\n if (newSvg) {\r\n svg.value = newSvg\r\n debouncedInitialize()\r\n\r\n // 检测是否成功渲染了 SVG(以 <svg 开头)\r\n if (newSvg.trim().startsWith('<svg')) {\r\n console.log('[SyntaxMermaid] Emitting ready event - Mermaid is available')\r\n emit('ready')\r\n } else {\r\n console.log('[SyntaxMermaid] Emitting degraded event - Mermaid not available')\r\n emit('degraded')\r\n }\r\n }\r\n },\r\n { immediate: true },\r\n)\r\n\r\nwatch(svg, (newSvg) => {\r\n if (newSvg) {\r\n debouncedInitialize()\r\n }\r\n})\r\n\r\nfunction zoomIn() {\r\n zoomControls?.zoomIn()\r\n}\r\n\r\nfunction zoomOut() {\r\n zoomControls?.zoomOut()\r\n}\r\n\r\nfunction reset() {\r\n zoomControls?.reset()\r\n}\r\n\r\nfunction fullscreen() {\r\n zoomControls?.fullscreen()\r\n zoomControls?.reset()\r\n}\r\n\r\nfunction download() {\r\n downloadSvgAsPng(svg.value)\r\n}\r\n\r\nfunction getSvg() {\r\n return svg.value\r\n}\r\n\r\nfunction reinitialize() {\r\n debouncedInitialize()\r\n}\r\n\r\nonMounted(() => {\r\n if (svg.value) {\r\n debouncedInitialize()\r\n }\r\n})\r\n\r\ndefineExpose({\r\n svg,\r\n isLoading,\r\n error,\r\n containerRef,\r\n zoomIn,\r\n zoomOut,\r\n reset,\r\n fullscreen,\r\n download,\r\n getSvg,\r\n reinitialize,\r\n})\r\n</script>\r\n\r\n<template>\r\n <div ref=\"containerRef\" class=\"syntax-mermaid\" :class=\"{ 'syntax-mermaid--dark': props.isDark }\">\r\n <div ref=\"renderContainerRef\" class=\"syntax-mermaid__render-container\" aria-hidden=\"true\" />\r\n\r\n <div v-if=\"isLoading\" class=\"syntax-mermaid__loading\">\r\n <slot name=\"loading\">\r\n <span class=\"syntax-mermaid__loading-text\">加载中...</span>\r\n </slot>\r\n </div>\r\n <div v-else class=\"syntax-mermaid__content\" v-html=\"svg\" />\r\n </div>\r\n</template>\r\n\r\n<style>\r\n.syntax-mermaid {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n min-height: 200px;\r\n overflow: hidden;\r\n cursor: grab;\r\n position: relative;\r\n}\r\n\r\n.syntax-mermaid__render-container {\r\n position: absolute;\r\n max-height: 0;\r\n opacity: 0;\r\n overflow: hidden;\r\n pointer-events: none;\r\n}\r\n\r\n.syntax-mermaid:active {\r\n cursor: grabbing;\r\n}\r\n\r\n.syntax-mermaid__content {\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.syntax-mermaid__content svg {\r\n transform-origin: center center;\r\n max-width: 100%;\r\n max-height: 100%;\r\n}\r\n\r\n.syntax-mermaid:fullscreen {\r\n max-height: 100vh;\r\n}\r\n\r\n.syntax-mermaid:fullscreen .syntax-mermaid__content {\r\n justify-content: center;\r\n}\r\n\r\n.syntax-mermaid__loading {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 100%;\r\n height: 100%;\r\n min-height: 200px;\r\n}\r\n\r\n.syntax-mermaid__loading-text {\r\n color: #666;\r\n font-size: 14px;\r\n}\r\n\r\n.syntax-mermaid--dark .syntax-mermaid__loading-text {\r\n color: #999;\r\n}\r\n</style>\r\n"],"names":["_createElementBlock","_normalizeClass","_createElementVNode","_openBlock","_renderSlot"],"mappings":"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"}
|