collabmd 0.1.26 → 0.1.29
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/README.md +27 -6
- package/dist/client/assets/{CodeMirrorEditor-UCMRAMCV-C5yVpm45.js → CodeMirrorEditor-UCMRAMCV-9k1Shd4H.js} +1 -1
- package/dist/client/assets/{_basePickBy-Dr0N-hVE.js → _basePickBy-B6kIfhzj.js} +1 -1
- package/dist/client/assets/{_baseUniq-BddJc3B1.js → _baseUniq-Bbn0_sHS.js} +1 -1
- package/dist/client/assets/actions-XO29hEzr.css +1 -0
- package/dist/client/assets/{ar-SA-NXDWD63E-C3GLfrYV.js → ar-SA-NXDWD63E-BWO5oYxe.js} +1 -1
- package/dist/client/assets/{arc-fx_D7wYg.js → arc-BIqum3oD.js} +1 -1
- package/dist/client/assets/architecture-PBZL5I3N-iRyVT2GQ.js +1 -0
- package/dist/client/assets/{architectureDiagram-2XIMDMQ5-T__yxKk2.js → architectureDiagram-2XIMDMQ5-Bhh8YQHn.js} +1 -1
- package/dist/client/assets/{az-AZ-MXSORGZV-BJ2t-y-C.js → az-AZ-MXSORGZV-Cfw6Z5oY.js} +1 -1
- package/dist/client/assets/base-B5gONpJK.css +1 -0
- package/dist/client/assets/base-r5Zg2n3k.js +1 -0
- package/dist/client/assets/{bg-BG-O6MV2KSF-Cd3kEZI-.js → bg-BG-O6MV2KSF-CQmG3YpD.js} +1 -1
- package/dist/client/assets/{blockDiagram-WCTKOSBZ-BivLpsk_.js → blockDiagram-WCTKOSBZ-0rR9ivwb.js} +1 -1
- package/dist/client/assets/{bn-IN-MMW2ORAC-Dn9W9dUT.js → bn-BD-T2VJNT7N-C4S6DZ6o.js} +1 -1
- package/dist/client/assets/{bn-BD-T2VJNT7N-BFCx9nbZ.js → bn-IN-MMW2ORAC-DZKVshfk.js} +1 -1
- package/dist/client/assets/{c4Diagram-IC4MRINW-nVzPTZmV.js → c4Diagram-IC4MRINW-DHwxcDlQ.js} +1 -1
- package/dist/client/assets/{ca-ES-MKBCGNOG-D_BNlrmg.js → ca-ES-MKBCGNOG-Do3aMgyu.js} +1 -1
- package/dist/client/assets/channel-s0w88EQN.js +1 -0
- package/dist/client/assets/{chunk-27N2SPOM-CyIruM79.js → chunk-27N2SPOM-DbHKsQ_j.js} +4 -4
- package/dist/client/assets/{chunk-4BX2VUAB-n_yl-toC.js → chunk-4BX2VUAB-BqEY6cCE.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-CJ9i_5Da.js → chunk-55IACEB6-039iVf6v.js} +1 -1
- package/dist/client/assets/{chunk-7E7YKBS2-CebEBDsj.js → chunk-7E7YKBS2-BreG0gYL.js} +1 -1
- package/dist/client/assets/{chunk-7R4GIKGN-BXNhzFkP.js → chunk-7R4GIKGN-BMrp52Pk.js} +2 -2
- package/dist/client/assets/{chunk-C72U2L5F-Cck8MvGP.js → chunk-C72U2L5F-BLB26v5d.js} +1 -1
- package/dist/client/assets/{chunk-EGIJ26TM-BDQ7tRV-.js → chunk-EGIJ26TM-fG-0Yh0k.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-DAcjCJR-.js → chunk-FMBD7UC4-EWK5Pt4D.js} +1 -1
- package/dist/client/assets/{chunk-GEFDOKGD-CYSNVsp-.js → chunk-GEFDOKGD-DYHmaq-c.js} +1 -1
- package/dist/client/assets/chunk-GLR3WWYH-ZnuaBvXp.js +2 -0
- package/dist/client/assets/chunk-HHEYEP7N-DOQ0PCdH.js +1 -0
- package/dist/client/assets/{chunk-JSJVCQXG-CLgStmEI.js → chunk-JSJVCQXG-B69YGtcQ.js} +1 -1
- package/dist/client/assets/{chunk-KX2RTZJC-B__vUl1o.js → chunk-KX2RTZJC-tuEC7hg1.js} +1 -1
- package/dist/client/assets/{chunk-KYZI473N-BpfobHkp.js → chunk-KYZI473N-D4r5eMJZ.js} +1 -1
- package/dist/client/assets/{chunk-L3YUKLVL-B7jdwbRL.js → chunk-L3YUKLVL-CD9nJYL8.js} +1 -1
- package/dist/client/assets/{chunk-MX3YWQON-DNcuP5dS.js → chunk-MX3YWQON-DqN0TF5Q.js} +1 -1
- package/dist/client/assets/{chunk-NQ4KR5QH-oaq5iS2W.js → chunk-NQ4KR5QH-BCjGNd0g.js} +1 -1
- package/dist/client/assets/{chunk-O4XLMI2P-NI4OcSZ6.js → chunk-O4XLMI2P-DaS3COAu.js} +1 -1
- package/dist/client/assets/{chunk-OZEHJAEY-BevHLeQ0.js → chunk-OZEHJAEY-BaBXI-8x.js} +1 -1
- package/dist/client/assets/{chunk-PQ6SQG4A-fQ_Oml5n.js → chunk-PQ6SQG4A-BY9_Srs_.js} +1 -1
- package/dist/client/assets/{chunk-PU5JKC2W-Bp4H-mwZ.js → chunk-PU5JKC2W-t0zUh6E3.js} +1 -1
- package/dist/client/assets/chunk-QZHKN3VN-B0v4d-CS.js +1 -0
- package/dist/client/assets/{chunk-R5LLSJPH-CZzZlfdI.js → chunk-R5LLSJPH-BjSMFnTi.js} +1 -1
- package/dist/client/assets/{chunk-SRAX5OIU-CtUYAya6.js → chunk-SRAX5OIU-CC2mobFL.js} +1 -1
- package/dist/client/assets/{chunk-WL4C6EOR-DnV9nMco.js → chunk-WL4C6EOR-OuH0lN6M.js} +1 -1
- package/dist/client/assets/{chunk-XIRO2GV7-BnkmoLpc.js → chunk-XIRO2GV7-2tirYN5A.js} +1 -1
- package/dist/client/assets/{chunk-XPW4576I-DOk6pMat.js → chunk-XPW4576I-C0GpOUHf.js} +1 -1
- package/dist/client/assets/{chunk-XZSTWKYB-DZzfqgVn.js → chunk-XZSTWKYB-DDkpyNVE.js} +1 -1
- package/dist/client/assets/{chunk-YBOYWFTD-CrI5WFnC.js → chunk-YBOYWFTD-CzyyfGQX.js} +1 -1
- package/dist/client/assets/{chunk-Z5NKEFVG-EGvolisB.js → chunk-Z5NKEFVG-Dgem5v98.js} +1 -1
- package/dist/client/assets/classDiagram-VBA2DB6C-Bpdym3dj.js +1 -0
- package/dist/client/assets/classDiagram-v2-RAHNMMFH-CRAsdVDB.js +1 -0
- package/dist/client/assets/clone-C-n46MFF.js +1 -0
- package/dist/client/assets/controls-CLpueX2m.css +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-PcMOD_rX.js → cose-bilkent-S5V4N54A-jZzFUguD.js} +1 -1
- package/dist/client/assets/{cs-CZ-V77HGUP7-gpioT6mv.js → cs-CZ-V77HGUP7-DmZRJ2UO.js} +1 -1
- package/dist/client/assets/{da-DK-I5RFNTM4-CVv-_qu9.js → da-DK-I5RFNTM4-CRIiLQ-G.js} +1 -1
- package/dist/client/assets/{dagre-KLK3FWXG-Ct1xwvCC.js → dagre-KLK3FWXG-CXSnjrX-.js} +1 -1
- package/dist/client/assets/{dagre-BD9xHP_z.js → dagre-fvYjRtTE.js} +1 -1
- package/dist/client/assets/{de-CH-WLRDEVBV-CL0gsFEp.js → de-CH-WLRDEVBV-k728UA4j.js} +1 -1
- package/dist/client/assets/{de-DE-DTI4WUSC-BQO1SHIK.js → de-DE-DTI4WUSC-MFge9MC3.js} +1 -1
- package/dist/client/assets/{diagram-E7M64L7V-DkHzt94k.js → diagram-E7M64L7V-De0StFef.js} +1 -1
- package/dist/client/assets/{diagram-IFDJBPK2-D4g8afpU.js → diagram-IFDJBPK2-B2m6AJbU.js} +1 -1
- package/dist/client/assets/{diagram-P4PSJMXO-DVwwx6ED.js → diagram-P4PSJMXO-YBWLVENw.js} +1 -1
- package/dist/client/assets/{dist-DzArd_Bk.js → dist-A0eSMIyy.js} +1 -1
- package/dist/client/assets/{dist-lbtQBzLu.js → dist-BNcU46Ik.js} +1 -1
- package/dist/client/assets/{dist-B2pRSR5A.js → dist-BOrlJDrR.js} +1 -1
- package/dist/client/assets/dist-BUEzOS23.js +1 -0
- package/dist/client/assets/{dist-BQhICHxD.js → dist-Bay3vk5z.js} +1 -1
- package/dist/client/assets/{dist-DhzldYic.js → dist-BbKpzsTB.js} +1 -1
- package/dist/client/assets/{dist-60g3bzYH.js → dist-BchrxlnW.js} +1 -1
- package/dist/client/assets/dist-BflL-_8D.js +1 -0
- package/dist/client/assets/{dist-Ciw3BJA2.js → dist-CEYpWxod.js} +1 -1
- package/dist/client/assets/{dist-CvMToPSN.js → dist-CEtbxXlI.js} +1 -1
- package/dist/client/assets/{dist-_L_gn5XE.js → dist-CI_qEj5K.js} +1 -1
- package/dist/client/assets/{dist-D2m8lD1h.js → dist-CMHIjMVe.js} +1 -1
- package/dist/client/assets/{dist-2HWwyMLA.js → dist-Cdzvi8cf.js} +1 -1
- package/dist/client/assets/{dist-BiFbHWxc.js → dist-CsYRf4AV.js} +1 -1
- package/dist/client/assets/{dist-fkQ6urpt.js → dist-Ct1bmQnL.js} +1 -1
- package/dist/client/assets/{dist-BlhsMbAl.js → dist-CtFNDttZ.js} +1 -1
- package/dist/client/assets/{dist-EPRNBXHp.js → dist-D-gRgZ6e.js} +1 -1
- package/dist/client/assets/{dist-WrbPKwPQ.js → dist-D0e6Qsad.js} +1 -1
- package/dist/client/assets/{dist-Q6uG0wie.js → dist-D9c0A4Uh.js} +1 -1
- package/dist/client/assets/{dist-BZc5d15t.js → dist-DS6mEQYy.js} +1 -1
- package/dist/client/assets/dist-DS_4VpEd.js +1 -0
- package/dist/client/assets/{dist-DAwSRqIJ.js → dist-DbhQ5ANS.js} +1 -1
- package/dist/client/assets/{dist-U9MIFRLF.js → dist-DnrO-JZd.js} +1 -1
- package/dist/client/assets/{dist-DrNF924C.js → dist-DveOCUUJ.js} +1 -1
- package/dist/client/assets/{dist-CLsz2DCg.js → dist-DwsFUbuB.js} +1 -1
- package/dist/client/assets/dist-VCYAp958.js +1 -0
- package/dist/client/assets/{dist-DZD5y4h6.js → dist-Yxt8txtM.js} +1 -1
- package/dist/client/assets/{dist-BdtPRC1F.js → dist-npxgF_6V.js} +1 -1
- package/dist/client/assets/{dist-a6bFAbQd.js → dist-u0zDRMQt.js} +1 -1
- package/dist/client/assets/{dockerfile-Ci0-ApQC.js → dockerfile-C0qQqxf9.js} +1 -1
- package/dist/client/assets/drawio-editor-CgbaOvpF.js +9 -0
- package/dist/client/assets/drawio-editor-UQQ8XHou.css +1 -0
- package/dist/client/assets/drawioEditor-Eb2yYhjE.js +2 -0
- package/dist/client/assets/editor-session-DFzBn4RY.js +16 -0
- package/dist/client/assets/{el-GR-ZXDJ2OS4-DGa9DqWI.js → el-GR-ZXDJ2OS4-Bbz93mrG.js} +1 -1
- package/dist/client/assets/embedded-editor-base-DXRHYz6R.css +1 -0
- package/dist/client/assets/{en-CTDJDZ6K-DC-4I8h8.js → en-CTDJDZ6K-BHbXrqU0.js} +1 -1
- package/dist/client/assets/{erDiagram-INFDFZHY-Dnub3poK.js → erDiagram-INFDFZHY-DP3f20BF.js} +1 -1
- package/dist/client/assets/{es-ES-DYQHAD43-Cox3GUnj.js → es-ES-DYQHAD43-CReXU-Nn.js} +1 -1
- package/dist/client/assets/{eu-ES-QDSYU5Y3-DrPM2uSX.js → eu-ES-QDSYU5Y3-jRpcaWwz.js} +1 -1
- package/dist/client/assets/{excalidraw-editor-D8O7A69r.css → excalidraw-editor-Bat1FRoT.css} +1 -1
- package/dist/client/assets/excalidraw-editor-Dj0c0PO6.js +9 -0
- package/dist/client/assets/{excalidraw-mermaid-stub-LpuTrLnr.js → excalidraw-mermaid-stub-efoh2lJm.js} +1 -1
- package/dist/client/assets/excalidraw-scene-CixfM-jL.js +174 -0
- package/dist/client/assets/excalidrawEditor-diK4VITg.js +2 -0
- package/dist/client/assets/export-page-CUOMczdp.js +39 -0
- package/dist/client/assets/exportDocument-BM4_f2n8.js +2 -0
- package/dist/client/assets/exportDocument-CLPYN_gg.css +1 -0
- package/dist/client/assets/{fa-IR-26LZG4PM-ViTdxAWX.js → fa-IR-26LZG4PM-DP8pJ8e3.js} +1 -1
- package/dist/client/assets/{factor-DMvifS-k.js → factor-2uy-lXe_.js} +1 -1
- package/dist/client/assets/{fi-FI-6YS4KDE4-BTBRGd69.js → fi-FI-6YS4KDE4-BLUDpNOj.js} +1 -1
- package/dist/client/assets/{flowDiagram-PKNHOUZH-DF4dDV_8.js → flowDiagram-PKNHOUZH-CRbK5_5h.js} +1 -1
- package/dist/client/assets/{fr-FR-BRLLPTZC-z-POHcHJ.js → fr-FR-BRLLPTZC-BoZz3Pi8.js} +1 -1
- package/dist/client/assets/{ganttDiagram-A5KZAMGK-CwrN53Gu.js → ganttDiagram-A5KZAMGK-R-AMIgxR.js} +1 -1
- package/dist/client/assets/gitGraph-HDMCJU4V-kkuqHGSM.js +1 -0
- package/dist/client/assets/{gitGraphDiagram-K3NZZRJ6-BV9w0K-N.js → gitGraphDiagram-K3NZZRJ6-CIPit_Sh.js} +1 -1
- package/dist/client/assets/{gl-ES-OKUZTLYG-BQtfDFNk.js → gl-ES-OKUZTLYG-CaEvhjDi.js} +1 -1
- package/dist/client/assets/{graphlib-B7v-yqry.js → graphlib-DSzYgMXB.js} +1 -1
- package/dist/client/assets/{he-IL-26MGYIU7-Dyw-xS4W.js → he-IL-26MGYIU7-DYOchgy9.js} +1 -1
- package/dist/client/assets/{hi-IN-Q4ZOGTP2-BqENUkZA.js → hi-IN-Q4ZOGTP2-yRs8g46n.js} +1 -1
- package/dist/client/assets/{hu-HU-P2OXPSN5-D1HGK0_M.js → hu-HU-P2OXPSN5-1skPmtgc.js} +1 -1
- package/dist/client/assets/{id-ID-2EIKXYN6-BEjyfllL.js → id-ID-2EIKXYN6-iUugQJd9.js} +1 -1
- package/dist/client/assets/image-32MOCVDX-BB6utPzr.js +1 -0
- package/dist/client/assets/index-BOOhEiLo.css +1 -0
- package/dist/client/assets/index-CVgVzuh6.js +2 -0
- package/dist/client/assets/info-3K5VOQVL-DPN78whf.js +1 -0
- package/dist/client/assets/infoDiagram-LFFYTUFH-CF8jXFTm.js +2 -0
- package/dist/client/assets/{isEmpty-CLDc0Kt_.js → isEmpty-C7iPDOO3.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-PHBUUO56-CmO_FyHY.js → ishikawaDiagram-PHBUUO56-BDVPgkv4.js} +1 -1
- package/dist/client/assets/{it-IT-4CFKVXI2-C24G-VcQ.js → it-IT-4CFKVXI2-a5DFhzuI.js} +1 -1
- package/dist/client/assets/{ja-JP-MAND2Z4V-DLhvsdYk.js → ja-JP-MAND2Z4V-DwogHVKd.js} +1 -1
- package/dist/client/assets/javascript-8DvdgifH.js +1 -0
- package/dist/client/assets/{journeyDiagram-4ABVD52K-DF4HAYLk.js → journeyDiagram-4ABVD52K-DtNnwL48.js} +1 -1
- package/dist/client/assets/{jsx-runtime-DJkgQklN.js → jsx-runtime-B8dyIONw.js} +1 -1
- package/dist/client/assets/{kaa-HQRTCXTJ-DC8l3BuJ.js → kaa-HQRTCXTJ-p81XNRfH.js} +1 -1
- package/dist/client/assets/{kab-KAB-JKIKKTGH-DVFog4hd.js → kab-KAB-JKIKKTGH-mV5VzQZc.js} +1 -1
- package/dist/client/assets/{kanban-definition-K7BYSVSG-nQoJJABn.js → kanban-definition-K7BYSVSG-C565sUNo.js} +1 -1
- package/dist/client/assets/{kk-KZ-HXQ63ZFC-CULUfwMg.js → kk-KZ-HXQ63ZFC-IIPX0GQv.js} +1 -1
- package/dist/client/assets/{km-KH-PKL3LSGX-CnLlEv7i.js → km-KH-PKL3LSGX-D7WQFJuZ.js} +1 -1
- package/dist/client/assets/{ko-KR-KXLREZX3-DNKXAYCx.js → ko-KR-KXLREZX3-Bs1oLtJs.js} +1 -1
- package/dist/client/assets/{ku-TR-MJ4IER3X-DLUiMa4h.js → ku-TR-MJ4IER3X-DlxOs6aZ.js} +1 -1
- package/dist/client/assets/{line-DvLjT0Gv.js → line-D57TbKb7.js} +1 -1
- package/dist/client/assets/{linear-CEb8O7zv.js → linear-BIf852wI.js} +1 -1
- package/dist/client/assets/{lt-LT-H6WFQ6FJ-CoFiurzb.js → lt-LT-H6WFQ6FJ-xuo-3zKH.js} +1 -1
- package/dist/client/assets/{lv-LV-GOCK6SJW-DzeEvHxX.js → lv-LV-GOCK6SJW-C7S3M1nr.js} +1 -1
- package/dist/client/assets/main-C8adLQnt.js +1174 -0
- package/dist/client/assets/{mermaid-parser.core-DllATXd7.js → mermaid-parser.core-By_5k2SF.js} +2 -2
- package/dist/client/assets/{mermaid-runtime-DbCLD8Ih.js → mermaid-runtime-DqncQoYK.js} +3 -3
- package/dist/client/assets/{mindmap-definition-YRQLILUH-DaMULsE9.js → mindmap-definition-YRQLILUH-BbYzGfTD.js} +1 -1
- package/dist/client/assets/{mr-IN-IXVLDMEQ-C5i5R9H5.js → mr-IN-IXVLDMEQ-BsoowyZT.js} +1 -1
- package/dist/client/assets/{my-MM-YG6MYTTD-DvwceqO-.js → my-MM-YG6MYTTD-DCqwN_K_.js} +1 -1
- package/dist/client/assets/navigation-Du6CLhvs.css +1 -0
- package/dist/client/assets/{nb-NO-XGWJISD2-BUhX8hX0.js → nb-NO-XGWJISD2-CZ5ytLgj.js} +1 -1
- package/dist/client/assets/{nl-NL-XVDVCPNC-BV6Y0-Q0.js → nl-NL-XVDVCPNC-wADsdb-h.js} +1 -1
- package/dist/client/assets/{nn-NO-EMX5MJX5-CF_bB9Jq.js → nn-NO-EMX5MJX5-D9zIKTL2.js} +1 -1
- package/dist/client/assets/{nsis-42hkxqLx.js → nsis-CUd4RnvJ.js} +1 -1
- package/dist/client/assets/{oc-FR-ROEINTVO-CiNI8fg8.js → oc-FR-ROEINTVO-BSbBugJB.js} +1 -1
- package/dist/client/assets/{ordinal-fW5lWpNM.js → ordinal-B0PAtOQ6.js} +1 -1
- package/dist/client/assets/{pa-IN-ZYN6SUDY-CsbIU150.js → pa-IN-ZYN6SUDY-1pFA_3Pb.js} +1 -1
- package/dist/client/assets/packet-RMMSAZCW-BymvQ5cQ.js +1 -0
- package/dist/client/assets/percentages-5DKR754L-CiI2D7zA.js +1 -0
- package/dist/client/assets/{pica-BbcTjVoI.js → pica-By-YDy_B.js} +1 -1
- package/dist/client/assets/pie-UPGHQEXC-MmzJzWOE.js +1 -0
- package/dist/client/assets/{pieDiagram-SKSYHLDU-BPFp1WBd.js → pieDiagram-SKSYHLDU-CAU_gC7U.js} +1 -1
- package/dist/client/assets/{pl-PL-6VTG7PHC-D1Nnx7R3.js → pl-PL-6VTG7PHC-DyYw0u_z.js} +1 -1
- package/dist/client/assets/preview-diagram-utils-Dc83ucbv.js +1 -0
- package/dist/client/assets/preview-render-compiler-CVfDHnqM.js +1 -0
- package/dist/client/assets/preview-render-compiler-CapHJDHT.js +1 -0
- package/dist/client/assets/{preview-render-profile-DQsam_Ol.js → preview-render-profile-DPzmho7I.js} +1 -1
- package/dist/client/assets/{preview-render-worker-CcASh3y3.js → preview-render-worker-wMS710Bv.js} +1 -1
- package/dist/client/assets/{pt-BR-5YFKRR5G-DEDTeWEP.js → pt-BR-5YFKRR5G-DJCCBBDl.js} +1 -1
- package/dist/client/assets/{pt-PT-GEIXXZ67-BpqPVZom.js → pt-PT-GEIXXZ67-BPJd09Ax.js} +1 -1
- package/dist/client/assets/{pug-BANqyQJ9.js → pug-BqBF8qF7.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-337W2JSQ-DjPGrcJM.js → quadrantDiagram-337W2JSQ-DhlKLozd.js} +1 -1
- package/dist/client/assets/{quick-switcher-controller-n6Jhu3Z9.js → quick-switcher-controller-DplOTsT3.js} +1 -1
- package/dist/client/assets/radar-KQ55EAFF-CCohASSY.js +1 -0
- package/dist/client/assets/{requirementDiagram-Z7DCOOCP-BmiYAMKV.js → requirementDiagram-Z7DCOOCP-B7ZOMsIb.js} +1 -1
- package/dist/client/assets/{ro-RO-E2P6TFZI-4vRM1jVT.js → ro-RO-E2P6TFZI-DWVyTV7V.js} +1 -1
- package/dist/client/assets/{room-DyhEnogt.js → room-B0UGbzQj.js} +1 -1
- package/dist/client/assets/{ru-RU-YBIIY43T-Cfbhz4Ew.js → ru-RU-YBIIY43T-Dyar7CYM.js} +1 -1
- package/dist/client/assets/runtime-config-CqX_f_Q4.js +1 -0
- package/dist/client/assets/{sankeyDiagram-WA2Y5GQK-BEoPAlcC.js → sankeyDiagram-WA2Y5GQK-CXRga6Op.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-2WXFIKYE-BXqojuDS.js → sequenceDiagram-2WXFIKYE-CeSFlFx5.js} +1 -1
- package/dist/client/assets/{si-LK-673C2CI2-0muNkOEn.js → si-LK-673C2CI2-C61aLrIy.js} +1 -1
- package/dist/client/assets/{sk-SK-CKZHQ4AP-EnLgxyJL.js → sk-SK-CKZHQ4AP-BlFwOxRD.js} +1 -1
- package/dist/client/assets/{sl-SI-557H2GWM-BN6npqVj.js → sl-SI-557H2GWM-DcAVW-_t.js} +1 -1
- package/dist/client/assets/{src-DUDi_GeV.js → src-E3c2cohN.js} +1 -1
- package/dist/client/assets/{stateDiagram-RAJIS63D-DTR2sQs8.js → stateDiagram-RAJIS63D-CPoSrNwn.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-FVOUBMTO-5GW0Y21a.js +1 -0
- package/dist/client/assets/states-P2LsGDDn.css +1 -0
- package/dist/client/assets/subset-shared.chunk-CC_u8ICU.js +1 -0
- package/dist/client/assets/{subset-worker.chunk-1FoL7eL0.js → subset-worker.chunk-DVGT6bvR.js} +1 -1
- package/dist/client/assets/{sv-SE-XOPKKDWS-D3VSs2SQ.js → sv-SE-XOPKKDWS-BkhfOHzh.js} +1 -1
- package/dist/client/assets/{ta-IN-XBH7DQI3-BKR1mqfo.js → ta-IN-XBH7DQI3-BIfwglZa.js} +1 -1
- package/dist/client/assets/{th-TH-TOCWH3R4-Bek1dQcW.js → th-TH-TOCWH3R4-CkrxqVkf.js} +1 -1
- package/dist/client/assets/{timeline-definition-YZTLITO2-BP09qqIh.js → timeline-definition-YZTLITO2-BXBHNWLQ.js} +1 -1
- package/dist/client/assets/{tr-TR-GXW6CYY5-xdLb7Dgi.js → tr-TR-GXW6CYY5-CDdvG9rD.js} +1 -1
- package/dist/client/assets/treemap-KZPCXAKY-9kxB0uNY.js +1 -0
- package/dist/client/assets/{uk-UA-IJKTNUDG-Cd0AhTti.js → uk-UA-IJKTNUDG-DRHp0lWp.js} +1 -1
- package/dist/client/assets/{uz-UZ-TBZZEA4V-DQH4e-QC.js → uz-UZ-TBZZEA4V-BIn-VE3Y.js} +1 -1
- package/dist/client/assets/vault-api-client-DIaCC56H.js +1 -0
- package/dist/client/assets/vault-api-client-De7kMvrE.css +1 -0
- package/dist/client/assets/{vennDiagram-LZ73GAT5-BvSlhnT0.js → vennDiagram-LZ73GAT5-Cs9aQmVM.js} +1 -1
- package/dist/client/assets/{vi-VN-MULSGNVB-BYDcPrAo.js → vi-VN-MULSGNVB-Du7t5I0v.js} +1 -1
- package/dist/client/assets/{xychartDiagram-JWTSCODW-BvZ78F0j.js → xychartDiagram-JWTSCODW-B40ybbzC.js} +1 -1
- package/dist/client/assets/yjs-provider-reset-guard-DUP9XupO.js +4 -0
- package/dist/client/assets/{zh-CN-MVX3E32U-BqZQ-18-.js → zh-CN-MVX3E32U-RcjS3rjt.js} +1 -1
- package/dist/client/assets/{zh-HK-JNU5RLIE-CbF8Agwa.js → zh-HK-JNU5RLIE-g8UeEw5v.js} +1 -1
- package/dist/client/assets/{zh-TW-LENVCA6T-CepoVycx.js → zh-TW-LENVCA6T-DwV25BqC.js} +1 -1
- package/dist/client/drawio-editor.html +4 -26
- package/dist/client/excalidraw-editor.html +4 -19
- package/dist/client/export-document.html +29 -0
- package/dist/client/index.html +7 -445
- package/package.json +4 -2
- package/src/client/app/drawio-editor.html +1 -23
- package/src/client/app/excalidraw-editor.html +1 -16
- package/src/client/app/export-document-entry.js +25 -0
- package/src/client/app/export-document.html +24 -0
- package/src/client/app/index.html +1 -441
- package/src/client/app/main-entry.js +2 -0
- package/src/client/application/app-shell/export-feature.js +39 -0
- package/src/client/application/app-shell/ui-feature-shell.js +65 -16
- package/src/client/application/app-shell/ui-feature-toolbar.js +1 -1
- package/src/client/application/app-shell/workspace-feature.js +31 -3
- package/src/client/application/app-shell-elements.js +3 -0
- package/src/client/application/preview-render-compiler.js +6 -3
- package/src/client/application/workspace-chrome-controller.js +3 -1
- package/src/client/application/workspace-coordinator.js +8 -1
- package/src/client/application/workspace-preview-controller.js +8 -3
- package/src/client/application/workspace-state-store.js +1 -0
- package/src/client/bootstrap/collabmd-app-shell.js +8 -1
- package/src/client/drawio-editor.js +4 -1
- package/src/client/excalidraw-editor.js +8 -0
- package/src/client/export/export-host.js +193 -0
- package/src/client/export/export-page.js +60 -0
- package/src/client/export/export-pipeline.js +1410 -0
- package/src/client/export/export-print-layout.js +50 -0
- package/src/client/infrastructure/auth-client.js +2 -203
- package/src/client/infrastructure/editor-session.js +8 -0
- package/src/client/infrastructure/editor-view-adapter.js +34 -0
- package/src/client/presentation/app-shell-renderer.js +13 -0
- package/src/client/presentation/app-shell-template.js +590 -0
- package/src/client/presentation/comment-ui/comment-ui-card.js +32 -10
- package/src/client/presentation/comments-panel.js +5 -3
- package/src/client/presentation/components/ui/badge.js +24 -0
- package/src/client/presentation/components/ui/button.js +78 -0
- package/src/client/presentation/components/ui/class-names.js +30 -0
- package/src/client/presentation/components/ui/ensure-ui-component-styles.js +18 -0
- package/src/client/presentation/components/ui/input.js +9 -0
- package/src/client/presentation/components/ui/segmented-control.js +31 -0
- package/src/client/presentation/create-menu-presenter.js +10 -2
- package/src/client/presentation/drawio-embed-controller.js +190 -31
- package/src/client/presentation/file-action-controller.js +4 -4
- package/src/client/presentation/file-explorer-view.js +9 -2
- package/src/client/presentation/file-history-view-controller.js +4 -3
- package/src/client/presentation/git-diff-view-controller.js +2 -1
- package/src/client/presentation/git-panel-controller.js +10 -8
- package/src/client/presentation/layout-controller.js +34 -4
- package/src/client/styles/components/actions.css +6 -0
- package/src/client/styles/components/navigation.css +1 -0
- package/src/client/styles/export-document.css +250 -0
- package/src/client/styles/features/auth-gate.css +182 -0
- package/src/client/styles/features/diagram-preview.css +66 -9
- package/src/client/styles/features/git-branch.css +30 -2
- package/src/client/styles/features/preview-markdown.css +7 -4
- package/src/client/styles/layout/editor-page.css +95 -3
- package/src/client/styles/layout/responsive.css +17 -7
- package/src/client/styles/layout/sidebar.css +1 -1
- package/src/client/styles/primitives/controls.css +22 -31
- package/src/client/styles/style.css +0 -4
- package/src/client/styles/surfaces/drawio-editor.css +104 -0
- package/src/client/styles/surfaces/embedded-editor-base.css +23 -0
- package/src/client/styles/surfaces/excalidraw-editor.css +16 -0
- package/src/server/create-app-server.js +3 -0
- package/src/server/domain/docx-exporter.js +62 -0
- package/src/server/infrastructure/http/create-request-handler.js +2 -0
- package/src/server/infrastructure/http/create-vault-api-command-handler.js +59 -1
- package/src/server/infrastructure/http/create-vault-api-handler.js +2 -0
- package/src/server/infrastructure/http/request-body.js +2 -2
- package/dist/client/assets/architecture-PBZL5I3N-C1Yv7agI.js +0 -1
- package/dist/client/assets/channel-DBZin7O0.js +0 -1
- package/dist/client/assets/chunk-GLR3WWYH-FplqAopN.js +0 -2
- package/dist/client/assets/chunk-HHEYEP7N-Bv_FKHmu.js +0 -1
- package/dist/client/assets/chunk-QZHKN3VN-Blawx8vd.js +0 -1
- package/dist/client/assets/classDiagram-VBA2DB6C-CreQafQu.js +0 -1
- package/dist/client/assets/classDiagram-v2-RAHNMMFH-BIYHzbiv.js +0 -1
- package/dist/client/assets/clone-C3ajWNce.js +0 -1
- package/dist/client/assets/dist-BS6yAJ9F.js +0 -1
- package/dist/client/assets/dist-BUnp4fHW.js +0 -1
- package/dist/client/assets/dist-BWEDjv8G.js +0 -1
- package/dist/client/assets/dist-naAaVPPS.js +0 -1
- package/dist/client/assets/drawio-editor-BW2z4NH2.js +0 -9
- package/dist/client/assets/drawioEditor-DgoA4Zqi.js +0 -2
- package/dist/client/assets/editor-session-xPvmulmt.js +0 -16
- package/dist/client/assets/excalidraw-editor-BAYca95w.js +0 -182
- package/dist/client/assets/excalidrawEditor-BY5rq_Bn.js +0 -2
- package/dist/client/assets/gitGraph-HDMCJU4V-DbS2XnWK.js +0 -1
- package/dist/client/assets/image-32MOCVDX-BBXPyAeU.js +0 -1
- package/dist/client/assets/index-C95nV7Tl.css +0 -1
- package/dist/client/assets/index-GE56R5t4.js +0 -2
- package/dist/client/assets/info-3K5VOQVL-Bre4VStM.js +0 -1
- package/dist/client/assets/infoDiagram-LFFYTUFH-CuUbZqrG.js +0 -2
- package/dist/client/assets/javascript-DdEc60Aj.js +0 -1
- package/dist/client/assets/main-AejRWvom.js +0 -600
- package/dist/client/assets/packet-RMMSAZCW-B7lnOkip.js +0 -1
- package/dist/client/assets/percentages-5DKR754L-Dp1vwDEq.js +0 -1
- package/dist/client/assets/pie-UPGHQEXC-D0gHdMgb.js +0 -1
- package/dist/client/assets/preview-render-compiler-BYiRMsPq.js +0 -1
- package/dist/client/assets/radar-KQ55EAFF-D48du2CB.js +0 -1
- package/dist/client/assets/stateDiagram-v2-FVOUBMTO-BwVII-kJ.js +0 -1
- package/dist/client/assets/subset-shared.chunk-C6pUl_Oh.js +0 -1
- package/dist/client/assets/treemap-KZPCXAKY-BBRObSiT.js +0 -1
- package/dist/client/assets/vault-api-client-fFJfUVXM.js +0 -188
- package/dist/client/assets/yjs-provider-reset-guard-Cj00kgyM.js +0 -4
- /package/dist/client/assets/{apl-CJPt5sW7.js → apl-QJCYYBkj.js} +0 -0
- /package/dist/client/assets/{array-e43ctQmx.js → array-DwdVlTkF.js} +0 -0
- /package/dist/client/assets/{asciiarmor-D0oCypDs.js → asciiarmor-DNy0UPqh.js} +0 -0
- /package/dist/client/assets/{asn1-8xgVfRoq.js → asn1-CNPXj-s7.js} +0 -0
- /package/dist/client/assets/{asterisk-B5kv5AQp.js → asterisk-BwMdLpT2.js} +0 -0
- /package/dist/client/assets/{brainfuck-Dh7M1Ucz.js → brainfuck-C2gHT8aA.js} +0 -0
- /package/dist/client/assets/{chunk-3PELD44J-D4qJ8fq7.js → chunk-3PELD44J-CL87tpFo.js} +0 -0
- /package/dist/client/assets/{chunk-A66AFZZU-CJuwmF1m.js → chunk-A66AFZZU-DuceaGnc.js} +0 -0
- /package/dist/client/assets/{chunk-D-fkvfCP.js → chunk-DpHwWhuW.js} +0 -0
- /package/dist/client/assets/{chunk-ETSVUAFD-C8C1JDu2.js → chunk-ETSVUAFD-CN-gPl_j.js} +0 -0
- /package/dist/client/assets/{clike-zYz_LEkw.js → clike-D5X7HJpo.js} +0 -0
- /package/dist/client/assets/{clojure-CdWlIeQh.js → clojure-BEDKZv_5.js} +0 -0
- /package/dist/client/assets/{cmake-wWuF5ifR.js → cmake-Y3shE7av.js} +0 -0
- /package/dist/client/assets/{cobol-D3WLbLVy.js → cobol-f-3TLk62.js} +0 -0
- /package/dist/client/assets/{coffeescript-DRtt-5a2.js → coffeescript-C0XA9-xa.js} +0 -0
- /package/dist/client/assets/{commonlisp-DJV75lsU.js → commonlisp-BOB6sIEu.js} +0 -0
- /package/dist/client/assets/{crystal-C7mEw92C.js → crystal-ByNgE_My.js} +0 -0
- /package/dist/client/assets/{css-_6KgQwpu.js → css-eaI-ENiR.js} +0 -0
- /package/dist/client/assets/{cypher-B3uWx7jm.js → cypher-CQ-dGGSi.js} +0 -0
- /package/dist/client/assets/{cytoscape.esm-BbbuX1pV.js → cytoscape.esm-DBDRhUia.js} +0 -0
- /package/dist/client/assets/{d-D3kOh3JF.js → d-D9pnu4Cr.js} +0 -0
- /package/dist/client/assets/{defaultLocale-DTn6RiRA.js → defaultLocale-BWgun1yJ.js} +0 -0
- /package/dist/client/assets/{diff-CoamybWh.js → diff-z9q33Lo6.js} +0 -0
- /package/dist/client/assets/{dist-yRVuIDKu.js → dist-DnxPQ0-w.js} +0 -0
- /package/dist/client/assets/{drawio-room-D6352KkV.js → drawio-room-C592VDk7.js} +0 -0
- /package/dist/client/assets/{dtd-BjGQwMWL.js → dtd-BDizf_te.js} +0 -0
- /package/dist/client/assets/{dylan-B9W3X2GI.js → dylan-Bk__XCKW.js} +0 -0
- /package/dist/client/assets/{ebnf-d5D0otVn.js → ebnf-SzN4Kxtp.js} +0 -0
- /package/dist/client/assets/{ecl-C5Q_IBPt.js → ecl-5ulxiKbt.js} +0 -0
- /package/dist/client/assets/{eiffel-BQA_6I3b.js → eiffel-Bhoaqbb6.js} +0 -0
- /package/dist/client/assets/{elm-unPS17vB.js → elm-C3je846J.js} +0 -0
- /package/dist/client/assets/{erlang-R8nOsUTx.js → erlang-Cgk9SIAz.js} +0 -0
- /package/dist/client/assets/{excalidraw-mermaid-stub-BJq3n7pR.js → excalidraw-mermaid-stub-B_2dv3Ll.js} +0 -0
- /package/dist/client/assets/{fcl-CVAfW9wK.js → fcl-dvkZwp9p.js} +0 -0
- /package/dist/client/assets/{forth-DHbsK8X8.js → forth-DmfSa3jN.js} +0 -0
- /package/dist/client/assets/{fortran-4jMwxW9-.js → fortran-BsZAiNnN.js} +0 -0
- /package/dist/client/assets/{gas-zC_XGrQT.js → gas-DBpKE9ut.js} +0 -0
- /package/dist/client/assets/{gherkin-CPBQou3u.js → gherkin-CceEbBs7.js} +0 -0
- /package/dist/client/assets/{groovy-Cqopym0q.js → groovy-CxJnDvES.js} +0 -0
- /package/dist/client/assets/{haskell-imzbNPgF.js → haskell-CUSb34Xy.js} +0 -0
- /package/dist/client/assets/{haxe-Doh225Ku.js → haxe-6EHO_h-N.js} +0 -0
- /package/dist/client/assets/{http-j4R5uEso.js → http-C3qcBpvG.js} +0 -0
- /package/dist/client/assets/{idl-l9d1__Hj.js → idl-C95wIO2I.js} +0 -0
- /package/dist/client/assets/{image-blob-reduce.esm-CQfEe3_g.js → image-blob-reduce.esm-BaW4gpT9.js} +0 -0
- /package/dist/client/assets/{init-207s1ipc.js → init-Bjj5fg68.js} +0 -0
- /package/dist/client/assets/{isArrayLikeObject-ZCMZRndo.js → isArrayLikeObject-Cmt1CYnI.js} +0 -0
- /package/dist/client/assets/{javascript-9dQYqEHJ.js → javascript-aWB87b1w.js} +0 -0
- /package/dist/client/assets/{julia-ByGjwiLn.js → julia-DF9PPAXG.js} +0 -0
- /package/dist/client/assets/{katex-XOVNa2d9.js → katex-BPsFnA3D.js} +0 -0
- /package/dist/client/assets/{livescript-B8l2m7xO.js → livescript-CnOyWwUY.js} +0 -0
- /package/dist/client/assets/{lua-DrfAKnQQ.js → lua-a0rEq19C.js} +0 -0
- /package/dist/client/assets/{math-BlD6rf4Z.js → math-BaavbII8.js} +0 -0
- /package/dist/client/assets/{mathematica-DYk_2Ik_.js → mathematica-CKUq0Ojc.js} +0 -0
- /package/dist/client/assets/{mbox-BOzVHzVt.js → mbox-a-u2PLog.js} +0 -0
- /package/dist/client/assets/{mirc-DStbUCmv.js → mirc-BOd43sOX.js} +0 -0
- /package/dist/client/assets/{mllike-BmhQglqS.js → mllike-fHruGivh.js} +0 -0
- /package/dist/client/assets/{modelica-ZElxtbqD.js → modelica-B0NJqf1C.js} +0 -0
- /package/dist/client/assets/{mscgen-f-YxHPr0.js → mscgen-DJZ33SrF.js} +0 -0
- /package/dist/client/assets/{mumps-B79RJJhR.js → mumps-DvMvHTxU.js} +0 -0
- /package/dist/client/assets/{nginx-c--axfuP.js → nginx-BVAs8laz.js} +0 -0
- /package/dist/client/assets/{ntriples-CgD4YZZC.js → ntriples-DrdyAZU1.js} +0 -0
- /package/dist/client/assets/{octave-BQk-bCrp.js → octave-_YqJ0g7E.js} +0 -0
- /package/dist/client/assets/{oz-DPCSPrx5.js → oz-k7T3LoMr.js} +0 -0
- /package/dist/client/assets/{pascal-C1iGzZ53.js → pascal-CftsTvte.js} +0 -0
- /package/dist/client/assets/{path-CDSE7Nw0.js → path-BUmMWM1-.js} +0 -0
- /package/dist/client/assets/{perl-DQ3L8ffg.js → perl-CbsLFc7A.js} +0 -0
- /package/dist/client/assets/{pig-B4S8acys.js → pig-C-jTwMS-.js} +0 -0
- /package/dist/client/assets/{powershell-BhSVdaeY.js → powershell-DqXLgSHX.js} +0 -0
- /package/dist/client/assets/{preload-helper-I1wKxk_B.js → preload-helper-Bo9GmnuQ.js} +0 -0
- /package/dist/client/assets/{properties-B2nfdtxE.js → properties-05jaw55P.js} +0 -0
- /package/dist/client/assets/{protobuf-BFW_iwVN.js → protobuf-DThTsZQN.js} +0 -0
- /package/dist/client/assets/{puppet-C1-CkyhQ.js → puppet-DuHxMpoj.js} +0 -0
- /package/dist/client/assets/{python-CYXPDD4I.js → python-BiE2VHJI.js} +0 -0
- /package/dist/client/assets/{q-Bub5Xmxm.js → q-DH46YfNw.js} +0 -0
- /package/dist/client/assets/{r-C59ONZO2.js → r-DmEm46kJ.js} +0 -0
- /package/dist/client/assets/{rough.esm-xhKrnp4d.js → rough.esm-jZQkcmER.js} +0 -0
- /package/dist/client/assets/{roundRect-CTz-kxJH.js → roundRect-CI6UmGg6.js} +0 -0
- /package/dist/client/assets/{rpm-DiM-R-wd.js → rpm-DILIIbRB.js} +0 -0
- /package/dist/client/assets/{ruby-DTqG95KX.js → ruby-2LcnHEMS.js} +0 -0
- /package/dist/client/assets/{runtime-config-loader-DwWsKc1-.js → runtime-config-loader-_D2KZKn-.js} +0 -0
- /package/dist/client/assets/{sas-BjdhmGHX.js → sas-Bn81MKuB.js} +0 -0
- /package/dist/client/assets/{scheme-CWNdoI17.js → scheme-B8kPNbgd.js} +0 -0
- /package/dist/client/assets/{shell-iaorleRB.js → shell-CGj6v8kb.js} +0 -0
- /package/dist/client/assets/{sieve-D8m9Etmd.js → sieve-CfVNFN1K.js} +0 -0
- /package/dist/client/assets/{simple-mode-kdHrpFjq.js → simple-mode-_FSHdiXs.js} +0 -0
- /package/dist/client/assets/{smalltalk-28WS1mUj.js → smalltalk-BpIFyCPt.js} +0 -0
- /package/dist/client/assets/{solr-x8qQ6eAP.js → solr-B7iFaetn.js} +0 -0
- /package/dist/client/assets/{sparql-BvLmi7B6.js → sparql-COhgMTFK.js} +0 -0
- /package/dist/client/assets/{spreadsheet-BuqSwScP.js → spreadsheet-BzuffEeg.js} +0 -0
- /package/dist/client/assets/{sql-B8tBavZM.js → sql-13lT5zDl.js} +0 -0
- /package/dist/client/assets/{stex-Bx4bLPxI.js → stex-BRSfZZYG.js} +0 -0
- /package/dist/client/assets/{stylus-CMEhEjuV.js → stylus-fFo0QRk_.js} +0 -0
- /package/dist/client/assets/{swift-wY9II8hY.js → swift-wb5gyb6a.js} +0 -0
- /package/dist/client/assets/{tcl-BGywDEsi.js → tcl-BJA7GgWY.js} +0 -0
- /package/dist/client/assets/{textile-K_mvsehZ.js → textile-BQjiYu-x.js} +0 -0
- /package/dist/client/assets/{tiddlywiki-BrpeQ34q.js → tiddlywiki-D2vUXB6n.js} +0 -0
- /package/dist/client/assets/{tiki-z2eQQPgI.js → tiki-BFhpdznG.js} +0 -0
- /package/dist/client/assets/{toml-Dcu7S7XA.js → toml-DN06iQUw.js} +0 -0
- /package/dist/client/assets/{troff-Djlumm7T.js → troff-DuQfjhPH.js} +0 -0
- /package/dist/client/assets/{ttcn-XqU6tthJ.js → ttcn-BCTy6d50.js} +0 -0
- /package/dist/client/assets/{ttcn-cfg-BzD0wr3i.js → ttcn-cfg-BYnZQqGa.js} +0 -0
- /package/dist/client/assets/{turtle-DcjXkx6M.js → turtle-BvN-Me9x.js} +0 -0
- /package/dist/client/assets/{vault-utils-BM4i-Ofm.js → vault-utils-BW53lKl1.js} +0 -0
- /package/dist/client/assets/{vb-DV4y2QrD.js → vb-DYk3wW9u.js} +0 -0
- /package/dist/client/assets/{vbscript-BS8DsYJ_.js → vbscript-BKI61VS6.js} +0 -0
- /package/dist/client/assets/{velocity-CS6Ly2yV.js → velocity-BrtitHHA.js} +0 -0
- /package/dist/client/assets/{verilog-DbEC7ose.js → verilog-CjUx3yiL.js} +0 -0
- /package/dist/client/assets/{vhdl-DBLrW9bF.js → vhdl-CPWwYF4V.js} +0 -0
- /package/dist/client/assets/{webidl-CnE8KY-y.js → webidl-PiVOzma8.js} +0 -0
- /package/dist/client/assets/{xquery--K5Za5EW.js → xquery-CiTzM_oK.js} +0 -0
- /package/dist/client/assets/{yacas-ClQfYBmX.js → yacas-4QS9CntY.js} +0 -0
- /package/dist/client/assets/{z80-Dr2oR3X2.js → z80-BxidrTKR.js} +0 -0
|
@@ -0,0 +1,1410 @@
|
|
|
1
|
+
import { exportToSvg as exportExcalidrawToSvg } from '@excalidraw/excalidraw';
|
|
2
|
+
|
|
3
|
+
import { sanitizeSvgMarkup } from '../application/preview-diagram-utils.js';
|
|
4
|
+
import { compilePreviewDocument } from '../application/preview-render-compiler.js';
|
|
5
|
+
import { stripVaultFileExtension } from '../../domain/file-kind.js';
|
|
6
|
+
import { parseSceneJson, sceneToInitialData } from '../domain/excalidraw-scene.js';
|
|
7
|
+
import { resolveApiUrl, resolveAppUrl } from '../infrastructure/runtime-config.js';
|
|
8
|
+
|
|
9
|
+
const EXPORT_PAGE_SOURCE = 'collabmd-export-page';
|
|
10
|
+
const EXPORT_HOST_SOURCE = 'collabmd-export-host';
|
|
11
|
+
const LIGHT_EXPORT_MERMAID_THEME = Object.freeze({
|
|
12
|
+
htmlLabels: false,
|
|
13
|
+
flowchart: {
|
|
14
|
+
defaultRenderer: 'dagre-wrapper',
|
|
15
|
+
useMaxWidth: true,
|
|
16
|
+
},
|
|
17
|
+
class: {
|
|
18
|
+
defaultRenderer: 'dagre-wrapper',
|
|
19
|
+
useMaxWidth: true,
|
|
20
|
+
},
|
|
21
|
+
startOnLoad: false,
|
|
22
|
+
theme: 'default',
|
|
23
|
+
});
|
|
24
|
+
const EXPORT_ASSET_FETCH_TIMEOUT_MS = 10_000;
|
|
25
|
+
const EXPORT_ASSET_MAX_BYTES = 10 * 1024 * 1024;
|
|
26
|
+
const VIDEO_POSTER_CAPTURE_TIMEOUT_MS = 10_000;
|
|
27
|
+
const VIDEO_POSTER_CAPTURE_SEEK_SECONDS = 1;
|
|
28
|
+
|
|
29
|
+
let mermaidLoaderPromise = null;
|
|
30
|
+
let assetCounter = 0;
|
|
31
|
+
|
|
32
|
+
function createAssetId(prefix = 'asset') {
|
|
33
|
+
assetCounter += 1;
|
|
34
|
+
return `${prefix}-${assetCounter.toString(36)}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function createDocumentTitle(filePath, title = '') {
|
|
38
|
+
const normalizedTitle = String(title ?? '').trim();
|
|
39
|
+
if (normalizedTitle) {
|
|
40
|
+
return normalizedTitle;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const leaf = String(filePath ?? '').split('/').filter(Boolean).pop() || 'document';
|
|
44
|
+
return stripVaultFileExtension(leaf) || 'document';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function encodeSvgDataUrl(svgMarkup) {
|
|
48
|
+
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgMarkup)}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function blobToDataUrl(blob) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const reader = new FileReader();
|
|
54
|
+
reader.addEventListener('load', () => resolve(String(reader.result ?? '')));
|
|
55
|
+
reader.addEventListener('error', () => reject(reader.error ?? new Error('Failed to read blob')));
|
|
56
|
+
reader.readAsDataURL(blob);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function loadImage(src) {
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
const image = new Image();
|
|
63
|
+
image.decoding = 'async';
|
|
64
|
+
image.addEventListener('load', () => resolve(image), { once: true });
|
|
65
|
+
image.addEventListener('error', () => reject(new Error(`Failed to load image: ${src}`)), { once: true });
|
|
66
|
+
image.src = src;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function resolveSvgDimensions(svgElement) {
|
|
71
|
+
const widthAttr = Number.parseFloat(svgElement.getAttribute('width') || '');
|
|
72
|
+
const heightAttr = Number.parseFloat(svgElement.getAttribute('height') || '');
|
|
73
|
+
const viewBox = svgElement.getAttribute('viewBox') || '';
|
|
74
|
+
const viewBoxParts = viewBox.split(/\s+/).map((value) => Number.parseFloat(value));
|
|
75
|
+
|
|
76
|
+
const width = Number.isFinite(widthAttr) && widthAttr > 0
|
|
77
|
+
? widthAttr
|
|
78
|
+
: (Number.isFinite(viewBoxParts[2]) && viewBoxParts[2] > 0 ? viewBoxParts[2] : 1200);
|
|
79
|
+
const height = Number.isFinite(heightAttr) && heightAttr > 0
|
|
80
|
+
? heightAttr
|
|
81
|
+
: (Number.isFinite(viewBoxParts[3]) && viewBoxParts[3] > 0 ? viewBoxParts[3] : 800);
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
height,
|
|
85
|
+
width,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function trimSvgCanvas(svgMarkup, { padding = 16 } = {}) {
|
|
90
|
+
const probe = document.createElement('div');
|
|
91
|
+
probe.style.position = 'fixed';
|
|
92
|
+
probe.style.left = '-10000px';
|
|
93
|
+
probe.style.top = '0';
|
|
94
|
+
probe.style.visibility = 'hidden';
|
|
95
|
+
probe.style.pointerEvents = 'none';
|
|
96
|
+
probe.innerHTML = svgMarkup;
|
|
97
|
+
document.body.appendChild(probe);
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
const svgElement = probe.querySelector('svg');
|
|
101
|
+
if (!(svgElement instanceof SVGSVGElement)) {
|
|
102
|
+
return svgMarkup;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let bounds = null;
|
|
106
|
+
try {
|
|
107
|
+
bounds = svgElement.getBBox();
|
|
108
|
+
} catch {
|
|
109
|
+
return svgMarkup;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!bounds || bounds.width <= 0 || bounds.height <= 0) {
|
|
113
|
+
return svgMarkup;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const inset = Math.max(0, Number(padding) || 0);
|
|
117
|
+
const nextViewBox = [
|
|
118
|
+
Math.floor(bounds.x - inset),
|
|
119
|
+
Math.floor(bounds.y - inset),
|
|
120
|
+
Math.ceil(bounds.width + (inset * 2)),
|
|
121
|
+
Math.ceil(bounds.height + (inset * 2)),
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
const trimmedWidth = Math.ceil(bounds.width + (inset * 2));
|
|
125
|
+
const trimmedHeight = Math.ceil(bounds.height + (inset * 2));
|
|
126
|
+
|
|
127
|
+
svgElement.setAttribute('viewBox', nextViewBox.join(' '));
|
|
128
|
+
svgElement.setAttribute('preserveAspectRatio', 'xMidYMid meet');
|
|
129
|
+
svgElement.setAttribute('width', String(trimmedWidth));
|
|
130
|
+
svgElement.setAttribute('height', String(trimmedHeight));
|
|
131
|
+
return svgElement.outerHTML;
|
|
132
|
+
} finally {
|
|
133
|
+
probe.remove();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function normalizeExportSvgMarkup(svgMarkup, options = {}) {
|
|
138
|
+
return trimSvgCanvas(sanitizeSvgMarkup(svgMarkup), options);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function svgMarkupToPngDataUrl(svgMarkup) {
|
|
142
|
+
const svgDataUrl = encodeSvgDataUrl(svgMarkup);
|
|
143
|
+
const image = await loadImage(svgDataUrl);
|
|
144
|
+
const svgProbe = document.createElement('div');
|
|
145
|
+
svgProbe.innerHTML = svgMarkup;
|
|
146
|
+
const svgElement = svgProbe.querySelector('svg');
|
|
147
|
+
const { width, height } = svgElement ? resolveSvgDimensions(svgElement) : {
|
|
148
|
+
height: image.naturalHeight || 800,
|
|
149
|
+
width: image.naturalWidth || 1200,
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const canvas = document.createElement('canvas');
|
|
153
|
+
canvas.width = Math.max(1, Math.ceil(width));
|
|
154
|
+
canvas.height = Math.max(1, Math.ceil(height));
|
|
155
|
+
const context = canvas.getContext('2d');
|
|
156
|
+
if (!context) {
|
|
157
|
+
throw new Error('Canvas is unavailable');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
context.fillStyle = '#ffffff';
|
|
161
|
+
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
162
|
+
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
163
|
+
return canvas.toDataURL('image/png');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async function imageDataUrlToPngDataUrl(dataUrl) {
|
|
167
|
+
const image = await loadImage(dataUrl);
|
|
168
|
+
const canvas = document.createElement('canvas');
|
|
169
|
+
canvas.width = Math.max(1, image.naturalWidth || image.width || 1);
|
|
170
|
+
canvas.height = Math.max(1, image.naturalHeight || image.height || 1);
|
|
171
|
+
const context = canvas.getContext('2d');
|
|
172
|
+
if (!context) {
|
|
173
|
+
throw new Error('Canvas is unavailable');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
177
|
+
return canvas.toDataURL('image/png');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function fetchJson(url, init = {}) {
|
|
181
|
+
const response = await fetch(url, {
|
|
182
|
+
headers: {
|
|
183
|
+
Accept: 'application/json',
|
|
184
|
+
...(init.headers ?? {}),
|
|
185
|
+
},
|
|
186
|
+
...init,
|
|
187
|
+
});
|
|
188
|
+
const data = await response.json().catch(() => null);
|
|
189
|
+
if (!response.ok) {
|
|
190
|
+
throw new Error(data?.error || `Request failed: ${response.status}`);
|
|
191
|
+
}
|
|
192
|
+
return data;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async function fetchTextFile(filePath) {
|
|
196
|
+
const payload = await fetchJson(resolveApiUrl(`/file?path=${encodeURIComponent(filePath)}`));
|
|
197
|
+
if (typeof payload?.content !== 'string') {
|
|
198
|
+
throw new Error(`Failed to load ${filePath}`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return payload.content;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async function fetchAsDataUrl(src, {
|
|
205
|
+
maxBytes = EXPORT_ASSET_MAX_BYTES,
|
|
206
|
+
timeoutMs = EXPORT_ASSET_FETCH_TIMEOUT_MS,
|
|
207
|
+
} = {}) {
|
|
208
|
+
const assetUrl = new URL(src, window.location.href);
|
|
209
|
+
const controller = new AbortController();
|
|
210
|
+
const timeoutId = window.setTimeout(() => controller.abort(), timeoutMs);
|
|
211
|
+
|
|
212
|
+
let response;
|
|
213
|
+
try {
|
|
214
|
+
response = await fetch(assetUrl.toString(), {
|
|
215
|
+
credentials: assetUrl.origin === window.location.origin ? 'same-origin' : 'omit',
|
|
216
|
+
signal: controller.signal,
|
|
217
|
+
});
|
|
218
|
+
} catch (error) {
|
|
219
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
220
|
+
throw new Error(`Timed out while fetching asset: ${assetUrl.toString()}`);
|
|
221
|
+
}
|
|
222
|
+
throw error;
|
|
223
|
+
} finally {
|
|
224
|
+
window.clearTimeout(timeoutId);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (!response.ok) {
|
|
228
|
+
throw new Error(`Failed to fetch asset: ${assetUrl.toString()}`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const contentLength = Number.parseInt(response.headers.get('content-length') || '', 10);
|
|
232
|
+
if (Number.isFinite(contentLength) && contentLength > maxBytes) {
|
|
233
|
+
throw new Error(`Asset is too large to inline: ${assetUrl.toString()}`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const blob = await response.blob();
|
|
237
|
+
if (blob.size > maxBytes) {
|
|
238
|
+
throw new Error(`Asset is too large to inline: ${assetUrl.toString()}`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return blobToDataUrl(blob);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function buildWikiLinkHref(target) {
|
|
245
|
+
const baseUrl = new URL(resolveAppUrl('/'), window.location.origin);
|
|
246
|
+
baseUrl.hash = new URLSearchParams({ file: target }).toString();
|
|
247
|
+
return baseUrl.toString();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function extractYouTubeVideoId(source = '') {
|
|
251
|
+
let url;
|
|
252
|
+
try {
|
|
253
|
+
url = new URL(String(source || '').trim());
|
|
254
|
+
} catch {
|
|
255
|
+
return '';
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const host = url.hostname.toLowerCase();
|
|
259
|
+
if (host === 'youtu.be' || host === 'www.youtu.be') {
|
|
260
|
+
return url.pathname.split('/').filter(Boolean)[0] || '';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (host.includes('youtube') || host.includes('youtube-nocookie')) {
|
|
264
|
+
if (url.pathname === '/watch') {
|
|
265
|
+
return url.searchParams.get('v') || '';
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (url.pathname.startsWith('/embed/')) {
|
|
269
|
+
return url.pathname.split('/').filter(Boolean)[1] || '';
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return '';
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function createVideoPosterElement(element, {
|
|
277
|
+
assetId = '',
|
|
278
|
+
docxPosterDataUrl = '',
|
|
279
|
+
posterDataUrl = '',
|
|
280
|
+
} = {}) {
|
|
281
|
+
const wrapper = document.createElement('figure');
|
|
282
|
+
wrapper.className = 'export-video-poster';
|
|
283
|
+
if (assetId) {
|
|
284
|
+
wrapper.setAttribute('data-export-asset-id', assetId);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const card = document.createElement('div');
|
|
288
|
+
card.className = 'export-video-poster-card';
|
|
289
|
+
|
|
290
|
+
if (posterDataUrl) {
|
|
291
|
+
const media = document.createElement('div');
|
|
292
|
+
media.className = 'export-video-poster-media';
|
|
293
|
+
|
|
294
|
+
const image = document.createElement('img');
|
|
295
|
+
image.alt = `${element.dataset.videoEmbedLabel || 'Embedded video'} poster`;
|
|
296
|
+
image.className = 'export-video-poster-image';
|
|
297
|
+
image.src = posterDataUrl;
|
|
298
|
+
image.setAttribute('data-export-docx-src', docxPosterDataUrl || posterDataUrl);
|
|
299
|
+
media.appendChild(image);
|
|
300
|
+
|
|
301
|
+
const badge = document.createElement('span');
|
|
302
|
+
badge.className = 'export-video-play-badge';
|
|
303
|
+
badge.setAttribute('aria-hidden', 'true');
|
|
304
|
+
badge.textContent = 'Play';
|
|
305
|
+
media.appendChild(badge);
|
|
306
|
+
|
|
307
|
+
card.appendChild(media);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const copy = document.createElement('div');
|
|
311
|
+
copy.className = 'export-video-poster-copy';
|
|
312
|
+
|
|
313
|
+
const title = document.createElement('strong');
|
|
314
|
+
title.textContent = element.dataset.videoEmbedLabel || 'Embedded video';
|
|
315
|
+
|
|
316
|
+
const meta = document.createElement('span');
|
|
317
|
+
meta.className = 'export-video-poster-meta';
|
|
318
|
+
meta.textContent = element.dataset.videoEmbedKind === 'youtube' ? 'YouTube video' : 'Video link';
|
|
319
|
+
|
|
320
|
+
copy.append(title, meta);
|
|
321
|
+
card.appendChild(copy);
|
|
322
|
+
|
|
323
|
+
const link = document.createElement('a');
|
|
324
|
+
link.className = 'export-video-link';
|
|
325
|
+
link.href = element.dataset.videoEmbedOriginalUrl || element.dataset.videoEmbedSource || element.dataset.videoEmbedUrl || '#';
|
|
326
|
+
link.target = '_blank';
|
|
327
|
+
link.rel = 'noopener noreferrer';
|
|
328
|
+
link.textContent = link.href;
|
|
329
|
+
|
|
330
|
+
wrapper.append(card, link);
|
|
331
|
+
return wrapper;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
async function captureVideoFrameDataUrl(src) {
|
|
335
|
+
const video = document.createElement('video');
|
|
336
|
+
video.muted = true;
|
|
337
|
+
video.playsInline = true;
|
|
338
|
+
video.preload = 'metadata';
|
|
339
|
+
video.crossOrigin = 'anonymous';
|
|
340
|
+
video.style.position = 'fixed';
|
|
341
|
+
video.style.left = '-10000px';
|
|
342
|
+
video.style.top = '0';
|
|
343
|
+
video.style.width = '1px';
|
|
344
|
+
video.style.height = '1px';
|
|
345
|
+
|
|
346
|
+
return new Promise((resolve, reject) => {
|
|
347
|
+
let settled = false;
|
|
348
|
+
|
|
349
|
+
const finish = (callback) => {
|
|
350
|
+
if (settled) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
settled = true;
|
|
355
|
+
window.clearTimeout(timeoutId);
|
|
356
|
+
video.pause?.();
|
|
357
|
+
video.removeEventListener('error', handleError);
|
|
358
|
+
video.removeEventListener('loadeddata', handleLoadedData);
|
|
359
|
+
video.removeEventListener('seeked', handleSeeked);
|
|
360
|
+
video.remove();
|
|
361
|
+
callback();
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
const fail = (message) => {
|
|
365
|
+
finish(() => reject(new Error(message)));
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const drawFrame = () => {
|
|
369
|
+
if (video.videoWidth <= 0 || video.videoHeight <= 0) {
|
|
370
|
+
fail(`Video poster capture returned no frame: ${src}`);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
try {
|
|
375
|
+
const canvas = document.createElement('canvas');
|
|
376
|
+
canvas.width = video.videoWidth;
|
|
377
|
+
canvas.height = video.videoHeight;
|
|
378
|
+
const context = canvas.getContext('2d');
|
|
379
|
+
if (!context) {
|
|
380
|
+
fail('Canvas is unavailable');
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
context.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
385
|
+
const dataUrl = canvas.toDataURL('image/png');
|
|
386
|
+
finish(() => resolve(dataUrl));
|
|
387
|
+
} catch (error) {
|
|
388
|
+
fail(error instanceof Error ? error.message : `Failed to capture video poster: ${src}`);
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
const handleError = () => {
|
|
393
|
+
fail(`Failed to load video poster: ${src}`);
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
const handleSeeked = () => {
|
|
397
|
+
drawFrame();
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
const handleLoadedData = () => {
|
|
401
|
+
const duration = Number.isFinite(video.duration) ? video.duration : 0;
|
|
402
|
+
const targetTime = duration > 0
|
|
403
|
+
? Math.min(VIDEO_POSTER_CAPTURE_SEEK_SECONDS, Math.max(duration * 0.1, 0))
|
|
404
|
+
: 0;
|
|
405
|
+
|
|
406
|
+
if (targetTime > 0.05) {
|
|
407
|
+
try {
|
|
408
|
+
video.currentTime = targetTime;
|
|
409
|
+
return;
|
|
410
|
+
} catch {
|
|
411
|
+
// Fall back to the first available frame when seeking is unavailable.
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
drawFrame();
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
const timeoutId = window.setTimeout(() => {
|
|
419
|
+
fail(`Timed out while loading video poster: ${src}`);
|
|
420
|
+
}, VIDEO_POSTER_CAPTURE_TIMEOUT_MS);
|
|
421
|
+
|
|
422
|
+
video.addEventListener('error', handleError, { once: true });
|
|
423
|
+
video.addEventListener('loadeddata', handleLoadedData, { once: true });
|
|
424
|
+
video.addEventListener('seeked', handleSeeked, { once: true });
|
|
425
|
+
document.body.appendChild(video);
|
|
426
|
+
video.src = src;
|
|
427
|
+
video.load();
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
async function resolveVideoPosterDataUrl(element) {
|
|
432
|
+
const originalUrl = element.dataset.videoEmbedOriginalUrl || element.dataset.videoEmbedSource || '';
|
|
433
|
+
const embedUrl = element.dataset.videoEmbedUrl || '';
|
|
434
|
+
const kind = element.dataset.videoEmbedKind || '';
|
|
435
|
+
|
|
436
|
+
if (kind === 'youtube') {
|
|
437
|
+
const videoId = extractYouTubeVideoId(originalUrl) || extractYouTubeVideoId(embedUrl);
|
|
438
|
+
if (!videoId) {
|
|
439
|
+
throw new Error('Failed to resolve YouTube video id for export');
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const thumbnailCandidates = [
|
|
443
|
+
`https://i.ytimg.com/vi_webp/${videoId}/maxresdefault.webp`,
|
|
444
|
+
`https://i.ytimg.com/vi_webp/${videoId}/hqdefault.webp`,
|
|
445
|
+
`https://i.ytimg.com/vi/${videoId}/maxresdefault.jpg`,
|
|
446
|
+
`https://i.ytimg.com/vi/${videoId}/hqdefault.jpg`,
|
|
447
|
+
];
|
|
448
|
+
|
|
449
|
+
let lastError = null;
|
|
450
|
+
for (const candidate of thumbnailCandidates) {
|
|
451
|
+
try {
|
|
452
|
+
return await fetchAsDataUrl(candidate, {
|
|
453
|
+
maxBytes: 3 * 1024 * 1024,
|
|
454
|
+
timeoutMs: EXPORT_ASSET_FETCH_TIMEOUT_MS,
|
|
455
|
+
});
|
|
456
|
+
} catch (error) {
|
|
457
|
+
lastError = error;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
throw lastError instanceof Error ? lastError : new Error('Failed to fetch YouTube thumbnail');
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (!originalUrl) {
|
|
465
|
+
throw new Error('Missing video source for export poster');
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return captureVideoFrameDataUrl(originalUrl);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
async function resolveVideoPoster(snapshot, shell) {
|
|
472
|
+
const posterDataUrl = await resolveVideoPosterDataUrl(shell);
|
|
473
|
+
const docxPosterDataUrl = await imageDataUrlToPngDataUrl(posterDataUrl).catch(() => posterDataUrl);
|
|
474
|
+
const assetId = registerAsset(snapshot, {
|
|
475
|
+
dataUrl: posterDataUrl,
|
|
476
|
+
id: createAssetId('video-poster'),
|
|
477
|
+
kind: 'video-poster',
|
|
478
|
+
mimeType: posterDataUrl.startsWith('data:image/webp') ? 'image/webp' : 'image/png',
|
|
479
|
+
variants: {
|
|
480
|
+
docx: docxPosterDataUrl,
|
|
481
|
+
},
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
shell.replaceWith(createVideoPosterElement(shell, {
|
|
485
|
+
assetId,
|
|
486
|
+
docxPosterDataUrl,
|
|
487
|
+
posterDataUrl,
|
|
488
|
+
}));
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
function createImageFallbackElement({
|
|
492
|
+
alt = '',
|
|
493
|
+
message = '',
|
|
494
|
+
src = '',
|
|
495
|
+
} = {}) {
|
|
496
|
+
const fallback = document.createElement('span');
|
|
497
|
+
fallback.className = 'export-warning export-image-fallback';
|
|
498
|
+
fallback.textContent = message || 'Image export failed';
|
|
499
|
+
|
|
500
|
+
if (!src) {
|
|
501
|
+
return fallback;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
fallback.append(' ');
|
|
505
|
+
const link = document.createElement('a');
|
|
506
|
+
link.href = src;
|
|
507
|
+
link.rel = 'noopener noreferrer';
|
|
508
|
+
link.target = '_blank';
|
|
509
|
+
link.textContent = alt || src;
|
|
510
|
+
fallback.append(link);
|
|
511
|
+
return fallback;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function createDiagramFigureElement({
|
|
515
|
+
alt,
|
|
516
|
+
assetId,
|
|
517
|
+
className,
|
|
518
|
+
dataUrl,
|
|
519
|
+
docxDataUrl,
|
|
520
|
+
svgMarkup = '',
|
|
521
|
+
}) {
|
|
522
|
+
const figure = document.createElement('figure');
|
|
523
|
+
figure.className = `export-diagram ${className}`.trim();
|
|
524
|
+
figure.setAttribute('data-export-asset-id', assetId);
|
|
525
|
+
figure.setAttribute('data-export-label', alt);
|
|
526
|
+
if (docxDataUrl) {
|
|
527
|
+
figure.setAttribute('data-export-docx-src', docxDataUrl);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (svgMarkup) {
|
|
531
|
+
const surface = document.createElement('div');
|
|
532
|
+
surface.className = 'export-diagram-surface';
|
|
533
|
+
surface.innerHTML = svgMarkup;
|
|
534
|
+
|
|
535
|
+
const svgElement = surface.querySelector('svg');
|
|
536
|
+
if (svgElement) {
|
|
537
|
+
const { width } = resolveSvgDimensions(svgElement);
|
|
538
|
+
surface.style.width = '100%';
|
|
539
|
+
surface.style.maxWidth = `${Math.ceil(width)}px`;
|
|
540
|
+
svgElement.classList.add('export-diagram-svg');
|
|
541
|
+
svgElement.setAttribute('role', 'img');
|
|
542
|
+
svgElement.setAttribute('aria-label', alt);
|
|
543
|
+
svgElement.removeAttribute('width');
|
|
544
|
+
svgElement.removeAttribute('height');
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
figure.appendChild(surface);
|
|
548
|
+
return figure;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
const image = document.createElement('img');
|
|
552
|
+
image.alt = alt;
|
|
553
|
+
image.className = 'export-diagram-image';
|
|
554
|
+
image.src = dataUrl;
|
|
555
|
+
if (docxDataUrl) {
|
|
556
|
+
image.setAttribute('data-export-docx-src', docxDataUrl);
|
|
557
|
+
}
|
|
558
|
+
figure.appendChild(image);
|
|
559
|
+
return figure;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
async function ensureMermaidRuntime() {
|
|
563
|
+
if (mermaidLoaderPromise) {
|
|
564
|
+
return mermaidLoaderPromise;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
mermaidLoaderPromise = import('../mermaid-runtime.js').then((module) => {
|
|
568
|
+
const runtime = module?.default;
|
|
569
|
+
if (!runtime) {
|
|
570
|
+
throw new Error('Mermaid runtime failed to initialize');
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
runtime.initialize(LIGHT_EXPORT_MERMAID_THEME);
|
|
574
|
+
return runtime;
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
return mermaidLoaderPromise;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
function prepareMermaidSource(source) {
|
|
581
|
+
let text = String(source ?? '');
|
|
582
|
+
|
|
583
|
+
if (!/%%\{[\s\S]*?\binit\s*:/m.test(text)) {
|
|
584
|
+
if (/^\s*stateDiagram(?:-v2)?\b/m.test(text) || /^\s*classDiagram\b/m.test(text) || /^\s*gantt\b/m.test(text)) {
|
|
585
|
+
text = `%%{init: ${JSON.stringify({ htmlLabels: false })}}%%\n${text}`;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if (/^\s*gantt\b/m.test(text) && !/\btodayMarker\b/.test(text)) {
|
|
590
|
+
const lines = text.split('\n');
|
|
591
|
+
const ganttLineIndex = lines.findIndex((line) => /^\s*gantt\b/.test(line));
|
|
592
|
+
if (ganttLineIndex !== -1) {
|
|
593
|
+
lines.splice(ganttLineIndex + 1, 0, ' todayMarker off');
|
|
594
|
+
text = lines.join('\n');
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
return text;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
async function renderMermaidToSvgMarkup(source) {
|
|
602
|
+
const mermaid = await ensureMermaidRuntime();
|
|
603
|
+
mermaid.initialize(LIGHT_EXPORT_MERMAID_THEME);
|
|
604
|
+
const renderHost = document.createElement('div');
|
|
605
|
+
renderHost.style.position = 'fixed';
|
|
606
|
+
renderHost.style.left = '-10000px';
|
|
607
|
+
renderHost.style.top = '0';
|
|
608
|
+
renderHost.style.width = '1200px';
|
|
609
|
+
document.body.appendChild(renderHost);
|
|
610
|
+
|
|
611
|
+
try {
|
|
612
|
+
const diagram = document.createElement('div');
|
|
613
|
+
diagram.className = 'mermaid';
|
|
614
|
+
diagram.id = createAssetId('mermaid-render');
|
|
615
|
+
diagram.textContent = prepareMermaidSource(source);
|
|
616
|
+
renderHost.appendChild(diagram);
|
|
617
|
+
await mermaid.run({ nodes: [diagram] });
|
|
618
|
+
const svg = diagram.querySelector('svg');
|
|
619
|
+
if (!svg) {
|
|
620
|
+
throw new Error('Mermaid render returned no SVG');
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
return normalizeExportSvgMarkup(svg.outerHTML, { padding: 24 });
|
|
624
|
+
} finally {
|
|
625
|
+
renderHost.remove();
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
async function renderPlantUmlToSvgMarkup(source) {
|
|
630
|
+
const payload = await fetchJson(resolveApiUrl('/plantuml/render'), {
|
|
631
|
+
body: JSON.stringify({ source }),
|
|
632
|
+
headers: {
|
|
633
|
+
'Content-Type': 'application/json',
|
|
634
|
+
},
|
|
635
|
+
method: 'POST',
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
if (typeof payload?.svg !== 'string' || !payload.svg.includes('<svg')) {
|
|
639
|
+
throw new Error('PlantUML render returned no SVG');
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
return normalizeExportSvgMarkup(payload.svg, { padding: 16 });
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
async function renderExcalidrawToSvgMarkup(filePath) {
|
|
646
|
+
const rawScene = await fetchTextFile(filePath);
|
|
647
|
+
const scene = parseSceneJson(rawScene);
|
|
648
|
+
const initialData = sceneToInitialData(scene, { theme: 'light' });
|
|
649
|
+
const svgElement = await exportExcalidrawToSvg({
|
|
650
|
+
appState: {
|
|
651
|
+
...initialData.appState,
|
|
652
|
+
exportBackground: true,
|
|
653
|
+
exportWithDarkMode: false,
|
|
654
|
+
},
|
|
655
|
+
elements: initialData.elements.filter((element) => !element.isDeleted),
|
|
656
|
+
exportPadding: 24,
|
|
657
|
+
files: initialData.files || null,
|
|
658
|
+
});
|
|
659
|
+
return normalizeExportSvgMarkup(svgElement.outerHTML, { padding: 24 });
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
async function renderDrawioToPngDataUrl(filePath) {
|
|
663
|
+
const instanceId = createAssetId('drawio-export');
|
|
664
|
+
|
|
665
|
+
return new Promise((resolve, reject) => {
|
|
666
|
+
const iframe = document.createElement('iframe');
|
|
667
|
+
iframe.className = 'drawio-export-iframe';
|
|
668
|
+
iframe.src = (() => {
|
|
669
|
+
const url = new URL(resolveAppUrl('/drawio-editor.html'), window.location.origin);
|
|
670
|
+
url.searchParams.set('file', filePath);
|
|
671
|
+
url.searchParams.set('hostMode', 'export-image');
|
|
672
|
+
url.searchParams.set('instanceId', instanceId);
|
|
673
|
+
url.searchParams.set('mode', 'view');
|
|
674
|
+
url.searchParams.set('theme', 'light');
|
|
675
|
+
url.searchParams.set('previewWidth', '1200');
|
|
676
|
+
return url.toString();
|
|
677
|
+
})();
|
|
678
|
+
|
|
679
|
+
const timeoutId = window.setTimeout(() => {
|
|
680
|
+
cleanup();
|
|
681
|
+
reject(new Error('Timed out while exporting draw.io diagram'));
|
|
682
|
+
}, 20000);
|
|
683
|
+
|
|
684
|
+
const handleMessage = (event) => {
|
|
685
|
+
if (event.origin !== window.location.origin) {
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
const payload = event.data;
|
|
690
|
+
if (!payload || payload.source !== 'drawio-editor' || payload.instanceId !== instanceId) {
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
if (payload.type === 'export-image' && typeof payload.data === 'string' && payload.data) {
|
|
695
|
+
cleanup();
|
|
696
|
+
resolve(payload.data);
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
if (payload.type === 'error' || payload.type === 'fallback-text') {
|
|
701
|
+
cleanup();
|
|
702
|
+
reject(new Error(payload.message || 'Failed to export draw.io diagram'));
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
|
|
706
|
+
const cleanup = () => {
|
|
707
|
+
window.clearTimeout(timeoutId);
|
|
708
|
+
window.removeEventListener('message', handleMessage);
|
|
709
|
+
iframe.remove();
|
|
710
|
+
};
|
|
711
|
+
|
|
712
|
+
window.addEventListener('message', handleMessage);
|
|
713
|
+
document.body.appendChild(iframe);
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
function registerAsset(snapshot, asset) {
|
|
718
|
+
snapshot.assets[asset.id] = asset;
|
|
719
|
+
return asset.id;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
async function resolveDiagramShell(snapshot, shell, { label, prefix, render }) {
|
|
723
|
+
let source = shell.querySelector(`.${prefix}-source`)?.textContent ?? '';
|
|
724
|
+
const target = shell.dataset[`${prefix}Target`];
|
|
725
|
+
if (!source.trim() && target) {
|
|
726
|
+
source = await fetchTextFile(target);
|
|
727
|
+
}
|
|
728
|
+
if (!source.trim()) {
|
|
729
|
+
throw new Error(`${label} source is empty`);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
const svgMarkup = await render(source, target);
|
|
733
|
+
const svgDataUrl = encodeSvgDataUrl(svgMarkup);
|
|
734
|
+
const pngDataUrl = await svgMarkupToPngDataUrl(svgMarkup);
|
|
735
|
+
const assetId = registerAsset(snapshot, {
|
|
736
|
+
dataUrl: svgDataUrl,
|
|
737
|
+
id: createAssetId(prefix),
|
|
738
|
+
kind: 'svg',
|
|
739
|
+
mimeType: 'image/svg+xml',
|
|
740
|
+
text: svgMarkup,
|
|
741
|
+
variants: {
|
|
742
|
+
docx: pngDataUrl,
|
|
743
|
+
},
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
shell.replaceWith(createDiagramFigureElement({
|
|
747
|
+
alt: label,
|
|
748
|
+
assetId,
|
|
749
|
+
className: `export-diagram--${prefix}`,
|
|
750
|
+
dataUrl: svgDataUrl,
|
|
751
|
+
docxDataUrl: pngDataUrl,
|
|
752
|
+
svgMarkup,
|
|
753
|
+
}));
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
async function resolveExcalidrawEmbed(snapshot, placeholder) {
|
|
757
|
+
const target = String(placeholder.dataset.embedTarget ?? '').trim();
|
|
758
|
+
if (!target) {
|
|
759
|
+
throw new Error('Missing Excalidraw file path');
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
const svgMarkup = await renderExcalidrawToSvgMarkup(target);
|
|
763
|
+
const svgDataUrl = encodeSvgDataUrl(svgMarkup);
|
|
764
|
+
const pngDataUrl = await svgMarkupToPngDataUrl(svgMarkup);
|
|
765
|
+
const assetId = registerAsset(snapshot, {
|
|
766
|
+
dataUrl: svgDataUrl,
|
|
767
|
+
id: createAssetId('excalidraw'),
|
|
768
|
+
kind: 'svg',
|
|
769
|
+
mimeType: 'image/svg+xml',
|
|
770
|
+
text: svgMarkup,
|
|
771
|
+
variants: {
|
|
772
|
+
docx: pngDataUrl,
|
|
773
|
+
},
|
|
774
|
+
});
|
|
775
|
+
|
|
776
|
+
placeholder.replaceWith(createDiagramFigureElement({
|
|
777
|
+
alt: placeholder.dataset.embedLabel || 'Excalidraw diagram',
|
|
778
|
+
assetId,
|
|
779
|
+
className: 'export-diagram--excalidraw',
|
|
780
|
+
dataUrl: svgDataUrl,
|
|
781
|
+
docxDataUrl: pngDataUrl,
|
|
782
|
+
svgMarkup,
|
|
783
|
+
}));
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
async function resolveDrawioEmbed(snapshot, placeholder) {
|
|
787
|
+
const target = String(placeholder.dataset.drawioTarget ?? '').trim();
|
|
788
|
+
if (!target) {
|
|
789
|
+
throw new Error('Missing draw.io file path');
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
const pngDataUrl = await renderDrawioToPngDataUrl(target);
|
|
793
|
+
const assetId = registerAsset(snapshot, {
|
|
794
|
+
dataUrl: pngDataUrl,
|
|
795
|
+
id: createAssetId('drawio'),
|
|
796
|
+
kind: 'png',
|
|
797
|
+
mimeType: 'image/png',
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
placeholder.replaceWith(createDiagramFigureElement({
|
|
801
|
+
alt: placeholder.dataset.drawioLabel || 'draw.io diagram',
|
|
802
|
+
assetId,
|
|
803
|
+
className: 'export-diagram--drawio',
|
|
804
|
+
dataUrl: pngDataUrl,
|
|
805
|
+
docxDataUrl: pngDataUrl,
|
|
806
|
+
}));
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
async function resolveImageAssets(snapshot, container) {
|
|
810
|
+
const imageNodes = Array.from(container.querySelectorAll('img'));
|
|
811
|
+
for (const imageNode of imageNodes) {
|
|
812
|
+
const src = imageNode.getAttribute('src') || '';
|
|
813
|
+
if (!src || src.startsWith('data:')) {
|
|
814
|
+
continue;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
try {
|
|
818
|
+
const imageUrl = new URL(src, window.location.href);
|
|
819
|
+
const dataUrl = await fetchAsDataUrl(imageUrl.toString());
|
|
820
|
+
const assetId = registerAsset(snapshot, {
|
|
821
|
+
dataUrl,
|
|
822
|
+
id: createAssetId('image'),
|
|
823
|
+
kind: 'image',
|
|
824
|
+
mimeType: dataUrl.startsWith('data:image/svg+xml') ? 'image/svg+xml' : 'image/png',
|
|
825
|
+
});
|
|
826
|
+
imageNode.src = dataUrl;
|
|
827
|
+
imageNode.setAttribute('data-export-asset-id', assetId);
|
|
828
|
+
imageNode.setAttribute('data-export-docx-src', dataUrl);
|
|
829
|
+
} catch (error) {
|
|
830
|
+
const message = error instanceof Error ? error.message : `Failed to inline ${src}`;
|
|
831
|
+
snapshot.warnings.push(message);
|
|
832
|
+
imageNode.replaceWith(createImageFallbackElement({
|
|
833
|
+
alt: imageNode.getAttribute('alt') || '',
|
|
834
|
+
message: `Image export failed: ${message}. Source:`,
|
|
835
|
+
src,
|
|
836
|
+
}));
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
function rewriteWikiLinks(container) {
|
|
842
|
+
Array.from(container.querySelectorAll('.wiki-link[data-wiki-target]')).forEach((link) => {
|
|
843
|
+
const target = String(link.getAttribute('data-wiki-target') || '').trim();
|
|
844
|
+
if (!target) {
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
link.setAttribute('href', buildWikiLinkHref(target));
|
|
849
|
+
link.setAttribute('target', '_blank');
|
|
850
|
+
link.setAttribute('rel', 'noopener noreferrer');
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
function rewriteTaskCheckboxes(container) {
|
|
855
|
+
Array.from(container.querySelectorAll('.task-list-item input[type="checkbox"]')).forEach((checkbox) => {
|
|
856
|
+
checkbox.setAttribute('disabled', 'true');
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
export async function resolveExportAssets(snapshot, {
|
|
861
|
+
container,
|
|
862
|
+
} = {}) {
|
|
863
|
+
rewriteWikiLinks(container);
|
|
864
|
+
rewriteTaskCheckboxes(container);
|
|
865
|
+
|
|
866
|
+
const videoShells = Array.from(container.querySelectorAll('.video-embed-placeholder[data-video-embed-key]'));
|
|
867
|
+
for (const shell of videoShells) {
|
|
868
|
+
try {
|
|
869
|
+
await resolveVideoPoster(snapshot, shell);
|
|
870
|
+
} catch (error) {
|
|
871
|
+
snapshot.warnings.push(error instanceof Error ? error.message : 'Failed to render video poster');
|
|
872
|
+
shell.replaceWith(createVideoPosterElement(shell));
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
const mermaidShells = Array.from(container.querySelectorAll('.mermaid-shell[data-mermaid-key]'));
|
|
877
|
+
for (const shell of mermaidShells) {
|
|
878
|
+
try {
|
|
879
|
+
await resolveDiagramShell(snapshot, shell, {
|
|
880
|
+
label: shell.dataset.mermaidLabel || 'Mermaid diagram',
|
|
881
|
+
prefix: 'mermaid',
|
|
882
|
+
render: (source) => renderMermaidToSvgMarkup(source),
|
|
883
|
+
});
|
|
884
|
+
} catch (error) {
|
|
885
|
+
snapshot.warnings.push(error instanceof Error ? error.message : 'Failed to render Mermaid diagram');
|
|
886
|
+
shell.replaceWith(Object.assign(document.createElement('p'), {
|
|
887
|
+
className: 'export-warning',
|
|
888
|
+
textContent: `Mermaid export failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
889
|
+
}));
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
const plantUmlShells = Array.from(container.querySelectorAll('.plantuml-shell[data-plantuml-key]'));
|
|
894
|
+
for (const shell of plantUmlShells) {
|
|
895
|
+
try {
|
|
896
|
+
await resolveDiagramShell(snapshot, shell, {
|
|
897
|
+
label: shell.dataset.plantumlLabel || 'PlantUML diagram',
|
|
898
|
+
prefix: 'plantuml',
|
|
899
|
+
render: (source) => renderPlantUmlToSvgMarkup(source),
|
|
900
|
+
});
|
|
901
|
+
} catch (error) {
|
|
902
|
+
snapshot.warnings.push(error instanceof Error ? error.message : 'Failed to render PlantUML diagram');
|
|
903
|
+
shell.replaceWith(Object.assign(document.createElement('p'), {
|
|
904
|
+
className: 'export-warning',
|
|
905
|
+
textContent: `PlantUML export failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
906
|
+
}));
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
const excalidrawEmbeds = Array.from(container.querySelectorAll('.excalidraw-embed-placeholder[data-embed-key]'));
|
|
911
|
+
for (const placeholder of excalidrawEmbeds) {
|
|
912
|
+
try {
|
|
913
|
+
await resolveExcalidrawEmbed(snapshot, placeholder);
|
|
914
|
+
} catch (error) {
|
|
915
|
+
snapshot.warnings.push(error instanceof Error ? error.message : 'Failed to render Excalidraw diagram');
|
|
916
|
+
placeholder.replaceWith(Object.assign(document.createElement('p'), {
|
|
917
|
+
className: 'export-warning',
|
|
918
|
+
textContent: `Excalidraw export failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
919
|
+
}));
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
const drawioEmbeds = Array.from(container.querySelectorAll('.drawio-embed-placeholder[data-drawio-key]'));
|
|
924
|
+
for (const placeholder of drawioEmbeds) {
|
|
925
|
+
try {
|
|
926
|
+
await resolveDrawioEmbed(snapshot, placeholder);
|
|
927
|
+
} catch (error) {
|
|
928
|
+
snapshot.warnings.push(error instanceof Error ? error.message : 'Failed to render draw.io diagram');
|
|
929
|
+
placeholder.replaceWith(Object.assign(document.createElement('p'), {
|
|
930
|
+
className: 'export-warning',
|
|
931
|
+
textContent: `draw.io export failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
932
|
+
}));
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
await resolveImageAssets(snapshot, container);
|
|
937
|
+
return snapshot;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
export async function prepareExportSnapshot({
|
|
941
|
+
fileList = [],
|
|
942
|
+
filePath,
|
|
943
|
+
markdownText = '',
|
|
944
|
+
title = '',
|
|
945
|
+
} = {}) {
|
|
946
|
+
const normalizedFilePath = String(filePath ?? '').trim();
|
|
947
|
+
const normalizedMarkdown = String(markdownText ?? '');
|
|
948
|
+
const snapshot = {
|
|
949
|
+
assets: {},
|
|
950
|
+
filePath: normalizedFilePath,
|
|
951
|
+
generatedAt: new Date().toISOString(),
|
|
952
|
+
html: '',
|
|
953
|
+
sourceMarkdown: normalizedMarkdown,
|
|
954
|
+
title: createDocumentTitle(normalizedFilePath, title),
|
|
955
|
+
warnings: [],
|
|
956
|
+
};
|
|
957
|
+
|
|
958
|
+
const compiled = compilePreviewDocument({
|
|
959
|
+
attachmentApiPath: resolveApiUrl('/attachment'),
|
|
960
|
+
fileList,
|
|
961
|
+
markdownText: normalizedMarkdown,
|
|
962
|
+
sourceFilePath: normalizedFilePath,
|
|
963
|
+
});
|
|
964
|
+
const container = document.createElement('div');
|
|
965
|
+
container.className = 'preview-content export-content';
|
|
966
|
+
container.innerHTML = compiled.html;
|
|
967
|
+
|
|
968
|
+
await resolveExportAssets(snapshot, { container });
|
|
969
|
+
snapshot.html = container.innerHTML;
|
|
970
|
+
return snapshot;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
function applyDocxTableStyles(table, {
|
|
974
|
+
borderColor = '#d1d5db',
|
|
975
|
+
cellPadding = '8px 10px',
|
|
976
|
+
headerBackground = '#f3f4f6',
|
|
977
|
+
} = {}) {
|
|
978
|
+
table.setAttribute('border', '1');
|
|
979
|
+
table.setAttribute('cellpadding', '0');
|
|
980
|
+
table.setAttribute('cellspacing', '0');
|
|
981
|
+
table.style.width = '100%';
|
|
982
|
+
table.style.borderCollapse = 'collapse';
|
|
983
|
+
table.style.border = `1px solid ${borderColor}`;
|
|
984
|
+
table.style.margin = '0 0 16px';
|
|
985
|
+
|
|
986
|
+
Array.from(table.querySelectorAll('th')).forEach((cell) => {
|
|
987
|
+
cell.style.border = `1px solid ${borderColor}`;
|
|
988
|
+
cell.style.padding = cellPadding;
|
|
989
|
+
cell.style.background = headerBackground;
|
|
990
|
+
cell.style.textAlign = 'left';
|
|
991
|
+
cell.style.verticalAlign = 'top';
|
|
992
|
+
});
|
|
993
|
+
|
|
994
|
+
Array.from(table.querySelectorAll('td')).forEach((cell) => {
|
|
995
|
+
cell.style.border = `1px solid ${borderColor}`;
|
|
996
|
+
cell.style.padding = cellPadding;
|
|
997
|
+
cell.style.textAlign = 'left';
|
|
998
|
+
cell.style.verticalAlign = 'top';
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
function createDocxFramedTable({
|
|
1003
|
+
contentNodes = [],
|
|
1004
|
+
borderColor = '#d1d5db',
|
|
1005
|
+
padding = '12px',
|
|
1006
|
+
shade = '',
|
|
1007
|
+
} = {}) {
|
|
1008
|
+
const table = document.createElement('table');
|
|
1009
|
+
table.setAttribute('border', '1');
|
|
1010
|
+
table.setAttribute('cellpadding', '0');
|
|
1011
|
+
table.setAttribute('cellspacing', '0');
|
|
1012
|
+
table.style.width = '100%';
|
|
1013
|
+
table.style.borderCollapse = 'collapse';
|
|
1014
|
+
table.style.border = `1px solid ${borderColor}`;
|
|
1015
|
+
table.style.margin = '0 0 16px';
|
|
1016
|
+
|
|
1017
|
+
const row = document.createElement('tr');
|
|
1018
|
+
const cell = document.createElement('td');
|
|
1019
|
+
cell.style.border = `1px solid ${borderColor}`;
|
|
1020
|
+
cell.style.padding = padding;
|
|
1021
|
+
cell.style.verticalAlign = 'top';
|
|
1022
|
+
if (shade) {
|
|
1023
|
+
cell.style.background = shade;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
contentNodes.forEach((node) => {
|
|
1027
|
+
if (node) {
|
|
1028
|
+
cell.appendChild(node);
|
|
1029
|
+
}
|
|
1030
|
+
});
|
|
1031
|
+
|
|
1032
|
+
row.appendChild(cell);
|
|
1033
|
+
table.appendChild(row);
|
|
1034
|
+
return table;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
function createDocxBlockquoteTable(blockquote) {
|
|
1038
|
+
const table = document.createElement('table');
|
|
1039
|
+
table.setAttribute('role', 'presentation');
|
|
1040
|
+
table.setAttribute('cellpadding', '0');
|
|
1041
|
+
table.setAttribute('cellspacing', '0');
|
|
1042
|
+
table.style.width = '100%';
|
|
1043
|
+
table.style.borderCollapse = 'collapse';
|
|
1044
|
+
table.style.margin = '0 0 16px';
|
|
1045
|
+
table.style.tableLayout = 'fixed';
|
|
1046
|
+
|
|
1047
|
+
const colgroup = document.createElement('colgroup');
|
|
1048
|
+
const accentCol = document.createElement('col');
|
|
1049
|
+
accentCol.style.width = '6px';
|
|
1050
|
+
const contentCol = document.createElement('col');
|
|
1051
|
+
colgroup.append(accentCol, contentCol);
|
|
1052
|
+
table.appendChild(colgroup);
|
|
1053
|
+
|
|
1054
|
+
const row = document.createElement('tr');
|
|
1055
|
+
const accentCell = document.createElement('td');
|
|
1056
|
+
accentCell.style.background = '#6366f1';
|
|
1057
|
+
accentCell.style.width = '6px';
|
|
1058
|
+
accentCell.style.padding = '0';
|
|
1059
|
+
accentCell.style.fontSize = '0';
|
|
1060
|
+
accentCell.style.lineHeight = '0';
|
|
1061
|
+
accentCell.innerHTML = ' ';
|
|
1062
|
+
|
|
1063
|
+
const contentCell = document.createElement('td');
|
|
1064
|
+
contentCell.style.background = '#f8fafc';
|
|
1065
|
+
contentCell.style.padding = '12px 16px';
|
|
1066
|
+
contentCell.style.verticalAlign = 'top';
|
|
1067
|
+
contentCell.style.color = '#4b5563';
|
|
1068
|
+
|
|
1069
|
+
Array.from(blockquote.childNodes).forEach((child) => {
|
|
1070
|
+
contentCell.appendChild(child.cloneNode(true));
|
|
1071
|
+
});
|
|
1072
|
+
|
|
1073
|
+
const firstParagraph = contentCell.querySelector('p');
|
|
1074
|
+
if (firstParagraph) {
|
|
1075
|
+
firstParagraph.style.marginTop = '0';
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
Array.from(contentCell.querySelectorAll('p')).forEach((paragraph) => {
|
|
1079
|
+
paragraph.style.margin = '0 0 10px';
|
|
1080
|
+
});
|
|
1081
|
+
const lastParagraph = contentCell.querySelector('p:last-of-type');
|
|
1082
|
+
if (lastParagraph) {
|
|
1083
|
+
lastParagraph.style.marginBottom = '0';
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
row.append(accentCell, contentCell);
|
|
1087
|
+
table.appendChild(row);
|
|
1088
|
+
return table;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
function createDocxCodeBlockTable(pre) {
|
|
1092
|
+
const codeText = (pre.textContent || '').replace(/\r\n/g, '\n');
|
|
1093
|
+
const lines = codeText.split('\n');
|
|
1094
|
+
const contentNodes = [];
|
|
1095
|
+
|
|
1096
|
+
lines.forEach((line, index) => {
|
|
1097
|
+
const paragraph = document.createElement('p');
|
|
1098
|
+
paragraph.style.margin = '0';
|
|
1099
|
+
if (index < lines.length - 1) {
|
|
1100
|
+
paragraph.style.marginBottom = '2px';
|
|
1101
|
+
}
|
|
1102
|
+
paragraph.style.fontFamily = "'JetBrains Mono', 'Courier New', monospace";
|
|
1103
|
+
paragraph.style.fontSize = '12px';
|
|
1104
|
+
paragraph.style.lineHeight = '1.55';
|
|
1105
|
+
paragraph.style.color = '#111827';
|
|
1106
|
+
|
|
1107
|
+
const text = (line || '').replace(/\t/g, ' ');
|
|
1108
|
+
if (!text) {
|
|
1109
|
+
paragraph.innerHTML = ' ';
|
|
1110
|
+
} else {
|
|
1111
|
+
paragraph.textContent = text;
|
|
1112
|
+
paragraph.innerHTML = paragraph.innerHTML.replace(/ /g, ' ');
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
contentNodes.push(paragraph);
|
|
1116
|
+
});
|
|
1117
|
+
|
|
1118
|
+
return createDocxFramedTable({
|
|
1119
|
+
borderColor: '#d1d5db',
|
|
1120
|
+
contentNodes,
|
|
1121
|
+
padding: '12px 14px',
|
|
1122
|
+
shade: '#f8fafc',
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
export function buildDocxHtmlDocument(snapshot) {
|
|
1127
|
+
const template = document.createElement('template');
|
|
1128
|
+
template.innerHTML = snapshot.html;
|
|
1129
|
+
|
|
1130
|
+
Array.from(template.content.querySelectorAll('.table-wrapper')).forEach((wrapper) => {
|
|
1131
|
+
const table = wrapper.querySelector(':scope > table');
|
|
1132
|
+
if (!table) {
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
applyDocxTableStyles(table);
|
|
1137
|
+
wrapper.replaceWith(table);
|
|
1138
|
+
});
|
|
1139
|
+
|
|
1140
|
+
Array.from(template.content.querySelectorAll('table')).forEach((table) => {
|
|
1141
|
+
applyDocxTableStyles(table);
|
|
1142
|
+
});
|
|
1143
|
+
|
|
1144
|
+
Array.from(template.content.querySelectorAll('pre')).forEach((pre) => {
|
|
1145
|
+
pre.replaceWith(createDocxCodeBlockTable(pre));
|
|
1146
|
+
});
|
|
1147
|
+
|
|
1148
|
+
Array.from(template.content.querySelectorAll('figure.export-diagram[data-export-docx-src]')).forEach((figure) => {
|
|
1149
|
+
const docxSrc = figure.getAttribute('data-export-docx-src');
|
|
1150
|
+
const svgElement = figure.querySelector('svg');
|
|
1151
|
+
if (!docxSrc || !svgElement) {
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
const image = document.createElement('img');
|
|
1156
|
+
image.alt = figure.getAttribute('data-export-label') || 'Diagram';
|
|
1157
|
+
image.className = 'export-diagram-image';
|
|
1158
|
+
image.src = docxSrc;
|
|
1159
|
+
image.style.display = 'block';
|
|
1160
|
+
image.style.width = '100%';
|
|
1161
|
+
image.style.height = 'auto';
|
|
1162
|
+
figure.replaceWith(createDocxFramedTable({
|
|
1163
|
+
contentNodes: [image],
|
|
1164
|
+
padding: '12px',
|
|
1165
|
+
}));
|
|
1166
|
+
});
|
|
1167
|
+
|
|
1168
|
+
Array.from(template.content.querySelectorAll('figure.export-video-poster')).forEach((figure) => {
|
|
1169
|
+
const card = figure.querySelector('.export-video-poster-card');
|
|
1170
|
+
const posterImage = figure.querySelector('.export-video-poster-image');
|
|
1171
|
+
const link = figure.querySelector('.export-video-link');
|
|
1172
|
+
const title = figure.querySelector('.export-video-poster-copy strong');
|
|
1173
|
+
const meta = figure.querySelector('.export-video-poster-meta');
|
|
1174
|
+
const replacement = document.createElement('div');
|
|
1175
|
+
replacement.className = 'export-video-poster-docx';
|
|
1176
|
+
|
|
1177
|
+
if (posterImage instanceof HTMLImageElement) {
|
|
1178
|
+
const image = document.createElement('img');
|
|
1179
|
+
image.alt = posterImage.alt || title?.textContent || 'Embedded video poster';
|
|
1180
|
+
image.className = 'export-video-poster-image';
|
|
1181
|
+
image.src = posterImage.getAttribute('data-export-docx-src') || posterImage.getAttribute('src') || '';
|
|
1182
|
+
replacement.appendChild(image);
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
if (title?.textContent) {
|
|
1186
|
+
const titleParagraph = document.createElement('p');
|
|
1187
|
+
const strong = document.createElement('strong');
|
|
1188
|
+
strong.textContent = title.textContent;
|
|
1189
|
+
titleParagraph.appendChild(strong);
|
|
1190
|
+
replacement.appendChild(titleParagraph);
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
if (meta?.textContent) {
|
|
1194
|
+
const metaParagraph = document.createElement('p');
|
|
1195
|
+
metaParagraph.className = 'export-video-poster-meta';
|
|
1196
|
+
metaParagraph.textContent = meta.textContent;
|
|
1197
|
+
replacement.appendChild(metaParagraph);
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
if (link instanceof HTMLAnchorElement && link.href) {
|
|
1201
|
+
const linkParagraph = document.createElement('p');
|
|
1202
|
+
const anchor = document.createElement('a');
|
|
1203
|
+
anchor.href = link.href;
|
|
1204
|
+
anchor.textContent = link.textContent || link.href;
|
|
1205
|
+
linkParagraph.appendChild(anchor);
|
|
1206
|
+
replacement.appendChild(linkParagraph);
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
if (!replacement.childNodes.length && card?.textContent) {
|
|
1210
|
+
const fallbackParagraph = document.createElement('p');
|
|
1211
|
+
fallbackParagraph.textContent = card.textContent;
|
|
1212
|
+
replacement.appendChild(fallbackParagraph);
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
figure.replaceWith(createDocxFramedTable({
|
|
1216
|
+
contentNodes: [replacement],
|
|
1217
|
+
padding: '12px',
|
|
1218
|
+
}));
|
|
1219
|
+
});
|
|
1220
|
+
|
|
1221
|
+
Array.from(template.content.querySelectorAll('[data-export-docx-src]')).forEach((element) => {
|
|
1222
|
+
if (!(element instanceof HTMLImageElement)) {
|
|
1223
|
+
return;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
const docxSrc = element.getAttribute('data-export-docx-src');
|
|
1227
|
+
if (!docxSrc) {
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1230
|
+
element.setAttribute('src', docxSrc);
|
|
1231
|
+
});
|
|
1232
|
+
|
|
1233
|
+
Array.from(template.content.querySelectorAll('blockquote')).forEach((blockquote) => {
|
|
1234
|
+
blockquote.replaceWith(createDocxBlockquoteTable(blockquote));
|
|
1235
|
+
});
|
|
1236
|
+
|
|
1237
|
+
Array.from(template.content.querySelectorAll('figure')).forEach((figure) => {
|
|
1238
|
+
if (figure.closest('table')) {
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
const image = figure.querySelector('img');
|
|
1243
|
+
if (!(image instanceof HTMLImageElement)) {
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
const framedImage = image.cloneNode(true);
|
|
1248
|
+
framedImage.style.display = 'block';
|
|
1249
|
+
framedImage.style.width = '100%';
|
|
1250
|
+
framedImage.style.height = 'auto';
|
|
1251
|
+
figure.replaceWith(createDocxFramedTable({
|
|
1252
|
+
contentNodes: [framedImage],
|
|
1253
|
+
padding: '12px',
|
|
1254
|
+
}));
|
|
1255
|
+
});
|
|
1256
|
+
|
|
1257
|
+
return `<!DOCTYPE html>
|
|
1258
|
+
<html lang="en">
|
|
1259
|
+
<head>
|
|
1260
|
+
<meta charset="UTF-8">
|
|
1261
|
+
<title>${snapshot.title}</title>
|
|
1262
|
+
<style>
|
|
1263
|
+
body { font-family: Arial, sans-serif; color: #111827; line-height: 1.6; }
|
|
1264
|
+
main { max-width: 760px; margin: 0 auto; }
|
|
1265
|
+
h1, h2, h3, h4, h5, h6 { color: #111827; margin: 1.3em 0 0.6em; line-height: 1.2; }
|
|
1266
|
+
h1 { font-size: 28px; border-bottom: 1px solid #d1d5db; padding-bottom: 8px; }
|
|
1267
|
+
h2 { font-size: 22px; }
|
|
1268
|
+
h3 { font-size: 18px; }
|
|
1269
|
+
p, ul, ol, blockquote, pre, table, figure { margin: 0 0 16px; }
|
|
1270
|
+
a { color: #4338ca; text-decoration: underline; }
|
|
1271
|
+
pre { padding: 12px; border: 1px solid #d1d5db; background: #f8fafc; overflow: hidden; }
|
|
1272
|
+
code { font-family: 'JetBrains Mono', 'Courier New', monospace; background: #f3f4f6; padding: 2px 4px; }
|
|
1273
|
+
pre code { background: transparent; padding: 0; display: block; white-space: pre-wrap; }
|
|
1274
|
+
blockquote { padding-left: 14px; border-left: 3px solid #6366f1; color: #4b5563; }
|
|
1275
|
+
table { width: 100%; border-collapse: collapse; border: 1px solid #d1d5db; }
|
|
1276
|
+
th, td { border: 1px solid #d1d5db; padding: 8px 10px; text-align: left; vertical-align: top; }
|
|
1277
|
+
th { background: #f3f4f6; }
|
|
1278
|
+
img { max-width: 100%; height: auto; }
|
|
1279
|
+
.export-video-poster-docx { margin: 0 0 16px; }
|
|
1280
|
+
.export-video-poster-card { padding: 14px 16px; border: 1px solid #d1d5db; background: #f8fafc; }
|
|
1281
|
+
.export-video-poster-image { display: block; margin: 0 0 12px; }
|
|
1282
|
+
.export-video-poster-meta { display: block; color: #6b7280; font-size: 12px; margin-top: 4px; }
|
|
1283
|
+
.export-video-link { display: block; margin-top: 8px; word-break: break-word; }
|
|
1284
|
+
.export-warning { color: #b45309; }
|
|
1285
|
+
</style>
|
|
1286
|
+
</head>
|
|
1287
|
+
<body>
|
|
1288
|
+
<main>${template.innerHTML}</main>
|
|
1289
|
+
</body>
|
|
1290
|
+
</html>`;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
export async function docxAdapter(snapshot) {
|
|
1294
|
+
const response = await fetch(resolveApiUrl('/export/docx'), {
|
|
1295
|
+
body: JSON.stringify({
|
|
1296
|
+
filePath: snapshot.filePath,
|
|
1297
|
+
html: buildDocxHtmlDocument(snapshot),
|
|
1298
|
+
title: snapshot.title,
|
|
1299
|
+
}),
|
|
1300
|
+
headers: {
|
|
1301
|
+
'Content-Type': 'application/json',
|
|
1302
|
+
},
|
|
1303
|
+
method: 'POST',
|
|
1304
|
+
});
|
|
1305
|
+
|
|
1306
|
+
if (!response.ok) {
|
|
1307
|
+
const payload = await response.json().catch(() => null);
|
|
1308
|
+
throw new Error(payload?.error || 'Failed to export DOCX');
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
const blob = await response.blob();
|
|
1312
|
+
const downloadUrl = URL.createObjectURL(blob);
|
|
1313
|
+
const anchor = document.createElement('a');
|
|
1314
|
+
anchor.href = downloadUrl;
|
|
1315
|
+
anchor.download = `${createDocumentTitle(snapshot.filePath, snapshot.title)}.docx`;
|
|
1316
|
+
document.body.appendChild(anchor);
|
|
1317
|
+
anchor.click();
|
|
1318
|
+
anchor.remove();
|
|
1319
|
+
window.setTimeout(() => URL.revokeObjectURL(downloadUrl), 1000);
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
export async function printPdfAdapter() {
|
|
1323
|
+
await new Promise((resolve) => requestAnimationFrame(() => resolve()));
|
|
1324
|
+
await new Promise((resolve) => requestAnimationFrame(() => resolve()));
|
|
1325
|
+
|
|
1326
|
+
await new Promise((resolve) => {
|
|
1327
|
+
const timeoutId = window.setTimeout(resolve, 1500);
|
|
1328
|
+
const handleAfterPrint = () => {
|
|
1329
|
+
window.clearTimeout(timeoutId);
|
|
1330
|
+
window.removeEventListener('afterprint', handleAfterPrint);
|
|
1331
|
+
resolve();
|
|
1332
|
+
};
|
|
1333
|
+
window.addEventListener('afterprint', handleAfterPrint, { once: true });
|
|
1334
|
+
window.print();
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
export async function runExportAdapter(snapshot, format) {
|
|
1339
|
+
if (format === 'pdf') {
|
|
1340
|
+
await printPdfAdapter(snapshot);
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
await docxAdapter(snapshot);
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
export function postExportPageMessage(type, payload = {}) {
|
|
1348
|
+
if (!window.opener || window.opener.closed) {
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
window.opener.postMessage({
|
|
1353
|
+
...payload,
|
|
1354
|
+
source: EXPORT_PAGE_SOURCE,
|
|
1355
|
+
type,
|
|
1356
|
+
}, window.location.origin);
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
export async function waitForBootstrapPayload() {
|
|
1360
|
+
const requestUrl = new URL(window.location.href);
|
|
1361
|
+
const action = requestUrl.searchParams.get('action') === 'pdf' ? 'pdf' : 'docx';
|
|
1362
|
+
const filePath = requestUrl.searchParams.get('file') || '';
|
|
1363
|
+
const jobId = requestUrl.searchParams.get('job') || '';
|
|
1364
|
+
|
|
1365
|
+
if (jobId && window.opener && !window.opener.closed) {
|
|
1366
|
+
postExportPageMessage('ready', { jobId });
|
|
1367
|
+
|
|
1368
|
+
return new Promise((resolve, reject) => {
|
|
1369
|
+
const timeoutId = window.setTimeout(() => {
|
|
1370
|
+
cleanup();
|
|
1371
|
+
reject(new Error('Timed out waiting for export data'));
|
|
1372
|
+
}, 10000);
|
|
1373
|
+
|
|
1374
|
+
const cleanup = () => {
|
|
1375
|
+
window.clearTimeout(timeoutId);
|
|
1376
|
+
window.removeEventListener('message', handleMessage);
|
|
1377
|
+
};
|
|
1378
|
+
|
|
1379
|
+
const handleMessage = (event) => {
|
|
1380
|
+
if (event.origin !== window.location.origin) {
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
const payload = event.data;
|
|
1385
|
+
if (!payload || payload.source !== EXPORT_HOST_SOURCE || payload.type !== 'bootstrap' || payload.jobId !== jobId) {
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
cleanup();
|
|
1390
|
+
resolve({
|
|
1391
|
+
action,
|
|
1392
|
+
fileList: Array.isArray(payload.fileList) ? payload.fileList : [],
|
|
1393
|
+
filePath: payload.filePath || filePath,
|
|
1394
|
+
title: payload.title || '',
|
|
1395
|
+
markdownText: payload.markdownText || '',
|
|
1396
|
+
});
|
|
1397
|
+
};
|
|
1398
|
+
|
|
1399
|
+
window.addEventListener('message', handleMessage);
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
return {
|
|
1404
|
+
action,
|
|
1405
|
+
fileList: [],
|
|
1406
|
+
filePath,
|
|
1407
|
+
markdownText: filePath ? await fetchTextFile(filePath) : '',
|
|
1408
|
+
title: '',
|
|
1409
|
+
};
|
|
1410
|
+
}
|