@hejiayue/x-markdown-test 0.0.1-beta.134 → 0.0.1-beta.136
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.cjs27.js +1 -1
- package/dist/x-markdown.cjs27.js.map +1 -1
- package/dist/x-markdown.cjs28.js +2 -0
- package/dist/x-markdown.cjs28.js.map +1 -0
- package/dist/x-markdown.cjs33.js +1 -1
- package/dist/x-markdown.cjs9.js +1 -1
- package/dist/x-markdown.cjs9.js.map +1 -1
- package/dist/x-markdown.es19.js +1 -1
- package/dist/x-markdown.es24.js +1 -1
- package/dist/x-markdown.es27.js +5 -139
- package/dist/x-markdown.es27.js.map +1 -1
- package/dist/x-markdown.es28.js +142 -0
- package/dist/x-markdown.es28.js.map +1 -0
- package/dist/x-markdown.es33.js +1 -1
- package/dist/x-markdown.es9.js +3 -1
- package/dist/x-markdown.es9.js.map +1 -1
- package/package.json +5 -3
- package/src/vite-plugin.js +116 -0
- package/dist/x-markdown.cjs29.js +0 -2
- package/dist/x-markdown.cjs29.js.map +0 -1
- package/dist/x-markdown.es29.js +0 -8
- package/dist/x-markdown.es29.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.cjs27.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.cjs28.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
|
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("
|
|
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
2
|
//# sourceMappingURL=x-markdown.cjs27.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs27.js","sources":[
|
|
1
|
+
{"version":3,"file":"x-markdown.cjs27.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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.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.cjs28.js");,/* empty css */exports.default=e.default;
|
|
2
2
|
//# sourceMappingURL=x-markdown.cjs33.js.map
|
package/dist/x-markdown.cjs9.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("lodash-es"),t=require("vue");let n=null,o=!1,a=null,r=null;const l=[];let u=!1;exports.checkMermaidAvailable=async function(){return null!==a?a:r||(r=(async()=>{try{const e=await import("mermaid");return a
|
|
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("lodash-es"),t=require("vue");let n=null,o=!1,a=null,r=null;const l=[];let u=!1;exports.checkMermaidAvailable=async function(){return null!==a?a:r||(r=(async()=>{try{const e=await import("mermaid"),t=e?.default,n=t&&("function"==typeof t.render||"function"==typeof t.initialize||"function"==typeof t.run);return a=n,a}catch{return a=!1,!1}})(),r)},exports.downloadSvgAsPng=function(e){if(e)try{const t=`data:image/svg+xml;charset=utf-8,${encodeURIComponent(e)}`,n=new Image;n.onload=()=>{try{const o=document.createElement("canvas"),a=o.getContext("2d",{willReadFrequently:!1});if(!a)return;const r=2;o.width=n.width*r,o.height=n.height*r,a.imageSmoothingEnabled=!0,a.imageSmoothingQuality="high",a.fillStyle="#ffffff",a.fillRect(0,0,o.width,o.height),a.drawImage(n,0,0,o.width,o.height);const l=(new Date).toISOString().slice(0,19).replace(/:/g,"-");try{o.toBlob(e=>{if(!e)return;const t=URL.createObjectURL(e),n=document.createElement("a");n.href=t,n.download=`mermaid-diagram-${l}.png`,document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(t)},"image/png",.95)}catch(e){console.error("Failed to convert canvas to blob:",e);try{const e=o.toDataURL("image/png",.95),t=document.createElement("a");t.href=e,t.download=`mermaid-diagram-${l}.png`,document.body.appendChild(t),t.click(),document.body.removeChild(t)}catch(t){console.error("Failed to convert canvas to data URL:",t)}}}catch(o){console.error("Canvas operation failed:",o)}},n.onerror=e=>{console.error("Failed to load image:",e)},n.src=t}catch(t){console.error("Failed to download SVG:",t)}},exports.useMermaid=function(a,r={}){const c=t.computed(()=>"object"==typeof r&&"value"in r?r.value:r),i=t.computed(()=>({suppressErrorRendering:!0,startOnLoad:!1,securityLevel:"loose",theme:c.value.theme||"default",...c.value.config||{}})),s=t.ref(""),d=t.ref(null),v=t.ref(!1);let m=!1;const f=e.throttle(()=>{const e="string"==typeof a?a:a.value;if(!e?.trim())return s.value="",d.value=null,void(v.value=!1);var t;v.value=!0,t=async()=>{if(!m)try{const t=await async function(){return"undefined"==typeof window?null:(n||(n=(async()=>{try{const e=await import("mermaid");return e?.default}catch{return o||(o=!0,console.log("%c[x-markdown]%c Mermaid 图表功能已降级为代码块显示","font-weight: bold; color: #9333ea;","color: #666;"),console.log("%c如需 Mermaid 图表渲染功能,请安装:","color: #666; font-weight: bold;"),console.log("%c pnpm add mermaid","color: #9333ea; font-family: monospace;"),console.log("%c安装后请重启开发服务器","color: #999; font-size: 12px;")),null}})()),n)}();if(!t)return s.value=e,d.value=null,void(v.value=!1);if(t.initialize(i.value),!(await t.parse(e.trim())))return s.value="",d.value=new Error("Mermaid parse error: Invalid syntax"),void(v.value=!1);const a=`${c.value.id||"mermaid"}-${Math.random().toString(36).substring(2,11)}`,r=(()=>{const e=c.value.container;return e?"object"==typeof e&&"value"in e?e.value:e:null})();if(!r)return void(v.value=!1);const{svg:l}=await t.render(a,e,r);s.value=l,d.value=null,v.value=!1}catch(t){s.value="",d.value=t,v.value=!1}},l.push(t),async function(){if(!u){for(u=!0;l.length>0;){const t=l.shift();if(t)try{await t()}catch(e){console.error("Mermaid render queue error:",e)}}u=!1}}()},100,{leading:!1,trailing:!0});return t.watch([()=>"string"==typeof a?a:a.value,()=>i.value],()=>{f()},{immediate:!0}),t.onUnmounted(()=>{m=!0}),{data:s,error:d,isLoading:v}},exports.useMermaidZoom=function(n){const{container:o}=n,a=t.ref(1),r=t.ref(0),l=t.ref(0),u=t.ref(!1);let c=null;const i=()=>o.value?.querySelector(".syntax-mermaid__content svg"),s=e=>{e.style.transformOrigin="center center",e.style.transform=`translate(${r.value}px, ${l.value}px) scale(${a.value})`},d=()=>{a.value=1,r.value=0,l.value=0,u.value=!1},v=()=>{c?.(),c=null,d()};return t.watch(()=>o.value,()=>{v(),d()}),t.onUnmounted(v),{zoomIn:()=>{const e=i();e&&(a.value=Math.min(a.value+.2,10),s(e))},zoomOut:()=>{const e=i();e&&(a.value=Math.max(a.value-.2,.1),s(e))},reset:()=>{const e=i();e&&(d(),s(e))},fullscreen:()=>{o.value&&(document.fullscreenElement?document.exitFullscreen():o.value.requestFullscreen?.())},destroy:v,initialize:()=>{if(!o.value)return;d(),c=(t=>{let n=0,o=0,c=!1;const d=(e,t)=>{u.value=!0,n=e-r.value,o=t-l.value,document.body.style.userSelect="none"},v=(e,t)=>{if(u.value&&c){r.value=e-n,l.value=t-o;const a=i();a&&s(a)}},m=()=>{u.value=!1,c=!1,document.body.style.userSelect=""},f=e=>{0===e.button&&(e.target===t||t.contains(e.target))&&(e.preventDefault(),c=!0,d(e.clientX,e.clientY))},h=e=>{c&&v(e.clientX,e.clientY)},g=e.throttle(e=>{const n=i();if(!n)return;const o=t.getBoundingClientRect(),u=n.getBoundingClientRect(),c=e.clientX-o.left,d=e.clientY-o.top,v=u.left-o.left+u.width/2,m=u.top-o.top+u.height/2,f=(c-v-r.value)/a.value,h=(d-m-l.value)/a.value,g=e.deltaY>0?-.05:.05,p=Math.min(Math.max(a.value+g,.1),10);p!==a.value&&(a.value=p,r.value=c-v-f*a.value,l.value=d-m-h*a.value,s(n))},20,{leading:!0,trailing:!0}),p=e=>{(e.target===t||t.contains(e.target))&&(e.preventDefault(),g(e))},y=e=>{(e.target===t||t.contains(e.target))&&1===e.touches.length&&(e.preventDefault(),c=!0,d(e.touches[0].clientX,e.touches[0].clientY))},w=e=>{c&&(e.preventDefault(),v(e.touches[0].clientX,e.touches[0].clientY))};return t.addEventListener("mousedown",f),document.addEventListener("mousemove",h),document.addEventListener("mouseup",m),t.addEventListener("wheel",p,{passive:!1}),t.addEventListener("touchstart",y,{passive:!1}),t.addEventListener("touchmove",w,{passive:!1}),document.addEventListener("touchend",m),()=>{t.removeEventListener("mousedown",f),document.removeEventListener("mousemove",h),document.removeEventListener("mouseup",m),t.removeEventListener("wheel",p),t.removeEventListener("touchstart",y),t.removeEventListener("touchmove",w),document.removeEventListener("touchend",m),document.body.style.userSelect=""}})(o.value);const t=i();t&&s(t)}}};
|
|
2
2
|
//# sourceMappingURL=x-markdown.cjs9.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs9.js","sources":["../src/hooks/useMermaid.ts"],"sourcesContent":["import type { Ref } from 'vue'\r\nimport { throttle } from 'lodash-es'\r\nimport { computed, ref, watch, onUnmounted } from 'vue'\r\nimport type { MermaidZoomControls, UseMermaidZoomOptions, UseMermaidResult } from '../components/Mermaid/types'\r\n\r\nexport function downloadSvgAsPng(svg: string): void {\r\n if (!svg) return\r\n\r\n try {\r\n const svgDataUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`\r\n const img = new Image()\r\n\r\n img.onload = () => {\r\n try {\r\n const canvas = document.createElement('canvas')\r\n const ctx = canvas.getContext('2d', { willReadFrequently: false })\r\n if (!ctx) return\r\n\r\n const scale = 2\r\n canvas.width = img.width * scale\r\n canvas.height = img.height * scale\r\n ctx.imageSmoothingEnabled = true\r\n ctx.imageSmoothingQuality = 'high'\r\n\r\n ctx.fillStyle = '#ffffff'\r\n ctx.fillRect(0, 0, canvas.width, canvas.height)\r\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height)\r\n\r\n const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-')\r\n\r\n try {\r\n canvas.toBlob(\r\n (blob) => {\r\n if (!blob) return\r\n const url = URL.createObjectURL(blob)\r\n const link = document.createElement('a')\r\n link.href = url\r\n link.download = `mermaid-diagram-${timestamp}.png`\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n URL.revokeObjectURL(url)\r\n },\r\n 'image/png',\r\n 0.95,\r\n )\r\n } catch (toBlobError) {\r\n console.error('Failed to convert canvas to blob:', toBlobError)\r\n try {\r\n const dataUrl = canvas.toDataURL('image/png', 0.95)\r\n const link = document.createElement('a')\r\n link.href = dataUrl\r\n link.download = `mermaid-diagram-${timestamp}.png`\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n } catch (dataUrlError) {\r\n console.error('Failed to convert canvas to data URL:', dataUrlError)\r\n }\r\n }\r\n } catch (canvasError) {\r\n console.error('Canvas operation failed:', canvasError)\r\n }\r\n }\r\n\r\n img.onerror = (error) => {\r\n console.error('Failed to load image:', error)\r\n }\r\n\r\n img.src = svgDataUrl\r\n } catch (error) {\r\n console.error('Failed to download SVG:', error)\r\n }\r\n}\r\n\r\ninterface UseMermaidOptions {\r\n id?: string\r\n theme?: 'default' | 'dark' | 'forest' | 'neutral' | string\r\n config?: any\r\n container?: HTMLElement | Ref<HTMLElement | null> | null\r\n}\r\n\r\ntype UseMermaidOptionsInput = UseMermaidOptions | Ref<UseMermaidOptions>\r\n\r\nlet mermaidPromise: Promise<any> | null = null\r\nlet hasShownMermaidHint = false\r\nlet mermaidAvailableCache: boolean | null = null\r\nlet mermaidCheckPromise: Promise<boolean> | null = null\r\n\r\n/**\r\n * 同步检查缓存状态(不触发检测)\r\n * @returns 缓存状态,null 表示未检测\r\n */\r\nexport function getMermaidAvailableCache(): boolean | null {\r\n return mermaidAvailableCache\r\n}\r\n\r\n/**\r\n * 检测 mermaid 是否可用(全局缓存,只检测一次)\r\n */\r\nexport async function checkMermaidAvailable(): Promise<boolean> {\r\n // 如果已经有缓存结果,直接返回\r\n if (mermaidAvailableCache !== null) {\r\n return mermaidAvailableCache\r\n }\r\n\r\n // 如果正在检测,返回检测 Promise\r\n if (mermaidCheckPromise) {\r\n return mermaidCheckPromise\r\n }\r\n\r\n // 开始检测\r\n mermaidCheckPromise = (async () => {\r\n try {\r\n const mod = await import('mermaid')\r\n mermaidAvailableCache = !!mod\r\n return mermaidAvailableCache\r\n } catch {\r\n // 静默失败,mermaid 不可用\r\n mermaidAvailableCache = false\r\n return false\r\n }\r\n })()\r\n\r\n return mermaidCheckPromise\r\n}\r\n\r\nconst showMermaidHint = () => {\r\n if (hasShownMermaidHint) return\r\n hasShownMermaidHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c Mermaid 图表功能已降级为代码块显示',\r\n 'font-weight: bold; color: #9333ea;',\r\n 'color: #666;'\r\n )\r\n console.log(\r\n '%c如需 Mermaid 图表渲染功能,请安装:',\r\n 'color: #666; font-weight: bold;'\r\n )\r\n console.log(\r\n '%c pnpm add mermaid',\r\n 'color: #9333ea; 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\nasync function loadMermaid() {\r\n if (typeof window === 'undefined') return null\r\n if (!mermaidPromise) {\r\n mermaidPromise = (async () => {\r\n try {\r\n const mod = await import('mermaid')\r\n return (mod as any)?.default\r\n } catch {\r\n // 静默失败,显示友好提示\r\n showMermaidHint()\r\n return null\r\n }\r\n })()\r\n }\r\n return mermaidPromise\r\n}\r\n\r\ntype RenderTask = () => Promise<void>\r\nconst renderQueue: RenderTask[] = []\r\nlet isProcessingQueue = false\r\n\r\nasync function processRenderQueue() {\r\n if (isProcessingQueue) return\r\n isProcessingQueue = true\r\n\r\n while (renderQueue.length > 0) {\r\n const task = renderQueue.shift()\r\n if (task) {\r\n try {\r\n await task()\r\n } catch (err) {\r\n console.error('Mermaid render queue error:', err)\r\n }\r\n }\r\n }\r\n\r\n isProcessingQueue = false\r\n}\r\n\r\nfunction addToRenderQueue(task: RenderTask) {\r\n renderQueue.push(task)\r\n processRenderQueue()\r\n}\r\n\r\nexport function useMermaid(content: string | Ref<string>, options: UseMermaidOptionsInput = {}): UseMermaidResult {\r\n const optionsRef = computed(() => (typeof options === 'object' && 'value' in options ? options.value : options))\r\n const mermaidConfig = computed(() => ({\r\n suppressErrorRendering: true,\r\n startOnLoad: false,\r\n securityLevel: 'loose',\r\n theme: optionsRef.value.theme || 'default',\r\n ...(optionsRef.value.config || {}),\r\n }))\r\n const data = ref('')\r\n const error = ref<unknown>(null)\r\n const isLoading = ref(false)\r\n\r\n let isUnmounted = false\r\n\r\n const getRenderContainer = () => {\r\n const containerOption = optionsRef.value.container\r\n if (containerOption) {\r\n return typeof containerOption === 'object' && 'value' in containerOption ? containerOption.value : containerOption\r\n }\r\n return null\r\n }\r\n\r\n const throttledRender = throttle(\r\n () => {\r\n const contentValue = typeof content === 'string' ? content : content.value\r\n if (!contentValue?.trim()) {\r\n data.value = ''\r\n error.value = null\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n isLoading.value = true\r\n\r\n addToRenderQueue(async () => {\r\n if (isUnmounted) return\r\n\r\n try {\r\n const mermaidInstance = await loadMermaid()\r\n if (!mermaidInstance) {\r\n data.value = contentValue\r\n error.value = null\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n mermaidInstance.initialize(mermaidConfig.value)\r\n\r\n const isValid = await mermaidInstance.parse(contentValue.trim())\r\n if (!isValid) {\r\n data.value = ''\r\n error.value = new Error('Mermaid parse error: Invalid syntax')\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n const renderId = `${optionsRef.value.id || 'mermaid'}-${Math.random().toString(36).substring(2, 11)}`\r\n const container = getRenderContainer()\r\n if (!container) {\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n const { svg } = await mermaidInstance.render(renderId, contentValue, container)\r\n data.value = svg\r\n error.value = null\r\n isLoading.value = false\r\n } catch (err) {\r\n // Mermaid render error\r\n data.value = ''\r\n error.value = err\r\n isLoading.value = false\r\n }\r\n })\r\n },\r\n 100,\r\n { leading: false, trailing: true },\r\n )\r\n\r\n watch(\r\n [() => (typeof content === 'string' ? content : content.value), () => mermaidConfig.value],\r\n () => {\r\n throttledRender()\r\n },\r\n { immediate: true },\r\n )\r\n\r\n onUnmounted(() => {\r\n isUnmounted = true\r\n })\r\n\r\n return {\r\n data,\r\n error,\r\n isLoading,\r\n }\r\n}\r\n\r\nexport function useMermaidZoom(options: UseMermaidZoomOptions): MermaidZoomControls {\r\n const { container } = options\r\n\r\n const scale = ref(1)\r\n const posX = ref(0)\r\n const posY = ref(0)\r\n const isDragging = ref(false)\r\n\r\n let removeEvents: (() => void) | null = null\r\n\r\n const getSvg = () => container.value?.querySelector('.syntax-mermaid__content svg') as HTMLElement\r\n\r\n const updateTransform = (svg: HTMLElement) => {\r\n svg.style.transformOrigin = 'center center'\r\n svg.style.transform = `translate(${posX.value}px, ${posY.value}px) scale(${scale.value})`\r\n }\r\n\r\n const resetState = () => {\r\n scale.value = 1\r\n posX.value = 0\r\n posY.value = 0\r\n isDragging.value = false\r\n }\r\n\r\n const addInteractionEvents = (containerEl: HTMLElement) => {\r\n let startX = 0\r\n let startY = 0\r\n let isInteractingWithMermaid = false\r\n\r\n const onStart = (clientX: number, clientY: number) => {\r\n isDragging.value = true\r\n startX = clientX - posX.value\r\n startY = clientY - posY.value\r\n document.body.style.userSelect = 'none'\r\n }\r\n\r\n const onMove = (clientX: number, clientY: number) => {\r\n if (isDragging.value && isInteractingWithMermaid) {\r\n posX.value = clientX - startX\r\n posY.value = clientY - startY\r\n const svg = getSvg()\r\n if (svg) {\r\n updateTransform(svg)\r\n }\r\n }\r\n }\r\n\r\n const onEnd = () => {\r\n isDragging.value = false\r\n isInteractingWithMermaid = false\r\n document.body.style.userSelect = ''\r\n }\r\n\r\n const onMouseDown = (e: MouseEvent) => {\r\n if (e.button !== 0) return\r\n if (e.target === containerEl || containerEl.contains(e.target as Node)) {\r\n e.preventDefault()\r\n isInteractingWithMermaid = true\r\n onStart(e.clientX, e.clientY)\r\n }\r\n }\r\n\r\n const onMouseMove = (e: MouseEvent) => {\r\n if (isInteractingWithMermaid) {\r\n onMove(e.clientX, e.clientY)\r\n }\r\n }\r\n\r\n const handleWheelZoom = (e: WheelEvent) => {\r\n const svg = getSvg()\r\n if (!svg) return\r\n\r\n const containerRect = containerEl.getBoundingClientRect()\r\n const svgRect = svg.getBoundingClientRect()\r\n\r\n const mouseX = e.clientX - containerRect.left\r\n const mouseY = e.clientY - containerRect.top\r\n\r\n const svgCenterX = svgRect.left - containerRect.left + svgRect.width / 2\r\n const svgCenterY = svgRect.top - containerRect.top + svgRect.height / 2\r\n\r\n const offsetX = (mouseX - svgCenterX - posX.value) / scale.value\r\n const offsetY = (mouseY - svgCenterY - posY.value) / scale.value\r\n\r\n const delta = e.deltaY > 0 ? -0.05 : 0.05\r\n const newScale = Math.min(Math.max(scale.value + delta, 0.1), 10)\r\n\r\n if (newScale === scale.value) return\r\n\r\n scale.value = newScale\r\n\r\n posX.value = mouseX - svgCenterX - offsetX * scale.value\r\n posY.value = mouseY - svgCenterY - offsetY * scale.value\r\n\r\n updateTransform(svg)\r\n }\r\n\r\n const throttledWheelZoom = throttle(handleWheelZoom, 20, { leading: true, trailing: true })\r\n\r\n const onWheel = (e: WheelEvent) => {\r\n if (e.target === containerEl || containerEl.contains(e.target as Node)) {\r\n e.preventDefault()\r\n throttledWheelZoom(e)\r\n }\r\n }\r\n\r\n const onTouchStart = (e: TouchEvent) => {\r\n if (e.target === containerEl || containerEl.contains(e.target as Node)) {\r\n if (e.touches.length === 1) {\r\n e.preventDefault()\r\n isInteractingWithMermaid = true\r\n onStart(e.touches[0].clientX, e.touches[0].clientY)\r\n }\r\n }\r\n }\r\n\r\n const onTouchMove = (e: TouchEvent) => {\r\n if (isInteractingWithMermaid) {\r\n e.preventDefault()\r\n onMove(e.touches[0].clientX, e.touches[0].clientY)\r\n }\r\n }\r\n\r\n containerEl.addEventListener('mousedown', onMouseDown)\r\n document.addEventListener('mousemove', onMouseMove)\r\n document.addEventListener('mouseup', onEnd)\r\n containerEl.addEventListener('wheel', onWheel, { passive: false })\r\n containerEl.addEventListener('touchstart', onTouchStart, { passive: false })\r\n containerEl.addEventListener('touchmove', onTouchMove, { passive: false })\r\n document.addEventListener('touchend', onEnd)\r\n\r\n return () => {\r\n containerEl.removeEventListener('mousedown', onMouseDown)\r\n document.removeEventListener('mousemove', onMouseMove)\r\n document.removeEventListener('mouseup', onEnd)\r\n containerEl.removeEventListener('wheel', onWheel)\r\n containerEl.removeEventListener('touchstart', onTouchStart)\r\n containerEl.removeEventListener('touchmove', onTouchMove)\r\n document.removeEventListener('touchend', onEnd)\r\n document.body.style.userSelect = ''\r\n }\r\n }\r\n\r\n const zoomIn = () => {\r\n const svg = getSvg()\r\n if (svg) {\r\n scale.value = Math.min(scale.value + 0.2, 10)\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const zoomOut = () => {\r\n const svg = getSvg()\r\n if (svg) {\r\n scale.value = Math.max(scale.value - 0.2, 0.1)\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const reset = () => {\r\n const svg = getSvg()\r\n if (svg) {\r\n resetState()\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const fullscreen = () => {\r\n if (!container.value) return\r\n\r\n if (document.fullscreenElement) {\r\n document.exitFullscreen()\r\n } else {\r\n container.value.requestFullscreen?.()\r\n }\r\n }\r\n\r\n const initialize = () => {\r\n if (!container.value) return\r\n\r\n resetState()\r\n\r\n removeEvents = addInteractionEvents(container.value)\r\n\r\n const svg = getSvg()\r\n if (svg) {\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const destroy = () => {\r\n removeEvents?.()\r\n removeEvents = null\r\n resetState()\r\n }\r\n\r\n watch(\r\n () => container.value,\r\n () => {\r\n destroy()\r\n resetState()\r\n },\r\n )\r\n\r\n onUnmounted(destroy)\r\n\r\n return {\r\n zoomIn,\r\n zoomOut,\r\n reset,\r\n fullscreen,\r\n destroy,\r\n initialize,\r\n }\r\n}\r\n"],"names":["mermaidPromise","hasShownMermaidHint","mermaidAvailableCache","mermaidCheckPromise","renderQueue","isProcessingQueue","async","mod","import","svg","svgDataUrl","encodeURIComponent","img","Image","onload","canvas","document","createElement","ctx","getContext","willReadFrequently","scale","width","height","imageSmoothingEnabled","imageSmoothingQuality","fillStyle","fillRect","drawImage","timestamp","Date","toISOString","slice","replace","toBlob","blob","url","URL","createObjectURL","link","href","download","body","appendChild","click","removeChild","revokeObjectURL","toBlobError","console","error","dataUrl","toDataURL","dataUrlError","canvasError","onerror","src","content","options","optionsRef","computed","value","mermaidConfig","suppressErrorRendering","startOnLoad","securityLevel","theme","config","data","ref","isLoading","isUnmounted","throttledRender","throttle","contentValue","trim","task","mermaidInstance","window","default","log","loadMermaid","initialize","parse","Error","renderId","id","Math","random","toString","substring","container","containerOption","getRenderContainer","render","err","push","length","shift","processRenderQueue","leading","trailing","watch","immediate","onUnmounted","posX","posY","isDragging","removeEvents","getSvg","querySelector","updateTransform","style","transformOrigin","transform","resetState","destroy","zoomIn","min","zoomOut","max","reset","fullscreen","fullscreenElement","exitFullscreen","requestFullscreen","containerEl","startX","startY","isInteractingWithMermaid","onStart","clientX","clientY","userSelect","onMove","onEnd","onMouseDown","e","button","target","contains","preventDefault","onMouseMove","throttledWheelZoom","containerRect","getBoundingClientRect","svgRect","mouseX","left","mouseY","top","svgCenterX","svgCenterY","offsetX","offsetY","delta","deltaY","newScale","onWheel","onTouchStart","touches","onTouchMove","addEventListener","passive","removeEventListener","addInteractionEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"x-markdown.cjs9.js","sources":["../src/hooks/useMermaid.ts"],"sourcesContent":["import type { Ref } from 'vue'\r\nimport { throttle } from 'lodash-es'\r\nimport { computed, ref, watch, onUnmounted } from 'vue'\r\nimport type { MermaidZoomControls, UseMermaidZoomOptions, UseMermaidResult } from '../components/Mermaid/types'\r\n\r\nexport function downloadSvgAsPng(svg: string): void {\r\n if (!svg) return\r\n\r\n try {\r\n const svgDataUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`\r\n const img = new Image()\r\n\r\n img.onload = () => {\r\n try {\r\n const canvas = document.createElement('canvas')\r\n const ctx = canvas.getContext('2d', { willReadFrequently: false })\r\n if (!ctx) return\r\n\r\n const scale = 2\r\n canvas.width = img.width * scale\r\n canvas.height = img.height * scale\r\n ctx.imageSmoothingEnabled = true\r\n ctx.imageSmoothingQuality = 'high'\r\n\r\n ctx.fillStyle = '#ffffff'\r\n ctx.fillRect(0, 0, canvas.width, canvas.height)\r\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height)\r\n\r\n const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-')\r\n\r\n try {\r\n canvas.toBlob(\r\n (blob) => {\r\n if (!blob) return\r\n const url = URL.createObjectURL(blob)\r\n const link = document.createElement('a')\r\n link.href = url\r\n link.download = `mermaid-diagram-${timestamp}.png`\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n URL.revokeObjectURL(url)\r\n },\r\n 'image/png',\r\n 0.95,\r\n )\r\n } catch (toBlobError) {\r\n console.error('Failed to convert canvas to blob:', toBlobError)\r\n try {\r\n const dataUrl = canvas.toDataURL('image/png', 0.95)\r\n const link = document.createElement('a')\r\n link.href = dataUrl\r\n link.download = `mermaid-diagram-${timestamp}.png`\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n } catch (dataUrlError) {\r\n console.error('Failed to convert canvas to data URL:', dataUrlError)\r\n }\r\n }\r\n } catch (canvasError) {\r\n console.error('Canvas operation failed:', canvasError)\r\n }\r\n }\r\n\r\n img.onerror = (error) => {\r\n console.error('Failed to load image:', error)\r\n }\r\n\r\n img.src = svgDataUrl\r\n } catch (error) {\r\n console.error('Failed to download SVG:', error)\r\n }\r\n}\r\n\r\ninterface UseMermaidOptions {\r\n id?: string\r\n theme?: 'default' | 'dark' | 'forest' | 'neutral' | string\r\n config?: any\r\n container?: HTMLElement | Ref<HTMLElement | null> | null\r\n}\r\n\r\ntype UseMermaidOptionsInput = UseMermaidOptions | Ref<UseMermaidOptions>\r\n\r\nlet mermaidPromise: Promise<any> | null = null\r\nlet hasShownMermaidHint = false\r\nlet mermaidAvailableCache: boolean | null = null\r\nlet mermaidCheckPromise: Promise<boolean | null> | null = null\r\n\r\n/**\r\n * 同步检查缓存状态(不触发检测)\r\n * @returns 缓存状态,null 表示未检测\r\n */\r\nexport function getMermaidAvailableCache(): boolean | null {\r\n return mermaidAvailableCache\r\n}\r\n\r\n/**\r\n * 检测 mermaid 是否可用(全局缓存,只检测一次)\r\n */\r\nexport async function checkMermaidAvailable(): Promise<boolean> {\r\n // 如果已经有缓存结果,直接返回\r\n if (mermaidAvailableCache !== null) {\r\n return mermaidAvailableCache\r\n }\r\n\r\n // 如果正在检测,返回检测 Promise\r\n if (mermaidCheckPromise) {\r\n return mermaidCheckPromise as Promise<boolean>\r\n }\r\n\r\n // 开始检测\r\n mermaidCheckPromise = (async () => {\r\n try {\r\n const mod = await import('mermaid')\r\n // 检查模块是否有实际的 mermaid 功能\r\n // 虚拟模块返回 { default: null },所以需要检查 default 是否存在且有效\r\n const mermaidInstance = (mod as any)?.default\r\n // 检查是否有 mermaid 的关键方法或属性\r\n const hasMermaidAPI = mermaidInstance && (\r\n typeof mermaidInstance.render === 'function' ||\r\n typeof mermaidInstance.initialize === 'function' ||\r\n typeof mermaidInstance.run === 'function'\r\n )\r\n mermaidAvailableCache = hasMermaidAPI\r\n return mermaidAvailableCache\r\n } catch {\r\n // 静默失败,mermaid 不可用\r\n mermaidAvailableCache = false\r\n return false\r\n }\r\n })()\r\n\r\n return mermaidCheckPromise as Promise<boolean>\r\n}\r\n\r\nconst showMermaidHint = () => {\r\n if (hasShownMermaidHint) return\r\n hasShownMermaidHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c Mermaid 图表功能已降级为代码块显示',\r\n 'font-weight: bold; color: #9333ea;',\r\n 'color: #666;'\r\n )\r\n console.log(\r\n '%c如需 Mermaid 图表渲染功能,请安装:',\r\n 'color: #666; font-weight: bold;'\r\n )\r\n console.log(\r\n '%c pnpm add mermaid',\r\n 'color: #9333ea; 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\nasync function loadMermaid() {\r\n if (typeof window === 'undefined') return null\r\n if (!mermaidPromise) {\r\n mermaidPromise = (async () => {\r\n try {\r\n const mod = await import('mermaid')\r\n return (mod as any)?.default\r\n } catch {\r\n // 静默失败,显示友好提示\r\n showMermaidHint()\r\n return null\r\n }\r\n })()\r\n }\r\n return mermaidPromise\r\n}\r\n\r\ntype RenderTask = () => Promise<void>\r\nconst renderQueue: RenderTask[] = []\r\nlet isProcessingQueue = false\r\n\r\nasync function processRenderQueue() {\r\n if (isProcessingQueue) return\r\n isProcessingQueue = true\r\n\r\n while (renderQueue.length > 0) {\r\n const task = renderQueue.shift()\r\n if (task) {\r\n try {\r\n await task()\r\n } catch (err) {\r\n console.error('Mermaid render queue error:', err)\r\n }\r\n }\r\n }\r\n\r\n isProcessingQueue = false\r\n}\r\n\r\nfunction addToRenderQueue(task: RenderTask) {\r\n renderQueue.push(task)\r\n processRenderQueue()\r\n}\r\n\r\nexport function useMermaid(content: string | Ref<string>, options: UseMermaidOptionsInput = {}): UseMermaidResult {\r\n const optionsRef = computed(() => (typeof options === 'object' && 'value' in options ? options.value : options))\r\n const mermaidConfig = computed(() => ({\r\n suppressErrorRendering: true,\r\n startOnLoad: false,\r\n securityLevel: 'loose',\r\n theme: optionsRef.value.theme || 'default',\r\n ...(optionsRef.value.config || {}),\r\n }))\r\n const data = ref('')\r\n const error = ref<unknown>(null)\r\n const isLoading = ref(false)\r\n\r\n let isUnmounted = false\r\n\r\n const getRenderContainer = () => {\r\n const containerOption = optionsRef.value.container\r\n if (containerOption) {\r\n return typeof containerOption === 'object' && 'value' in containerOption ? containerOption.value : containerOption\r\n }\r\n return null\r\n }\r\n\r\n const throttledRender = throttle(\r\n () => {\r\n const contentValue = typeof content === 'string' ? content : content.value\r\n if (!contentValue?.trim()) {\r\n data.value = ''\r\n error.value = null\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n isLoading.value = true\r\n\r\n addToRenderQueue(async () => {\r\n if (isUnmounted) return\r\n\r\n try {\r\n const mermaidInstance = await loadMermaid()\r\n if (!mermaidInstance) {\r\n data.value = contentValue\r\n error.value = null\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n mermaidInstance.initialize(mermaidConfig.value)\r\n\r\n const isValid = await mermaidInstance.parse(contentValue.trim())\r\n if (!isValid) {\r\n data.value = ''\r\n error.value = new Error('Mermaid parse error: Invalid syntax')\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n const renderId = `${optionsRef.value.id || 'mermaid'}-${Math.random().toString(36).substring(2, 11)}`\r\n const container = getRenderContainer()\r\n if (!container) {\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n const { svg } = await mermaidInstance.render(renderId, contentValue, container)\r\n data.value = svg\r\n error.value = null\r\n isLoading.value = false\r\n } catch (err) {\r\n // Mermaid render error\r\n data.value = ''\r\n error.value = err\r\n isLoading.value = false\r\n }\r\n })\r\n },\r\n 100,\r\n { leading: false, trailing: true },\r\n )\r\n\r\n watch(\r\n [() => (typeof content === 'string' ? content : content.value), () => mermaidConfig.value],\r\n () => {\r\n throttledRender()\r\n },\r\n { immediate: true },\r\n )\r\n\r\n onUnmounted(() => {\r\n isUnmounted = true\r\n })\r\n\r\n return {\r\n data,\r\n error,\r\n isLoading,\r\n }\r\n}\r\n\r\nexport function useMermaidZoom(options: UseMermaidZoomOptions): MermaidZoomControls {\r\n const { container } = options\r\n\r\n const scale = ref(1)\r\n const posX = ref(0)\r\n const posY = ref(0)\r\n const isDragging = ref(false)\r\n\r\n let removeEvents: (() => void) | null = null\r\n\r\n const getSvg = () => container.value?.querySelector('.syntax-mermaid__content svg') as HTMLElement\r\n\r\n const updateTransform = (svg: HTMLElement) => {\r\n svg.style.transformOrigin = 'center center'\r\n svg.style.transform = `translate(${posX.value}px, ${posY.value}px) scale(${scale.value})`\r\n }\r\n\r\n const resetState = () => {\r\n scale.value = 1\r\n posX.value = 0\r\n posY.value = 0\r\n isDragging.value = false\r\n }\r\n\r\n const addInteractionEvents = (containerEl: HTMLElement) => {\r\n let startX = 0\r\n let startY = 0\r\n let isInteractingWithMermaid = false\r\n\r\n const onStart = (clientX: number, clientY: number) => {\r\n isDragging.value = true\r\n startX = clientX - posX.value\r\n startY = clientY - posY.value\r\n document.body.style.userSelect = 'none'\r\n }\r\n\r\n const onMove = (clientX: number, clientY: number) => {\r\n if (isDragging.value && isInteractingWithMermaid) {\r\n posX.value = clientX - startX\r\n posY.value = clientY - startY\r\n const svg = getSvg()\r\n if (svg) {\r\n updateTransform(svg)\r\n }\r\n }\r\n }\r\n\r\n const onEnd = () => {\r\n isDragging.value = false\r\n isInteractingWithMermaid = false\r\n document.body.style.userSelect = ''\r\n }\r\n\r\n const onMouseDown = (e: MouseEvent) => {\r\n if (e.button !== 0) return\r\n if (e.target === containerEl || containerEl.contains(e.target as Node)) {\r\n e.preventDefault()\r\n isInteractingWithMermaid = true\r\n onStart(e.clientX, e.clientY)\r\n }\r\n }\r\n\r\n const onMouseMove = (e: MouseEvent) => {\r\n if (isInteractingWithMermaid) {\r\n onMove(e.clientX, e.clientY)\r\n }\r\n }\r\n\r\n const handleWheelZoom = (e: WheelEvent) => {\r\n const svg = getSvg()\r\n if (!svg) return\r\n\r\n const containerRect = containerEl.getBoundingClientRect()\r\n const svgRect = svg.getBoundingClientRect()\r\n\r\n const mouseX = e.clientX - containerRect.left\r\n const mouseY = e.clientY - containerRect.top\r\n\r\n const svgCenterX = svgRect.left - containerRect.left + svgRect.width / 2\r\n const svgCenterY = svgRect.top - containerRect.top + svgRect.height / 2\r\n\r\n const offsetX = (mouseX - svgCenterX - posX.value) / scale.value\r\n const offsetY = (mouseY - svgCenterY - posY.value) / scale.value\r\n\r\n const delta = e.deltaY > 0 ? -0.05 : 0.05\r\n const newScale = Math.min(Math.max(scale.value + delta, 0.1), 10)\r\n\r\n if (newScale === scale.value) return\r\n\r\n scale.value = newScale\r\n\r\n posX.value = mouseX - svgCenterX - offsetX * scale.value\r\n posY.value = mouseY - svgCenterY - offsetY * scale.value\r\n\r\n updateTransform(svg)\r\n }\r\n\r\n const throttledWheelZoom = throttle(handleWheelZoom, 20, { leading: true, trailing: true })\r\n\r\n const onWheel = (e: WheelEvent) => {\r\n if (e.target === containerEl || containerEl.contains(e.target as Node)) {\r\n e.preventDefault()\r\n throttledWheelZoom(e)\r\n }\r\n }\r\n\r\n const onTouchStart = (e: TouchEvent) => {\r\n if (e.target === containerEl || containerEl.contains(e.target as Node)) {\r\n if (e.touches.length === 1) {\r\n e.preventDefault()\r\n isInteractingWithMermaid = true\r\n onStart(e.touches[0].clientX, e.touches[0].clientY)\r\n }\r\n }\r\n }\r\n\r\n const onTouchMove = (e: TouchEvent) => {\r\n if (isInteractingWithMermaid) {\r\n e.preventDefault()\r\n onMove(e.touches[0].clientX, e.touches[0].clientY)\r\n }\r\n }\r\n\r\n containerEl.addEventListener('mousedown', onMouseDown)\r\n document.addEventListener('mousemove', onMouseMove)\r\n document.addEventListener('mouseup', onEnd)\r\n containerEl.addEventListener('wheel', onWheel, { passive: false })\r\n containerEl.addEventListener('touchstart', onTouchStart, { passive: false })\r\n containerEl.addEventListener('touchmove', onTouchMove, { passive: false })\r\n document.addEventListener('touchend', onEnd)\r\n\r\n return () => {\r\n containerEl.removeEventListener('mousedown', onMouseDown)\r\n document.removeEventListener('mousemove', onMouseMove)\r\n document.removeEventListener('mouseup', onEnd)\r\n containerEl.removeEventListener('wheel', onWheel)\r\n containerEl.removeEventListener('touchstart', onTouchStart)\r\n containerEl.removeEventListener('touchmove', onTouchMove)\r\n document.removeEventListener('touchend', onEnd)\r\n document.body.style.userSelect = ''\r\n }\r\n }\r\n\r\n const zoomIn = () => {\r\n const svg = getSvg()\r\n if (svg) {\r\n scale.value = Math.min(scale.value + 0.2, 10)\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const zoomOut = () => {\r\n const svg = getSvg()\r\n if (svg) {\r\n scale.value = Math.max(scale.value - 0.2, 0.1)\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const reset = () => {\r\n const svg = getSvg()\r\n if (svg) {\r\n resetState()\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const fullscreen = () => {\r\n if (!container.value) return\r\n\r\n if (document.fullscreenElement) {\r\n document.exitFullscreen()\r\n } else {\r\n container.value.requestFullscreen?.()\r\n }\r\n }\r\n\r\n const initialize = () => {\r\n if (!container.value) return\r\n\r\n resetState()\r\n\r\n removeEvents = addInteractionEvents(container.value)\r\n\r\n const svg = getSvg()\r\n if (svg) {\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const destroy = () => {\r\n removeEvents?.()\r\n removeEvents = null\r\n resetState()\r\n }\r\n\r\n watch(\r\n () => container.value,\r\n () => {\r\n destroy()\r\n resetState()\r\n },\r\n )\r\n\r\n onUnmounted(destroy)\r\n\r\n return {\r\n zoomIn,\r\n zoomOut,\r\n reset,\r\n fullscreen,\r\n destroy,\r\n initialize,\r\n }\r\n}\r\n"],"names":["mermaidPromise","hasShownMermaidHint","mermaidAvailableCache","mermaidCheckPromise","renderQueue","isProcessingQueue","async","mod","import","mermaidInstance","default","hasMermaidAPI","render","initialize","run","svg","svgDataUrl","encodeURIComponent","img","Image","onload","canvas","document","createElement","ctx","getContext","willReadFrequently","scale","width","height","imageSmoothingEnabled","imageSmoothingQuality","fillStyle","fillRect","drawImage","timestamp","Date","toISOString","slice","replace","toBlob","blob","url","URL","createObjectURL","link","href","download","body","appendChild","click","removeChild","revokeObjectURL","toBlobError","console","error","dataUrl","toDataURL","dataUrlError","canvasError","onerror","src","content","options","optionsRef","computed","value","mermaidConfig","suppressErrorRendering","startOnLoad","securityLevel","theme","config","data","ref","isLoading","isUnmounted","throttledRender","throttle","contentValue","trim","task","window","log","loadMermaid","parse","Error","renderId","id","Math","random","toString","substring","container","containerOption","getRenderContainer","err","push","length","shift","processRenderQueue","leading","trailing","watch","immediate","onUnmounted","posX","posY","isDragging","removeEvents","getSvg","querySelector","updateTransform","style","transformOrigin","transform","resetState","destroy","zoomIn","min","zoomOut","max","reset","fullscreen","fullscreenElement","exitFullscreen","requestFullscreen","containerEl","startX","startY","isInteractingWithMermaid","onStart","clientX","clientY","userSelect","onMove","onEnd","onMouseDown","e","button","target","contains","preventDefault","onMouseMove","throttledWheelZoom","containerRect","getBoundingClientRect","svgRect","mouseX","left","mouseY","top","svgCenterX","svgCenterY","offsetX","offsetY","delta","deltaY","newScale","onWheel","onTouchStart","touches","onTouchMove","addEventListener","passive","removeEventListener","addInteractionEvents"],"mappings":"mRAoFA,IAAIA,EAAsC,KACtCC,GAAsB,EACtBC,EAAwC,KACxCC,EAAsD,KA0F1D,MAAMC,EAA4B,GAClC,IAAIC,GAAoB,gCA9ExBC,iBAEE,OAA8B,OAA1BJ,EACKA,EAILC,IAKJA,EAAA,WACE,IACE,MAAMI,QAAYC,OAAO,WAGnBC,EAAmBF,GAAaG,QAEhCC,EAAgBF,IACc,mBAA3BA,EAAgBG,QACe,mBAA/BH,EAAgBI,YACQ,mBAAxBJ,EAAgBK,KAGzB,OADAZ,EAAwBS,EACjBT,CACT,CAAA,MAGE,OADAA,GAAwB,GACjB,CACT,CACF,EAnBA,GAqBOC,EACT,2BAjIO,SAA0BY,GAC/B,GAAKA,EAEL,IACE,MAAMC,EAAa,oCAAoCC,mBAAmBF,KACpEG,EAAM,IAAIC,MAEhBD,EAAIE,OAAS,KACX,IACE,MAAMC,EAASC,SAASC,cAAc,UAChCC,EAAMH,EAAOI,WAAW,KAAM,CAAEC,oBAAoB,IAC1D,IAAKF,EAAK,OAEV,MAAMG,EAAQ,EACdN,EAAOO,MAAQV,EAAIU,MAAQD,EAC3BN,EAAOQ,OAASX,EAAIW,OAASF,EAC7BH,EAAIM,uBAAwB,EAC5BN,EAAIO,sBAAwB,OAE5BP,EAAIQ,UAAY,UAChBR,EAAIS,SAAS,EAAG,EAAGZ,EAAOO,MAAOP,EAAOQ,QACxCL,EAAIU,UAAUhB,EAAK,EAAG,EAAGG,EAAOO,MAAOP,EAAOQ,QAE9C,MAAMM,GAAA,IAAgBC,MAAOC,cAAcC,MAAM,EAAG,IAAIC,QAAQ,KAAM,KAEtE,IACElB,EAAOmB,OACJC,IACC,IAAKA,EAAM,OACX,MAAMC,EAAMC,IAAIC,gBAAgBH,GAC1BI,EAAOvB,SAASC,cAAc,KACpCsB,EAAKC,KAAOJ,EACZG,EAAKE,SAAW,mBAAmBZ,QACnCb,SAAS0B,KAAKC,YAAYJ,GAC1BA,EAAKK,QACL5B,SAAS0B,KAAKG,YAAYN,GAC1BF,IAAIS,gBAAgBV,IAEtB,YACA,IAEJ,OAASW,GACPC,QAAQC,MAAM,oCAAqCF,GACnD,IACE,MAAMG,EAAUnC,EAAOoC,UAAU,YAAa,KACxCZ,EAAOvB,SAASC,cAAc,KACpCsB,EAAKC,KAAOU,EACZX,EAAKE,SAAW,mBAAmBZ,QACnCb,SAAS0B,KAAKC,YAAYJ,GAC1BA,EAAKK,QACL5B,SAAS0B,KAAKG,YAAYN,EAC5B,OAASa,GACPJ,QAAQC,MAAM,wCAAyCG,EACzD,CACF,CACF,OAASC,GACPL,QAAQC,MAAM,2BAA4BI,EAC5C,GAGFzC,EAAI0C,QAAWL,IACbD,QAAQC,MAAM,wBAAyBA,IAGzCrC,EAAI2C,IAAM7C,CACZ,OAASuC,GACPD,QAAQC,MAAM,0BAA2BA,EAC3C,CACF,qBAkIO,SAAoBO,EAA+BC,EAAkC,IAC1F,MAAMC,EAAaC,EAAAA,SAAS,IAA0B,iBAAZF,GAAwB,UAAWA,EAAUA,EAAQG,MAAQH,GACjGI,EAAgBF,EAAAA,SAAS,KAAA,CAC7BG,wBAAwB,EACxBC,aAAa,EACbC,cAAe,QACfC,MAAOP,EAAWE,MAAMK,OAAS,aAC7BP,EAAWE,MAAMM,QAAU,CAAA,KAE3BC,EAAOC,EAAAA,IAAI,IACXnB,EAAQmB,EAAAA,IAAa,MACrBC,EAAYD,EAAAA,KAAI,GAEtB,IAAIE,GAAc,EAElB,MAQMC,EAAkBC,EAAAA,SACtB,KACE,MAAMC,EAAkC,iBAAZjB,EAAuBA,EAAUA,EAAQI,MACrE,IAAKa,GAAcC,OAIjB,OAHAP,EAAKP,MAAQ,GACbX,EAAMW,MAAQ,UACdS,EAAUT,OAAQ,GAlC1B,IAA0Be,EAsCpBN,EAAUT,OAAQ,EAtCEe,EAwCH3E,UACf,IAAIsE,EAEJ,IACE,MAAMnE,QAnFhBH,iBACE,MAAsB,oBAAX4E,OAA+B,MACrClF,IACHA,EAAA,WACE,IACE,MAAMO,QAAYC,OAAO,WACzB,OAAQD,GAAaG,OACvB,CAAA,MAGE,OAhCFT,IACJA,GAAsB,EAEtBqD,QAAQ6B,IACN,yCACA,qCACA,gBAEF7B,QAAQ6B,IACN,2BACA,mCAEF7B,QAAQ6B,IACN,uBACA,2CAEF7B,QAAQ6B,IACN,gBACA,kCAcW,IACT,CACF,EATA,IAWKnF,EACT,CAoEwCoF,GAC9B,IAAK3E,EAIH,OAHAgE,EAAKP,MAAQa,EACbxB,EAAMW,MAAQ,UACdS,EAAUT,OAAQ,GAOpB,GAHAzD,EAAgBI,WAAWsD,EAAcD,eAEnBzD,EAAgB4E,MAAMN,EAAaC,SAKvD,OAHAP,EAAKP,MAAQ,GACbX,EAAMW,MAAQ,IAAIoB,MAAM,4CACxBX,EAAUT,OAAQ,GAIpB,MAAMqB,EAAW,GAAGvB,EAAWE,MAAMsB,IAAM,aAAaC,KAAKC,SAASC,SAAS,IAAIC,UAAU,EAAG,MAC1FC,EA3Ca,MACzB,MAAMC,EAAkB9B,EAAWE,MAAM2B,UACzC,OAAIC,EACgC,iBAApBA,GAAgC,UAAWA,EAAkBA,EAAgB5B,MAAQ4B,EAE9F,MAsCiBC,GAClB,IAAKF,EAEH,YADAlB,EAAUT,OAAQ,GAIpB,MAAMnD,IAAEA,SAAcN,EAAgBG,OAAO2E,EAAUR,EAAcc,GACrEpB,EAAKP,MAAQnD,EACbwC,EAAMW,MAAQ,KACdS,EAAUT,OAAQ,CACpB,OAAS8B,GAEPvB,EAAKP,MAAQ,GACbX,EAAMW,MAAQ8B,EACdrB,EAAUT,OAAQ,CACpB,GA7EN9D,EAAY6F,KAAKhB,GAnBnB3E,iBACE,IAAID,EAAJ,CAGA,IAFAA,GAAoB,EAEbD,EAAY8F,OAAS,GAAG,CAC7B,MAAMjB,EAAO7E,EAAY+F,QACzB,GAAIlB,EACF,UACQA,GACR,OAASe,GACP1C,QAAQC,MAAM,8BAA+ByC,EAC/C,CAEJ,CAEA3F,GAAoB,CAdG,CAezB,CAIE+F,IA+EE,IACA,CAAEC,SAAS,EAAOC,UAAU,IAe9B,OAZAC,EAAAA,MACE,CAAC,IAA0B,iBAAZzC,EAAuBA,EAAUA,EAAQI,MAAQ,IAAMC,EAAcD,OACpF,KACEW,KAEF,CAAE2B,WAAW,IAGfC,EAAAA,YAAY,KACV7B,GAAc,IAGT,CACLH,OACAlB,QACAoB,YAEJ,yBAEO,SAAwBZ,GAC7B,MAAM8B,UAAEA,GAAc9B,EAEhBpC,EAAQ+C,EAAAA,IAAI,GACZgC,EAAOhC,EAAAA,IAAI,GACXiC,EAAOjC,EAAAA,IAAI,GACXkC,EAAalC,EAAAA,KAAI,GAEvB,IAAImC,EAAoC,KAExC,MAAMC,EAAS,IAAMjB,EAAU3B,OAAO6C,cAAc,gCAE9CC,EAAmBjG,IACvBA,EAAIkG,MAAMC,gBAAkB,gBAC5BnG,EAAIkG,MAAME,UAAY,aAAaT,EAAKxC,YAAYyC,EAAKzC,kBAAkBvC,EAAMuC,UAG7EkD,EAAa,KACjBzF,EAAMuC,MAAQ,EACdwC,EAAKxC,MAAQ,EACbyC,EAAKzC,MAAQ,EACb0C,EAAW1C,OAAQ,GAyKfmD,EAAU,KACdR,MACAA,EAAe,KACfO,KAaF,OAVAb,EAAAA,MACE,IAAMV,EAAU3B,MAChB,KACEmD,IACAD,MAIJX,EAAAA,YAAYY,GAEL,CACLC,OAhEa,KACb,MAAMvG,EAAM+F,IACR/F,IACFY,EAAMuC,MAAQuB,KAAK8B,IAAI5F,EAAMuC,MAAQ,GAAK,IAC1C8C,EAAgBjG,KA6DlByG,QAzDc,KACd,MAAMzG,EAAM+F,IACR/F,IACFY,EAAMuC,MAAQuB,KAAKgC,IAAI9F,EAAMuC,MAAQ,GAAK,IAC1C8C,EAAgBjG,KAsDlB2G,MAlDY,KACZ,MAAM3G,EAAM+F,IACR/F,IACFqG,IACAJ,EAAgBjG,KA+ClB4G,WA3CiB,KACZ9B,EAAU3B,QAEX5C,SAASsG,kBACXtG,SAASuG,iBAEThC,EAAU3B,MAAM4D,wBAsClBT,UACAxG,WAnCiB,KACjB,IAAKgF,EAAU3B,MAAO,OAEtBkD,IAEAP,EA9J2B,CAACkB,IAC5B,IAAIC,EAAS,EACTC,EAAS,EACTC,GAA2B,EAE/B,MAAMC,EAAU,CAACC,EAAiBC,KAChCzB,EAAW1C,OAAQ,EACnB8D,EAASI,EAAU1B,EAAKxC,MACxB+D,EAASI,EAAU1B,EAAKzC,MACxB5C,SAAS0B,KAAKiE,MAAMqB,WAAa,QAG7BC,EAAS,CAACH,EAAiBC,KAC/B,GAAIzB,EAAW1C,OAASgE,EAA0B,CAChDxB,EAAKxC,MAAQkE,EAAUJ,EACvBrB,EAAKzC,MAAQmE,EAAUJ,EACvB,MAAMlH,EAAM+F,IACR/F,GACFiG,EAAgBjG,EAEpB,GAGIyH,EAAQ,KACZ5B,EAAW1C,OAAQ,EACnBgE,GAA2B,EAC3B5G,SAAS0B,KAAKiE,MAAMqB,WAAa,IAG7BG,EAAeC,IACF,IAAbA,EAAEC,SACFD,EAAEE,SAAWb,GAAeA,EAAYc,SAASH,EAAEE,WACrDF,EAAEI,iBACFZ,GAA2B,EAC3BC,EAAQO,EAAEN,QAASM,EAAEL,WAInBU,EAAeL,IACfR,GACFK,EAAOG,EAAEN,QAASM,EAAEL,UAiClBW,EAAqBlE,WA7BF4D,IACvB,MAAM3H,EAAM+F,IACZ,IAAK/F,EAAK,OAEV,MAAMkI,EAAgBlB,EAAYmB,wBAC5BC,EAAUpI,EAAImI,wBAEdE,EAASV,EAAEN,QAAUa,EAAcI,KACnCC,EAASZ,EAAEL,QAAUY,EAAcM,IAEnCC,EAAaL,EAAQE,KAAOJ,EAAcI,KAAOF,EAAQvH,MAAQ,EACjE6H,EAAaN,EAAQI,IAAMN,EAAcM,IAAMJ,EAAQtH,OAAS,EAEhE6H,GAAWN,EAASI,EAAa9C,EAAKxC,OAASvC,EAAMuC,MACrDyF,GAAWL,EAASG,EAAa9C,EAAKzC,OAASvC,EAAMuC,MAErD0F,EAAQlB,EAAEmB,OAAS,GAAI,IAAQ,IAC/BC,EAAWrE,KAAK8B,IAAI9B,KAAKgC,IAAI9F,EAAMuC,MAAQ0F,EAAO,IAAM,IAE1DE,IAAanI,EAAMuC,QAEvBvC,EAAMuC,MAAQ4F,EAEdpD,EAAKxC,MAAQkF,EAASI,EAAaE,EAAU/H,EAAMuC,MACnDyC,EAAKzC,MAAQoF,EAASG,EAAaE,EAAUhI,EAAMuC,MAEnD8C,EAAgBjG,KAGmC,GAAI,CAAEsF,SAAS,EAAMC,UAAU,IAE9EyD,EAAWrB,KACXA,EAAEE,SAAWb,GAAeA,EAAYc,SAASH,EAAEE,WACrDF,EAAEI,iBACFE,EAAmBN,KAIjBsB,EAAgBtB,KAChBA,EAAEE,SAAWb,GAAeA,EAAYc,SAASH,EAAEE,UAC5B,IAArBF,EAAEuB,QAAQ/D,SACZwC,EAAEI,iBACFZ,GAA2B,EAC3BC,EAAQO,EAAEuB,QAAQ,GAAG7B,QAASM,EAAEuB,QAAQ,GAAG5B,WAK3C6B,EAAexB,IACfR,IACFQ,EAAEI,iBACFP,EAAOG,EAAEuB,QAAQ,GAAG7B,QAASM,EAAEuB,QAAQ,GAAG5B,WAY9C,OARAN,EAAYoC,iBAAiB,YAAa1B,GAC1CnH,SAAS6I,iBAAiB,YAAapB,GACvCzH,SAAS6I,iBAAiB,UAAW3B,GACrCT,EAAYoC,iBAAiB,QAASJ,EAAS,CAAEK,SAAS,IAC1DrC,EAAYoC,iBAAiB,aAAcH,EAAc,CAAEI,SAAS,IACpErC,EAAYoC,iBAAiB,YAAaD,EAAa,CAAEE,SAAS,IAClE9I,SAAS6I,iBAAiB,WAAY3B,GAE/B,KACLT,EAAYsC,oBAAoB,YAAa5B,GAC7CnH,SAAS+I,oBAAoB,YAAatB,GAC1CzH,SAAS+I,oBAAoB,UAAW7B,GACxCT,EAAYsC,oBAAoB,QAASN,GACzChC,EAAYsC,oBAAoB,aAAcL,GAC9CjC,EAAYsC,oBAAoB,YAAaH,GAC7C5I,SAAS+I,oBAAoB,WAAY7B,GACzClH,SAAS0B,KAAKiE,MAAMqB,WAAa,KA2CpBgC,CAAqBzE,EAAU3B,OAE9C,MAAMnD,EAAM+F,IACR/F,GACFiG,EAAgBjG,IA4BtB"}
|
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.es27.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.es28.js";
|
|
5
5
|
/* empty css */
|
|
6
6
|
import CodeBlock from "./x-markdown.es17.js";
|
|
7
7
|
const _hoisted_1 = { class: "toolbar-container" };
|
package/dist/x-markdown.es27.js
CHANGED
|
@@ -1,142 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
const
|
|
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
|
-
});
|
|
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"]]);
|
|
139
5
|
export {
|
|
140
|
-
|
|
6
|
+
SyntaxCodeBlock as default
|
|
141
7
|
};
|
|
142
8
|
//# sourceMappingURL=x-markdown.es27.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es27.js","sources":[
|
|
1
|
+
{"version":3,"file":"x-markdown.es27.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -0,0 +1,142 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
package/dist/x-markdown.es33.js
CHANGED
package/dist/x-markdown.es9.js
CHANGED
|
@@ -75,7 +75,9 @@ async function checkMermaidAvailable() {
|
|
|
75
75
|
mermaidCheckPromise = (async () => {
|
|
76
76
|
try {
|
|
77
77
|
const mod = await import("mermaid");
|
|
78
|
-
|
|
78
|
+
const mermaidInstance = mod?.default;
|
|
79
|
+
const hasMermaidAPI = mermaidInstance && (typeof mermaidInstance.render === "function" || typeof mermaidInstance.initialize === "function" || typeof mermaidInstance.run === "function");
|
|
80
|
+
mermaidAvailableCache = hasMermaidAPI;
|
|
79
81
|
return mermaidAvailableCache;
|
|
80
82
|
} catch {
|
|
81
83
|
mermaidAvailableCache = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es9.js","sources":["../src/hooks/useMermaid.ts"],"sourcesContent":["import type { Ref } from 'vue'\r\nimport { throttle } from 'lodash-es'\r\nimport { computed, ref, watch, onUnmounted } from 'vue'\r\nimport type { MermaidZoomControls, UseMermaidZoomOptions, UseMermaidResult } from '../components/Mermaid/types'\r\n\r\nexport function downloadSvgAsPng(svg: string): void {\r\n if (!svg) return\r\n\r\n try {\r\n const svgDataUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`\r\n const img = new Image()\r\n\r\n img.onload = () => {\r\n try {\r\n const canvas = document.createElement('canvas')\r\n const ctx = canvas.getContext('2d', { willReadFrequently: false })\r\n if (!ctx) return\r\n\r\n const scale = 2\r\n canvas.width = img.width * scale\r\n canvas.height = img.height * scale\r\n ctx.imageSmoothingEnabled = true\r\n ctx.imageSmoothingQuality = 'high'\r\n\r\n ctx.fillStyle = '#ffffff'\r\n ctx.fillRect(0, 0, canvas.width, canvas.height)\r\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height)\r\n\r\n const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-')\r\n\r\n try {\r\n canvas.toBlob(\r\n (blob) => {\r\n if (!blob) return\r\n const url = URL.createObjectURL(blob)\r\n const link = document.createElement('a')\r\n link.href = url\r\n link.download = `mermaid-diagram-${timestamp}.png`\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n URL.revokeObjectURL(url)\r\n },\r\n 'image/png',\r\n 0.95,\r\n )\r\n } catch (toBlobError) {\r\n console.error('Failed to convert canvas to blob:', toBlobError)\r\n try {\r\n const dataUrl = canvas.toDataURL('image/png', 0.95)\r\n const link = document.createElement('a')\r\n link.href = dataUrl\r\n link.download = `mermaid-diagram-${timestamp}.png`\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n } catch (dataUrlError) {\r\n console.error('Failed to convert canvas to data URL:', dataUrlError)\r\n }\r\n }\r\n } catch (canvasError) {\r\n console.error('Canvas operation failed:', canvasError)\r\n }\r\n }\r\n\r\n img.onerror = (error) => {\r\n console.error('Failed to load image:', error)\r\n }\r\n\r\n img.src = svgDataUrl\r\n } catch (error) {\r\n console.error('Failed to download SVG:', error)\r\n }\r\n}\r\n\r\ninterface UseMermaidOptions {\r\n id?: string\r\n theme?: 'default' | 'dark' | 'forest' | 'neutral' | string\r\n config?: any\r\n container?: HTMLElement | Ref<HTMLElement | null> | null\r\n}\r\n\r\ntype UseMermaidOptionsInput = UseMermaidOptions | Ref<UseMermaidOptions>\r\n\r\nlet mermaidPromise: Promise<any> | null = null\r\nlet hasShownMermaidHint = false\r\nlet mermaidAvailableCache: boolean | null = null\r\nlet mermaidCheckPromise: Promise<boolean> | null = null\r\n\r\n/**\r\n * 同步检查缓存状态(不触发检测)\r\n * @returns 缓存状态,null 表示未检测\r\n */\r\nexport function getMermaidAvailableCache(): boolean | null {\r\n return mermaidAvailableCache\r\n}\r\n\r\n/**\r\n * 检测 mermaid 是否可用(全局缓存,只检测一次)\r\n */\r\nexport async function checkMermaidAvailable(): Promise<boolean> {\r\n // 如果已经有缓存结果,直接返回\r\n if (mermaidAvailableCache !== null) {\r\n return mermaidAvailableCache\r\n }\r\n\r\n // 如果正在检测,返回检测 Promise\r\n if (mermaidCheckPromise) {\r\n return mermaidCheckPromise\r\n }\r\n\r\n // 开始检测\r\n mermaidCheckPromise = (async () => {\r\n try {\r\n const mod = await import('mermaid')\r\n mermaidAvailableCache = !!mod\r\n return mermaidAvailableCache\r\n } catch {\r\n // 静默失败,mermaid 不可用\r\n mermaidAvailableCache = false\r\n return false\r\n }\r\n })()\r\n\r\n return mermaidCheckPromise\r\n}\r\n\r\nconst showMermaidHint = () => {\r\n if (hasShownMermaidHint) return\r\n hasShownMermaidHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c Mermaid 图表功能已降级为代码块显示',\r\n 'font-weight: bold; color: #9333ea;',\r\n 'color: #666;'\r\n )\r\n console.log(\r\n '%c如需 Mermaid 图表渲染功能,请安装:',\r\n 'color: #666; font-weight: bold;'\r\n )\r\n console.log(\r\n '%c pnpm add mermaid',\r\n 'color: #9333ea; 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\nasync function loadMermaid() {\r\n if (typeof window === 'undefined') return null\r\n if (!mermaidPromise) {\r\n mermaidPromise = (async () => {\r\n try {\r\n const mod = await import('mermaid')\r\n return (mod as any)?.default\r\n } catch {\r\n // 静默失败,显示友好提示\r\n showMermaidHint()\r\n return null\r\n }\r\n })()\r\n }\r\n return mermaidPromise\r\n}\r\n\r\ntype RenderTask = () => Promise<void>\r\nconst renderQueue: RenderTask[] = []\r\nlet isProcessingQueue = false\r\n\r\nasync function processRenderQueue() {\r\n if (isProcessingQueue) return\r\n isProcessingQueue = true\r\n\r\n while (renderQueue.length > 0) {\r\n const task = renderQueue.shift()\r\n if (task) {\r\n try {\r\n await task()\r\n } catch (err) {\r\n console.error('Mermaid render queue error:', err)\r\n }\r\n }\r\n }\r\n\r\n isProcessingQueue = false\r\n}\r\n\r\nfunction addToRenderQueue(task: RenderTask) {\r\n renderQueue.push(task)\r\n processRenderQueue()\r\n}\r\n\r\nexport function useMermaid(content: string | Ref<string>, options: UseMermaidOptionsInput = {}): UseMermaidResult {\r\n const optionsRef = computed(() => (typeof options === 'object' && 'value' in options ? options.value : options))\r\n const mermaidConfig = computed(() => ({\r\n suppressErrorRendering: true,\r\n startOnLoad: false,\r\n securityLevel: 'loose',\r\n theme: optionsRef.value.theme || 'default',\r\n ...(optionsRef.value.config || {}),\r\n }))\r\n const data = ref('')\r\n const error = ref<unknown>(null)\r\n const isLoading = ref(false)\r\n\r\n let isUnmounted = false\r\n\r\n const getRenderContainer = () => {\r\n const containerOption = optionsRef.value.container\r\n if (containerOption) {\r\n return typeof containerOption === 'object' && 'value' in containerOption ? containerOption.value : containerOption\r\n }\r\n return null\r\n }\r\n\r\n const throttledRender = throttle(\r\n () => {\r\n const contentValue = typeof content === 'string' ? content : content.value\r\n if (!contentValue?.trim()) {\r\n data.value = ''\r\n error.value = null\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n isLoading.value = true\r\n\r\n addToRenderQueue(async () => {\r\n if (isUnmounted) return\r\n\r\n try {\r\n const mermaidInstance = await loadMermaid()\r\n if (!mermaidInstance) {\r\n data.value = contentValue\r\n error.value = null\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n mermaidInstance.initialize(mermaidConfig.value)\r\n\r\n const isValid = await mermaidInstance.parse(contentValue.trim())\r\n if (!isValid) {\r\n data.value = ''\r\n error.value = new Error('Mermaid parse error: Invalid syntax')\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n const renderId = `${optionsRef.value.id || 'mermaid'}-${Math.random().toString(36).substring(2, 11)}`\r\n const container = getRenderContainer()\r\n if (!container) {\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n const { svg } = await mermaidInstance.render(renderId, contentValue, container)\r\n data.value = svg\r\n error.value = null\r\n isLoading.value = false\r\n } catch (err) {\r\n // Mermaid render error\r\n data.value = ''\r\n error.value = err\r\n isLoading.value = false\r\n }\r\n })\r\n },\r\n 100,\r\n { leading: false, trailing: true },\r\n )\r\n\r\n watch(\r\n [() => (typeof content === 'string' ? content : content.value), () => mermaidConfig.value],\r\n () => {\r\n throttledRender()\r\n },\r\n { immediate: true },\r\n )\r\n\r\n onUnmounted(() => {\r\n isUnmounted = true\r\n })\r\n\r\n return {\r\n data,\r\n error,\r\n isLoading,\r\n }\r\n}\r\n\r\nexport function useMermaidZoom(options: UseMermaidZoomOptions): MermaidZoomControls {\r\n const { container } = options\r\n\r\n const scale = ref(1)\r\n const posX = ref(0)\r\n const posY = ref(0)\r\n const isDragging = ref(false)\r\n\r\n let removeEvents: (() => void) | null = null\r\n\r\n const getSvg = () => container.value?.querySelector('.syntax-mermaid__content svg') as HTMLElement\r\n\r\n const updateTransform = (svg: HTMLElement) => {\r\n svg.style.transformOrigin = 'center center'\r\n svg.style.transform = `translate(${posX.value}px, ${posY.value}px) scale(${scale.value})`\r\n }\r\n\r\n const resetState = () => {\r\n scale.value = 1\r\n posX.value = 0\r\n posY.value = 0\r\n isDragging.value = false\r\n }\r\n\r\n const addInteractionEvents = (containerEl: HTMLElement) => {\r\n let startX = 0\r\n let startY = 0\r\n let isInteractingWithMermaid = false\r\n\r\n const onStart = (clientX: number, clientY: number) => {\r\n isDragging.value = true\r\n startX = clientX - posX.value\r\n startY = clientY - posY.value\r\n document.body.style.userSelect = 'none'\r\n }\r\n\r\n const onMove = (clientX: number, clientY: number) => {\r\n if (isDragging.value && isInteractingWithMermaid) {\r\n posX.value = clientX - startX\r\n posY.value = clientY - startY\r\n const svg = getSvg()\r\n if (svg) {\r\n updateTransform(svg)\r\n }\r\n }\r\n }\r\n\r\n const onEnd = () => {\r\n isDragging.value = false\r\n isInteractingWithMermaid = false\r\n document.body.style.userSelect = ''\r\n }\r\n\r\n const onMouseDown = (e: MouseEvent) => {\r\n if (e.button !== 0) return\r\n if (e.target === containerEl || containerEl.contains(e.target as Node)) {\r\n e.preventDefault()\r\n isInteractingWithMermaid = true\r\n onStart(e.clientX, e.clientY)\r\n }\r\n }\r\n\r\n const onMouseMove = (e: MouseEvent) => {\r\n if (isInteractingWithMermaid) {\r\n onMove(e.clientX, e.clientY)\r\n }\r\n }\r\n\r\n const handleWheelZoom = (e: WheelEvent) => {\r\n const svg = getSvg()\r\n if (!svg) return\r\n\r\n const containerRect = containerEl.getBoundingClientRect()\r\n const svgRect = svg.getBoundingClientRect()\r\n\r\n const mouseX = e.clientX - containerRect.left\r\n const mouseY = e.clientY - containerRect.top\r\n\r\n const svgCenterX = svgRect.left - containerRect.left + svgRect.width / 2\r\n const svgCenterY = svgRect.top - containerRect.top + svgRect.height / 2\r\n\r\n const offsetX = (mouseX - svgCenterX - posX.value) / scale.value\r\n const offsetY = (mouseY - svgCenterY - posY.value) / scale.value\r\n\r\n const delta = e.deltaY > 0 ? -0.05 : 0.05\r\n const newScale = Math.min(Math.max(scale.value + delta, 0.1), 10)\r\n\r\n if (newScale === scale.value) return\r\n\r\n scale.value = newScale\r\n\r\n posX.value = mouseX - svgCenterX - offsetX * scale.value\r\n posY.value = mouseY - svgCenterY - offsetY * scale.value\r\n\r\n updateTransform(svg)\r\n }\r\n\r\n const throttledWheelZoom = throttle(handleWheelZoom, 20, { leading: true, trailing: true })\r\n\r\n const onWheel = (e: WheelEvent) => {\r\n if (e.target === containerEl || containerEl.contains(e.target as Node)) {\r\n e.preventDefault()\r\n throttledWheelZoom(e)\r\n }\r\n }\r\n\r\n const onTouchStart = (e: TouchEvent) => {\r\n if (e.target === containerEl || containerEl.contains(e.target as Node)) {\r\n if (e.touches.length === 1) {\r\n e.preventDefault()\r\n isInteractingWithMermaid = true\r\n onStart(e.touches[0].clientX, e.touches[0].clientY)\r\n }\r\n }\r\n }\r\n\r\n const onTouchMove = (e: TouchEvent) => {\r\n if (isInteractingWithMermaid) {\r\n e.preventDefault()\r\n onMove(e.touches[0].clientX, e.touches[0].clientY)\r\n }\r\n }\r\n\r\n containerEl.addEventListener('mousedown', onMouseDown)\r\n document.addEventListener('mousemove', onMouseMove)\r\n document.addEventListener('mouseup', onEnd)\r\n containerEl.addEventListener('wheel', onWheel, { passive: false })\r\n containerEl.addEventListener('touchstart', onTouchStart, { passive: false })\r\n containerEl.addEventListener('touchmove', onTouchMove, { passive: false })\r\n document.addEventListener('touchend', onEnd)\r\n\r\n return () => {\r\n containerEl.removeEventListener('mousedown', onMouseDown)\r\n document.removeEventListener('mousemove', onMouseMove)\r\n document.removeEventListener('mouseup', onEnd)\r\n containerEl.removeEventListener('wheel', onWheel)\r\n containerEl.removeEventListener('touchstart', onTouchStart)\r\n containerEl.removeEventListener('touchmove', onTouchMove)\r\n document.removeEventListener('touchend', onEnd)\r\n document.body.style.userSelect = ''\r\n }\r\n }\r\n\r\n const zoomIn = () => {\r\n const svg = getSvg()\r\n if (svg) {\r\n scale.value = Math.min(scale.value + 0.2, 10)\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const zoomOut = () => {\r\n const svg = getSvg()\r\n if (svg) {\r\n scale.value = Math.max(scale.value - 0.2, 0.1)\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const reset = () => {\r\n const svg = getSvg()\r\n if (svg) {\r\n resetState()\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const fullscreen = () => {\r\n if (!container.value) return\r\n\r\n if (document.fullscreenElement) {\r\n document.exitFullscreen()\r\n } else {\r\n container.value.requestFullscreen?.()\r\n }\r\n }\r\n\r\n const initialize = () => {\r\n if (!container.value) return\r\n\r\n resetState()\r\n\r\n removeEvents = addInteractionEvents(container.value)\r\n\r\n const svg = getSvg()\r\n if (svg) {\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const destroy = () => {\r\n removeEvents?.()\r\n removeEvents = null\r\n resetState()\r\n }\r\n\r\n watch(\r\n () => container.value,\r\n () => {\r\n destroy()\r\n resetState()\r\n },\r\n )\r\n\r\n onUnmounted(destroy)\r\n\r\n return {\r\n zoomIn,\r\n zoomOut,\r\n reset,\r\n fullscreen,\r\n destroy,\r\n initialize,\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"x-markdown.es9.js","sources":["../src/hooks/useMermaid.ts"],"sourcesContent":["import type { Ref } from 'vue'\r\nimport { throttle } from 'lodash-es'\r\nimport { computed, ref, watch, onUnmounted } from 'vue'\r\nimport type { MermaidZoomControls, UseMermaidZoomOptions, UseMermaidResult } from '../components/Mermaid/types'\r\n\r\nexport function downloadSvgAsPng(svg: string): void {\r\n if (!svg) return\r\n\r\n try {\r\n const svgDataUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`\r\n const img = new Image()\r\n\r\n img.onload = () => {\r\n try {\r\n const canvas = document.createElement('canvas')\r\n const ctx = canvas.getContext('2d', { willReadFrequently: false })\r\n if (!ctx) return\r\n\r\n const scale = 2\r\n canvas.width = img.width * scale\r\n canvas.height = img.height * scale\r\n ctx.imageSmoothingEnabled = true\r\n ctx.imageSmoothingQuality = 'high'\r\n\r\n ctx.fillStyle = '#ffffff'\r\n ctx.fillRect(0, 0, canvas.width, canvas.height)\r\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height)\r\n\r\n const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-')\r\n\r\n try {\r\n canvas.toBlob(\r\n (blob) => {\r\n if (!blob) return\r\n const url = URL.createObjectURL(blob)\r\n const link = document.createElement('a')\r\n link.href = url\r\n link.download = `mermaid-diagram-${timestamp}.png`\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n URL.revokeObjectURL(url)\r\n },\r\n 'image/png',\r\n 0.95,\r\n )\r\n } catch (toBlobError) {\r\n console.error('Failed to convert canvas to blob:', toBlobError)\r\n try {\r\n const dataUrl = canvas.toDataURL('image/png', 0.95)\r\n const link = document.createElement('a')\r\n link.href = dataUrl\r\n link.download = `mermaid-diagram-${timestamp}.png`\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n } catch (dataUrlError) {\r\n console.error('Failed to convert canvas to data URL:', dataUrlError)\r\n }\r\n }\r\n } catch (canvasError) {\r\n console.error('Canvas operation failed:', canvasError)\r\n }\r\n }\r\n\r\n img.onerror = (error) => {\r\n console.error('Failed to load image:', error)\r\n }\r\n\r\n img.src = svgDataUrl\r\n } catch (error) {\r\n console.error('Failed to download SVG:', error)\r\n }\r\n}\r\n\r\ninterface UseMermaidOptions {\r\n id?: string\r\n theme?: 'default' | 'dark' | 'forest' | 'neutral' | string\r\n config?: any\r\n container?: HTMLElement | Ref<HTMLElement | null> | null\r\n}\r\n\r\ntype UseMermaidOptionsInput = UseMermaidOptions | Ref<UseMermaidOptions>\r\n\r\nlet mermaidPromise: Promise<any> | null = null\r\nlet hasShownMermaidHint = false\r\nlet mermaidAvailableCache: boolean | null = null\r\nlet mermaidCheckPromise: Promise<boolean | null> | null = null\r\n\r\n/**\r\n * 同步检查缓存状态(不触发检测)\r\n * @returns 缓存状态,null 表示未检测\r\n */\r\nexport function getMermaidAvailableCache(): boolean | null {\r\n return mermaidAvailableCache\r\n}\r\n\r\n/**\r\n * 检测 mermaid 是否可用(全局缓存,只检测一次)\r\n */\r\nexport async function checkMermaidAvailable(): Promise<boolean> {\r\n // 如果已经有缓存结果,直接返回\r\n if (mermaidAvailableCache !== null) {\r\n return mermaidAvailableCache\r\n }\r\n\r\n // 如果正在检测,返回检测 Promise\r\n if (mermaidCheckPromise) {\r\n return mermaidCheckPromise as Promise<boolean>\r\n }\r\n\r\n // 开始检测\r\n mermaidCheckPromise = (async () => {\r\n try {\r\n const mod = await import('mermaid')\r\n // 检查模块是否有实际的 mermaid 功能\r\n // 虚拟模块返回 { default: null },所以需要检查 default 是否存在且有效\r\n const mermaidInstance = (mod as any)?.default\r\n // 检查是否有 mermaid 的关键方法或属性\r\n const hasMermaidAPI = mermaidInstance && (\r\n typeof mermaidInstance.render === 'function' ||\r\n typeof mermaidInstance.initialize === 'function' ||\r\n typeof mermaidInstance.run === 'function'\r\n )\r\n mermaidAvailableCache = hasMermaidAPI\r\n return mermaidAvailableCache\r\n } catch {\r\n // 静默失败,mermaid 不可用\r\n mermaidAvailableCache = false\r\n return false\r\n }\r\n })()\r\n\r\n return mermaidCheckPromise as Promise<boolean>\r\n}\r\n\r\nconst showMermaidHint = () => {\r\n if (hasShownMermaidHint) return\r\n hasShownMermaidHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c Mermaid 图表功能已降级为代码块显示',\r\n 'font-weight: bold; color: #9333ea;',\r\n 'color: #666;'\r\n )\r\n console.log(\r\n '%c如需 Mermaid 图表渲染功能,请安装:',\r\n 'color: #666; font-weight: bold;'\r\n )\r\n console.log(\r\n '%c pnpm add mermaid',\r\n 'color: #9333ea; 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\nasync function loadMermaid() {\r\n if (typeof window === 'undefined') return null\r\n if (!mermaidPromise) {\r\n mermaidPromise = (async () => {\r\n try {\r\n const mod = await import('mermaid')\r\n return (mod as any)?.default\r\n } catch {\r\n // 静默失败,显示友好提示\r\n showMermaidHint()\r\n return null\r\n }\r\n })()\r\n }\r\n return mermaidPromise\r\n}\r\n\r\ntype RenderTask = () => Promise<void>\r\nconst renderQueue: RenderTask[] = []\r\nlet isProcessingQueue = false\r\n\r\nasync function processRenderQueue() {\r\n if (isProcessingQueue) return\r\n isProcessingQueue = true\r\n\r\n while (renderQueue.length > 0) {\r\n const task = renderQueue.shift()\r\n if (task) {\r\n try {\r\n await task()\r\n } catch (err) {\r\n console.error('Mermaid render queue error:', err)\r\n }\r\n }\r\n }\r\n\r\n isProcessingQueue = false\r\n}\r\n\r\nfunction addToRenderQueue(task: RenderTask) {\r\n renderQueue.push(task)\r\n processRenderQueue()\r\n}\r\n\r\nexport function useMermaid(content: string | Ref<string>, options: UseMermaidOptionsInput = {}): UseMermaidResult {\r\n const optionsRef = computed(() => (typeof options === 'object' && 'value' in options ? options.value : options))\r\n const mermaidConfig = computed(() => ({\r\n suppressErrorRendering: true,\r\n startOnLoad: false,\r\n securityLevel: 'loose',\r\n theme: optionsRef.value.theme || 'default',\r\n ...(optionsRef.value.config || {}),\r\n }))\r\n const data = ref('')\r\n const error = ref<unknown>(null)\r\n const isLoading = ref(false)\r\n\r\n let isUnmounted = false\r\n\r\n const getRenderContainer = () => {\r\n const containerOption = optionsRef.value.container\r\n if (containerOption) {\r\n return typeof containerOption === 'object' && 'value' in containerOption ? containerOption.value : containerOption\r\n }\r\n return null\r\n }\r\n\r\n const throttledRender = throttle(\r\n () => {\r\n const contentValue = typeof content === 'string' ? content : content.value\r\n if (!contentValue?.trim()) {\r\n data.value = ''\r\n error.value = null\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n isLoading.value = true\r\n\r\n addToRenderQueue(async () => {\r\n if (isUnmounted) return\r\n\r\n try {\r\n const mermaidInstance = await loadMermaid()\r\n if (!mermaidInstance) {\r\n data.value = contentValue\r\n error.value = null\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n mermaidInstance.initialize(mermaidConfig.value)\r\n\r\n const isValid = await mermaidInstance.parse(contentValue.trim())\r\n if (!isValid) {\r\n data.value = ''\r\n error.value = new Error('Mermaid parse error: Invalid syntax')\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n const renderId = `${optionsRef.value.id || 'mermaid'}-${Math.random().toString(36).substring(2, 11)}`\r\n const container = getRenderContainer()\r\n if (!container) {\r\n isLoading.value = false\r\n return\r\n }\r\n\r\n const { svg } = await mermaidInstance.render(renderId, contentValue, container)\r\n data.value = svg\r\n error.value = null\r\n isLoading.value = false\r\n } catch (err) {\r\n // Mermaid render error\r\n data.value = ''\r\n error.value = err\r\n isLoading.value = false\r\n }\r\n })\r\n },\r\n 100,\r\n { leading: false, trailing: true },\r\n )\r\n\r\n watch(\r\n [() => (typeof content === 'string' ? content : content.value), () => mermaidConfig.value],\r\n () => {\r\n throttledRender()\r\n },\r\n { immediate: true },\r\n )\r\n\r\n onUnmounted(() => {\r\n isUnmounted = true\r\n })\r\n\r\n return {\r\n data,\r\n error,\r\n isLoading,\r\n }\r\n}\r\n\r\nexport function useMermaidZoom(options: UseMermaidZoomOptions): MermaidZoomControls {\r\n const { container } = options\r\n\r\n const scale = ref(1)\r\n const posX = ref(0)\r\n const posY = ref(0)\r\n const isDragging = ref(false)\r\n\r\n let removeEvents: (() => void) | null = null\r\n\r\n const getSvg = () => container.value?.querySelector('.syntax-mermaid__content svg') as HTMLElement\r\n\r\n const updateTransform = (svg: HTMLElement) => {\r\n svg.style.transformOrigin = 'center center'\r\n svg.style.transform = `translate(${posX.value}px, ${posY.value}px) scale(${scale.value})`\r\n }\r\n\r\n const resetState = () => {\r\n scale.value = 1\r\n posX.value = 0\r\n posY.value = 0\r\n isDragging.value = false\r\n }\r\n\r\n const addInteractionEvents = (containerEl: HTMLElement) => {\r\n let startX = 0\r\n let startY = 0\r\n let isInteractingWithMermaid = false\r\n\r\n const onStart = (clientX: number, clientY: number) => {\r\n isDragging.value = true\r\n startX = clientX - posX.value\r\n startY = clientY - posY.value\r\n document.body.style.userSelect = 'none'\r\n }\r\n\r\n const onMove = (clientX: number, clientY: number) => {\r\n if (isDragging.value && isInteractingWithMermaid) {\r\n posX.value = clientX - startX\r\n posY.value = clientY - startY\r\n const svg = getSvg()\r\n if (svg) {\r\n updateTransform(svg)\r\n }\r\n }\r\n }\r\n\r\n const onEnd = () => {\r\n isDragging.value = false\r\n isInteractingWithMermaid = false\r\n document.body.style.userSelect = ''\r\n }\r\n\r\n const onMouseDown = (e: MouseEvent) => {\r\n if (e.button !== 0) return\r\n if (e.target === containerEl || containerEl.contains(e.target as Node)) {\r\n e.preventDefault()\r\n isInteractingWithMermaid = true\r\n onStart(e.clientX, e.clientY)\r\n }\r\n }\r\n\r\n const onMouseMove = (e: MouseEvent) => {\r\n if (isInteractingWithMermaid) {\r\n onMove(e.clientX, e.clientY)\r\n }\r\n }\r\n\r\n const handleWheelZoom = (e: WheelEvent) => {\r\n const svg = getSvg()\r\n if (!svg) return\r\n\r\n const containerRect = containerEl.getBoundingClientRect()\r\n const svgRect = svg.getBoundingClientRect()\r\n\r\n const mouseX = e.clientX - containerRect.left\r\n const mouseY = e.clientY - containerRect.top\r\n\r\n const svgCenterX = svgRect.left - containerRect.left + svgRect.width / 2\r\n const svgCenterY = svgRect.top - containerRect.top + svgRect.height / 2\r\n\r\n const offsetX = (mouseX - svgCenterX - posX.value) / scale.value\r\n const offsetY = (mouseY - svgCenterY - posY.value) / scale.value\r\n\r\n const delta = e.deltaY > 0 ? -0.05 : 0.05\r\n const newScale = Math.min(Math.max(scale.value + delta, 0.1), 10)\r\n\r\n if (newScale === scale.value) return\r\n\r\n scale.value = newScale\r\n\r\n posX.value = mouseX - svgCenterX - offsetX * scale.value\r\n posY.value = mouseY - svgCenterY - offsetY * scale.value\r\n\r\n updateTransform(svg)\r\n }\r\n\r\n const throttledWheelZoom = throttle(handleWheelZoom, 20, { leading: true, trailing: true })\r\n\r\n const onWheel = (e: WheelEvent) => {\r\n if (e.target === containerEl || containerEl.contains(e.target as Node)) {\r\n e.preventDefault()\r\n throttledWheelZoom(e)\r\n }\r\n }\r\n\r\n const onTouchStart = (e: TouchEvent) => {\r\n if (e.target === containerEl || containerEl.contains(e.target as Node)) {\r\n if (e.touches.length === 1) {\r\n e.preventDefault()\r\n isInteractingWithMermaid = true\r\n onStart(e.touches[0].clientX, e.touches[0].clientY)\r\n }\r\n }\r\n }\r\n\r\n const onTouchMove = (e: TouchEvent) => {\r\n if (isInteractingWithMermaid) {\r\n e.preventDefault()\r\n onMove(e.touches[0].clientX, e.touches[0].clientY)\r\n }\r\n }\r\n\r\n containerEl.addEventListener('mousedown', onMouseDown)\r\n document.addEventListener('mousemove', onMouseMove)\r\n document.addEventListener('mouseup', onEnd)\r\n containerEl.addEventListener('wheel', onWheel, { passive: false })\r\n containerEl.addEventListener('touchstart', onTouchStart, { passive: false })\r\n containerEl.addEventListener('touchmove', onTouchMove, { passive: false })\r\n document.addEventListener('touchend', onEnd)\r\n\r\n return () => {\r\n containerEl.removeEventListener('mousedown', onMouseDown)\r\n document.removeEventListener('mousemove', onMouseMove)\r\n document.removeEventListener('mouseup', onEnd)\r\n containerEl.removeEventListener('wheel', onWheel)\r\n containerEl.removeEventListener('touchstart', onTouchStart)\r\n containerEl.removeEventListener('touchmove', onTouchMove)\r\n document.removeEventListener('touchend', onEnd)\r\n document.body.style.userSelect = ''\r\n }\r\n }\r\n\r\n const zoomIn = () => {\r\n const svg = getSvg()\r\n if (svg) {\r\n scale.value = Math.min(scale.value + 0.2, 10)\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const zoomOut = () => {\r\n const svg = getSvg()\r\n if (svg) {\r\n scale.value = Math.max(scale.value - 0.2, 0.1)\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const reset = () => {\r\n const svg = getSvg()\r\n if (svg) {\r\n resetState()\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const fullscreen = () => {\r\n if (!container.value) return\r\n\r\n if (document.fullscreenElement) {\r\n document.exitFullscreen()\r\n } else {\r\n container.value.requestFullscreen?.()\r\n }\r\n }\r\n\r\n const initialize = () => {\r\n if (!container.value) return\r\n\r\n resetState()\r\n\r\n removeEvents = addInteractionEvents(container.value)\r\n\r\n const svg = getSvg()\r\n if (svg) {\r\n updateTransform(svg)\r\n }\r\n }\r\n\r\n const destroy = () => {\r\n removeEvents?.()\r\n removeEvents = null\r\n resetState()\r\n }\r\n\r\n watch(\r\n () => container.value,\r\n () => {\r\n destroy()\r\n resetState()\r\n },\r\n )\r\n\r\n onUnmounted(destroy)\r\n\r\n return {\r\n zoomIn,\r\n zoomOut,\r\n reset,\r\n fullscreen,\r\n destroy,\r\n initialize,\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.136",
|
|
4
4
|
"description": "A markdown component library for Vue",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/x-markdown.cjs.js",
|
|
@@ -17,10 +17,12 @@
|
|
|
17
17
|
"default": "./dist/x-markdown.cjs.js"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
|
-
"./style": "./dist/style.css"
|
|
20
|
+
"./style": "./dist/style.css",
|
|
21
|
+
"./vite-plugin": "./src/vite-plugin.js"
|
|
21
22
|
},
|
|
22
23
|
"files": [
|
|
23
|
-
"dist"
|
|
24
|
+
"dist",
|
|
25
|
+
"src/vite-plugin.js"
|
|
24
26
|
],
|
|
25
27
|
"sideEffects": [
|
|
26
28
|
"*.css",
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { resolve } from 'node:path'
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* x-markdown Vite 插件
|
|
7
|
+
*
|
|
8
|
+
* 自动处理可选依赖(shiki、shiki-stream、mermaid)的虚拟模块配置
|
|
9
|
+
* 当这些依赖未安装时,自动映射到虚拟模块避免构建失败
|
|
10
|
+
*
|
|
11
|
+
* @param {Object} options - 插件配置选项
|
|
12
|
+
* @param {string[]} options.optionalDeps - 可选依赖列表(默认:['mermaid', 'shiki', 'shiki-stream'])
|
|
13
|
+
* @param {string} options.virtualModulesDir - 虚拟模块目录(相对于项目根目录)
|
|
14
|
+
* @returns {import('vite').Plugin} Vite 插件
|
|
15
|
+
*/
|
|
16
|
+
export function createXMarkdownVitePlugin(options = {}) {
|
|
17
|
+
const {
|
|
18
|
+
optionalDeps = ['mermaid', 'shiki', 'shiki-stream'],
|
|
19
|
+
virtualModulesDir = './node_modules/@hejiayue/x-markdown-test/virtual-modules',
|
|
20
|
+
} = options
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
name: '@hejiayue/x-markdown-test:vite-plugin',
|
|
24
|
+
enforce: 'pre', // 在其他插件之前执行
|
|
25
|
+
config(config) {
|
|
26
|
+
// 获取项目根目录
|
|
27
|
+
const projectRoot = process.cwd()
|
|
28
|
+
|
|
29
|
+
// 动态生成可选依赖的 alias 配置
|
|
30
|
+
const optionalAliases = []
|
|
31
|
+
|
|
32
|
+
for (const dep of optionalDeps) {
|
|
33
|
+
const depPath = resolve(projectRoot, 'node_modules', dep)
|
|
34
|
+
|
|
35
|
+
if (!existsSync(depPath)) {
|
|
36
|
+
// 依赖未安装,使用虚拟模块
|
|
37
|
+
// 尝试从多个可能的位置查找虚拟模块
|
|
38
|
+
const virtualModulePaths = [
|
|
39
|
+
resolve(projectRoot, virtualModulesDir, `${dep}.js`),
|
|
40
|
+
resolve(projectRoot, 'src/virtual-modules', `${dep}.js`),
|
|
41
|
+
// 最后尝试:从 x-markdown 包内部获取
|
|
42
|
+
resolve(__dirname, 'virtual-modules', `${dep}.js`),
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
let virtualModulePath = null
|
|
46
|
+
for (const path of virtualModulePaths) {
|
|
47
|
+
if (existsSync(path)) {
|
|
48
|
+
virtualModulePath = path
|
|
49
|
+
break
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (virtualModulePath) {
|
|
54
|
+
optionalAliases.push({
|
|
55
|
+
find: dep,
|
|
56
|
+
replacement: virtualModulePath,
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
// 在开发环境显示提示信息
|
|
60
|
+
if (config.mode === 'development') {
|
|
61
|
+
console.log(
|
|
62
|
+
`\x1b[33m[@hejiayue/x-markdown-test]\x1b[0m ${dep} 未安装,使用虚拟模块`
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 如果有需要添加的 alias,更新配置
|
|
70
|
+
if (optionalAliases.length > 0) {
|
|
71
|
+
// 保留原有的 alias 配置
|
|
72
|
+
const existingAlias = config.resolve?.alias || []
|
|
73
|
+
|
|
74
|
+
// 合并 alias 配置
|
|
75
|
+
config.resolve = {
|
|
76
|
+
...config.resolve,
|
|
77
|
+
alias: [
|
|
78
|
+
...optionalAliases,
|
|
79
|
+
...(Array.isArray(existingAlias) ? existingAlias : [existingAlias]),
|
|
80
|
+
],
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// 确保 optionalDeps 不被预构建
|
|
85
|
+
const optimizeDeps = config.optimizeDeps || {}
|
|
86
|
+
const excludeDeps = optimizeDeps.exclude || []
|
|
87
|
+
const includeDeps = optimizeDeps.include || []
|
|
88
|
+
|
|
89
|
+
// 移除未安装的依赖从 include
|
|
90
|
+
const filteredInclude = includeDeps.filter(dep => {
|
|
91
|
+
const depPath = resolve(projectRoot, 'node_modules', dep)
|
|
92
|
+
return existsSync(depPath)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
// 添加未安装的依赖到 exclude
|
|
96
|
+
const newExclude = [...optionalDeps.filter(dep => {
|
|
97
|
+
const depPath = resolve(projectRoot, 'node_modules', dep)
|
|
98
|
+
return !existsSync(depPath)
|
|
99
|
+
}), ...excludeDeps]
|
|
100
|
+
|
|
101
|
+
config.optimizeDeps = {
|
|
102
|
+
...optimizeDeps,
|
|
103
|
+
include: filteredInclude,
|
|
104
|
+
exclude: [...new Set(newExclude)],
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 默认导出,方便使用
|
|
111
|
+
export default createXMarkdownVitePlugin
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 为了兼容性,也提供一个具名导出
|
|
115
|
+
*/
|
|
116
|
+
export { createXMarkdownVitePlugin as xMarkdownVitePlugin }
|
package/dist/x-markdown.cjs29.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs29.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/dist/x-markdown.es29.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es29.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|