+1
-1
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>登录系统</title>
|
||||
<title>DeepSeek转Word/AI公式转Word/Markdown转Word</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
+10
@@ -1492,6 +1492,16 @@
|
||||
"lodash-es": "^4.17.21"
|
||||
}
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/date-fns/-/date-fns-4.1.0.tgz",
|
||||
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.20",
|
||||
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.20.tgz",
|
||||
|
||||
+122
-116
@@ -1,163 +1,181 @@
|
||||
{
|
||||
"hash": "fa567820",
|
||||
"hash": "3d5c4e79",
|
||||
"configHash": "f11dda13",
|
||||
"lockfileHash": "56fcde5d",
|
||||
"browserHash": "1b1b85b7",
|
||||
"lockfileHash": "39ef18ae",
|
||||
"browserHash": "5be55438",
|
||||
"optimized": {
|
||||
"react": {
|
||||
"src": "../../react/index.js",
|
||||
"file": "react.js",
|
||||
"fileHash": "f9bc2b2c",
|
||||
"fileHash": "86655a07",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react-dom": {
|
||||
"src": "../../react-dom/index.js",
|
||||
"file": "react-dom.js",
|
||||
"fileHash": "cc78eba4",
|
||||
"fileHash": "22cece85",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react/jsx-dev-runtime": {
|
||||
"src": "../../react/jsx-dev-runtime.js",
|
||||
"file": "react_jsx-dev-runtime.js",
|
||||
"fileHash": "1ca6de6c",
|
||||
"fileHash": "27a51c15",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react/jsx-runtime": {
|
||||
"src": "../../react/jsx-runtime.js",
|
||||
"file": "react_jsx-runtime.js",
|
||||
"fileHash": "a8bb69b7",
|
||||
"fileHash": "136db0cc",
|
||||
"needsInterop": true
|
||||
},
|
||||
"date-fns": {
|
||||
"src": "../../date-fns/index.js",
|
||||
"file": "date-fns.js",
|
||||
"fileHash": "b6664223",
|
||||
"needsInterop": false
|
||||
},
|
||||
"file-saver": {
|
||||
"src": "../../file-saver/dist/FileSaver.min.js",
|
||||
"file": "file-saver.js",
|
||||
"fileHash": "913bcfe4",
|
||||
"fileHash": "04e7caea",
|
||||
"needsInterop": true
|
||||
},
|
||||
"katex": {
|
||||
"src": "../../katex/dist/katex.mjs",
|
||||
"file": "katex.js",
|
||||
"fileHash": "d6f6b368",
|
||||
"fileHash": "78494ab3",
|
||||
"needsInterop": false
|
||||
},
|
||||
"marked": {
|
||||
"src": "../../marked/lib/marked.esm.js",
|
||||
"file": "marked.js",
|
||||
"fileHash": "6e2efd02",
|
||||
"fileHash": "72f12a09",
|
||||
"needsInterop": false
|
||||
},
|
||||
"mermaid": {
|
||||
"src": "../../mermaid/dist/mermaid.core.mjs",
|
||||
"file": "mermaid.js",
|
||||
"fileHash": "86c5ba2a",
|
||||
"fileHash": "97b95f2b",
|
||||
"needsInterop": false
|
||||
},
|
||||
"react-dom/client": {
|
||||
"src": "../../react-dom/client.js",
|
||||
"file": "react-dom_client.js",
|
||||
"fileHash": "d287acb0",
|
||||
"fileHash": "36286df1",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react-router-dom": {
|
||||
"src": "../../react-router-dom/dist/index.js",
|
||||
"file": "react-router-dom.js",
|
||||
"fileHash": "c0f2a93b",
|
||||
"fileHash": "095024c9",
|
||||
"needsInterop": false
|
||||
}
|
||||
},
|
||||
"chunks": {
|
||||
"diagram-G4DWMVQ6-HUNNRCTF": {
|
||||
"file": "diagram-G4DWMVQ6-HUNNRCTF.js"
|
||||
"vennDiagram-DHZGUBPP-6W7QQVEL": {
|
||||
"file": "vennDiagram-DHZGUBPP-6W7QQVEL.js"
|
||||
},
|
||||
"wardleyDiagram-NUSXRM2D-CUADBIPO": {
|
||||
"file": "wardleyDiagram-NUSXRM2D-CUADBIPO.js"
|
||||
"diagram-G4DWMVQ6-GQLFITVI": {
|
||||
"file": "diagram-G4DWMVQ6-GQLFITVI.js"
|
||||
},
|
||||
"wardleyDiagram-NUSXRM2D-FB3VHWKT": {
|
||||
"file": "wardleyDiagram-NUSXRM2D-FB3VHWKT.js"
|
||||
},
|
||||
"kanban-definition-6JOO6SKY-C76UIEWS": {
|
||||
"file": "kanban-definition-6JOO6SKY-C76UIEWS.js"
|
||||
},
|
||||
"sankeyDiagram-XADWPNL6-TCPCRY26": {
|
||||
"file": "sankeyDiagram-XADWPNL6-TCPCRY26.js"
|
||||
},
|
||||
"diagram-TYMM5635-Q3N53YW4": {
|
||||
"file": "diagram-TYMM5635-Q3N53YW4.js"
|
||||
"diagram-TYMM5635-CFW6SUOY": {
|
||||
"file": "diagram-TYMM5635-CFW6SUOY.js"
|
||||
},
|
||||
"diagram-MMDJMWI5-NZUC24PO": {
|
||||
"file": "diagram-MMDJMWI5-NZUC24PO.js"
|
||||
"diagram-MMDJMWI5-H3XSHQUY": {
|
||||
"file": "diagram-MMDJMWI5-H3XSHQUY.js"
|
||||
},
|
||||
"blockDiagram-DXYQGD6D-FC6IY7CP": {
|
||||
"file": "blockDiagram-DXYQGD6D-FC6IY7CP.js"
|
||||
"blockDiagram-DXYQGD6D-7IODELZG": {
|
||||
"file": "blockDiagram-DXYQGD6D-7IODELZG.js"
|
||||
},
|
||||
"diagram-5BDNPKRD-CQ5OTDU7": {
|
||||
"file": "diagram-5BDNPKRD-CQ5OTDU7.js"
|
||||
"diagram-5BDNPKRD-IMF7AYPE": {
|
||||
"file": "diagram-5BDNPKRD-IMF7AYPE.js"
|
||||
},
|
||||
"architectureDiagram-Q4EWVU46-RWWCHLOA": {
|
||||
"file": "architectureDiagram-Q4EWVU46-RWWCHLOA.js"
|
||||
"architectureDiagram-Q4EWVU46-ORB3VMUH": {
|
||||
"file": "architectureDiagram-Q4EWVU46-ORB3VMUH.js"
|
||||
},
|
||||
"ishikawaDiagram-UXIWVN3A-XGPMMOSO": {
|
||||
"file": "ishikawaDiagram-UXIWVN3A-XGPMMOSO.js"
|
||||
"ishikawaDiagram-UXIWVN3A-OJDVWUGD": {
|
||||
"file": "ishikawaDiagram-UXIWVN3A-OJDVWUGD.js"
|
||||
},
|
||||
"vennDiagram-DHZGUBPP-OWCMMGRH": {
|
||||
"file": "vennDiagram-DHZGUBPP-OWCMMGRH.js"
|
||||
"sequenceDiagram-FGHM5R23-FE23XAP6": {
|
||||
"file": "sequenceDiagram-FGHM5R23-FE23XAP6.js"
|
||||
},
|
||||
"classDiagram-6PBFFD2Q-MPADOIGT": {
|
||||
"file": "classDiagram-6PBFFD2Q-MPADOIGT.js"
|
||||
"classDiagram-6PBFFD2Q-ZDYBHCGS": {
|
||||
"file": "classDiagram-6PBFFD2Q-ZDYBHCGS.js"
|
||||
},
|
||||
"classDiagram-v2-HSJHXN6E-ZI2B5S6D": {
|
||||
"file": "classDiagram-v2-HSJHXN6E-ZI2B5S6D.js"
|
||||
"classDiagram-v2-HSJHXN6E-X6473I6M": {
|
||||
"file": "classDiagram-v2-HSJHXN6E-X6473I6M.js"
|
||||
},
|
||||
"chunk-IJJLXIVN": {
|
||||
"file": "chunk-IJJLXIVN.js"
|
||||
"chunk-WNLCKUOK": {
|
||||
"file": "chunk-WNLCKUOK.js"
|
||||
},
|
||||
"stateDiagram-FHFEXIEX-DGJIBEPL": {
|
||||
"file": "stateDiagram-FHFEXIEX-DGJIBEPL.js"
|
||||
"stateDiagram-FHFEXIEX-7ATV6PPH": {
|
||||
"file": "stateDiagram-FHFEXIEX-7ATV6PPH.js"
|
||||
},
|
||||
"stateDiagram-v2-QKLJ7IA2-KWG254M5": {
|
||||
"file": "stateDiagram-v2-QKLJ7IA2-KWG254M5.js"
|
||||
"stateDiagram-v2-QKLJ7IA2-7INTSFRA": {
|
||||
"file": "stateDiagram-v2-QKLJ7IA2-7INTSFRA.js"
|
||||
},
|
||||
"chunk-74EEDPU4": {
|
||||
"file": "chunk-74EEDPU4.js"
|
||||
"chunk-KQJD2BDO": {
|
||||
"file": "chunk-KQJD2BDO.js"
|
||||
},
|
||||
"journeyDiagram-VCZTEJTY-XA33HUDQ": {
|
||||
"file": "journeyDiagram-VCZTEJTY-XA33HUDQ.js"
|
||||
},
|
||||
"timeline-definition-GMOUNBTQ-MPQYWR4P": {
|
||||
"file": "timeline-definition-GMOUNBTQ-MPQYWR4P.js"
|
||||
"timeline-definition-GMOUNBTQ-7EV5FJ2Q": {
|
||||
"file": "timeline-definition-GMOUNBTQ-7EV5FJ2Q.js"
|
||||
},
|
||||
"mindmap-definition-QFDTVHPH-34XYZ66K": {
|
||||
"file": "mindmap-definition-QFDTVHPH-34XYZ66K.js"
|
||||
"mindmap-definition-QFDTVHPH-LWJWKYOI": {
|
||||
"file": "mindmap-definition-QFDTVHPH-LWJWKYOI.js"
|
||||
},
|
||||
"kanban-definition-6JOO6SKY-HLVAUPHO": {
|
||||
"file": "kanban-definition-6JOO6SKY-HLVAUPHO.js"
|
||||
"wardley-RL74JXVD-Y6MKPAVO": {
|
||||
"file": "wardley-RL74JXVD-Y6MKPAVO.js"
|
||||
},
|
||||
"gitGraphDiagram-UUTBAWPF-N536INYS": {
|
||||
"file": "gitGraphDiagram-UUTBAWPF-N536INYS.js"
|
||||
"gitGraphDiagram-UUTBAWPF-VBDJJKXB": {
|
||||
"file": "gitGraphDiagram-UUTBAWPF-VBDJJKXB.js"
|
||||
},
|
||||
"ganttDiagram-T4ZO3ILL-SBGJESGM": {
|
||||
"file": "ganttDiagram-T4ZO3ILL-SBGJESGM.js"
|
||||
"chunk-VPVLR6E4": {
|
||||
"file": "chunk-VPVLR6E4.js"
|
||||
},
|
||||
"infoDiagram-42DDH7IO-WFU564PT": {
|
||||
"file": "infoDiagram-42DDH7IO-WFU564PT.js"
|
||||
"ganttDiagram-T4ZO3ILL-E7U5E2D3": {
|
||||
"file": "ganttDiagram-T4ZO3ILL-E7U5E2D3.js"
|
||||
},
|
||||
"pieDiagram-DEJITSTG-PI57EMVX": {
|
||||
"file": "pieDiagram-DEJITSTG-PI57EMVX.js"
|
||||
"infoDiagram-42DDH7IO-SPOK6NRM": {
|
||||
"file": "infoDiagram-42DDH7IO-SPOK6NRM.js"
|
||||
},
|
||||
"pieDiagram-DEJITSTG-B2LEWLGH": {
|
||||
"file": "pieDiagram-DEJITSTG-B2LEWLGH.js"
|
||||
},
|
||||
"chunk-BEGFPAJS": {
|
||||
"file": "chunk-BEGFPAJS.js"
|
||||
},
|
||||
"chunk-ZO353HVL": {
|
||||
"file": "chunk-ZO353HVL.js"
|
||||
"chunk-R5NQBCLB": {
|
||||
"file": "chunk-R5NQBCLB.js"
|
||||
},
|
||||
"chunk-JH6V2QOE": {
|
||||
"file": "chunk-JH6V2QOE.js"
|
||||
},
|
||||
"quadrantDiagram-34T5L4WZ-774SDUEW": {
|
||||
"file": "quadrantDiagram-34T5L4WZ-774SDUEW.js"
|
||||
},
|
||||
"xychartDiagram-5P7HB3ND-LBWHJ2M7": {
|
||||
"file": "xychartDiagram-5P7HB3ND-LBWHJ2M7.js"
|
||||
"xychartDiagram-5P7HB3ND-TWZ3LHIN": {
|
||||
"file": "xychartDiagram-5P7HB3ND-TWZ3LHIN.js"
|
||||
},
|
||||
"requirementDiagram-MS252O5E-26H5QBRG": {
|
||||
"file": "requirementDiagram-MS252O5E-26H5QBRG.js"
|
||||
"requirementDiagram-MS252O5E-45VOPIZB": {
|
||||
"file": "requirementDiagram-MS252O5E-45VOPIZB.js"
|
||||
},
|
||||
"sequenceDiagram-FGHM5R23-RF522XN2": {
|
||||
"file": "sequenceDiagram-FGHM5R23-RF522XN2.js"
|
||||
"info-OMHHGYJF-FWJRZDVY": {
|
||||
"file": "info-OMHHGYJF-FWJRZDVY.js"
|
||||
},
|
||||
"chunk-VPVLR6E4": {
|
||||
"file": "chunk-VPVLR6E4.js"
|
||||
"chunk-QLH66CIT": {
|
||||
"file": "chunk-QLH66CIT.js"
|
||||
},
|
||||
"packet-4T2RLAQJ-2LQDH5JO": {
|
||||
"file": "packet-4T2RLAQJ-2LQDH5JO.js"
|
||||
@@ -201,20 +219,20 @@
|
||||
"chunk-E3W5VJ2T": {
|
||||
"file": "chunk-E3W5VJ2T.js"
|
||||
},
|
||||
"wardley-RL74JXVD-Y6MKPAVO": {
|
||||
"file": "wardley-RL74JXVD-Y6MKPAVO.js"
|
||||
"chunk-S4AGLBPD": {
|
||||
"file": "chunk-S4AGLBPD.js"
|
||||
},
|
||||
"chunk-JH6V2QOE": {
|
||||
"file": "chunk-JH6V2QOE.js"
|
||||
"dagre-KV5264BT-2SB4YWJ2": {
|
||||
"file": "dagre-KV5264BT-2SB4YWJ2.js"
|
||||
},
|
||||
"dagre-KV5264BT-IXUN74XC": {
|
||||
"file": "dagre-KV5264BT-IXUN74XC.js"
|
||||
"chunk-6G6LCPI6": {
|
||||
"file": "chunk-6G6LCPI6.js"
|
||||
},
|
||||
"chunk-VXZL7VXQ": {
|
||||
"file": "chunk-VXZL7VXQ.js"
|
||||
"chunk-WBQMGXEP": {
|
||||
"file": "chunk-WBQMGXEP.js"
|
||||
},
|
||||
"chunk-T3HQBPEI": {
|
||||
"file": "chunk-T3HQBPEI.js"
|
||||
"chunk-K3ORWWMK": {
|
||||
"file": "chunk-K3ORWWMK.js"
|
||||
},
|
||||
"cose-bilkent-S5V4N54A-ZC3OT2QD": {
|
||||
"file": "cose-bilkent-S5V4N54A-ZC3OT2QD.js"
|
||||
@@ -222,11 +240,11 @@
|
||||
"chunk-OC2WCJ3A": {
|
||||
"file": "chunk-OC2WCJ3A.js"
|
||||
},
|
||||
"c4Diagram-AHTNJAMY-NWD472H5": {
|
||||
"file": "c4Diagram-AHTNJAMY-NWD472H5.js"
|
||||
"c4Diagram-AHTNJAMY-MDIB2U2D": {
|
||||
"file": "c4Diagram-AHTNJAMY-MDIB2U2D.js"
|
||||
},
|
||||
"flowDiagram-DWJPFMVM-FXQRIU6V": {
|
||||
"file": "flowDiagram-DWJPFMVM-FXQRIU6V.js"
|
||||
"flowDiagram-DWJPFMVM-5WOY4J6F": {
|
||||
"file": "flowDiagram-DWJPFMVM-5WOY4J6F.js"
|
||||
},
|
||||
"chunk-Q6MYXZJ3": {
|
||||
"file": "chunk-Q6MYXZJ3.js"
|
||||
@@ -234,8 +252,8 @@
|
||||
"chunk-DTWU5TRM": {
|
||||
"file": "chunk-DTWU5TRM.js"
|
||||
},
|
||||
"erDiagram-SMLLAGMA-6VRN6KCX": {
|
||||
"file": "erDiagram-SMLLAGMA-6VRN6KCX.js"
|
||||
"erDiagram-SMLLAGMA-KSPRYYBC": {
|
||||
"file": "erDiagram-SMLLAGMA-KSPRYYBC.js"
|
||||
},
|
||||
"chunk-NLS3CDEU": {
|
||||
"file": "chunk-NLS3CDEU.js"
|
||||
@@ -243,50 +261,41 @@
|
||||
"chunk-YVBSFUGN": {
|
||||
"file": "chunk-YVBSFUGN.js"
|
||||
},
|
||||
"info-OMHHGYJF-FWJRZDVY": {
|
||||
"file": "info-OMHHGYJF-FWJRZDVY.js"
|
||||
},
|
||||
"chunk-QLH66CIT": {
|
||||
"file": "chunk-QLH66CIT.js"
|
||||
},
|
||||
"chunk-S4AGLBPD": {
|
||||
"file": "chunk-S4AGLBPD.js"
|
||||
},
|
||||
"chunk-K3ORWWMK": {
|
||||
"file": "chunk-K3ORWWMK.js"
|
||||
},
|
||||
"chunk-QBIGODNM": {
|
||||
"file": "chunk-QBIGODNM.js"
|
||||
},
|
||||
"chunk-BQ2Z5GT2": {
|
||||
"file": "chunk-BQ2Z5GT2.js"
|
||||
},
|
||||
"chunk-RXFZAB4L": {
|
||||
"file": "chunk-RXFZAB4L.js"
|
||||
},
|
||||
"chunk-G5KDPKXZ": {
|
||||
"file": "chunk-G5KDPKXZ.js"
|
||||
"chunk-GSSDQWQG": {
|
||||
"file": "chunk-GSSDQWQG.js"
|
||||
},
|
||||
"chunk-QDQEHZH7": {
|
||||
"file": "chunk-QDQEHZH7.js"
|
||||
"chunk-LMNIJLJF": {
|
||||
"file": "chunk-LMNIJLJF.js"
|
||||
},
|
||||
"chunk-IHPTUWR5": {
|
||||
"file": "chunk-IHPTUWR5.js"
|
||||
},
|
||||
"chunk-DK5DI5R3": {
|
||||
"file": "chunk-DK5DI5R3.js"
|
||||
"chunk-POGYG5DQ": {
|
||||
"file": "chunk-POGYG5DQ.js"
|
||||
},
|
||||
"chunk-N2C52BYW": {
|
||||
"file": "chunk-N2C52BYW.js"
|
||||
},
|
||||
"chunk-MYK3ASHG": {
|
||||
"file": "chunk-MYK3ASHG.js"
|
||||
"chunk-IHPTUWR5": {
|
||||
"file": "chunk-IHPTUWR5.js"
|
||||
},
|
||||
"chunk-LN4HZV3Y": {
|
||||
"file": "chunk-LN4HZV3Y.js"
|
||||
},
|
||||
"chunk-TNWHCC6S": {
|
||||
"file": "chunk-TNWHCC6S.js"
|
||||
},
|
||||
"chunk-FFNMY5H5": {
|
||||
"file": "chunk-FFNMY5H5.js"
|
||||
"chunk-HX7G7X5J": {
|
||||
"file": "chunk-HX7G7X5J.js"
|
||||
},
|
||||
"chunk-3QKV3V7V": {
|
||||
"file": "chunk-3QKV3V7V.js"
|
||||
"chunk-GUBXVVWZ": {
|
||||
"file": "chunk-GUBXVVWZ.js"
|
||||
},
|
||||
"chunk-MOBZPS7F": {
|
||||
"file": "chunk-MOBZPS7F.js"
|
||||
@@ -294,15 +303,12 @@
|
||||
"chunk-6YWVU24R": {
|
||||
"file": "chunk-6YWVU24R.js"
|
||||
},
|
||||
"chunk-XOKMXDAB": {
|
||||
"file": "chunk-XOKMXDAB.js"
|
||||
},
|
||||
"chunk-BQ2Z5GT2": {
|
||||
"file": "chunk-BQ2Z5GT2.js"
|
||||
},
|
||||
"chunk-5ZDVNSGT": {
|
||||
"file": "chunk-5ZDVNSGT.js"
|
||||
},
|
||||
"chunk-XOKMXDAB": {
|
||||
"file": "chunk-XOKMXDAB.js"
|
||||
},
|
||||
"chunk-UKJ6E5ME": {
|
||||
"file": "chunk-UKJ6E5ME.js"
|
||||
},
|
||||
|
||||
-8889
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-3782
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-2593
File diff suppressed because one or more lines are too long
-7
File diff suppressed because one or more lines are too long
-1046
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-2049
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-5567
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-2736
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-101
@@ -1,101 +0,0 @@
|
||||
import {
|
||||
insertEdge,
|
||||
insertEdgeLabel,
|
||||
markers_default,
|
||||
positionEdgeLabel
|
||||
} from "./chunk-QDQEHZH7.js";
|
||||
import {
|
||||
insertCluster,
|
||||
insertNode,
|
||||
labelHelper
|
||||
} from "./chunk-DK5DI5R3.js";
|
||||
import {
|
||||
interpolateToCurve
|
||||
} from "./chunk-3QKV3V7V.js";
|
||||
import {
|
||||
common_default,
|
||||
getConfig
|
||||
} from "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name,
|
||||
log
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/chunk-336JU56O.mjs
|
||||
var internalHelpers = {
|
||||
common: common_default,
|
||||
getConfig,
|
||||
insertCluster,
|
||||
insertEdge,
|
||||
insertEdgeLabel,
|
||||
insertMarkers: markers_default,
|
||||
insertNode,
|
||||
interpolateToCurve,
|
||||
labelHelper,
|
||||
log,
|
||||
positionEdgeLabel
|
||||
};
|
||||
var layoutAlgorithms = {};
|
||||
var registerLayoutLoaders = __name((loaders) => {
|
||||
for (const loader of loaders) {
|
||||
layoutAlgorithms[loader.name] = loader;
|
||||
}
|
||||
}, "registerLayoutLoaders");
|
||||
var registerDefaultLayoutLoaders = __name(() => {
|
||||
registerLayoutLoaders([
|
||||
{
|
||||
name: "dagre",
|
||||
loader: __name(async () => await import("./dagre-KV5264BT-IXUN74XC.js"), "loader")
|
||||
},
|
||||
...true ? [
|
||||
{
|
||||
name: "cose-bilkent",
|
||||
loader: __name(async () => await import("./cose-bilkent-S5V4N54A-ZC3OT2QD.js"), "loader")
|
||||
}
|
||||
] : []
|
||||
]);
|
||||
}, "registerDefaultLayoutLoaders");
|
||||
registerDefaultLayoutLoaders();
|
||||
var render = __name(async (data4Layout, svg) => {
|
||||
if (!(data4Layout.layoutAlgorithm in layoutAlgorithms)) {
|
||||
throw new Error(`Unknown layout algorithm: ${data4Layout.layoutAlgorithm}`);
|
||||
}
|
||||
if (data4Layout.diagramId) {
|
||||
for (const node of data4Layout.nodes) {
|
||||
const originalDomId = node.domId || node.id;
|
||||
node.domId = `${data4Layout.diagramId}-${originalDomId}`;
|
||||
}
|
||||
}
|
||||
const layoutDefinition = layoutAlgorithms[data4Layout.layoutAlgorithm];
|
||||
const layoutRenderer = await layoutDefinition.loader();
|
||||
const { theme, themeVariables } = data4Layout.config;
|
||||
const { useGradient, gradientStart, gradientStop } = themeVariables;
|
||||
const svgId = svg.attr("id");
|
||||
svg.append("defs").append("filter").attr("id", `${svgId}-drop-shadow`).attr("height", "130%").attr("width", "130%").append("feDropShadow").attr("dx", "4").attr("dy", "4").attr("stdDeviation", 0).attr("flood-opacity", "0.06").attr("flood-color", `${(theme == null ? void 0 : theme.includes("dark")) ? "#FFFFFF" : "#000000"}`);
|
||||
svg.append("defs").append("filter").attr("id", `${svgId}-drop-shadow-small`).attr("height", "150%").attr("width", "150%").append("feDropShadow").attr("dx", "2").attr("dy", "2").attr("stdDeviation", 0).attr("flood-opacity", "0.06").attr("flood-color", `${(theme == null ? void 0 : theme.includes("dark")) ? "#FFFFFF" : "#000000"}`);
|
||||
if (useGradient) {
|
||||
const gradient = svg.append("linearGradient").attr("id", svg.attr("id") + "-gradient").attr("gradientUnits", "objectBoundingBox").attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%");
|
||||
gradient.append("svg:stop").attr("offset", "0%").attr("stop-color", gradientStart).attr("stop-opacity", 1);
|
||||
gradient.append("svg:stop").attr("offset", "100%").attr("stop-color", gradientStop).attr("stop-opacity", 1);
|
||||
}
|
||||
return layoutRenderer.render(data4Layout, svg, internalHelpers, {
|
||||
algorithm: layoutDefinition.algorithm
|
||||
});
|
||||
}, "render");
|
||||
var getRegisteredLayoutAlgorithm = __name((algorithm = "", { fallback = "dagre" } = {}) => {
|
||||
if (algorithm in layoutAlgorithms) {
|
||||
return algorithm;
|
||||
}
|
||||
if (fallback in layoutAlgorithms) {
|
||||
log.warn(`Layout algorithm ${algorithm} is not registered. Using ${fallback} as fallback.`);
|
||||
return fallback;
|
||||
}
|
||||
throw new Error(`Both layout algorithms ${algorithm} and ${fallback} are not registered.`);
|
||||
}, "getRegisteredLayoutAlgorithm");
|
||||
|
||||
export {
|
||||
registerLayoutLoaders,
|
||||
render,
|
||||
getRegisteredLayoutAlgorithm
|
||||
};
|
||||
//# sourceMappingURL=chunk-G5KDPKXZ.js.map
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../../mermaid/dist/chunks/mermaid.core/chunk-336JU56O.mjs"],
|
||||
"sourcesContent": ["import {\n insertEdge,\n insertEdgeLabel,\n markers_default,\n positionEdgeLabel\n} from \"./chunk-ENJZ2VHE.mjs\";\nimport {\n insertCluster,\n insertNode,\n labelHelper\n} from \"./chunk-5FUZZQ4R.mjs\";\nimport {\n interpolateToCurve\n} from \"./chunk-5PVQY5BW.mjs\";\nimport {\n common_default,\n getConfig\n} from \"./chunk-ICPOFSXX.mjs\";\nimport {\n __name,\n log\n} from \"./chunk-AGHRB4JF.mjs\";\n\n// src/internals.ts\nvar internalHelpers = {\n common: common_default,\n getConfig,\n insertCluster,\n insertEdge,\n insertEdgeLabel,\n insertMarkers: markers_default,\n insertNode,\n interpolateToCurve,\n labelHelper,\n log,\n positionEdgeLabel\n};\n\n// src/rendering-util/render.ts\nvar layoutAlgorithms = {};\nvar registerLayoutLoaders = /* @__PURE__ */ __name((loaders) => {\n for (const loader of loaders) {\n layoutAlgorithms[loader.name] = loader;\n }\n}, \"registerLayoutLoaders\");\nvar registerDefaultLayoutLoaders = /* @__PURE__ */ __name(() => {\n registerLayoutLoaders([\n {\n name: \"dagre\",\n loader: /* @__PURE__ */ __name(async () => await import(\"./dagre-KV5264BT.mjs\"), \"loader\")\n },\n ...true ? [\n {\n name: \"cose-bilkent\",\n loader: /* @__PURE__ */ __name(async () => await import(\"./cose-bilkent-S5V4N54A.mjs\"), \"loader\")\n }\n ] : []\n ]);\n}, \"registerDefaultLayoutLoaders\");\nregisterDefaultLayoutLoaders();\nvar render = /* @__PURE__ */ __name(async (data4Layout, svg) => {\n if (!(data4Layout.layoutAlgorithm in layoutAlgorithms)) {\n throw new Error(`Unknown layout algorithm: ${data4Layout.layoutAlgorithm}`);\n }\n if (data4Layout.diagramId) {\n for (const node of data4Layout.nodes) {\n const originalDomId = node.domId || node.id;\n node.domId = `${data4Layout.diagramId}-${originalDomId}`;\n }\n }\n const layoutDefinition = layoutAlgorithms[data4Layout.layoutAlgorithm];\n const layoutRenderer = await layoutDefinition.loader();\n const { theme, themeVariables } = data4Layout.config;\n const { useGradient, gradientStart, gradientStop } = themeVariables;\n const svgId = svg.attr(\"id\");\n svg.append(\"defs\").append(\"filter\").attr(\"id\", `${svgId}-drop-shadow`).attr(\"height\", \"130%\").attr(\"width\", \"130%\").append(\"feDropShadow\").attr(\"dx\", \"4\").attr(\"dy\", \"4\").attr(\"stdDeviation\", 0).attr(\"flood-opacity\", \"0.06\").attr(\"flood-color\", `${theme?.includes(\"dark\") ? \"#FFFFFF\" : \"#000000\"}`);\n svg.append(\"defs\").append(\"filter\").attr(\"id\", `${svgId}-drop-shadow-small`).attr(\"height\", \"150%\").attr(\"width\", \"150%\").append(\"feDropShadow\").attr(\"dx\", \"2\").attr(\"dy\", \"2\").attr(\"stdDeviation\", 0).attr(\"flood-opacity\", \"0.06\").attr(\"flood-color\", `${theme?.includes(\"dark\") ? \"#FFFFFF\" : \"#000000\"}`);\n if (useGradient) {\n const gradient = svg.append(\"linearGradient\").attr(\"id\", svg.attr(\"id\") + \"-gradient\").attr(\"gradientUnits\", \"objectBoundingBox\").attr(\"x1\", \"0%\").attr(\"y1\", \"0%\").attr(\"x2\", \"100%\").attr(\"y2\", \"0%\");\n gradient.append(\"svg:stop\").attr(\"offset\", \"0%\").attr(\"stop-color\", gradientStart).attr(\"stop-opacity\", 1);\n gradient.append(\"svg:stop\").attr(\"offset\", \"100%\").attr(\"stop-color\", gradientStop).attr(\"stop-opacity\", 1);\n }\n return layoutRenderer.render(data4Layout, svg, internalHelpers, {\n algorithm: layoutDefinition.algorithm\n });\n}, \"render\");\nvar getRegisteredLayoutAlgorithm = /* @__PURE__ */ __name((algorithm = \"\", { fallback = \"dagre\" } = {}) => {\n if (algorithm in layoutAlgorithms) {\n return algorithm;\n }\n if (fallback in layoutAlgorithms) {\n log.warn(`Layout algorithm ${algorithm} is not registered. Using ${fallback} as fallback.`);\n return fallback;\n }\n throw new Error(`Both layout algorithms ${algorithm} and ${fallback} are not registered.`);\n}, \"getRegisteredLayoutAlgorithm\");\n\nexport {\n registerLayoutLoaders,\n render,\n getRegisteredLayoutAlgorithm\n};\n"],
|
||||
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAwBA,IAAI,kBAAkB;AAAA,EACpB,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAI,mBAAmB,CAAC;AACxB,IAAI,wBAAwC,OAAO,CAAC,YAAY;AAC9D,aAAW,UAAU,SAAS;AAC5B,qBAAiB,OAAO,IAAI,IAAI;AAAA,EAClC;AACF,GAAG,uBAAuB;AAC1B,IAAI,+BAA+C,OAAO,MAAM;AAC9D,wBAAsB;AAAA,IACpB;AAAA,MACE,MAAM;AAAA,MACN,QAAwB,OAAO,YAAY,MAAM,OAAO,8BAAsB,GAAG,QAAQ;AAAA,IAC3F;AAAA,IACA,GAAG,OAAO;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN,QAAwB,OAAO,YAAY,MAAM,OAAO,qCAA6B,GAAG,QAAQ;AAAA,MAClG;AAAA,IACF,IAAI,CAAC;AAAA,EACP,CAAC;AACH,GAAG,8BAA8B;AACjC,6BAA6B;AAC7B,IAAI,SAAyB,OAAO,OAAO,aAAa,QAAQ;AAC9D,MAAI,EAAE,YAAY,mBAAmB,mBAAmB;AACtD,UAAM,IAAI,MAAM,6BAA6B,YAAY,eAAe,EAAE;AAAA,EAC5E;AACA,MAAI,YAAY,WAAW;AACzB,eAAW,QAAQ,YAAY,OAAO;AACpC,YAAM,gBAAgB,KAAK,SAAS,KAAK;AACzC,WAAK,QAAQ,GAAG,YAAY,SAAS,IAAI,aAAa;AAAA,IACxD;AAAA,EACF;AACA,QAAM,mBAAmB,iBAAiB,YAAY,eAAe;AACrE,QAAM,iBAAiB,MAAM,iBAAiB,OAAO;AACrD,QAAM,EAAE,OAAO,eAAe,IAAI,YAAY;AAC9C,QAAM,EAAE,aAAa,eAAe,aAAa,IAAI;AACrD,QAAM,QAAQ,IAAI,KAAK,IAAI;AAC3B,MAAI,OAAO,MAAM,EAAE,OAAO,QAAQ,EAAE,KAAK,MAAM,GAAG,KAAK,cAAc,EAAE,KAAK,UAAU,MAAM,EAAE,KAAK,SAAS,MAAM,EAAE,OAAO,cAAc,EAAE,KAAK,MAAM,GAAG,EAAE,KAAK,MAAM,GAAG,EAAE,KAAK,gBAAgB,CAAC,EAAE,KAAK,iBAAiB,MAAM,EAAE,KAAK,eAAe,IAAG,+BAAO,SAAS,WAAU,YAAY,SAAS,EAAE;AACzS,MAAI,OAAO,MAAM,EAAE,OAAO,QAAQ,EAAE,KAAK,MAAM,GAAG,KAAK,oBAAoB,EAAE,KAAK,UAAU,MAAM,EAAE,KAAK,SAAS,MAAM,EAAE,OAAO,cAAc,EAAE,KAAK,MAAM,GAAG,EAAE,KAAK,MAAM,GAAG,EAAE,KAAK,gBAAgB,CAAC,EAAE,KAAK,iBAAiB,MAAM,EAAE,KAAK,eAAe,IAAG,+BAAO,SAAS,WAAU,YAAY,SAAS,EAAE;AAC/S,MAAI,aAAa;AACf,UAAM,WAAW,IAAI,OAAO,gBAAgB,EAAE,KAAK,MAAM,IAAI,KAAK,IAAI,IAAI,WAAW,EAAE,KAAK,iBAAiB,mBAAmB,EAAE,KAAK,MAAM,IAAI,EAAE,KAAK,MAAM,IAAI,EAAE,KAAK,MAAM,MAAM,EAAE,KAAK,MAAM,IAAI;AACtM,aAAS,OAAO,UAAU,EAAE,KAAK,UAAU,IAAI,EAAE,KAAK,cAAc,aAAa,EAAE,KAAK,gBAAgB,CAAC;AACzG,aAAS,OAAO,UAAU,EAAE,KAAK,UAAU,MAAM,EAAE,KAAK,cAAc,YAAY,EAAE,KAAK,gBAAgB,CAAC;AAAA,EAC5G;AACA,SAAO,eAAe,OAAO,aAAa,KAAK,iBAAiB;AAAA,IAC9D,WAAW,iBAAiB;AAAA,EAC9B,CAAC;AACH,GAAG,QAAQ;AACX,IAAI,+BAA+C,OAAO,CAAC,YAAY,IAAI,EAAE,WAAW,QAAQ,IAAI,CAAC,MAAM;AACzG,MAAI,aAAa,kBAAkB;AACjC,WAAO;AAAA,EACT;AACA,MAAI,YAAY,kBAAkB;AAChC,QAAI,KAAK,oBAAoB,SAAS,6BAA6B,QAAQ,eAAe;AAC1F,WAAO;AAAA,EACT;AACA,QAAM,IAAI,MAAM,0BAA0B,SAAS,QAAQ,QAAQ,sBAAsB;AAC3F,GAAG,8BAA8B;",
|
||||
"names": []
|
||||
}
|
||||
-2041
File diff suppressed because one or more lines are too long
-7
File diff suppressed because one or more lines are too long
-68
@@ -1,68 +0,0 @@
|
||||
import {
|
||||
parseFontSize
|
||||
} from "./chunk-3QKV3V7V.js";
|
||||
import {
|
||||
defaultConfig_default,
|
||||
getConfig2
|
||||
} from "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/chunk-ZZ45TVLE.mjs
|
||||
var getSubGraphTitleMargins = __name(({
|
||||
flowchart
|
||||
}) => {
|
||||
var _a, _b;
|
||||
const subGraphTitleTopMargin = ((_a = flowchart == null ? void 0 : flowchart.subGraphTitleMargin) == null ? void 0 : _a.top) ?? 0;
|
||||
const subGraphTitleBottomMargin = ((_b = flowchart == null ? void 0 : flowchart.subGraphTitleMargin) == null ? void 0 : _b.bottom) ?? 0;
|
||||
const subGraphTitleTotalMargin = subGraphTitleTopMargin + subGraphTitleBottomMargin;
|
||||
return {
|
||||
subGraphTitleTopMargin,
|
||||
subGraphTitleBottomMargin,
|
||||
subGraphTitleTotalMargin
|
||||
};
|
||||
}, "getSubGraphTitleMargins");
|
||||
async function configureLabelImages(container, labelText) {
|
||||
const images = container.getElementsByTagName("img");
|
||||
if (!images || images.length === 0) {
|
||||
return;
|
||||
}
|
||||
const noImgText = labelText.replace(/<img[^>]*>/g, "").trim() === "";
|
||||
await Promise.all(
|
||||
[...images].map(
|
||||
(img) => new Promise((res) => {
|
||||
function setupImage() {
|
||||
img.style.display = "flex";
|
||||
img.style.flexDirection = "column";
|
||||
if (noImgText) {
|
||||
const bodyFontSize = getConfig2().fontSize ? getConfig2().fontSize : window.getComputedStyle(document.body).fontSize;
|
||||
const enlargingFactor = 5;
|
||||
const [parsedBodyFontSize = defaultConfig_default.fontSize] = parseFontSize(bodyFontSize);
|
||||
const width = parsedBodyFontSize * enlargingFactor + "px";
|
||||
img.style.minWidth = width;
|
||||
img.style.maxWidth = width;
|
||||
} else {
|
||||
img.style.width = "100%";
|
||||
}
|
||||
res(img);
|
||||
}
|
||||
__name(setupImage, "setupImage");
|
||||
setTimeout(() => {
|
||||
if (img.complete) {
|
||||
setupImage();
|
||||
}
|
||||
});
|
||||
img.addEventListener("error", setupImage);
|
||||
img.addEventListener("load", setupImage);
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
__name(configureLabelImages, "configureLabelImages");
|
||||
|
||||
export {
|
||||
getSubGraphTitleMargins,
|
||||
configureLabelImages
|
||||
};
|
||||
//# sourceMappingURL=chunk-MYK3ASHG.js.map
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../../mermaid/dist/chunks/mermaid.core/chunk-ZZ45TVLE.mjs"],
|
||||
"sourcesContent": ["import {\n parseFontSize\n} from \"./chunk-5PVQY5BW.mjs\";\nimport {\n defaultConfig_default,\n getConfig2 as getConfig\n} from \"./chunk-ICPOFSXX.mjs\";\nimport {\n __name\n} from \"./chunk-AGHRB4JF.mjs\";\n\n// src/utils/subGraphTitleMargins.ts\nvar getSubGraphTitleMargins = /* @__PURE__ */ __name(({\n flowchart\n}) => {\n const subGraphTitleTopMargin = flowchart?.subGraphTitleMargin?.top ?? 0;\n const subGraphTitleBottomMargin = flowchart?.subGraphTitleMargin?.bottom ?? 0;\n const subGraphTitleTotalMargin = subGraphTitleTopMargin + subGraphTitleBottomMargin;\n return {\n subGraphTitleTopMargin,\n subGraphTitleBottomMargin,\n subGraphTitleTotalMargin\n };\n}, \"getSubGraphTitleMargins\");\n\n// src/rendering-util/rendering-elements/shapes/labelImageUtils.ts\nasync function configureLabelImages(container, labelText) {\n const images = container.getElementsByTagName(\"img\");\n if (!images || images.length === 0) {\n return;\n }\n const noImgText = labelText.replace(/<img[^>]*>/g, \"\").trim() === \"\";\n await Promise.all(\n [...images].map(\n (img) => new Promise((res) => {\n function setupImage() {\n img.style.display = \"flex\";\n img.style.flexDirection = \"column\";\n if (noImgText) {\n const bodyFontSize = getConfig().fontSize ? getConfig().fontSize : window.getComputedStyle(document.body).fontSize;\n const enlargingFactor = 5;\n const [parsedBodyFontSize = defaultConfig_default.fontSize] = parseFontSize(bodyFontSize);\n const width = parsedBodyFontSize * enlargingFactor + \"px\";\n img.style.minWidth = width;\n img.style.maxWidth = width;\n } else {\n img.style.width = \"100%\";\n }\n res(img);\n }\n __name(setupImage, \"setupImage\");\n setTimeout(() => {\n if (img.complete) {\n setupImage();\n }\n });\n img.addEventListener(\"error\", setupImage);\n img.addEventListener(\"load\", setupImage);\n })\n )\n );\n}\n__name(configureLabelImages, \"configureLabelImages\");\n\nexport {\n configureLabelImages,\n getSubGraphTitleMargins\n};\n"],
|
||||
"mappings": ";;;;;;;;;;;;AAYA,IAAI,0BAA0C,OAAO,CAAC;AAAA,EACpD;AACF,MAAM;AAdN;AAeE,QAAM,2BAAyB,4CAAW,wBAAX,mBAAgC,QAAO;AACtE,QAAM,8BAA4B,4CAAW,wBAAX,mBAAgC,WAAU;AAC5E,QAAM,2BAA2B,yBAAyB;AAC1D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF,GAAG,yBAAyB;AAG5B,eAAe,qBAAqB,WAAW,WAAW;AACxD,QAAM,SAAS,UAAU,qBAAqB,KAAK;AACnD,MAAI,CAAC,UAAU,OAAO,WAAW,GAAG;AAClC;AAAA,EACF;AACA,QAAM,YAAY,UAAU,QAAQ,eAAe,EAAE,EAAE,KAAK,MAAM;AAClE,QAAM,QAAQ;AAAA,IACZ,CAAC,GAAG,MAAM,EAAE;AAAA,MACV,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ;AAC5B,iBAAS,aAAa;AACpB,cAAI,MAAM,UAAU;AACpB,cAAI,MAAM,gBAAgB;AAC1B,cAAI,WAAW;AACb,kBAAM,eAAe,WAAU,EAAE,WAAW,WAAU,EAAE,WAAW,OAAO,iBAAiB,SAAS,IAAI,EAAE;AAC1G,kBAAM,kBAAkB;AACxB,kBAAM,CAAC,qBAAqB,sBAAsB,QAAQ,IAAI,cAAc,YAAY;AACxF,kBAAM,QAAQ,qBAAqB,kBAAkB;AACrD,gBAAI,MAAM,WAAW;AACrB,gBAAI,MAAM,WAAW;AAAA,UACvB,OAAO;AACL,gBAAI,MAAM,QAAQ;AAAA,UACpB;AACA,cAAI,GAAG;AAAA,QACT;AACA,eAAO,YAAY,YAAY;AAC/B,mBAAW,MAAM;AACf,cAAI,IAAI,UAAU;AAChB,uBAAW;AAAA,UACb;AAAA,QACF,CAAC;AACD,YAAI,iBAAiB,SAAS,UAAU;AACxC,YAAI,iBAAiB,QAAQ,UAAU;AAAA,MACzC,CAAC;AAAA,IACH;AAAA,EACF;AACF;AACA,OAAO,sBAAsB,sBAAsB;",
|
||||
"names": []
|
||||
}
|
||||
-1053
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-6974
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-2048
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-91
@@ -1,91 +0,0 @@
|
||||
import {
|
||||
__name
|
||||
} from "./chunk-S4AGLBPD.js";
|
||||
|
||||
// node_modules/@mermaid-js/parser/dist/mermaid-parser.core.mjs
|
||||
var parsers = {};
|
||||
var initializers = {
|
||||
info: __name(async () => {
|
||||
const { createInfoServices: createInfoServices2 } = await import("./info-OMHHGYJF-FWJRZDVY.js");
|
||||
const parser = createInfoServices2().Info.parser.LangiumParser;
|
||||
parsers.info = parser;
|
||||
}, "info"),
|
||||
packet: __name(async () => {
|
||||
const { createPacketServices: createPacketServices2 } = await import("./packet-4T2RLAQJ-2LQDH5JO.js");
|
||||
const parser = createPacketServices2().Packet.parser.LangiumParser;
|
||||
parsers.packet = parser;
|
||||
}, "packet"),
|
||||
pie: __name(async () => {
|
||||
const { createPieServices: createPieServices2 } = await import("./pie-ZZUOXDRM-KQGNYE5Y.js");
|
||||
const parser = createPieServices2().Pie.parser.LangiumParser;
|
||||
parsers.pie = parser;
|
||||
}, "pie"),
|
||||
treeView: __name(async () => {
|
||||
const { createTreeViewServices: createTreeViewServices2 } = await import("./treeView-SZITEDCU-TBMOS4J3.js");
|
||||
const parser = createTreeViewServices2().TreeView.parser.LangiumParser;
|
||||
parsers.treeView = parser;
|
||||
}, "treeView"),
|
||||
architecture: __name(async () => {
|
||||
const { createArchitectureServices: createArchitectureServices2 } = await import("./architecture-YZFGNWBL-NAU23UHH.js");
|
||||
const parser = createArchitectureServices2().Architecture.parser.LangiumParser;
|
||||
parsers.architecture = parser;
|
||||
}, "architecture"),
|
||||
gitGraph: __name(async () => {
|
||||
const { createGitGraphServices: createGitGraphServices2 } = await import("./gitGraph-7Q5UKJZL-ODOWYJI5.js");
|
||||
const parser = createGitGraphServices2().GitGraph.parser.LangiumParser;
|
||||
parsers.gitGraph = parser;
|
||||
}, "gitGraph"),
|
||||
radar: __name(async () => {
|
||||
const { createRadarServices: createRadarServices2 } = await import("./radar-PYXPWWZC-PFNTPJ6C.js");
|
||||
const parser = createRadarServices2().Radar.parser.LangiumParser;
|
||||
parsers.radar = parser;
|
||||
}, "radar"),
|
||||
treemap: __name(async () => {
|
||||
const { createTreemapServices: createTreemapServices2 } = await import("./treemap-W4RFUUIX-JB5N3RDV.js");
|
||||
const parser = createTreemapServices2().Treemap.parser.LangiumParser;
|
||||
parsers.treemap = parser;
|
||||
}, "treemap"),
|
||||
wardley: __name(async () => {
|
||||
const { createWardleyServices: createWardleyServices2 } = await import("./wardley-RL74JXVD-Y6MKPAVO.js");
|
||||
const parser = createWardleyServices2().Wardley.parser.LangiumParser;
|
||||
parsers.wardley = parser;
|
||||
}, "wardley")
|
||||
};
|
||||
async function parse(diagramType, text) {
|
||||
const initializer = initializers[diagramType];
|
||||
if (!initializer) {
|
||||
throw new Error(`Unknown diagram type: ${diagramType}`);
|
||||
}
|
||||
if (!parsers[diagramType]) {
|
||||
await initializer();
|
||||
}
|
||||
const parser = parsers[diagramType];
|
||||
const result = parser.parse(text);
|
||||
if (result.lexerErrors.length > 0 || result.parserErrors.length > 0) {
|
||||
throw new MermaidParseError(result);
|
||||
}
|
||||
return result.value;
|
||||
}
|
||||
__name(parse, "parse");
|
||||
var _a;
|
||||
var MermaidParseError = (_a = class extends Error {
|
||||
constructor(result) {
|
||||
const lexerErrors = result.lexerErrors.map((err) => {
|
||||
const line = err.line !== void 0 && !isNaN(err.line) ? err.line : "?";
|
||||
const column = err.column !== void 0 && !isNaN(err.column) ? err.column : "?";
|
||||
return `Lexer error on line ${line}, column ${column}: ${err.message}`;
|
||||
}).join("\n");
|
||||
const parserErrors = result.parserErrors.map((err) => {
|
||||
const line = err.token.startLine !== void 0 && !isNaN(err.token.startLine) ? err.token.startLine : "?";
|
||||
const column = err.token.startColumn !== void 0 && !isNaN(err.token.startColumn) ? err.token.startColumn : "?";
|
||||
return `Parse error on line ${line}, column ${column}: ${err.message}`;
|
||||
}).join("\n");
|
||||
super(`Parsing failed: ${lexerErrors} ${parserErrors}`);
|
||||
this.result = result;
|
||||
}
|
||||
}, __name(_a, "MermaidParseError"), _a);
|
||||
|
||||
export {
|
||||
parse
|
||||
};
|
||||
//# sourceMappingURL=chunk-ZO353HVL.js.map
|
||||
-7
File diff suppressed because one or more lines are too long
-46
@@ -1,46 +0,0 @@
|
||||
import {
|
||||
ClassDB,
|
||||
classDiagram_default,
|
||||
classRenderer_v3_unified_default,
|
||||
styles_default
|
||||
} from "./chunk-IJJLXIVN.js";
|
||||
import "./chunk-Q6MYXZJ3.js";
|
||||
import "./chunk-DTWU5TRM.js";
|
||||
import "./chunk-NLS3CDEU.js";
|
||||
import "./chunk-YVBSFUGN.js";
|
||||
import "./chunk-G5KDPKXZ.js";
|
||||
import "./chunk-QDQEHZH7.js";
|
||||
import "./chunk-IHPTUWR5.js";
|
||||
import "./chunk-DK5DI5R3.js";
|
||||
import "./chunk-N2C52BYW.js";
|
||||
import "./chunk-MYK3ASHG.js";
|
||||
import "./chunk-TNWHCC6S.js";
|
||||
import "./chunk-FFNMY5H5.js";
|
||||
import "./chunk-3QKV3V7V.js";
|
||||
import "./chunk-MOBZPS7F.js";
|
||||
import "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/classDiagram-6PBFFD2Q.mjs
|
||||
var diagram = {
|
||||
parser: classDiagram_default,
|
||||
get db() {
|
||||
return new ClassDB();
|
||||
},
|
||||
renderer: classRenderer_v3_unified_default,
|
||||
styles: styles_default,
|
||||
init: __name((cnf) => {
|
||||
if (!cnf.class) {
|
||||
cnf.class = {};
|
||||
}
|
||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
}, "init")
|
||||
};
|
||||
export {
|
||||
diagram
|
||||
};
|
||||
//# sourceMappingURL=classDiagram-6PBFFD2Q-MPADOIGT.js.map
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../../mermaid/dist/chunks/mermaid.core/classDiagram-6PBFFD2Q.mjs"],
|
||||
"sourcesContent": ["import {\n ClassDB,\n classDiagram_default,\n classRenderer_v3_unified_default,\n styles_default\n} from \"./chunk-4TB4RGXK.mjs\";\nimport \"./chunk-FMBD7UC4.mjs\";\nimport \"./chunk-YZCP3GAM.mjs\";\nimport \"./chunk-55IACEB6.mjs\";\nimport \"./chunk-EDXVE4YY.mjs\";\nimport \"./chunk-336JU56O.mjs\";\nimport \"./chunk-ENJZ2VHE.mjs\";\nimport \"./chunk-BSJP7CBP.mjs\";\nimport \"./chunk-5FUZZQ4R.mjs\";\nimport \"./chunk-ZZ45TVLE.mjs\";\nimport \"./chunk-X2U36JSP.mjs\";\nimport \"./chunk-U2HBQHQK.mjs\";\nimport \"./chunk-5PVQY5BW.mjs\";\nimport \"./chunk-ICPOFSXX.mjs\";\nimport {\n __name\n} from \"./chunk-AGHRB4JF.mjs\";\n\n// src/diagrams/class/classDiagram.ts\nvar diagram = {\n parser: classDiagram_default,\n get db() {\n return new ClassDB();\n },\n renderer: classRenderer_v3_unified_default,\n styles: styles_default,\n init: /* @__PURE__ */ __name((cnf) => {\n if (!cnf.class) {\n cnf.class = {};\n }\n cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;\n }, \"init\")\n};\nexport {\n diagram\n};\n"],
|
||||
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,IAAI,UAAU;AAAA,EACZ,QAAQ;AAAA,EACR,IAAI,KAAK;AACP,WAAO,IAAI,QAAQ;AAAA,EACrB;AAAA,EACA,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,MAAsB,OAAO,CAAC,QAAQ;AACpC,QAAI,CAAC,IAAI,OAAO;AACd,UAAI,QAAQ,CAAC;AAAA,IACf;AACA,QAAI,MAAM,sBAAsB,IAAI;AAAA,EACtC,GAAG,MAAM;AACX;",
|
||||
"names": []
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
import {
|
||||
ClassDB,
|
||||
classDiagram_default,
|
||||
classRenderer_v3_unified_default,
|
||||
styles_default
|
||||
} from "./chunk-IJJLXIVN.js";
|
||||
import "./chunk-Q6MYXZJ3.js";
|
||||
import "./chunk-DTWU5TRM.js";
|
||||
import "./chunk-NLS3CDEU.js";
|
||||
import "./chunk-YVBSFUGN.js";
|
||||
import "./chunk-G5KDPKXZ.js";
|
||||
import "./chunk-QDQEHZH7.js";
|
||||
import "./chunk-IHPTUWR5.js";
|
||||
import "./chunk-DK5DI5R3.js";
|
||||
import "./chunk-N2C52BYW.js";
|
||||
import "./chunk-MYK3ASHG.js";
|
||||
import "./chunk-TNWHCC6S.js";
|
||||
import "./chunk-FFNMY5H5.js";
|
||||
import "./chunk-3QKV3V7V.js";
|
||||
import "./chunk-MOBZPS7F.js";
|
||||
import "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/classDiagram-v2-HSJHXN6E.mjs
|
||||
var diagram = {
|
||||
parser: classDiagram_default,
|
||||
get db() {
|
||||
return new ClassDB();
|
||||
},
|
||||
renderer: classRenderer_v3_unified_default,
|
||||
styles: styles_default,
|
||||
init: __name((cnf) => {
|
||||
if (!cnf.class) {
|
||||
cnf.class = {};
|
||||
}
|
||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
}, "init")
|
||||
};
|
||||
export {
|
||||
diagram
|
||||
};
|
||||
//# sourceMappingURL=classDiagram-v2-HSJHXN6E-ZI2B5S6D.js.map
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../../mermaid/dist/chunks/mermaid.core/classDiagram-v2-HSJHXN6E.mjs"],
|
||||
"sourcesContent": ["import {\n ClassDB,\n classDiagram_default,\n classRenderer_v3_unified_default,\n styles_default\n} from \"./chunk-4TB4RGXK.mjs\";\nimport \"./chunk-FMBD7UC4.mjs\";\nimport \"./chunk-YZCP3GAM.mjs\";\nimport \"./chunk-55IACEB6.mjs\";\nimport \"./chunk-EDXVE4YY.mjs\";\nimport \"./chunk-336JU56O.mjs\";\nimport \"./chunk-ENJZ2VHE.mjs\";\nimport \"./chunk-BSJP7CBP.mjs\";\nimport \"./chunk-5FUZZQ4R.mjs\";\nimport \"./chunk-ZZ45TVLE.mjs\";\nimport \"./chunk-X2U36JSP.mjs\";\nimport \"./chunk-U2HBQHQK.mjs\";\nimport \"./chunk-5PVQY5BW.mjs\";\nimport \"./chunk-ICPOFSXX.mjs\";\nimport {\n __name\n} from \"./chunk-AGHRB4JF.mjs\";\n\n// src/diagrams/class/classDiagram-v2.ts\nvar diagram = {\n parser: classDiagram_default,\n get db() {\n return new ClassDB();\n },\n renderer: classRenderer_v3_unified_default,\n styles: styles_default,\n init: /* @__PURE__ */ __name((cnf) => {\n if (!cnf.class) {\n cnf.class = {};\n }\n cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;\n }, \"init\")\n};\nexport {\n diagram\n};\n"],
|
||||
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,IAAI,UAAU;AAAA,EACZ,QAAQ;AAAA,EACR,IAAI,KAAK;AACP,WAAO,IAAI,QAAQ;AAAA,EACrB;AAAA,EACA,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,MAAsB,OAAO,CAAC,QAAQ;AACpC,QAAI,CAAC,IAAI,OAAO;AACd,UAAI,QAAQ,CAAC;AAAA,IACf;AACA,QAAI,MAAM,sBAAsB,IAAI;AAAA,EACtC,GAAG,MAAM;AACX;",
|
||||
"names": []
|
||||
}
|
||||
-742
@@ -1,742 +0,0 @@
|
||||
import {
|
||||
layout
|
||||
} from "./chunk-VXZL7VXQ.js";
|
||||
import {
|
||||
Graph,
|
||||
clone_default,
|
||||
isUndefined_default
|
||||
} from "./chunk-T3HQBPEI.js";
|
||||
import {
|
||||
map_default
|
||||
} from "./chunk-K3ORWWMK.js";
|
||||
import {
|
||||
clear as clear3,
|
||||
insertEdge,
|
||||
insertEdgeLabel,
|
||||
markers_default,
|
||||
positionEdgeLabel
|
||||
} from "./chunk-QDQEHZH7.js";
|
||||
import "./chunk-IHPTUWR5.js";
|
||||
import {
|
||||
clear,
|
||||
clear2,
|
||||
insertCluster,
|
||||
insertNode,
|
||||
positionNode,
|
||||
setNodeElem,
|
||||
updateNodeBounds
|
||||
} from "./chunk-DK5DI5R3.js";
|
||||
import "./chunk-N2C52BYW.js";
|
||||
import {
|
||||
getSubGraphTitleMargins
|
||||
} from "./chunk-MYK3ASHG.js";
|
||||
import "./chunk-TNWHCC6S.js";
|
||||
import "./chunk-FFNMY5H5.js";
|
||||
import "./chunk-3QKV3V7V.js";
|
||||
import "./chunk-MOBZPS7F.js";
|
||||
import {
|
||||
getConfig2
|
||||
} from "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name,
|
||||
log
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import "./chunk-BQ2Z5GT2.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/dagre-d3-es/src/graphlib/json.js
|
||||
function write(g) {
|
||||
var json = {
|
||||
options: {
|
||||
directed: g.isDirected(),
|
||||
multigraph: g.isMultigraph(),
|
||||
compound: g.isCompound()
|
||||
},
|
||||
nodes: writeNodes(g),
|
||||
edges: writeEdges(g)
|
||||
};
|
||||
if (!isUndefined_default(g.graph())) {
|
||||
json.value = clone_default(g.graph());
|
||||
}
|
||||
return json;
|
||||
}
|
||||
function writeNodes(g) {
|
||||
return map_default(g.nodes(), function(v) {
|
||||
var nodeValue = g.node(v);
|
||||
var parent = g.parent(v);
|
||||
var node = { v };
|
||||
if (!isUndefined_default(nodeValue)) {
|
||||
node.value = nodeValue;
|
||||
}
|
||||
if (!isUndefined_default(parent)) {
|
||||
node.parent = parent;
|
||||
}
|
||||
return node;
|
||||
});
|
||||
}
|
||||
function writeEdges(g) {
|
||||
return map_default(g.edges(), function(e) {
|
||||
var edgeValue = g.edge(e);
|
||||
var edge = { v: e.v, w: e.w };
|
||||
if (!isUndefined_default(e.name)) {
|
||||
edge.name = e.name;
|
||||
}
|
||||
if (!isUndefined_default(edgeValue)) {
|
||||
edge.value = edgeValue;
|
||||
}
|
||||
return edge;
|
||||
});
|
||||
}
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/dagre-KV5264BT.mjs
|
||||
var clusterDb = /* @__PURE__ */ new Map();
|
||||
var descendants = /* @__PURE__ */ new Map();
|
||||
var parents = /* @__PURE__ */ new Map();
|
||||
var clear4 = __name(() => {
|
||||
descendants.clear();
|
||||
parents.clear();
|
||||
clusterDb.clear();
|
||||
}, "clear");
|
||||
var isDescendant = __name((id, ancestorId) => {
|
||||
const ancestorDescendants = descendants.get(ancestorId) || [];
|
||||
log.trace("In isDescendant", ancestorId, " ", id, " = ", ancestorDescendants.includes(id));
|
||||
return ancestorDescendants.includes(id);
|
||||
}, "isDescendant");
|
||||
var edgeInCluster = __name((edge, clusterId) => {
|
||||
const clusterDescendants = descendants.get(clusterId) || [];
|
||||
log.info("Descendants of ", clusterId, " is ", clusterDescendants);
|
||||
log.info("Edge is ", edge);
|
||||
if (edge.v === clusterId || edge.w === clusterId) {
|
||||
return false;
|
||||
}
|
||||
if (!clusterDescendants) {
|
||||
log.debug("Tilt, ", clusterId, ",not in descendants");
|
||||
return false;
|
||||
}
|
||||
return clusterDescendants.includes(edge.v) || isDescendant(edge.v, clusterId) || isDescendant(edge.w, clusterId) || clusterDescendants.includes(edge.w);
|
||||
}, "edgeInCluster");
|
||||
var copy = __name((clusterId, graph, newGraph, rootId) => {
|
||||
log.warn(
|
||||
"Copying children of ",
|
||||
clusterId,
|
||||
"root",
|
||||
rootId,
|
||||
"data",
|
||||
graph.node(clusterId),
|
||||
rootId
|
||||
);
|
||||
const nodes = graph.children(clusterId) || [];
|
||||
if (clusterId !== rootId) {
|
||||
nodes.push(clusterId);
|
||||
}
|
||||
log.warn("Copying (nodes) clusterId", clusterId, "nodes", nodes);
|
||||
nodes.forEach((node) => {
|
||||
if (graph.children(node).length > 0) {
|
||||
copy(node, graph, newGraph, rootId);
|
||||
} else {
|
||||
const data = graph.node(node);
|
||||
log.info("cp ", node, " to ", rootId, " with parent ", clusterId);
|
||||
newGraph.setNode(node, data);
|
||||
if (rootId !== graph.parent(node)) {
|
||||
log.warn("Setting parent", node, graph.parent(node));
|
||||
newGraph.setParent(node, graph.parent(node));
|
||||
}
|
||||
if (clusterId !== rootId && node !== clusterId) {
|
||||
log.debug("Setting parent", node, clusterId);
|
||||
newGraph.setParent(node, clusterId);
|
||||
} else {
|
||||
log.info("In copy ", clusterId, "root", rootId, "data", graph.node(clusterId), rootId);
|
||||
log.debug(
|
||||
"Not Setting parent for node=",
|
||||
node,
|
||||
"cluster!==rootId",
|
||||
clusterId !== rootId,
|
||||
"node!==clusterId",
|
||||
node !== clusterId
|
||||
);
|
||||
}
|
||||
const edges = graph.edges(node);
|
||||
log.debug("Copying Edges", edges);
|
||||
edges.forEach((edge) => {
|
||||
log.info("Edge", edge);
|
||||
const data2 = graph.edge(edge.v, edge.w, edge.name);
|
||||
log.info("Edge data", data2, rootId);
|
||||
try {
|
||||
if (edgeInCluster(edge, rootId)) {
|
||||
log.info("Copying as ", edge.v, edge.w, data2, edge.name);
|
||||
newGraph.setEdge(edge.v, edge.w, data2, edge.name);
|
||||
log.info("newGraph edges ", newGraph.edges(), newGraph.edge(newGraph.edges()[0]));
|
||||
} else {
|
||||
log.info(
|
||||
"Skipping copy of edge ",
|
||||
edge.v,
|
||||
"-->",
|
||||
edge.w,
|
||||
" rootId: ",
|
||||
rootId,
|
||||
" clusterId:",
|
||||
clusterId
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
log.error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
log.debug("Removing node", node);
|
||||
graph.removeNode(node);
|
||||
});
|
||||
}, "copy");
|
||||
var extractDescendants = __name((id, graph) => {
|
||||
const children = graph.children(id);
|
||||
let res = [...children];
|
||||
for (const child of children) {
|
||||
parents.set(child, id);
|
||||
res = [...res, ...extractDescendants(child, graph)];
|
||||
}
|
||||
return res;
|
||||
}, "extractDescendants");
|
||||
var findCommonEdges = __name((graph, id1, id2) => {
|
||||
const edges1 = graph.edges().filter((edge) => edge.v === id1 || edge.w === id1);
|
||||
const edges2 = graph.edges().filter((edge) => edge.v === id2 || edge.w === id2);
|
||||
const edges1Prim = edges1.map((edge) => {
|
||||
return { v: edge.v === id1 ? id2 : edge.v, w: edge.w === id1 ? id1 : edge.w };
|
||||
});
|
||||
const edges2Prim = edges2.map((edge) => {
|
||||
return { v: edge.v, w: edge.w };
|
||||
});
|
||||
const result = edges1Prim.filter((edgeIn1) => {
|
||||
return edges2Prim.some((edge) => edgeIn1.v === edge.v && edgeIn1.w === edge.w);
|
||||
});
|
||||
return result;
|
||||
}, "findCommonEdges");
|
||||
var findNonClusterChild = __name((id, graph, clusterId) => {
|
||||
const children = graph.children(id);
|
||||
log.trace("Searching children of id ", id, children);
|
||||
if (children.length < 1) {
|
||||
return id;
|
||||
}
|
||||
let reserve;
|
||||
for (const child of children) {
|
||||
const _id = findNonClusterChild(child, graph, clusterId);
|
||||
const commonEdges = findCommonEdges(graph, clusterId, _id);
|
||||
if (_id) {
|
||||
if (commonEdges.length > 0) {
|
||||
reserve = _id;
|
||||
} else {
|
||||
return _id;
|
||||
}
|
||||
}
|
||||
}
|
||||
return reserve;
|
||||
}, "findNonClusterChild");
|
||||
var getAnchorId = __name((id) => {
|
||||
if (!clusterDb.has(id)) {
|
||||
return id;
|
||||
}
|
||||
if (!clusterDb.get(id).externalConnections) {
|
||||
return id;
|
||||
}
|
||||
if (clusterDb.has(id)) {
|
||||
return clusterDb.get(id).id;
|
||||
}
|
||||
return id;
|
||||
}, "getAnchorId");
|
||||
var adjustClustersAndEdges = __name((graph, depth) => {
|
||||
if (!graph || depth > 10) {
|
||||
log.debug("Opting out, no graph ");
|
||||
return;
|
||||
} else {
|
||||
log.debug("Opting in, graph ");
|
||||
}
|
||||
graph.nodes().forEach(function(id) {
|
||||
const children = graph.children(id);
|
||||
if (children.length > 0) {
|
||||
log.warn(
|
||||
"Cluster identified",
|
||||
id,
|
||||
" Replacement id in edges: ",
|
||||
findNonClusterChild(id, graph, id)
|
||||
);
|
||||
descendants.set(id, extractDescendants(id, graph));
|
||||
clusterDb.set(id, { id: findNonClusterChild(id, graph, id), clusterData: graph.node(id) });
|
||||
}
|
||||
});
|
||||
graph.nodes().forEach(function(id) {
|
||||
const children = graph.children(id);
|
||||
const edges = graph.edges();
|
||||
if (children.length > 0) {
|
||||
log.debug("Cluster identified", id, descendants);
|
||||
edges.forEach((edge) => {
|
||||
const d1 = isDescendant(edge.v, id);
|
||||
const d2 = isDescendant(edge.w, id);
|
||||
if (d1 ^ d2) {
|
||||
log.warn("Edge: ", edge, " leaves cluster ", id);
|
||||
log.warn("Descendants of XXX ", id, ": ", descendants.get(id));
|
||||
clusterDb.get(id).externalConnections = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log.debug("Not a cluster ", id, descendants);
|
||||
}
|
||||
});
|
||||
for (let id of clusterDb.keys()) {
|
||||
const nonClusterChild = clusterDb.get(id).id;
|
||||
const parent = graph.parent(nonClusterChild);
|
||||
if (parent !== id && clusterDb.has(parent) && !clusterDb.get(parent).externalConnections) {
|
||||
clusterDb.get(id).id = parent;
|
||||
}
|
||||
}
|
||||
graph.edges().forEach(function(e) {
|
||||
const edge = graph.edge(e);
|
||||
log.warn("Edge " + e.v + " -> " + e.w + ": " + JSON.stringify(e));
|
||||
log.warn("Edge " + e.v + " -> " + e.w + ": " + JSON.stringify(graph.edge(e)));
|
||||
let v = e.v;
|
||||
let w = e.w;
|
||||
log.warn(
|
||||
"Fix XXX",
|
||||
clusterDb,
|
||||
"ids:",
|
||||
e.v,
|
||||
e.w,
|
||||
"Translating: ",
|
||||
clusterDb.get(e.v),
|
||||
" --- ",
|
||||
clusterDb.get(e.w)
|
||||
);
|
||||
if (clusterDb.get(e.v) || clusterDb.get(e.w)) {
|
||||
log.warn("Fixing and trying - removing XXX", e.v, e.w, e.name);
|
||||
v = getAnchorId(e.v);
|
||||
w = getAnchorId(e.w);
|
||||
graph.removeEdge(e.v, e.w, e.name);
|
||||
if (v !== e.v) {
|
||||
const parent = graph.parent(v);
|
||||
clusterDb.get(parent).externalConnections = true;
|
||||
edge.fromCluster = e.v;
|
||||
}
|
||||
if (w !== e.w) {
|
||||
const parent = graph.parent(w);
|
||||
clusterDb.get(parent).externalConnections = true;
|
||||
edge.toCluster = e.w;
|
||||
}
|
||||
log.warn("Fix Replacing with XXX", v, w, e.name);
|
||||
graph.setEdge(v, w, edge, e.name);
|
||||
}
|
||||
});
|
||||
log.warn("Adjusted Graph", write(graph));
|
||||
extractor(graph, 0);
|
||||
log.trace(clusterDb);
|
||||
}, "adjustClustersAndEdges");
|
||||
var extractor = __name((graph, depth) => {
|
||||
var _a, _b;
|
||||
log.warn("extractor - ", depth, write(graph), graph.children("D"));
|
||||
if (depth > 10) {
|
||||
log.error("Bailing out");
|
||||
return;
|
||||
}
|
||||
let nodes = graph.nodes();
|
||||
let hasChildren = false;
|
||||
for (const node of nodes) {
|
||||
const children = graph.children(node);
|
||||
hasChildren = hasChildren || children.length > 0;
|
||||
}
|
||||
if (!hasChildren) {
|
||||
log.debug("Done, no node has children", graph.nodes());
|
||||
return;
|
||||
}
|
||||
log.debug("Nodes = ", nodes, depth);
|
||||
for (const node of nodes) {
|
||||
log.debug(
|
||||
"Extracting node",
|
||||
node,
|
||||
clusterDb,
|
||||
clusterDb.has(node) && !clusterDb.get(node).externalConnections,
|
||||
!graph.parent(node),
|
||||
graph.node(node),
|
||||
graph.children("D"),
|
||||
" Depth ",
|
||||
depth
|
||||
);
|
||||
if (!clusterDb.has(node)) {
|
||||
log.debug("Not a cluster", node, depth);
|
||||
} else if (!clusterDb.get(node).externalConnections && graph.children(node) && graph.children(node).length > 0) {
|
||||
log.warn(
|
||||
"Cluster without external connections, without a parent and with children",
|
||||
node,
|
||||
depth
|
||||
);
|
||||
const graphSettings = graph.graph();
|
||||
let dir = graphSettings.rankdir === "TB" ? "LR" : "TB";
|
||||
if ((_b = (_a = clusterDb.get(node)) == null ? void 0 : _a.clusterData) == null ? void 0 : _b.dir) {
|
||||
dir = clusterDb.get(node).clusterData.dir;
|
||||
log.warn("Fixing dir", clusterDb.get(node).clusterData.dir, dir);
|
||||
}
|
||||
const clusterGraph = new Graph({
|
||||
multigraph: true,
|
||||
compound: true
|
||||
}).setGraph({
|
||||
rankdir: dir,
|
||||
nodesep: 50,
|
||||
ranksep: 50,
|
||||
marginx: 8,
|
||||
marginy: 8
|
||||
}).setDefaultEdgeLabel(function() {
|
||||
return {};
|
||||
});
|
||||
log.warn("Old graph before copy", write(graph));
|
||||
copy(node, graph, clusterGraph, node);
|
||||
graph.setNode(node, {
|
||||
clusterNode: true,
|
||||
id: node,
|
||||
clusterData: clusterDb.get(node).clusterData,
|
||||
label: clusterDb.get(node).label,
|
||||
graph: clusterGraph
|
||||
});
|
||||
log.warn("New graph after copy node: (", node, ")", write(clusterGraph));
|
||||
log.debug("Old graph after copy", write(graph));
|
||||
} else {
|
||||
log.warn(
|
||||
"Cluster ** ",
|
||||
node,
|
||||
" **not meeting the criteria !externalConnections:",
|
||||
!clusterDb.get(node).externalConnections,
|
||||
" no parent: ",
|
||||
!graph.parent(node),
|
||||
" children ",
|
||||
graph.children(node) && graph.children(node).length > 0,
|
||||
graph.children("D"),
|
||||
depth
|
||||
);
|
||||
log.debug(clusterDb);
|
||||
}
|
||||
}
|
||||
nodes = graph.nodes();
|
||||
log.warn("New list of nodes", nodes);
|
||||
for (const node of nodes) {
|
||||
const data = graph.node(node);
|
||||
log.warn(" Now next level", node, data);
|
||||
if (data == null ? void 0 : data.clusterNode) {
|
||||
extractor(data.graph, depth + 1);
|
||||
}
|
||||
}
|
||||
}, "extractor");
|
||||
var sorter = __name((graph, nodes) => {
|
||||
if (nodes.length === 0) {
|
||||
return [];
|
||||
}
|
||||
let result = Object.assign([], nodes);
|
||||
nodes.forEach((node) => {
|
||||
const children = graph.children(node);
|
||||
const sorted = sorter(graph, children);
|
||||
result = [...result, ...sorted];
|
||||
});
|
||||
return result;
|
||||
}, "sorter");
|
||||
var sortNodesByHierarchy = __name((graph) => sorter(graph, graph.children()), "sortNodesByHierarchy");
|
||||
var recursiveRender = __name(async (_elem, graph, diagramType, id, parentCluster, siteConfig) => {
|
||||
log.warn("Graph in recursive render:XAX", write(graph), parentCluster);
|
||||
const dir = graph.graph().rankdir;
|
||||
log.trace("Dir in recursive render - dir:", dir);
|
||||
const elem = _elem.insert("g").attr("class", "root");
|
||||
if (!graph.nodes()) {
|
||||
log.info("No nodes found for", graph);
|
||||
} else {
|
||||
log.info("Recursive render XXX", graph.nodes());
|
||||
}
|
||||
if (graph.edges().length > 0) {
|
||||
log.info("Recursive edges", graph.edge(graph.edges()[0]));
|
||||
}
|
||||
const clusters = elem.insert("g").attr("class", "clusters");
|
||||
const edgePaths = elem.insert("g").attr("class", "edgePaths");
|
||||
const edgeLabels = elem.insert("g").attr("class", "edgeLabels");
|
||||
const nodes = elem.insert("g").attr("class", "nodes");
|
||||
await Promise.all(
|
||||
graph.nodes().map(async function(v) {
|
||||
const node = graph.node(v);
|
||||
if (parentCluster !== void 0) {
|
||||
const data = JSON.parse(JSON.stringify(parentCluster.clusterData));
|
||||
log.trace(
|
||||
"Setting data for parent cluster XXX\n Node.id = ",
|
||||
v,
|
||||
"\n data=",
|
||||
data.height,
|
||||
"\nParent cluster",
|
||||
parentCluster.height
|
||||
);
|
||||
graph.setNode(parentCluster.id, data);
|
||||
if (!graph.parent(v)) {
|
||||
log.trace("Setting parent", v, parentCluster.id);
|
||||
graph.setParent(v, parentCluster.id, data);
|
||||
}
|
||||
}
|
||||
log.info("(Insert) Node XXX" + v + ": " + JSON.stringify(graph.node(v)));
|
||||
if (node == null ? void 0 : node.clusterNode) {
|
||||
log.info("Cluster identified XBX", v, node.width, graph.node(v));
|
||||
const { ranksep, nodesep } = graph.graph();
|
||||
node.graph.setGraph({
|
||||
...node.graph.graph(),
|
||||
ranksep: ranksep + 25,
|
||||
nodesep
|
||||
});
|
||||
const o = await recursiveRender(
|
||||
nodes,
|
||||
node.graph,
|
||||
diagramType,
|
||||
id,
|
||||
graph.node(v),
|
||||
siteConfig
|
||||
);
|
||||
const newEl = o.elem;
|
||||
updateNodeBounds(node, newEl);
|
||||
node.diff = o.diff || 0;
|
||||
log.info(
|
||||
"New compound node after recursive render XAX",
|
||||
v,
|
||||
"width",
|
||||
// node,
|
||||
node.width,
|
||||
"height",
|
||||
node.height
|
||||
// node.x,
|
||||
// node.y
|
||||
);
|
||||
setNodeElem(newEl, node);
|
||||
} else {
|
||||
if (graph.children(v).length > 0) {
|
||||
log.trace(
|
||||
"Cluster - the non recursive path XBX",
|
||||
v,
|
||||
node.id,
|
||||
node,
|
||||
node.width,
|
||||
"Graph:",
|
||||
graph
|
||||
);
|
||||
log.trace(findNonClusterChild(node.id, graph));
|
||||
clusterDb.set(node.id, { id: findNonClusterChild(node.id, graph), node });
|
||||
} else {
|
||||
log.trace("Node - the non recursive path XAX", v, nodes, graph.node(v), dir);
|
||||
await insertNode(nodes, graph.node(v), { config: siteConfig, dir });
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
const processEdges = __name(async () => {
|
||||
const edgePromises = graph.edges().map(async function(e) {
|
||||
const edge = graph.edge(e.v, e.w, e.name);
|
||||
log.info("Edge " + e.v + " -> " + e.w + ": " + JSON.stringify(e));
|
||||
log.info("Edge " + e.v + " -> " + e.w + ": ", e, " ", JSON.stringify(graph.edge(e)));
|
||||
log.info(
|
||||
"Fix",
|
||||
clusterDb,
|
||||
"ids:",
|
||||
e.v,
|
||||
e.w,
|
||||
"Translating: ",
|
||||
clusterDb.get(e.v),
|
||||
clusterDb.get(e.w)
|
||||
);
|
||||
await insertEdgeLabel(edgeLabels, edge);
|
||||
});
|
||||
await Promise.all(edgePromises);
|
||||
}, "processEdges");
|
||||
await processEdges();
|
||||
log.info("Graph before layout:", JSON.stringify(write(graph)));
|
||||
log.info("############################################# XXX");
|
||||
log.info("### Layout ### XXX");
|
||||
log.info("############################################# XXX");
|
||||
layout(graph);
|
||||
log.info("Graph after layout:", JSON.stringify(write(graph)));
|
||||
let diff = 0;
|
||||
let { subGraphTitleTotalMargin } = getSubGraphTitleMargins(siteConfig);
|
||||
await Promise.all(
|
||||
sortNodesByHierarchy(graph).map(async function(v) {
|
||||
var _a;
|
||||
const node = graph.node(v);
|
||||
log.info(
|
||||
"Position XBX => " + v + ": (" + node.x,
|
||||
"," + node.y,
|
||||
") width: ",
|
||||
node.width,
|
||||
" height: ",
|
||||
node.height
|
||||
);
|
||||
if (node == null ? void 0 : node.clusterNode) {
|
||||
node.y += subGraphTitleTotalMargin;
|
||||
log.info(
|
||||
"A tainted cluster node XBX1",
|
||||
v,
|
||||
node.id,
|
||||
node.width,
|
||||
node.height,
|
||||
node.x,
|
||||
node.y,
|
||||
graph.parent(v)
|
||||
);
|
||||
clusterDb.get(node.id).node = node;
|
||||
positionNode(node);
|
||||
} else {
|
||||
if (graph.children(v).length > 0) {
|
||||
log.info(
|
||||
"A pure cluster node XBX1",
|
||||
v,
|
||||
node.id,
|
||||
node.x,
|
||||
node.y,
|
||||
node.width,
|
||||
node.height,
|
||||
graph.parent(v)
|
||||
);
|
||||
node.height += subGraphTitleTotalMargin;
|
||||
graph.node(node.parentId);
|
||||
const halfPadding = (node == null ? void 0 : node.padding) / 2 || 0;
|
||||
const labelHeight = ((_a = node == null ? void 0 : node.labelBBox) == null ? void 0 : _a.height) || 0;
|
||||
const offsetY = labelHeight - halfPadding || 0;
|
||||
log.debug("OffsetY", offsetY, "labelHeight", labelHeight, "halfPadding", halfPadding);
|
||||
await insertCluster(clusters, node);
|
||||
clusterDb.get(node.id).node = node;
|
||||
} else {
|
||||
const parent = graph.node(node.parentId);
|
||||
node.y += subGraphTitleTotalMargin / 2;
|
||||
log.info(
|
||||
"A regular node XBX1 - using the padding",
|
||||
node.id,
|
||||
"parent",
|
||||
node.parentId,
|
||||
node.width,
|
||||
node.height,
|
||||
node.x,
|
||||
node.y,
|
||||
"offsetY",
|
||||
node.offsetY,
|
||||
"parent",
|
||||
parent,
|
||||
parent == null ? void 0 : parent.offsetY,
|
||||
node
|
||||
);
|
||||
positionNode(node);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
graph.edges().forEach(function(e) {
|
||||
const edge = graph.edge(e);
|
||||
log.info("Edge " + e.v + " -> " + e.w + ": " + JSON.stringify(edge), edge);
|
||||
edge.points.forEach((point) => point.y += subGraphTitleTotalMargin / 2);
|
||||
const startNode = graph.node(e.v);
|
||||
var endNode = graph.node(e.w);
|
||||
const paths = insertEdge(edgePaths, edge, clusterDb, diagramType, startNode, endNode, id);
|
||||
positionEdgeLabel(edge, paths);
|
||||
});
|
||||
graph.nodes().forEach(function(v) {
|
||||
const n = graph.node(v);
|
||||
log.info(v, n.type, n.diff);
|
||||
if (n.isGroup) {
|
||||
diff = n.diff;
|
||||
}
|
||||
});
|
||||
log.warn("Returning from recursive render XAX", elem, diff);
|
||||
return { elem, diff };
|
||||
}, "recursiveRender");
|
||||
var render = __name(async (data4Layout, svg) => {
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
const graph = new Graph({
|
||||
multigraph: true,
|
||||
compound: true
|
||||
}).setGraph({
|
||||
rankdir: data4Layout.direction,
|
||||
nodesep: ((_a = data4Layout.config) == null ? void 0 : _a.nodeSpacing) || ((_c = (_b = data4Layout.config) == null ? void 0 : _b.flowchart) == null ? void 0 : _c.nodeSpacing) || data4Layout.nodeSpacing,
|
||||
ranksep: ((_d = data4Layout.config) == null ? void 0 : _d.rankSpacing) || ((_f = (_e = data4Layout.config) == null ? void 0 : _e.flowchart) == null ? void 0 : _f.rankSpacing) || data4Layout.rankSpacing,
|
||||
marginx: 8,
|
||||
marginy: 8
|
||||
}).setDefaultEdgeLabel(function() {
|
||||
return {};
|
||||
});
|
||||
const element = svg.select("g");
|
||||
markers_default(element, data4Layout.markers, data4Layout.type, data4Layout.diagramId);
|
||||
clear2();
|
||||
clear3();
|
||||
clear();
|
||||
clear4();
|
||||
data4Layout.nodes.forEach((node) => {
|
||||
graph.setNode(node.id, { ...node });
|
||||
if (node.parentId) {
|
||||
graph.setParent(node.id, node.parentId);
|
||||
}
|
||||
});
|
||||
log.debug("Edges:", data4Layout.edges);
|
||||
data4Layout.edges.forEach((edge) => {
|
||||
if (edge.start === edge.end) {
|
||||
const nodeId = edge.start;
|
||||
const specialId1 = nodeId + "---" + nodeId + "---1";
|
||||
const specialId2 = nodeId + "---" + nodeId + "---2";
|
||||
const node = graph.node(nodeId);
|
||||
graph.setNode(specialId1, {
|
||||
domId: specialId1,
|
||||
id: specialId1,
|
||||
parentId: node.parentId,
|
||||
labelStyle: "",
|
||||
label: "",
|
||||
padding: 0,
|
||||
shape: "labelRect",
|
||||
// shape: 'rect',
|
||||
style: "",
|
||||
width: 10,
|
||||
height: 10
|
||||
});
|
||||
graph.setParent(specialId1, node.parentId);
|
||||
graph.setNode(specialId2, {
|
||||
domId: specialId2,
|
||||
id: specialId2,
|
||||
parentId: node.parentId,
|
||||
labelStyle: "",
|
||||
padding: 0,
|
||||
// shape: 'rect',
|
||||
shape: "labelRect",
|
||||
label: "",
|
||||
style: "",
|
||||
width: 10,
|
||||
height: 10
|
||||
});
|
||||
graph.setParent(specialId2, node.parentId);
|
||||
const edge1 = structuredClone(edge);
|
||||
const edgeMid = structuredClone(edge);
|
||||
const edge2 = structuredClone(edge);
|
||||
edge1.label = "";
|
||||
edge1.arrowTypeEnd = "none";
|
||||
edge1.id = nodeId + "-cyclic-special-1";
|
||||
edgeMid.arrowTypeStart = "none";
|
||||
edgeMid.arrowTypeEnd = "none";
|
||||
edgeMid.id = nodeId + "-cyclic-special-mid";
|
||||
edge2.label = "";
|
||||
if (node.isGroup) {
|
||||
edge1.fromCluster = nodeId;
|
||||
edge2.toCluster = nodeId;
|
||||
}
|
||||
edge2.id = nodeId + "-cyclic-special-2";
|
||||
edge2.arrowTypeStart = "none";
|
||||
graph.setEdge(nodeId, specialId1, edge1, nodeId + "-cyclic-special-0");
|
||||
graph.setEdge(specialId1, specialId2, edgeMid, nodeId + "-cyclic-special-1");
|
||||
graph.setEdge(specialId2, nodeId, edge2, nodeId + "-cyc<lic-special-2");
|
||||
} else {
|
||||
graph.setEdge(edge.start, edge.end, { ...edge }, edge.id);
|
||||
}
|
||||
});
|
||||
log.warn("Graph at first:", JSON.stringify(write(graph)));
|
||||
adjustClustersAndEdges(graph);
|
||||
log.warn("Graph after XAX:", JSON.stringify(write(graph)));
|
||||
const siteConfig = getConfig2();
|
||||
await recursiveRender(
|
||||
element,
|
||||
graph,
|
||||
data4Layout.type,
|
||||
data4Layout.diagramId,
|
||||
void 0,
|
||||
siteConfig
|
||||
);
|
||||
}, "render");
|
||||
export {
|
||||
render
|
||||
};
|
||||
//# sourceMappingURL=dagre-KV5264BT-IXUN74XC.js.map
|
||||
-7
File diff suppressed because one or more lines are too long
-214
@@ -1,214 +0,0 @@
|
||||
import {
|
||||
populateCommonDb
|
||||
} from "./chunk-BEGFPAJS.js";
|
||||
import {
|
||||
parse
|
||||
} from "./chunk-ZO353HVL.js";
|
||||
import {
|
||||
ImperativeState
|
||||
} from "./chunk-VPVLR6E4.js";
|
||||
import "./chunk-SHHXTPWA.js";
|
||||
import "./chunk-JLNTX6TF.js";
|
||||
import "./chunk-IELG6YWI.js";
|
||||
import "./chunk-ZOQ3FUUK.js";
|
||||
import "./chunk-TAVNOOKD.js";
|
||||
import "./chunk-5D6MANWW.js";
|
||||
import "./chunk-E3W5VJ2T.js";
|
||||
import "./chunk-JH6V2QOE.js";
|
||||
import "./chunk-QLH66CIT.js";
|
||||
import "./chunk-S4AGLBPD.js";
|
||||
import "./chunk-K3ORWWMK.js";
|
||||
import {
|
||||
selectSvgElement
|
||||
} from "./chunk-QBIGODNM.js";
|
||||
import {
|
||||
cleanAndMerge
|
||||
} from "./chunk-3QKV3V7V.js";
|
||||
import "./chunk-MOBZPS7F.js";
|
||||
import {
|
||||
clear,
|
||||
configureSvgSize,
|
||||
defaultConfig_default,
|
||||
getAccDescription,
|
||||
getAccTitle,
|
||||
getConfig,
|
||||
getDiagramTitle,
|
||||
setAccDescription,
|
||||
setAccTitle,
|
||||
setDiagramTitle
|
||||
} from "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name,
|
||||
log
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import "./chunk-BQ2Z5GT2.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/diagram-5BDNPKRD.mjs
|
||||
var state = new ImperativeState(() => ({
|
||||
cnt: 1,
|
||||
stack: [
|
||||
{
|
||||
id: 0,
|
||||
level: -1,
|
||||
name: "/",
|
||||
children: []
|
||||
}
|
||||
]
|
||||
}));
|
||||
var clear2 = __name(() => {
|
||||
state.reset();
|
||||
clear();
|
||||
}, "clear");
|
||||
var getRoot = __name(() => {
|
||||
return state.records.stack[0];
|
||||
}, "getRoot");
|
||||
var getCount = __name(() => state.records.cnt, "getCount");
|
||||
var defaultConfig = defaultConfig_default.treeView;
|
||||
var getConfig2 = __name(() => {
|
||||
return cleanAndMerge(defaultConfig, getConfig().treeView);
|
||||
}, "getConfig");
|
||||
var addNode = __name((level, name) => {
|
||||
while (level <= state.records.stack[state.records.stack.length - 1].level) {
|
||||
state.records.stack.pop();
|
||||
}
|
||||
const node = {
|
||||
id: state.records.cnt++,
|
||||
level,
|
||||
name,
|
||||
children: []
|
||||
};
|
||||
state.records.stack[state.records.stack.length - 1].children.push(node);
|
||||
state.records.stack.push(node);
|
||||
}, "addNode");
|
||||
var db = {
|
||||
clear: clear2,
|
||||
addNode,
|
||||
getRoot,
|
||||
getCount,
|
||||
getConfig: getConfig2,
|
||||
getAccTitle,
|
||||
getAccDescription,
|
||||
getDiagramTitle,
|
||||
setAccDescription,
|
||||
setAccTitle,
|
||||
setDiagramTitle
|
||||
};
|
||||
var db_default = db;
|
||||
var populate = __name((ast) => {
|
||||
populateCommonDb(ast, db_default);
|
||||
ast.nodes.map((node) => db_default.addNode(node.indent ? parseInt(node.indent) : 0, node.name));
|
||||
}, "populate");
|
||||
var parser = {
|
||||
parse: __name(async (input) => {
|
||||
const ast = await parse("treeView", input);
|
||||
log.debug(ast);
|
||||
populate(ast);
|
||||
}, "parse")
|
||||
};
|
||||
var positionLabel = __name((x, y, node, domElem, config) => {
|
||||
const label = domElem.append("text").text(node.name).attr("dominant-baseline", "middle").attr("class", "treeView-node-label");
|
||||
const { height: labelHeight, width: labelWidth } = label.node().getBBox();
|
||||
const height = labelHeight + config.paddingY * 2;
|
||||
const width = labelWidth + config.paddingX * 2;
|
||||
label.attr("x", x + config.paddingX);
|
||||
label.attr("y", y + height / 2);
|
||||
node.BBox = {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height
|
||||
};
|
||||
}, "positionLabel");
|
||||
var positionLine = __name((domElem, x1, y1, x2, y2, lineThickness) => {
|
||||
return domElem.append("line").attr("x1", x1).attr("y1", y1).attr("x2", x2).attr("y2", y2).attr("stroke-width", lineThickness).attr("class", "treeView-node-line");
|
||||
}, "positionLine");
|
||||
var drawTree = __name((elem, root, config) => {
|
||||
let totalHeight = 0;
|
||||
let totalWidth = 0;
|
||||
const drawNode = __name((elem2, node, config2, depth) => {
|
||||
const indent = depth * (config2.rowIndent + config2.paddingX);
|
||||
positionLabel(indent, totalHeight, node, elem2, config2);
|
||||
const { height, width } = node.BBox;
|
||||
positionLine(
|
||||
elem2,
|
||||
indent - config2.rowIndent,
|
||||
totalHeight + height / 2,
|
||||
indent,
|
||||
totalHeight + height / 2,
|
||||
config2.lineThickness
|
||||
);
|
||||
totalWidth = Math.max(totalWidth, indent + width);
|
||||
totalHeight += height;
|
||||
}, "drawNode");
|
||||
const processNode = __name((node, depth = 0) => {
|
||||
drawNode(elem, node, config, depth);
|
||||
node.children.forEach((child) => {
|
||||
processNode(child, depth + 1);
|
||||
});
|
||||
const { x, y, height } = node.BBox;
|
||||
if (node.children.length) {
|
||||
const { y: endY, height: endHeight } = node.children[node.children.length - 1].BBox;
|
||||
positionLine(
|
||||
elem,
|
||||
x + config.paddingX,
|
||||
y + height,
|
||||
x + config.paddingX,
|
||||
endY + endHeight / 2 + config.lineThickness / 2,
|
||||
config.lineThickness
|
||||
);
|
||||
}
|
||||
}, "processNode");
|
||||
processNode(root);
|
||||
return { totalHeight, totalWidth };
|
||||
}, "drawTree");
|
||||
var draw = __name((text, id, _ver, diagObj) => {
|
||||
log.debug("Rendering treeView diagram\n" + text);
|
||||
const db2 = diagObj.db;
|
||||
const root = db2.getRoot();
|
||||
const config = db2.getConfig();
|
||||
const svg = selectSvgElement(id);
|
||||
const treeElem = svg.append("g");
|
||||
treeElem.attr("class", "tree-view");
|
||||
const { totalHeight, totalWidth } = drawTree(treeElem, root, config);
|
||||
svg.attr("viewBox", `-${config.lineThickness / 2} 0 ${totalWidth} ${totalHeight}`);
|
||||
configureSvgSize(svg, totalHeight, totalWidth, config.useMaxWidth);
|
||||
}, "draw");
|
||||
var renderer = {
|
||||
draw
|
||||
};
|
||||
var renderer_default = renderer;
|
||||
var defaultTreeViewDiagramStyles = {
|
||||
labelFontSize: "16px",
|
||||
labelColor: "black",
|
||||
lineColor: "black"
|
||||
};
|
||||
var styles = __name(({
|
||||
treeView
|
||||
}) => {
|
||||
const { labelFontSize, labelColor, lineColor } = cleanAndMerge(
|
||||
defaultTreeViewDiagramStyles,
|
||||
treeView
|
||||
);
|
||||
return `
|
||||
.treeView-node-label {
|
||||
font-size: ${labelFontSize};
|
||||
fill: ${labelColor};
|
||||
}
|
||||
.treeView-node-line {
|
||||
stroke: ${lineColor};
|
||||
}
|
||||
`;
|
||||
}, "styles");
|
||||
var styles_default = styles;
|
||||
var diagram = {
|
||||
db: db_default,
|
||||
renderer: renderer_default,
|
||||
parser,
|
||||
styles: styles_default
|
||||
};
|
||||
export {
|
||||
diagram
|
||||
};
|
||||
//# sourceMappingURL=diagram-5BDNPKRD-CQ5OTDU7.js.map
|
||||
-7
File diff suppressed because one or more lines are too long
-578
@@ -1,578 +0,0 @@
|
||||
import {
|
||||
populateCommonDb
|
||||
} from "./chunk-BEGFPAJS.js";
|
||||
import {
|
||||
parse
|
||||
} from "./chunk-ZO353HVL.js";
|
||||
import "./chunk-SHHXTPWA.js";
|
||||
import "./chunk-JLNTX6TF.js";
|
||||
import "./chunk-IELG6YWI.js";
|
||||
import "./chunk-ZOQ3FUUK.js";
|
||||
import "./chunk-TAVNOOKD.js";
|
||||
import "./chunk-5D6MANWW.js";
|
||||
import "./chunk-E3W5VJ2T.js";
|
||||
import "./chunk-JH6V2QOE.js";
|
||||
import {
|
||||
setupViewPortForSVG
|
||||
} from "./chunk-YVBSFUGN.js";
|
||||
import "./chunk-QLH66CIT.js";
|
||||
import "./chunk-S4AGLBPD.js";
|
||||
import "./chunk-K3ORWWMK.js";
|
||||
import {
|
||||
selectSvgElement
|
||||
} from "./chunk-QBIGODNM.js";
|
||||
import {
|
||||
isLabelStyle,
|
||||
styles2String
|
||||
} from "./chunk-N2C52BYW.js";
|
||||
import {
|
||||
cleanAndMerge
|
||||
} from "./chunk-3QKV3V7V.js";
|
||||
import "./chunk-MOBZPS7F.js";
|
||||
import {
|
||||
clear,
|
||||
configureSvgSize,
|
||||
defaultConfig_default,
|
||||
getAccDescription,
|
||||
getAccTitle,
|
||||
getConfig,
|
||||
getDiagramTitle,
|
||||
getThemeVariables3,
|
||||
setAccDescription,
|
||||
setAccTitle,
|
||||
setDiagramTitle
|
||||
} from "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name,
|
||||
format,
|
||||
hierarchy,
|
||||
log,
|
||||
ordinal,
|
||||
select_default,
|
||||
treemap_default
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import "./chunk-BQ2Z5GT2.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/diagram-G4DWMVQ6.mjs
|
||||
var _a;
|
||||
var TreeMapDB = (_a = class {
|
||||
constructor() {
|
||||
this.nodes = [];
|
||||
this.levels = /* @__PURE__ */ new Map();
|
||||
this.outerNodes = [];
|
||||
this.classes = /* @__PURE__ */ new Map();
|
||||
this.setAccTitle = setAccTitle;
|
||||
this.getAccTitle = getAccTitle;
|
||||
this.setDiagramTitle = setDiagramTitle;
|
||||
this.getDiagramTitle = getDiagramTitle;
|
||||
this.getAccDescription = getAccDescription;
|
||||
this.setAccDescription = setAccDescription;
|
||||
}
|
||||
getNodes() {
|
||||
return this.nodes;
|
||||
}
|
||||
getConfig() {
|
||||
const defaultConfig = defaultConfig_default;
|
||||
const userConfig = getConfig();
|
||||
return cleanAndMerge({
|
||||
...defaultConfig.treemap,
|
||||
...userConfig.treemap ?? {}
|
||||
});
|
||||
}
|
||||
addNode(node, level) {
|
||||
this.nodes.push(node);
|
||||
this.levels.set(node, level);
|
||||
if (level === 0) {
|
||||
this.outerNodes.push(node);
|
||||
this.root ?? (this.root = node);
|
||||
}
|
||||
}
|
||||
getRoot() {
|
||||
return { name: "", children: this.outerNodes };
|
||||
}
|
||||
addClass(id, _style) {
|
||||
const styleClass = this.classes.get(id) ?? { id, styles: [], textStyles: [] };
|
||||
const styles = _style.replace(/\\,/g, "§§§").replace(/,/g, ";").replace(/§§§/g, ",").split(";");
|
||||
if (styles) {
|
||||
styles.forEach((s) => {
|
||||
if (isLabelStyle(s)) {
|
||||
if (styleClass == null ? void 0 : styleClass.textStyles) {
|
||||
styleClass.textStyles.push(s);
|
||||
} else {
|
||||
styleClass.textStyles = [s];
|
||||
}
|
||||
}
|
||||
if (styleClass == null ? void 0 : styleClass.styles) {
|
||||
styleClass.styles.push(s);
|
||||
} else {
|
||||
styleClass.styles = [s];
|
||||
}
|
||||
});
|
||||
}
|
||||
this.classes.set(id, styleClass);
|
||||
}
|
||||
getClasses() {
|
||||
return this.classes;
|
||||
}
|
||||
getStylesForClass(classSelector) {
|
||||
var _a2;
|
||||
return ((_a2 = this.classes.get(classSelector)) == null ? void 0 : _a2.styles) ?? [];
|
||||
}
|
||||
clear() {
|
||||
clear();
|
||||
this.nodes = [];
|
||||
this.levels = /* @__PURE__ */ new Map();
|
||||
this.outerNodes = [];
|
||||
this.classes = /* @__PURE__ */ new Map();
|
||||
this.root = void 0;
|
||||
}
|
||||
}, __name(_a, "TreeMapDB"), _a);
|
||||
function buildHierarchy(items) {
|
||||
if (!items.length) {
|
||||
return [];
|
||||
}
|
||||
const root = [];
|
||||
const stack = [];
|
||||
items.forEach((item) => {
|
||||
const node = {
|
||||
name: item.name,
|
||||
children: item.type === "Leaf" ? void 0 : []
|
||||
};
|
||||
node.classSelector = item == null ? void 0 : item.classSelector;
|
||||
if (item == null ? void 0 : item.cssCompiledStyles) {
|
||||
node.cssCompiledStyles = item.cssCompiledStyles;
|
||||
}
|
||||
if (item.type === "Leaf" && item.value !== void 0) {
|
||||
node.value = item.value;
|
||||
}
|
||||
while (stack.length > 0 && stack[stack.length - 1].level >= item.level) {
|
||||
stack.pop();
|
||||
}
|
||||
if (stack.length === 0) {
|
||||
root.push(node);
|
||||
} else {
|
||||
const parent = stack[stack.length - 1].node;
|
||||
if (parent.children) {
|
||||
parent.children.push(node);
|
||||
} else {
|
||||
parent.children = [node];
|
||||
}
|
||||
}
|
||||
if (item.type !== "Leaf") {
|
||||
stack.push({ node, level: item.level });
|
||||
}
|
||||
});
|
||||
return root;
|
||||
}
|
||||
__name(buildHierarchy, "buildHierarchy");
|
||||
var populate = __name((ast, db) => {
|
||||
populateCommonDb(ast, db);
|
||||
const items = [];
|
||||
for (const row of ast.TreemapRows ?? []) {
|
||||
if (row.$type === "ClassDefStatement") {
|
||||
db.addClass(row.className ?? "", row.styleText ?? "");
|
||||
}
|
||||
}
|
||||
for (const row of ast.TreemapRows ?? []) {
|
||||
const item = row.item;
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
const level = row.indent ? parseInt(row.indent) : 0;
|
||||
const name = getItemName(item);
|
||||
const styles = item.classSelector ? db.getStylesForClass(item.classSelector) : [];
|
||||
const cssCompiledStyles = styles.length > 0 ? styles : void 0;
|
||||
const itemData = {
|
||||
level,
|
||||
name,
|
||||
type: item.$type,
|
||||
value: item.value,
|
||||
classSelector: item.classSelector,
|
||||
cssCompiledStyles
|
||||
};
|
||||
items.push(itemData);
|
||||
}
|
||||
const hierarchyNodes = buildHierarchy(items);
|
||||
const addNodesRecursively = __name((nodes, level) => {
|
||||
for (const node of nodes) {
|
||||
db.addNode(node, level);
|
||||
if (node.children && node.children.length > 0) {
|
||||
addNodesRecursively(node.children, level + 1);
|
||||
}
|
||||
}
|
||||
}, "addNodesRecursively");
|
||||
addNodesRecursively(hierarchyNodes, 0);
|
||||
}, "populate");
|
||||
var getItemName = __name((item) => {
|
||||
return item.name ? String(item.name) : "";
|
||||
}, "getItemName");
|
||||
var parser = {
|
||||
// @ts-expect-error - TreeMapDB is not assignable to DiagramDB
|
||||
parser: { yy: void 0 },
|
||||
parse: __name(async (text) => {
|
||||
var _a2;
|
||||
try {
|
||||
const parseFunc = parse;
|
||||
const ast = await parseFunc("treemap", text);
|
||||
log.debug("Treemap AST:", ast);
|
||||
const db = (_a2 = parser.parser) == null ? void 0 : _a2.yy;
|
||||
if (!(db instanceof TreeMapDB)) {
|
||||
throw new Error(
|
||||
"parser.parser?.yy was not a TreemapDB. This is due to a bug within Mermaid, please report this issue at https://github.com/mermaid-js/mermaid/issues."
|
||||
);
|
||||
}
|
||||
populate(ast, db);
|
||||
} catch (error) {
|
||||
log.error("Error parsing treemap:", error);
|
||||
throw error;
|
||||
}
|
||||
}, "parse")
|
||||
};
|
||||
var DEFAULT_INNER_PADDING = 10;
|
||||
var SECTION_INNER_PADDING = 10;
|
||||
var SECTION_HEADER_HEIGHT = 25;
|
||||
var draw = __name((_text, id, _version, diagram2) => {
|
||||
const treemapDb = diagram2.db;
|
||||
const config = treemapDb.getConfig();
|
||||
const treemapInnerPadding = config.padding ?? DEFAULT_INNER_PADDING;
|
||||
const title = treemapDb.getDiagramTitle();
|
||||
const root = treemapDb.getRoot();
|
||||
const { themeVariables } = getConfig();
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
const titleHeight = title ? 30 : 0;
|
||||
const svg = selectSvgElement(id);
|
||||
const width = config.nodeWidth ? config.nodeWidth * SECTION_INNER_PADDING : 960;
|
||||
const height = config.nodeHeight ? config.nodeHeight * SECTION_INNER_PADDING : 500;
|
||||
const svgWidth = width;
|
||||
const svgHeight = height + titleHeight;
|
||||
svg.attr("viewBox", `0 0 ${svgWidth} ${svgHeight}`);
|
||||
configureSvgSize(svg, svgHeight, svgWidth, config.useMaxWidth);
|
||||
let valueFormat;
|
||||
try {
|
||||
const formatStr = config.valueFormat || ",";
|
||||
if (formatStr === "$0,0") {
|
||||
valueFormat = __name((value) => "$" + format(",")(value), "valueFormat");
|
||||
} else if (formatStr.startsWith("$") && formatStr.includes(",")) {
|
||||
const precision = /\.\d+/.exec(formatStr);
|
||||
const precisionStr = precision ? precision[0] : "";
|
||||
valueFormat = __name((value) => "$" + format("," + precisionStr)(value), "valueFormat");
|
||||
} else if (formatStr.startsWith("$")) {
|
||||
const restOfFormat = formatStr.substring(1);
|
||||
valueFormat = __name((value) => "$" + format(restOfFormat || "")(value), "valueFormat");
|
||||
} else {
|
||||
valueFormat = format(formatStr);
|
||||
}
|
||||
} catch (error) {
|
||||
log.error("Error creating format function:", error);
|
||||
valueFormat = format(",");
|
||||
}
|
||||
const colorScale = ordinal().range([
|
||||
"transparent",
|
||||
themeVariables.cScale0,
|
||||
themeVariables.cScale1,
|
||||
themeVariables.cScale2,
|
||||
themeVariables.cScale3,
|
||||
themeVariables.cScale4,
|
||||
themeVariables.cScale5,
|
||||
themeVariables.cScale6,
|
||||
themeVariables.cScale7,
|
||||
themeVariables.cScale8,
|
||||
themeVariables.cScale9,
|
||||
themeVariables.cScale10,
|
||||
themeVariables.cScale11
|
||||
]);
|
||||
const colorScalePeer = ordinal().range([
|
||||
"transparent",
|
||||
themeVariables.cScalePeer0,
|
||||
themeVariables.cScalePeer1,
|
||||
themeVariables.cScalePeer2,
|
||||
themeVariables.cScalePeer3,
|
||||
themeVariables.cScalePeer4,
|
||||
themeVariables.cScalePeer5,
|
||||
themeVariables.cScalePeer6,
|
||||
themeVariables.cScalePeer7,
|
||||
themeVariables.cScalePeer8,
|
||||
themeVariables.cScalePeer9,
|
||||
themeVariables.cScalePeer10,
|
||||
themeVariables.cScalePeer11
|
||||
]);
|
||||
const colorScaleLabel = ordinal().range([
|
||||
themeVariables.cScaleLabel0,
|
||||
themeVariables.cScaleLabel1,
|
||||
themeVariables.cScaleLabel2,
|
||||
themeVariables.cScaleLabel3,
|
||||
themeVariables.cScaleLabel4,
|
||||
themeVariables.cScaleLabel5,
|
||||
themeVariables.cScaleLabel6,
|
||||
themeVariables.cScaleLabel7,
|
||||
themeVariables.cScaleLabel8,
|
||||
themeVariables.cScaleLabel9,
|
||||
themeVariables.cScaleLabel10,
|
||||
themeVariables.cScaleLabel11
|
||||
]);
|
||||
if (title) {
|
||||
svg.append("text").attr("x", svgWidth / 2).attr("y", titleHeight / 2).attr("class", "treemapTitle").attr("text-anchor", "middle").attr("dominant-baseline", "middle").text(title);
|
||||
}
|
||||
const g = svg.append("g").attr("transform", `translate(0, ${titleHeight})`).attr("class", "treemapContainer");
|
||||
const hierarchyRoot = hierarchy(root).sum((d) => d.value ?? 0).sort((a, b) => (b.value ?? 0) - (a.value ?? 0));
|
||||
const treemapLayout = treemap_default().size([width, height]).paddingTop(
|
||||
(d) => d.children && d.children.length > 0 ? SECTION_HEADER_HEIGHT + SECTION_INNER_PADDING : 0
|
||||
).paddingInner(treemapInnerPadding).paddingLeft((d) => d.children && d.children.length > 0 ? SECTION_INNER_PADDING : 0).paddingRight((d) => d.children && d.children.length > 0 ? SECTION_INNER_PADDING : 0).paddingBottom((d) => d.children && d.children.length > 0 ? SECTION_INNER_PADDING : 0).round(true);
|
||||
const treemapData = treemapLayout(hierarchyRoot);
|
||||
const branchNodes = treemapData.descendants().filter((d) => d.children && d.children.length > 0);
|
||||
const sections = g.selectAll(".treemapSection").data(branchNodes).enter().append("g").attr("class", "treemapSection").attr("transform", (d) => `translate(${d.x0},${d.y0})`);
|
||||
sections.append("rect").attr("width", (d) => d.x1 - d.x0).attr("height", SECTION_HEADER_HEIGHT).attr("class", "treemapSectionHeader").attr("fill", "none").attr("fill-opacity", 0.6).attr("stroke-width", 0.6).attr("style", (d) => {
|
||||
if (d.depth === 0) {
|
||||
return "display: none;";
|
||||
}
|
||||
return "";
|
||||
});
|
||||
sections.append("clipPath").attr("id", (_d, i) => `clip-section-${id}-${i}`).append("rect").attr("width", (d) => Math.max(0, d.x1 - d.x0 - 12)).attr("height", SECTION_HEADER_HEIGHT);
|
||||
sections.append("rect").attr("width", (d) => d.x1 - d.x0).attr("height", (d) => d.y1 - d.y0).attr("class", (_d, i) => {
|
||||
return `treemapSection section${i}`;
|
||||
}).attr("fill", (d) => colorScale(d.data.name)).attr("fill-opacity", 0.6).attr("stroke", (d) => colorScalePeer(d.data.name)).attr("stroke-width", 2).attr("stroke-opacity", 0.4).attr("style", (d) => {
|
||||
if (d.depth === 0) {
|
||||
return "display: none;";
|
||||
}
|
||||
const styles = styles2String({ cssCompiledStyles: d.data.cssCompiledStyles });
|
||||
return styles.nodeStyles + ";" + styles.borderStyles.join(";");
|
||||
});
|
||||
sections.append("text").attr("class", "treemapSectionLabel").attr("x", 6).attr("y", SECTION_HEADER_HEIGHT / 2).attr("dominant-baseline", "middle").text((d) => d.depth === 0 ? "" : d.data.name).attr("font-weight", "bold").attr("style", (d) => {
|
||||
if (d.depth === 0) {
|
||||
return "display: none;";
|
||||
}
|
||||
const labelStyles = "dominant-baseline: middle; font-size: 12px; fill:" + colorScaleLabel(d.data.name) + "; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;";
|
||||
const styles = styles2String({ cssCompiledStyles: d.data.cssCompiledStyles });
|
||||
return labelStyles + styles.labelStyles.replace("color:", "fill:");
|
||||
}).each(function(d) {
|
||||
if (d.depth === 0) {
|
||||
return;
|
||||
}
|
||||
const self = select_default(this);
|
||||
const originalText = d.data.name;
|
||||
self.text(originalText);
|
||||
const totalHeaderWidth = d.x1 - d.x0;
|
||||
const labelXPosition = 6;
|
||||
let spaceForTextContent;
|
||||
if (config.showValues !== false && d.value) {
|
||||
const valueEndsAtXRelative = totalHeaderWidth - 10;
|
||||
const estimatedValueTextActualWidth = 30;
|
||||
const gapBetweenLabelAndValue = 10;
|
||||
const labelMustEndBeforeX = valueEndsAtXRelative - estimatedValueTextActualWidth - gapBetweenLabelAndValue;
|
||||
spaceForTextContent = labelMustEndBeforeX - labelXPosition;
|
||||
} else {
|
||||
const labelOwnRightPadding = 6;
|
||||
spaceForTextContent = totalHeaderWidth - labelXPosition - labelOwnRightPadding;
|
||||
}
|
||||
const minimumWidthToDisplay = 15;
|
||||
const actualAvailableWidth = Math.max(minimumWidthToDisplay, spaceForTextContent);
|
||||
const textNode = self.node();
|
||||
const currentTextContentLength = textNode.getComputedTextLength();
|
||||
if (currentTextContentLength > actualAvailableWidth) {
|
||||
const ellipsis = "...";
|
||||
let currentTruncatedText = originalText;
|
||||
while (currentTruncatedText.length > 0) {
|
||||
currentTruncatedText = originalText.substring(0, currentTruncatedText.length - 1);
|
||||
if (currentTruncatedText.length === 0) {
|
||||
self.text(ellipsis);
|
||||
if (textNode.getComputedTextLength() > actualAvailableWidth) {
|
||||
self.text("");
|
||||
}
|
||||
break;
|
||||
}
|
||||
self.text(currentTruncatedText + ellipsis);
|
||||
if (textNode.getComputedTextLength() <= actualAvailableWidth) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (config.showValues !== false) {
|
||||
sections.append("text").attr("class", "treemapSectionValue").attr("x", (d) => d.x1 - d.x0 - 10).attr("y", SECTION_HEADER_HEIGHT / 2).attr("text-anchor", "end").attr("dominant-baseline", "middle").text((d) => d.value ? valueFormat(d.value) : "").attr("font-style", "italic").attr("style", (d) => {
|
||||
if (d.depth === 0) {
|
||||
return "display: none;";
|
||||
}
|
||||
const labelStyles = "text-anchor: end; dominant-baseline: middle; font-size: 10px; fill:" + colorScaleLabel(d.data.name) + "; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;";
|
||||
const styles = styles2String({ cssCompiledStyles: d.data.cssCompiledStyles });
|
||||
return labelStyles + styles.labelStyles.replace("color:", "fill:");
|
||||
});
|
||||
}
|
||||
const leafNodes = treemapData.leaves();
|
||||
const cell = g.selectAll(".treemapLeafGroup").data(leafNodes).enter().append("g").attr("class", (d, i) => {
|
||||
return `treemapNode treemapLeafGroup leaf${i}${d.data.classSelector ? ` ${d.data.classSelector}` : ""}x`;
|
||||
}).attr("transform", (d) => `translate(${d.x0},${d.y0})`);
|
||||
cell.append("rect").attr("width", (d) => d.x1 - d.x0).attr("height", (d) => d.y1 - d.y0).attr("class", "treemapLeaf").attr("fill", (d) => {
|
||||
return d.parent ? colorScale(d.parent.data.name) : colorScale(d.data.name);
|
||||
}).attr("style", (d) => {
|
||||
const styles = styles2String({ cssCompiledStyles: d.data.cssCompiledStyles });
|
||||
return styles.nodeStyles;
|
||||
}).attr("fill-opacity", 0.3).attr("stroke", (d) => {
|
||||
return d.parent ? colorScale(d.parent.data.name) : colorScale(d.data.name);
|
||||
}).attr("stroke-width", 3);
|
||||
cell.append("clipPath").attr("id", (_d, i) => `clip-${id}-${i}`).append("rect").attr("width", (d) => Math.max(0, d.x1 - d.x0 - 4)).attr("height", (d) => Math.max(0, d.y1 - d.y0 - 4));
|
||||
const leafLabels = cell.append("text").attr("class", "treemapLabel").attr("x", (d) => (d.x1 - d.x0) / 2).attr("y", (d) => (d.y1 - d.y0) / 2).attr("style", (d) => {
|
||||
const labelStyles = "text-anchor: middle; dominant-baseline: middle; font-size: 38px;fill:" + colorScaleLabel(d.data.name) + ";";
|
||||
const styles = styles2String({ cssCompiledStyles: d.data.cssCompiledStyles });
|
||||
return labelStyles + styles.labelStyles.replace("color:", "fill:");
|
||||
}).attr("clip-path", (_d, i) => `url(#clip-${id}-${i})`).text((d) => d.data.name);
|
||||
leafLabels.each(function(d) {
|
||||
const self = select_default(this);
|
||||
const nodeWidth = d.x1 - d.x0;
|
||||
const nodeHeight = d.y1 - d.y0;
|
||||
const textNode = self.node();
|
||||
const padding = 4;
|
||||
const availableWidth = nodeWidth - 2 * padding;
|
||||
const availableHeight = nodeHeight - 2 * padding;
|
||||
if (availableWidth < 10 || availableHeight < 10) {
|
||||
self.style("display", "none");
|
||||
return;
|
||||
}
|
||||
let currentLabelFontSize = parseInt(self.style("font-size"), 10);
|
||||
const minLabelFontSize = 8;
|
||||
const originalValueRelFontSize = 28;
|
||||
const valueScaleFactor = 0.6;
|
||||
const minValueFontSize = 6;
|
||||
const spacingBetweenLabelAndValue = 2;
|
||||
while (textNode.getComputedTextLength() > availableWidth && currentLabelFontSize > minLabelFontSize) {
|
||||
currentLabelFontSize--;
|
||||
self.style("font-size", `${currentLabelFontSize}px`);
|
||||
}
|
||||
let prospectiveValueFontSize = Math.max(
|
||||
minValueFontSize,
|
||||
Math.min(originalValueRelFontSize, Math.round(currentLabelFontSize * valueScaleFactor))
|
||||
);
|
||||
let combinedHeight = currentLabelFontSize + spacingBetweenLabelAndValue + prospectiveValueFontSize;
|
||||
while (combinedHeight > availableHeight && currentLabelFontSize > minLabelFontSize) {
|
||||
currentLabelFontSize--;
|
||||
prospectiveValueFontSize = Math.max(
|
||||
minValueFontSize,
|
||||
Math.min(originalValueRelFontSize, Math.round(currentLabelFontSize * valueScaleFactor))
|
||||
);
|
||||
if (prospectiveValueFontSize < minValueFontSize && currentLabelFontSize === minLabelFontSize) {
|
||||
break;
|
||||
}
|
||||
self.style("font-size", `${currentLabelFontSize}px`);
|
||||
combinedHeight = currentLabelFontSize + spacingBetweenLabelAndValue + prospectiveValueFontSize;
|
||||
if (prospectiveValueFontSize <= minValueFontSize && combinedHeight > availableHeight) {
|
||||
}
|
||||
}
|
||||
self.style("font-size", `${currentLabelFontSize}px`);
|
||||
if (textNode.getComputedTextLength() > availableWidth || currentLabelFontSize < minLabelFontSize || availableHeight < currentLabelFontSize) {
|
||||
self.style("display", "none");
|
||||
}
|
||||
});
|
||||
if (config.showValues !== false) {
|
||||
const leafValues = cell.append("text").attr("class", "treemapValue").attr("x", (d) => (d.x1 - d.x0) / 2).attr("y", function(d) {
|
||||
return (d.y1 - d.y0) / 2;
|
||||
}).attr("style", (d) => {
|
||||
const labelStyles = "text-anchor: middle; dominant-baseline: hanging; font-size: 28px;fill:" + colorScaleLabel(d.data.name) + ";";
|
||||
const styles = styles2String({ cssCompiledStyles: d.data.cssCompiledStyles });
|
||||
return labelStyles + styles.labelStyles.replace("color:", "fill:");
|
||||
}).attr("clip-path", (_d, i) => `url(#clip-${id}-${i})`).text((d) => d.value ? valueFormat(d.value) : "");
|
||||
leafValues.each(function(d) {
|
||||
const valueTextElement = select_default(this);
|
||||
const parentCellNode = this.parentNode;
|
||||
if (!parentCellNode) {
|
||||
valueTextElement.style("display", "none");
|
||||
return;
|
||||
}
|
||||
const labelElement = select_default(parentCellNode).select(".treemapLabel");
|
||||
if (labelElement.empty() || labelElement.style("display") === "none") {
|
||||
valueTextElement.style("display", "none");
|
||||
return;
|
||||
}
|
||||
const finalLabelFontSize = parseFloat(labelElement.style("font-size"));
|
||||
const originalValueFontSize = 28;
|
||||
const valueScaleFactor = 0.6;
|
||||
const minValueFontSize = 6;
|
||||
const spacingBetweenLabelAndValue = 2;
|
||||
const actualValueFontSize = Math.max(
|
||||
minValueFontSize,
|
||||
Math.min(originalValueFontSize, Math.round(finalLabelFontSize * valueScaleFactor))
|
||||
);
|
||||
valueTextElement.style("font-size", `${actualValueFontSize}px`);
|
||||
const labelCenterY = (d.y1 - d.y0) / 2;
|
||||
const valueTopActualY = labelCenterY + finalLabelFontSize / 2 + spacingBetweenLabelAndValue;
|
||||
valueTextElement.attr("y", valueTopActualY);
|
||||
const nodeWidth = d.x1 - d.x0;
|
||||
const nodeTotalHeight = d.y1 - d.y0;
|
||||
const cellBottomPadding = 4;
|
||||
const maxValueBottomY = nodeTotalHeight - cellBottomPadding;
|
||||
const availableWidthForValue = nodeWidth - 2 * 4;
|
||||
if (valueTextElement.node().getComputedTextLength() > availableWidthForValue || valueTopActualY + actualValueFontSize > maxValueBottomY || actualValueFontSize < minValueFontSize) {
|
||||
valueTextElement.style("display", "none");
|
||||
} else {
|
||||
valueTextElement.style("display", null);
|
||||
}
|
||||
});
|
||||
}
|
||||
const diagramPadding = config.diagramPadding ?? 8;
|
||||
setupViewPortForSVG(svg, diagramPadding, "flowchart", (config == null ? void 0 : config.useMaxWidth) || false);
|
||||
}, "draw");
|
||||
var getClasses = __name(function(_text, diagramObj) {
|
||||
return diagramObj.db.getClasses();
|
||||
}, "getClasses");
|
||||
var renderer = { draw, getClasses };
|
||||
var defaultTreemapStyleOptions = {
|
||||
sectionStrokeColor: "black",
|
||||
sectionStrokeWidth: "1",
|
||||
sectionFillColor: "#efefef",
|
||||
leafStrokeColor: "black",
|
||||
leafStrokeWidth: "1",
|
||||
leafFillColor: "#efefef",
|
||||
labelFontSize: "12px",
|
||||
valueFontSize: "10px",
|
||||
titleFontSize: "14px"
|
||||
};
|
||||
var getStyles = __name(({
|
||||
treemap: treemap2
|
||||
} = {}) => {
|
||||
const defaultThemeVariables = getThemeVariables3();
|
||||
const currentConfig = getConfig();
|
||||
const themeVariables = cleanAndMerge(defaultThemeVariables, currentConfig.themeVariables);
|
||||
const options = cleanAndMerge(defaultTreemapStyleOptions, treemap2);
|
||||
const titleColor = options.titleColor ?? themeVariables.titleColor;
|
||||
const labelColor = options.labelColor ?? themeVariables.textColor;
|
||||
const valueColor = options.valueColor ?? themeVariables.textColor;
|
||||
return `
|
||||
.treemapNode.section {
|
||||
stroke: ${options.sectionStrokeColor};
|
||||
stroke-width: ${options.sectionStrokeWidth};
|
||||
fill: ${options.sectionFillColor};
|
||||
}
|
||||
.treemapNode.leaf {
|
||||
stroke: ${options.leafStrokeColor};
|
||||
stroke-width: ${options.leafStrokeWidth};
|
||||
fill: ${options.leafFillColor};
|
||||
}
|
||||
.treemapLabel {
|
||||
fill: ${labelColor};
|
||||
font-size: ${options.labelFontSize};
|
||||
}
|
||||
.treemapValue {
|
||||
fill: ${valueColor};
|
||||
font-size: ${options.valueFontSize};
|
||||
}
|
||||
.treemapTitle {
|
||||
fill: ${titleColor};
|
||||
font-size: ${options.titleFontSize};
|
||||
}
|
||||
`;
|
||||
}, "getStyles");
|
||||
var styles_default = getStyles;
|
||||
var diagram = {
|
||||
parser,
|
||||
get db() {
|
||||
return new TreeMapDB();
|
||||
},
|
||||
renderer,
|
||||
styles: styles_default
|
||||
};
|
||||
export {
|
||||
diagram
|
||||
};
|
||||
//# sourceMappingURL=diagram-G4DWMVQ6-HUNNRCTF.js.map
|
||||
-7
File diff suppressed because one or more lines are too long
-349
@@ -1,349 +0,0 @@
|
||||
import {
|
||||
populateCommonDb
|
||||
} from "./chunk-BEGFPAJS.js";
|
||||
import {
|
||||
parse
|
||||
} from "./chunk-ZO353HVL.js";
|
||||
import "./chunk-SHHXTPWA.js";
|
||||
import "./chunk-JLNTX6TF.js";
|
||||
import "./chunk-IELG6YWI.js";
|
||||
import "./chunk-ZOQ3FUUK.js";
|
||||
import "./chunk-TAVNOOKD.js";
|
||||
import "./chunk-5D6MANWW.js";
|
||||
import "./chunk-E3W5VJ2T.js";
|
||||
import "./chunk-JH6V2QOE.js";
|
||||
import "./chunk-QLH66CIT.js";
|
||||
import "./chunk-S4AGLBPD.js";
|
||||
import "./chunk-K3ORWWMK.js";
|
||||
import {
|
||||
selectSvgElement
|
||||
} from "./chunk-QBIGODNM.js";
|
||||
import {
|
||||
cleanAndMerge
|
||||
} from "./chunk-3QKV3V7V.js";
|
||||
import "./chunk-MOBZPS7F.js";
|
||||
import {
|
||||
clear,
|
||||
configureSvgSize,
|
||||
defaultConfig_default,
|
||||
getAccDescription,
|
||||
getAccTitle,
|
||||
getConfig,
|
||||
getDiagramTitle,
|
||||
getThemeVariables3,
|
||||
setAccDescription,
|
||||
setAccTitle,
|
||||
setDiagramTitle
|
||||
} from "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name,
|
||||
log
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import "./chunk-BQ2Z5GT2.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/diagram-MMDJMWI5.mjs
|
||||
var defaultOptions = {
|
||||
showLegend: true,
|
||||
ticks: 5,
|
||||
max: null,
|
||||
min: 0,
|
||||
graticule: "circle"
|
||||
};
|
||||
var defaultRadarData = {
|
||||
axes: [],
|
||||
curves: [],
|
||||
options: defaultOptions
|
||||
};
|
||||
var data = structuredClone(defaultRadarData);
|
||||
var DEFAULT_RADAR_CONFIG = defaultConfig_default.radar;
|
||||
var getConfig2 = __name(() => {
|
||||
const config = cleanAndMerge({
|
||||
...DEFAULT_RADAR_CONFIG,
|
||||
...getConfig().radar
|
||||
});
|
||||
return config;
|
||||
}, "getConfig");
|
||||
var getAxes = __name(() => data.axes, "getAxes");
|
||||
var getCurves = __name(() => data.curves, "getCurves");
|
||||
var getOptions = __name(() => data.options, "getOptions");
|
||||
var setAxes = __name((axes) => {
|
||||
data.axes = axes.map((axis) => {
|
||||
return {
|
||||
name: axis.name,
|
||||
label: axis.label ?? axis.name
|
||||
};
|
||||
});
|
||||
}, "setAxes");
|
||||
var setCurves = __name((curves) => {
|
||||
data.curves = curves.map((curve) => {
|
||||
return {
|
||||
name: curve.name,
|
||||
label: curve.label ?? curve.name,
|
||||
entries: computeCurveEntries(curve.entries)
|
||||
};
|
||||
});
|
||||
}, "setCurves");
|
||||
var computeCurveEntries = __name((entries) => {
|
||||
if (entries[0].axis == void 0) {
|
||||
return entries.map((entry) => entry.value);
|
||||
}
|
||||
const axes = getAxes();
|
||||
if (axes.length === 0) {
|
||||
throw new Error("Axes must be populated before curves for reference entries");
|
||||
}
|
||||
return axes.map((axis) => {
|
||||
const entry = entries.find((entry2) => {
|
||||
var _a;
|
||||
return ((_a = entry2.axis) == null ? void 0 : _a.$refText) === axis.name;
|
||||
});
|
||||
if (entry === void 0) {
|
||||
throw new Error("Missing entry for axis " + axis.label);
|
||||
}
|
||||
return entry.value;
|
||||
});
|
||||
}, "computeCurveEntries");
|
||||
var setOptions = __name((options) => {
|
||||
var _a, _b, _c, _d, _e;
|
||||
const optionMap = options.reduce(
|
||||
(acc, option) => {
|
||||
acc[option.name] = option;
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
data.options = {
|
||||
showLegend: ((_a = optionMap.showLegend) == null ? void 0 : _a.value) ?? defaultOptions.showLegend,
|
||||
ticks: ((_b = optionMap.ticks) == null ? void 0 : _b.value) ?? defaultOptions.ticks,
|
||||
max: ((_c = optionMap.max) == null ? void 0 : _c.value) ?? defaultOptions.max,
|
||||
min: ((_d = optionMap.min) == null ? void 0 : _d.value) ?? defaultOptions.min,
|
||||
graticule: ((_e = optionMap.graticule) == null ? void 0 : _e.value) ?? defaultOptions.graticule
|
||||
};
|
||||
}, "setOptions");
|
||||
var clear2 = __name(() => {
|
||||
clear();
|
||||
data = structuredClone(defaultRadarData);
|
||||
}, "clear");
|
||||
var db = {
|
||||
getAxes,
|
||||
getCurves,
|
||||
getOptions,
|
||||
setAxes,
|
||||
setCurves,
|
||||
setOptions,
|
||||
getConfig: getConfig2,
|
||||
clear: clear2,
|
||||
setAccTitle,
|
||||
getAccTitle,
|
||||
setDiagramTitle,
|
||||
getDiagramTitle,
|
||||
getAccDescription,
|
||||
setAccDescription
|
||||
};
|
||||
var populate = __name((ast) => {
|
||||
populateCommonDb(ast, db);
|
||||
const { axes, curves, options } = ast;
|
||||
db.setAxes(axes);
|
||||
db.setCurves(curves);
|
||||
db.setOptions(options);
|
||||
}, "populate");
|
||||
var parser = {
|
||||
parse: __name(async (input) => {
|
||||
const ast = await parse("radar", input);
|
||||
log.debug(ast);
|
||||
populate(ast);
|
||||
}, "parse")
|
||||
};
|
||||
var draw = __name((_text, id, _version, diagram2) => {
|
||||
const db2 = diagram2.db;
|
||||
const axes = db2.getAxes();
|
||||
const curves = db2.getCurves();
|
||||
const options = db2.getOptions();
|
||||
const config = db2.getConfig();
|
||||
const title = db2.getDiagramTitle();
|
||||
const svg = selectSvgElement(id);
|
||||
const g = drawFrame(svg, config);
|
||||
const maxValue = options.max ?? Math.max(...curves.map((curve) => Math.max(...curve.entries)));
|
||||
const minValue = options.min;
|
||||
const radius = Math.min(config.width, config.height) / 2;
|
||||
drawGraticule(g, axes, radius, options.ticks, options.graticule);
|
||||
drawAxes(g, axes, radius, config);
|
||||
drawCurves(g, axes, curves, minValue, maxValue, options.graticule, config);
|
||||
drawLegend(g, curves, options.showLegend, config);
|
||||
g.append("text").attr("class", "radarTitle").text(title).attr("x", 0).attr("y", -config.height / 2 - config.marginTop);
|
||||
}, "draw");
|
||||
var drawFrame = __name((svg, config) => {
|
||||
const totalWidth = config.width + config.marginLeft + config.marginRight;
|
||||
const totalHeight = config.height + config.marginTop + config.marginBottom;
|
||||
const center = {
|
||||
x: config.marginLeft + config.width / 2,
|
||||
y: config.marginTop + config.height / 2
|
||||
};
|
||||
configureSvgSize(svg, totalHeight, totalWidth, config.useMaxWidth ?? true);
|
||||
svg.attr("viewBox", `0 0 ${totalWidth} ${totalHeight}`);
|
||||
return svg.append("g").attr("transform", `translate(${center.x}, ${center.y})`);
|
||||
}, "drawFrame");
|
||||
var drawGraticule = __name((g, axes, radius, ticks, graticule) => {
|
||||
if (graticule === "circle") {
|
||||
for (let i = 0; i < ticks; i++) {
|
||||
const r = radius * (i + 1) / ticks;
|
||||
g.append("circle").attr("r", r).attr("class", "radarGraticule");
|
||||
}
|
||||
} else if (graticule === "polygon") {
|
||||
const numAxes = axes.length;
|
||||
for (let i = 0; i < ticks; i++) {
|
||||
const r = radius * (i + 1) / ticks;
|
||||
const points = axes.map((_, j) => {
|
||||
const angle = 2 * j * Math.PI / numAxes - Math.PI / 2;
|
||||
const x = r * Math.cos(angle);
|
||||
const y = r * Math.sin(angle);
|
||||
return `${x},${y}`;
|
||||
}).join(" ");
|
||||
g.append("polygon").attr("points", points).attr("class", "radarGraticule");
|
||||
}
|
||||
}
|
||||
}, "drawGraticule");
|
||||
var drawAxes = __name((g, axes, radius, config) => {
|
||||
const numAxes = axes.length;
|
||||
for (let i = 0; i < numAxes; i++) {
|
||||
const label = axes[i].label;
|
||||
const angle = 2 * i * Math.PI / numAxes - Math.PI / 2;
|
||||
g.append("line").attr("x1", 0).attr("y1", 0).attr("x2", radius * config.axisScaleFactor * Math.cos(angle)).attr("y2", radius * config.axisScaleFactor * Math.sin(angle)).attr("class", "radarAxisLine");
|
||||
g.append("text").text(label).attr("x", radius * config.axisLabelFactor * Math.cos(angle)).attr("y", radius * config.axisLabelFactor * Math.sin(angle)).attr("class", "radarAxisLabel");
|
||||
}
|
||||
}, "drawAxes");
|
||||
function drawCurves(g, axes, curves, minValue, maxValue, graticule, config) {
|
||||
const numAxes = axes.length;
|
||||
const radius = Math.min(config.width, config.height) / 2;
|
||||
curves.forEach((curve, index) => {
|
||||
if (curve.entries.length !== numAxes) {
|
||||
return;
|
||||
}
|
||||
const points = curve.entries.map((entry, i) => {
|
||||
const angle = 2 * Math.PI * i / numAxes - Math.PI / 2;
|
||||
const r = relativeRadius(entry, minValue, maxValue, radius);
|
||||
const x = r * Math.cos(angle);
|
||||
const y = r * Math.sin(angle);
|
||||
return { x, y };
|
||||
});
|
||||
if (graticule === "circle") {
|
||||
g.append("path").attr("d", closedRoundCurve(points, config.curveTension)).attr("class", `radarCurve-${index}`);
|
||||
} else if (graticule === "polygon") {
|
||||
g.append("polygon").attr("points", points.map((p) => `${p.x},${p.y}`).join(" ")).attr("class", `radarCurve-${index}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
__name(drawCurves, "drawCurves");
|
||||
function relativeRadius(value, minValue, maxValue, radius) {
|
||||
const clippedValue = Math.min(Math.max(value, minValue), maxValue);
|
||||
return radius * (clippedValue - minValue) / (maxValue - minValue);
|
||||
}
|
||||
__name(relativeRadius, "relativeRadius");
|
||||
function closedRoundCurve(points, tension) {
|
||||
const numPoints = points.length;
|
||||
let d = `M${points[0].x},${points[0].y}`;
|
||||
for (let i = 0; i < numPoints; i++) {
|
||||
const p0 = points[(i - 1 + numPoints) % numPoints];
|
||||
const p1 = points[i];
|
||||
const p2 = points[(i + 1) % numPoints];
|
||||
const p3 = points[(i + 2) % numPoints];
|
||||
const cp1 = {
|
||||
x: p1.x + (p2.x - p0.x) * tension,
|
||||
y: p1.y + (p2.y - p0.y) * tension
|
||||
};
|
||||
const cp2 = {
|
||||
x: p2.x - (p3.x - p1.x) * tension,
|
||||
y: p2.y - (p3.y - p1.y) * tension
|
||||
};
|
||||
d += ` C${cp1.x},${cp1.y} ${cp2.x},${cp2.y} ${p2.x},${p2.y}`;
|
||||
}
|
||||
return `${d} Z`;
|
||||
}
|
||||
__name(closedRoundCurve, "closedRoundCurve");
|
||||
function drawLegend(g, curves, showLegend, config) {
|
||||
if (!showLegend) {
|
||||
return;
|
||||
}
|
||||
const legendX = (config.width / 2 + config.marginRight) * 3 / 4;
|
||||
const legendY = -(config.height / 2 + config.marginTop) * 3 / 4;
|
||||
const lineHeight = 20;
|
||||
curves.forEach((curve, index) => {
|
||||
const itemGroup = g.append("g").attr("transform", `translate(${legendX}, ${legendY + index * lineHeight})`);
|
||||
itemGroup.append("rect").attr("width", 12).attr("height", 12).attr("class", `radarLegendBox-${index}`);
|
||||
itemGroup.append("text").attr("x", 16).attr("y", 0).attr("class", "radarLegendText").text(curve.label);
|
||||
});
|
||||
}
|
||||
__name(drawLegend, "drawLegend");
|
||||
var renderer = { draw };
|
||||
var genIndexStyles = __name((themeVariables, radarOptions) => {
|
||||
let sections = "";
|
||||
for (let i = 0; i < themeVariables.THEME_COLOR_LIMIT; i++) {
|
||||
const indexColor = themeVariables[`cScale${i}`];
|
||||
sections += `
|
||||
.radarCurve-${i} {
|
||||
color: ${indexColor};
|
||||
fill: ${indexColor};
|
||||
fill-opacity: ${radarOptions.curveOpacity};
|
||||
stroke: ${indexColor};
|
||||
stroke-width: ${radarOptions.curveStrokeWidth};
|
||||
}
|
||||
.radarLegendBox-${i} {
|
||||
fill: ${indexColor};
|
||||
fill-opacity: ${radarOptions.curveOpacity};
|
||||
stroke: ${indexColor};
|
||||
}
|
||||
`;
|
||||
}
|
||||
return sections;
|
||||
}, "genIndexStyles");
|
||||
var buildRadarStyleOptions = __name((radar) => {
|
||||
const defaultThemeVariables = getThemeVariables3();
|
||||
const currentConfig = getConfig();
|
||||
const themeVariables = cleanAndMerge(defaultThemeVariables, currentConfig.themeVariables);
|
||||
const radarOptions = cleanAndMerge(themeVariables.radar, radar);
|
||||
return { themeVariables, radarOptions };
|
||||
}, "buildRadarStyleOptions");
|
||||
var styles = __name(({ radar } = {}) => {
|
||||
const { themeVariables, radarOptions } = buildRadarStyleOptions(radar);
|
||||
return `
|
||||
.radarTitle {
|
||||
font-size: ${themeVariables.fontSize};
|
||||
color: ${themeVariables.titleColor};
|
||||
dominant-baseline: hanging;
|
||||
text-anchor: middle;
|
||||
}
|
||||
.radarAxisLine {
|
||||
stroke: ${radarOptions.axisColor};
|
||||
stroke-width: ${radarOptions.axisStrokeWidth};
|
||||
}
|
||||
.radarAxisLabel {
|
||||
dominant-baseline: middle;
|
||||
text-anchor: middle;
|
||||
font-size: ${radarOptions.axisLabelFontSize}px;
|
||||
color: ${radarOptions.axisColor};
|
||||
}
|
||||
.radarGraticule {
|
||||
fill: ${radarOptions.graticuleColor};
|
||||
fill-opacity: ${radarOptions.graticuleOpacity};
|
||||
stroke: ${radarOptions.graticuleColor};
|
||||
stroke-width: ${radarOptions.graticuleStrokeWidth};
|
||||
}
|
||||
.radarLegendText {
|
||||
text-anchor: start;
|
||||
font-size: ${radarOptions.legendFontSize}px;
|
||||
dominant-baseline: hanging;
|
||||
}
|
||||
${genIndexStyles(themeVariables, radarOptions)}
|
||||
`;
|
||||
}, "styles");
|
||||
var diagram = {
|
||||
parser,
|
||||
db,
|
||||
renderer,
|
||||
styles
|
||||
};
|
||||
export {
|
||||
diagram
|
||||
};
|
||||
//# sourceMappingURL=diagram-MMDJMWI5-NZUC24PO.js.map
|
||||
-7
File diff suppressed because one or more lines are too long
-254
@@ -1,254 +0,0 @@
|
||||
import {
|
||||
populateCommonDb
|
||||
} from "./chunk-BEGFPAJS.js";
|
||||
import {
|
||||
parse
|
||||
} from "./chunk-ZO353HVL.js";
|
||||
import "./chunk-SHHXTPWA.js";
|
||||
import "./chunk-JLNTX6TF.js";
|
||||
import "./chunk-IELG6YWI.js";
|
||||
import "./chunk-ZOQ3FUUK.js";
|
||||
import "./chunk-TAVNOOKD.js";
|
||||
import "./chunk-5D6MANWW.js";
|
||||
import "./chunk-E3W5VJ2T.js";
|
||||
import "./chunk-JH6V2QOE.js";
|
||||
import "./chunk-QLH66CIT.js";
|
||||
import "./chunk-S4AGLBPD.js";
|
||||
import "./chunk-K3ORWWMK.js";
|
||||
import {
|
||||
selectSvgElement
|
||||
} from "./chunk-QBIGODNM.js";
|
||||
import {
|
||||
cleanAndMerge
|
||||
} from "./chunk-3QKV3V7V.js";
|
||||
import "./chunk-MOBZPS7F.js";
|
||||
import {
|
||||
clear,
|
||||
configureSvgSize,
|
||||
defaultConfig_default,
|
||||
getAccDescription,
|
||||
getAccTitle,
|
||||
getConfig,
|
||||
getDiagramTitle,
|
||||
setAccDescription,
|
||||
setAccTitle,
|
||||
setDiagramTitle
|
||||
} from "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name,
|
||||
log
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import "./chunk-BQ2Z5GT2.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/diagram-TYMM5635.mjs
|
||||
var DEFAULT_PACKET_CONFIG = defaultConfig_default.packet;
|
||||
var _a;
|
||||
var PacketDB = (_a = class {
|
||||
constructor() {
|
||||
this.packet = [];
|
||||
this.setAccTitle = setAccTitle;
|
||||
this.getAccTitle = getAccTitle;
|
||||
this.setDiagramTitle = setDiagramTitle;
|
||||
this.getDiagramTitle = getDiagramTitle;
|
||||
this.getAccDescription = getAccDescription;
|
||||
this.setAccDescription = setAccDescription;
|
||||
}
|
||||
getConfig() {
|
||||
const config = cleanAndMerge({
|
||||
...DEFAULT_PACKET_CONFIG,
|
||||
...getConfig().packet
|
||||
});
|
||||
if (config.showBits) {
|
||||
config.paddingY += 10;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
getPacket() {
|
||||
return this.packet;
|
||||
}
|
||||
pushWord(word) {
|
||||
if (word.length > 0) {
|
||||
this.packet.push(word);
|
||||
}
|
||||
}
|
||||
clear() {
|
||||
clear();
|
||||
this.packet = [];
|
||||
}
|
||||
}, __name(_a, "PacketDB"), _a);
|
||||
var maxPacketSize = 1e4;
|
||||
var populate = __name((ast, db) => {
|
||||
populateCommonDb(ast, db);
|
||||
let lastBit = -1;
|
||||
let word = [];
|
||||
let row = 1;
|
||||
const { bitsPerRow } = db.getConfig();
|
||||
for (let { start, end, bits, label } of ast.blocks) {
|
||||
if (start !== void 0 && end !== void 0 && end < start) {
|
||||
throw new Error(`Packet block ${start} - ${end} is invalid. End must be greater than start.`);
|
||||
}
|
||||
start ?? (start = lastBit + 1);
|
||||
if (start !== lastBit + 1) {
|
||||
throw new Error(
|
||||
`Packet block ${start} - ${end ?? start} is not contiguous. It should start from ${lastBit + 1}.`
|
||||
);
|
||||
}
|
||||
if (bits === 0) {
|
||||
throw new Error(`Packet block ${start} is invalid. Cannot have a zero bit field.`);
|
||||
}
|
||||
end ?? (end = start + (bits ?? 1) - 1);
|
||||
bits ?? (bits = end - start + 1);
|
||||
lastBit = end;
|
||||
log.debug(`Packet block ${start} - ${lastBit} with label ${label}`);
|
||||
while (word.length <= bitsPerRow + 1 && db.getPacket().length < maxPacketSize) {
|
||||
const [block, nextBlock] = getNextFittingBlock({ start, end, bits, label }, row, bitsPerRow);
|
||||
word.push(block);
|
||||
if (block.end + 1 === row * bitsPerRow) {
|
||||
db.pushWord(word);
|
||||
word = [];
|
||||
row++;
|
||||
}
|
||||
if (!nextBlock) {
|
||||
break;
|
||||
}
|
||||
({ start, end, bits, label } = nextBlock);
|
||||
}
|
||||
}
|
||||
db.pushWord(word);
|
||||
}, "populate");
|
||||
var getNextFittingBlock = __name((block, row, bitsPerRow) => {
|
||||
if (block.start === void 0) {
|
||||
throw new Error("start should have been set during first phase");
|
||||
}
|
||||
if (block.end === void 0) {
|
||||
throw new Error("end should have been set during first phase");
|
||||
}
|
||||
if (block.start > block.end) {
|
||||
throw new Error(`Block start ${block.start} is greater than block end ${block.end}.`);
|
||||
}
|
||||
if (block.end + 1 <= row * bitsPerRow) {
|
||||
return [block, void 0];
|
||||
}
|
||||
const rowEnd = row * bitsPerRow - 1;
|
||||
const rowStart = row * bitsPerRow;
|
||||
return [
|
||||
{
|
||||
start: block.start,
|
||||
end: rowEnd,
|
||||
label: block.label,
|
||||
bits: rowEnd - block.start
|
||||
},
|
||||
{
|
||||
start: rowStart,
|
||||
end: block.end,
|
||||
label: block.label,
|
||||
bits: block.end - rowStart
|
||||
}
|
||||
];
|
||||
}, "getNextFittingBlock");
|
||||
var parser = {
|
||||
// @ts-expect-error - PacketDB is not assignable to DiagramDB
|
||||
parser: { yy: void 0 },
|
||||
parse: __name(async (input) => {
|
||||
var _a2;
|
||||
const ast = await parse("packet", input);
|
||||
const db = (_a2 = parser.parser) == null ? void 0 : _a2.yy;
|
||||
if (!(db instanceof PacketDB)) {
|
||||
throw new Error(
|
||||
"parser.parser?.yy was not a PacketDB. This is due to a bug within Mermaid, please report this issue at https://github.com/mermaid-js/mermaid/issues."
|
||||
);
|
||||
}
|
||||
log.debug(ast);
|
||||
populate(ast, db);
|
||||
}, "parse")
|
||||
};
|
||||
var draw = __name((_text, id, _version, diagram2) => {
|
||||
const db = diagram2.db;
|
||||
const config = db.getConfig();
|
||||
const { rowHeight, paddingY, bitWidth, bitsPerRow } = config;
|
||||
const words = db.getPacket();
|
||||
const title = db.getDiagramTitle();
|
||||
const totalRowHeight = rowHeight + paddingY;
|
||||
const svgHeight = totalRowHeight * (words.length + 1) - (title ? 0 : rowHeight);
|
||||
const svgWidth = bitWidth * bitsPerRow + 2;
|
||||
const svg = selectSvgElement(id);
|
||||
svg.attr("viewBox", `0 0 ${svgWidth} ${svgHeight}`);
|
||||
configureSvgSize(svg, svgHeight, svgWidth, config.useMaxWidth);
|
||||
for (const [word, packet] of words.entries()) {
|
||||
drawWord(svg, packet, word, config);
|
||||
}
|
||||
svg.append("text").text(title).attr("x", svgWidth / 2).attr("y", svgHeight - totalRowHeight / 2).attr("dominant-baseline", "middle").attr("text-anchor", "middle").attr("class", "packetTitle");
|
||||
}, "draw");
|
||||
var drawWord = __name((svg, word, rowNumber, { rowHeight, paddingX, paddingY, bitWidth, bitsPerRow, showBits }) => {
|
||||
const group = svg.append("g");
|
||||
const wordY = rowNumber * (rowHeight + paddingY) + paddingY;
|
||||
for (const block of word) {
|
||||
const blockX = block.start % bitsPerRow * bitWidth + 1;
|
||||
const width = (block.end - block.start + 1) * bitWidth - paddingX;
|
||||
group.append("rect").attr("x", blockX).attr("y", wordY).attr("width", width).attr("height", rowHeight).attr("class", "packetBlock");
|
||||
group.append("text").attr("x", blockX + width / 2).attr("y", wordY + rowHeight / 2).attr("class", "packetLabel").attr("dominant-baseline", "middle").attr("text-anchor", "middle").text(block.label);
|
||||
if (!showBits) {
|
||||
continue;
|
||||
}
|
||||
const isSingleBlock = block.end === block.start;
|
||||
const bitNumberY = wordY - 2;
|
||||
group.append("text").attr("x", blockX + (isSingleBlock ? width / 2 : 0)).attr("y", bitNumberY).attr("class", "packetByte start").attr("dominant-baseline", "auto").attr("text-anchor", isSingleBlock ? "middle" : "start").text(block.start);
|
||||
if (!isSingleBlock) {
|
||||
group.append("text").attr("x", blockX + width).attr("y", bitNumberY).attr("class", "packetByte end").attr("dominant-baseline", "auto").attr("text-anchor", "end").text(block.end);
|
||||
}
|
||||
}
|
||||
}, "drawWord");
|
||||
var renderer = { draw };
|
||||
var defaultPacketStyleOptions = {
|
||||
byteFontSize: "10px",
|
||||
startByteColor: "black",
|
||||
endByteColor: "black",
|
||||
labelColor: "black",
|
||||
labelFontSize: "12px",
|
||||
titleColor: "black",
|
||||
titleFontSize: "14px",
|
||||
blockStrokeColor: "black",
|
||||
blockStrokeWidth: "1",
|
||||
blockFillColor: "#efefef"
|
||||
};
|
||||
var styles = __name(({ packet } = {}) => {
|
||||
const options = cleanAndMerge(defaultPacketStyleOptions, packet);
|
||||
return `
|
||||
.packetByte {
|
||||
font-size: ${options.byteFontSize};
|
||||
}
|
||||
.packetByte.start {
|
||||
fill: ${options.startByteColor};
|
||||
}
|
||||
.packetByte.end {
|
||||
fill: ${options.endByteColor};
|
||||
}
|
||||
.packetLabel {
|
||||
fill: ${options.labelColor};
|
||||
font-size: ${options.labelFontSize};
|
||||
}
|
||||
.packetTitle {
|
||||
fill: ${options.titleColor};
|
||||
font-size: ${options.titleFontSize};
|
||||
}
|
||||
.packetBlock {
|
||||
stroke: ${options.blockStrokeColor};
|
||||
stroke-width: ${options.blockStrokeWidth};
|
||||
fill: ${options.blockFillColor};
|
||||
}
|
||||
`;
|
||||
}, "styles");
|
||||
var diagram = {
|
||||
parser,
|
||||
get db() {
|
||||
return new PacketDB();
|
||||
},
|
||||
renderer,
|
||||
styles
|
||||
};
|
||||
export {
|
||||
diagram
|
||||
};
|
||||
//# sourceMappingURL=diagram-TYMM5635-Q3N53YW4.js.map
|
||||
-7
File diff suppressed because one or more lines are too long
-1348
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-2506
File diff suppressed because one or more lines are too long
-7
File diff suppressed because one or more lines are too long
-2654
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-1957
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-59
@@ -1,59 +0,0 @@
|
||||
import {
|
||||
parse
|
||||
} from "./chunk-ZO353HVL.js";
|
||||
import "./chunk-SHHXTPWA.js";
|
||||
import "./chunk-JLNTX6TF.js";
|
||||
import "./chunk-IELG6YWI.js";
|
||||
import "./chunk-ZOQ3FUUK.js";
|
||||
import "./chunk-TAVNOOKD.js";
|
||||
import "./chunk-5D6MANWW.js";
|
||||
import "./chunk-E3W5VJ2T.js";
|
||||
import "./chunk-JH6V2QOE.js";
|
||||
import "./chunk-QLH66CIT.js";
|
||||
import "./chunk-S4AGLBPD.js";
|
||||
import "./chunk-K3ORWWMK.js";
|
||||
import {
|
||||
selectSvgElement
|
||||
} from "./chunk-QBIGODNM.js";
|
||||
import {
|
||||
configureSvgSize
|
||||
} from "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name,
|
||||
log
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import "./chunk-BQ2Z5GT2.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/infoDiagram-42DDH7IO.mjs
|
||||
var parser = {
|
||||
parse: __name(async (input) => {
|
||||
const ast = await parse("info", input);
|
||||
log.debug(ast);
|
||||
}, "parse")
|
||||
};
|
||||
var DEFAULT_INFO_DB = {
|
||||
version: "11.14.0" + (true ? "" : "-tiny")
|
||||
};
|
||||
var getVersion = __name(() => DEFAULT_INFO_DB.version, "getVersion");
|
||||
var db = {
|
||||
getVersion
|
||||
};
|
||||
var draw = __name((text, id, version) => {
|
||||
log.debug("rendering info diagram\n" + text);
|
||||
const svg = selectSvgElement(id);
|
||||
configureSvgSize(svg, 100, 400, true);
|
||||
const group = svg.append("g");
|
||||
group.append("text").attr("x", 100).attr("y", 40).attr("class", "version").attr("font-size", 32).style("text-anchor", "middle").text(`v${version}`);
|
||||
}, "draw");
|
||||
var renderer = { draw };
|
||||
var diagram = {
|
||||
parser,
|
||||
db,
|
||||
renderer
|
||||
};
|
||||
export {
|
||||
diagram
|
||||
};
|
||||
//# sourceMappingURL=infoDiagram-42DDH7IO-WFU564PT.js.map
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../../mermaid/dist/chunks/mermaid.core/infoDiagram-42DDH7IO.mjs"],
|
||||
"sourcesContent": ["import {\n selectSvgElement\n} from \"./chunk-426QAEUC.mjs\";\nimport {\n configureSvgSize\n} from \"./chunk-ICPOFSXX.mjs\";\nimport {\n __name,\n log\n} from \"./chunk-AGHRB4JF.mjs\";\n\n// src/diagrams/info/infoParser.ts\nimport { parse } from \"@mermaid-js/parser\";\nvar parser = {\n parse: /* @__PURE__ */ __name(async (input) => {\n const ast = await parse(\"info\", input);\n log.debug(ast);\n }, \"parse\")\n};\n\n// src/diagrams/info/infoDb.ts\nvar DEFAULT_INFO_DB = {\n version: \"11.14.0\" + (true ? \"\" : \"-tiny\")\n};\nvar getVersion = /* @__PURE__ */ __name(() => DEFAULT_INFO_DB.version, \"getVersion\");\nvar db = {\n getVersion\n};\n\n// src/diagrams/info/infoRenderer.ts\nvar draw = /* @__PURE__ */ __name((text, id, version) => {\n log.debug(\"rendering info diagram\\n\" + text);\n const svg = selectSvgElement(id);\n configureSvgSize(svg, 100, 400, true);\n const group = svg.append(\"g\");\n group.append(\"text\").attr(\"x\", 100).attr(\"y\", 40).attr(\"class\", \"version\").attr(\"font-size\", 32).style(\"text-anchor\", \"middle\").text(`v${version}`);\n}, \"draw\");\nvar renderer = { draw };\n\n// src/diagrams/info/infoDiagram.ts\nvar diagram = {\n parser,\n db,\n renderer\n};\nexport {\n diagram\n};\n"],
|
||||
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,IAAI,SAAS;AAAA,EACX,OAAuB,OAAO,OAAO,UAAU;AAC7C,UAAM,MAAM,MAAM,MAAM,QAAQ,KAAK;AACrC,QAAI,MAAM,GAAG;AAAA,EACf,GAAG,OAAO;AACZ;AAGA,IAAI,kBAAkB;AAAA,EACpB,SAAS,aAAa,OAAO,KAAK;AACpC;AACA,IAAI,aAA6B,OAAO,MAAM,gBAAgB,SAAS,YAAY;AACnF,IAAI,KAAK;AAAA,EACP;AACF;AAGA,IAAI,OAAuB,OAAO,CAAC,MAAM,IAAI,YAAY;AACvD,MAAI,MAAM,6BAA6B,IAAI;AAC3C,QAAM,MAAM,iBAAiB,EAAE;AAC/B,mBAAiB,KAAK,KAAK,KAAK,IAAI;AACpC,QAAM,QAAQ,IAAI,OAAO,GAAG;AAC5B,QAAM,OAAO,MAAM,EAAE,KAAK,KAAK,GAAG,EAAE,KAAK,KAAK,EAAE,EAAE,KAAK,SAAS,SAAS,EAAE,KAAK,aAAa,EAAE,EAAE,MAAM,eAAe,QAAQ,EAAE,KAAK,IAAI,OAAO,EAAE;AACpJ,GAAG,MAAM;AACT,IAAI,WAAW,EAAE,KAAK;AAGtB,IAAI,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AACF;",
|
||||
"names": []
|
||||
}
|
||||
-1011
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-1132
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
+39
-39
@@ -1,23 +1,26 @@
|
||||
import {
|
||||
selectSvgElement
|
||||
} from "./chunk-QBIGODNM.js";
|
||||
import {
|
||||
isEmpty_default
|
||||
} from "./chunk-BQ2Z5GT2.js";
|
||||
import {
|
||||
JSON_SCHEMA,
|
||||
load
|
||||
} from "./chunk-RXFZAB4L.js";
|
||||
import {
|
||||
registerLayoutLoaders
|
||||
} from "./chunk-G5KDPKXZ.js";
|
||||
import "./chunk-QDQEHZH7.js";
|
||||
import "./chunk-IHPTUWR5.js";
|
||||
import "./chunk-DK5DI5R3.js";
|
||||
} from "./chunk-GSSDQWQG.js";
|
||||
import "./chunk-LMNIJLJF.js";
|
||||
import "./chunk-POGYG5DQ.js";
|
||||
import "./chunk-N2C52BYW.js";
|
||||
import "./chunk-MYK3ASHG.js";
|
||||
import "./chunk-IHPTUWR5.js";
|
||||
import "./chunk-LN4HZV3Y.js";
|
||||
import "./chunk-TNWHCC6S.js";
|
||||
import {
|
||||
dedent,
|
||||
registerIconPacks
|
||||
} from "./chunk-FFNMY5H5.js";
|
||||
} from "./chunk-HX7G7X5J.js";
|
||||
import {
|
||||
cleanAndMerge,
|
||||
decodeEntities,
|
||||
@@ -25,7 +28,7 @@ import {
|
||||
isDetailedError,
|
||||
removeDirectives,
|
||||
utils_default
|
||||
} from "./chunk-3QKV3V7V.js";
|
||||
} from "./chunk-GUBXVVWZ.js";
|
||||
import "./chunk-MOBZPS7F.js";
|
||||
import {
|
||||
UnknownDiagramError,
|
||||
@@ -53,16 +56,13 @@ import {
|
||||
themes_default,
|
||||
updateSiteConfig
|
||||
} from "./chunk-6YWVU24R.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import {
|
||||
__name,
|
||||
log,
|
||||
select_default,
|
||||
setLogLevel
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import {
|
||||
isEmpty_default
|
||||
} from "./chunk-BQ2Z5GT2.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/stylis/src/Enum.js
|
||||
@@ -401,7 +401,7 @@ var detector = __name((txt) => {
|
||||
return /^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/.test(txt);
|
||||
}, "detector");
|
||||
var loader = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./c4Diagram-AHTNJAMY-NWD472H5.js");
|
||||
const { diagram: diagram2 } = await import("./c4Diagram-AHTNJAMY-MDIB2U2D.js");
|
||||
return { id, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin = {
|
||||
@@ -419,7 +419,7 @@ var detector2 = __name((txt, config) => {
|
||||
return /^\s*graph/.test(txt);
|
||||
}, "detector");
|
||||
var loader2 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./flowDiagram-DWJPFMVM-FXQRIU6V.js");
|
||||
const { diagram: diagram2 } = await import("./flowDiagram-DWJPFMVM-5WOY4J6F.js");
|
||||
return { id: id2, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin2 = {
|
||||
@@ -443,7 +443,7 @@ var detector3 = __name((txt, config) => {
|
||||
return /^\s*flowchart/.test(txt);
|
||||
}, "detector");
|
||||
var loader3 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./flowDiagram-DWJPFMVM-FXQRIU6V.js");
|
||||
const { diagram: diagram2 } = await import("./flowDiagram-DWJPFMVM-5WOY4J6F.js");
|
||||
return { id: id3, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin3 = {
|
||||
@@ -457,7 +457,7 @@ var detector4 = __name((txt) => {
|
||||
return /^\s*erDiagram/.test(txt);
|
||||
}, "detector");
|
||||
var loader4 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./erDiagram-SMLLAGMA-6VRN6KCX.js");
|
||||
const { diagram: diagram2 } = await import("./erDiagram-SMLLAGMA-KSPRYYBC.js");
|
||||
return { id: id4, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin4 = {
|
||||
@@ -471,7 +471,7 @@ var detector5 = __name((txt) => {
|
||||
return /^\s*gitGraph/.test(txt);
|
||||
}, "detector");
|
||||
var loader5 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./gitGraphDiagram-UUTBAWPF-N536INYS.js");
|
||||
const { diagram: diagram2 } = await import("./gitGraphDiagram-UUTBAWPF-VBDJJKXB.js");
|
||||
return { id: id5, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin5 = {
|
||||
@@ -485,7 +485,7 @@ var detector6 = __name((txt) => {
|
||||
return /^\s*gantt/.test(txt);
|
||||
}, "detector");
|
||||
var loader6 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./ganttDiagram-T4ZO3ILL-SBGJESGM.js");
|
||||
const { diagram: diagram2 } = await import("./ganttDiagram-T4ZO3ILL-E7U5E2D3.js");
|
||||
return { id: id6, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin6 = {
|
||||
@@ -499,7 +499,7 @@ var detector7 = __name((txt) => {
|
||||
return /^\s*info/.test(txt);
|
||||
}, "detector");
|
||||
var loader7 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./infoDiagram-42DDH7IO-WFU564PT.js");
|
||||
const { diagram: diagram2 } = await import("./infoDiagram-42DDH7IO-SPOK6NRM.js");
|
||||
return { id: id7, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var info = {
|
||||
@@ -512,7 +512,7 @@ var detector8 = __name((txt) => {
|
||||
return /^\s*pie/.test(txt);
|
||||
}, "detector");
|
||||
var loader8 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./pieDiagram-DEJITSTG-PI57EMVX.js");
|
||||
const { diagram: diagram2 } = await import("./pieDiagram-DEJITSTG-B2LEWLGH.js");
|
||||
return { id: id8, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var pie = {
|
||||
@@ -539,7 +539,7 @@ var detector10 = __name((txt) => {
|
||||
return /^\s*xychart(-beta)?/.test(txt);
|
||||
}, "detector");
|
||||
var loader10 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./xychartDiagram-5P7HB3ND-LBWHJ2M7.js");
|
||||
const { diagram: diagram2 } = await import("./xychartDiagram-5P7HB3ND-TWZ3LHIN.js");
|
||||
return { id: id10, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin8 = {
|
||||
@@ -553,7 +553,7 @@ var detector11 = __name((txt) => {
|
||||
return /^\s*requirement(Diagram)?/.test(txt);
|
||||
}, "detector");
|
||||
var loader11 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./requirementDiagram-MS252O5E-26H5QBRG.js");
|
||||
const { diagram: diagram2 } = await import("./requirementDiagram-MS252O5E-45VOPIZB.js");
|
||||
return { id: id11, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin9 = {
|
||||
@@ -567,7 +567,7 @@ var detector12 = __name((txt) => {
|
||||
return /^\s*sequenceDiagram/.test(txt);
|
||||
}, "detector");
|
||||
var loader12 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./sequenceDiagram-FGHM5R23-RF522XN2.js");
|
||||
const { diagram: diagram2 } = await import("./sequenceDiagram-FGHM5R23-FE23XAP6.js");
|
||||
return { id: id12, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin10 = {
|
||||
@@ -585,7 +585,7 @@ var detector13 = __name((txt, config) => {
|
||||
return /^\s*classDiagram/.test(txt);
|
||||
}, "detector");
|
||||
var loader13 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./classDiagram-6PBFFD2Q-MPADOIGT.js");
|
||||
const { diagram: diagram2 } = await import("./classDiagram-6PBFFD2Q-ZDYBHCGS.js");
|
||||
return { id: id13, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin11 = {
|
||||
@@ -603,7 +603,7 @@ var detector14 = __name((txt, config) => {
|
||||
return /^\s*classDiagram-v2/.test(txt);
|
||||
}, "detector");
|
||||
var loader14 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./classDiagram-v2-HSJHXN6E-ZI2B5S6D.js");
|
||||
const { diagram: diagram2 } = await import("./classDiagram-v2-HSJHXN6E-X6473I6M.js");
|
||||
return { id: id14, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin12 = {
|
||||
@@ -621,7 +621,7 @@ var detector15 = __name((txt, config) => {
|
||||
return /^\s*stateDiagram/.test(txt);
|
||||
}, "detector");
|
||||
var loader15 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./stateDiagram-FHFEXIEX-DGJIBEPL.js");
|
||||
const { diagram: diagram2 } = await import("./stateDiagram-FHFEXIEX-7ATV6PPH.js");
|
||||
return { id: id15, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin13 = {
|
||||
@@ -642,7 +642,7 @@ var detector16 = __name((txt, config) => {
|
||||
return false;
|
||||
}, "detector");
|
||||
var loader16 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./stateDiagram-v2-QKLJ7IA2-KWG254M5.js");
|
||||
const { diagram: diagram2 } = await import("./stateDiagram-v2-QKLJ7IA2-7INTSFRA.js");
|
||||
return { id: id16, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin14 = {
|
||||
@@ -724,7 +724,7 @@ var detector18 = __name((txt, config = {}) => {
|
||||
return false;
|
||||
}, "detector");
|
||||
var loader18 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./flowDiagram-DWJPFMVM-FXQRIU6V.js");
|
||||
const { diagram: diagram2 } = await import("./flowDiagram-DWJPFMVM-5WOY4J6F.js");
|
||||
return { id: id18, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin16 = {
|
||||
@@ -738,7 +738,7 @@ var detector19 = __name((txt) => {
|
||||
return /^\s*timeline/.test(txt);
|
||||
}, "detector");
|
||||
var loader19 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./timeline-definition-GMOUNBTQ-MPQYWR4P.js");
|
||||
const { diagram: diagram2 } = await import("./timeline-definition-GMOUNBTQ-7EV5FJ2Q.js");
|
||||
return { id: id19, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin17 = {
|
||||
@@ -752,7 +752,7 @@ var detector20 = __name((txt) => {
|
||||
return /^\s*mindmap/.test(txt);
|
||||
}, "detector");
|
||||
var loader20 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./mindmap-definition-QFDTVHPH-34XYZ66K.js");
|
||||
const { diagram: diagram2 } = await import("./mindmap-definition-QFDTVHPH-LWJWKYOI.js");
|
||||
return { id: id20, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin18 = {
|
||||
@@ -766,7 +766,7 @@ var detector21 = __name((txt) => {
|
||||
return /^\s*kanban/.test(txt);
|
||||
}, "detector");
|
||||
var loader21 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./kanban-definition-6JOO6SKY-HLVAUPHO.js");
|
||||
const { diagram: diagram2 } = await import("./kanban-definition-6JOO6SKY-C76UIEWS.js");
|
||||
return { id: id21, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin19 = {
|
||||
@@ -794,7 +794,7 @@ var detector23 = __name((txt) => {
|
||||
return /^\s*packet(-beta)?/.test(txt);
|
||||
}, "detector");
|
||||
var loader23 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./diagram-TYMM5635-Q3N53YW4.js");
|
||||
const { diagram: diagram2 } = await import("./diagram-TYMM5635-CFW6SUOY.js");
|
||||
return { id: id23, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var packet = {
|
||||
@@ -807,7 +807,7 @@ var detector24 = __name((txt) => {
|
||||
return /^\s*radar-beta/.test(txt);
|
||||
}, "detector");
|
||||
var loader24 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./diagram-MMDJMWI5-NZUC24PO.js");
|
||||
const { diagram: diagram2 } = await import("./diagram-MMDJMWI5-H3XSHQUY.js");
|
||||
return { id: id24, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var radar = {
|
||||
@@ -820,7 +820,7 @@ var detector25 = __name((txt) => {
|
||||
return /^\s*block(-beta)?/.test(txt);
|
||||
}, "detector");
|
||||
var loader25 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./blockDiagram-DXYQGD6D-FC6IY7CP.js");
|
||||
const { diagram: diagram2 } = await import("./blockDiagram-DXYQGD6D-7IODELZG.js");
|
||||
return { id: id25, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin21 = {
|
||||
@@ -834,7 +834,7 @@ var detector26 = __name((txt) => {
|
||||
return /^\s*treeView-beta/.test(txt);
|
||||
}, "detector");
|
||||
var loader26 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./diagram-5BDNPKRD-CQ5OTDU7.js");
|
||||
const { diagram: diagram2 } = await import("./diagram-5BDNPKRD-IMF7AYPE.js");
|
||||
return { id: id26, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin22 = {
|
||||
@@ -848,7 +848,7 @@ var detector27 = __name((txt) => {
|
||||
return /^\s*architecture/.test(txt);
|
||||
}, "detector");
|
||||
var loader27 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./architectureDiagram-Q4EWVU46-RWWCHLOA.js");
|
||||
const { diagram: diagram2 } = await import("./architectureDiagram-Q4EWVU46-ORB3VMUH.js");
|
||||
return { id: id27, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var architecture = {
|
||||
@@ -862,7 +862,7 @@ var detector28 = __name((txt) => {
|
||||
return /^\s*ishikawa(-beta)?\b/i.test(txt);
|
||||
}, "detector");
|
||||
var loader28 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./ishikawaDiagram-UXIWVN3A-XGPMMOSO.js");
|
||||
const { diagram: diagram2 } = await import("./ishikawaDiagram-UXIWVN3A-OJDVWUGD.js");
|
||||
return { id: id28, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var ishikawa = {
|
||||
@@ -875,7 +875,7 @@ var detector29 = __name((txt) => {
|
||||
return /^\s*venn-beta/.test(txt);
|
||||
}, "detector");
|
||||
var loader29 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./vennDiagram-DHZGUBPP-OWCMMGRH.js");
|
||||
const { diagram: diagram2 } = await import("./vennDiagram-DHZGUBPP-6W7QQVEL.js");
|
||||
return { id: id29, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin23 = {
|
||||
@@ -889,7 +889,7 @@ var detector30 = __name((txt) => {
|
||||
return /^\s*treemap/.test(txt);
|
||||
}, "detector");
|
||||
var loader30 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./diagram-G4DWMVQ6-HUNNRCTF.js");
|
||||
const { diagram: diagram2 } = await import("./diagram-G4DWMVQ6-GQLFITVI.js");
|
||||
return { id: id30, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var treemap = {
|
||||
@@ -902,7 +902,7 @@ var detector31 = __name((text) => {
|
||||
return /^\s*wardley-beta/i.test(text);
|
||||
}, "detector");
|
||||
var loader31 = __name(async () => {
|
||||
const { diagram: diagram2 } = await import("./wardleyDiagram-NUSXRM2D-CUADBIPO.js");
|
||||
const { diagram: diagram2 } = await import("./wardleyDiagram-NUSXRM2D-FB3VHWKT.js");
|
||||
return { id: id31, diagram: diagram2 };
|
||||
}, "loader");
|
||||
var plugin24 = {
|
||||
|
||||
-1555
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-239
@@ -1,239 +0,0 @@
|
||||
import {
|
||||
populateCommonDb
|
||||
} from "./chunk-BEGFPAJS.js";
|
||||
import {
|
||||
parse
|
||||
} from "./chunk-ZO353HVL.js";
|
||||
import "./chunk-SHHXTPWA.js";
|
||||
import "./chunk-JLNTX6TF.js";
|
||||
import "./chunk-IELG6YWI.js";
|
||||
import "./chunk-ZOQ3FUUK.js";
|
||||
import "./chunk-TAVNOOKD.js";
|
||||
import "./chunk-5D6MANWW.js";
|
||||
import "./chunk-E3W5VJ2T.js";
|
||||
import "./chunk-JH6V2QOE.js";
|
||||
import "./chunk-QLH66CIT.js";
|
||||
import "./chunk-S4AGLBPD.js";
|
||||
import "./chunk-K3ORWWMK.js";
|
||||
import {
|
||||
selectSvgElement
|
||||
} from "./chunk-QBIGODNM.js";
|
||||
import {
|
||||
cleanAndMerge,
|
||||
parseFontSize
|
||||
} from "./chunk-3QKV3V7V.js";
|
||||
import "./chunk-MOBZPS7F.js";
|
||||
import {
|
||||
clear,
|
||||
configureSvgSize,
|
||||
defaultConfig_default,
|
||||
getAccDescription,
|
||||
getAccTitle,
|
||||
getConfig2,
|
||||
getDiagramTitle,
|
||||
setAccDescription,
|
||||
setAccTitle,
|
||||
setDiagramTitle
|
||||
} from "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name,
|
||||
arc_default,
|
||||
log,
|
||||
ordinal,
|
||||
pie_default
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import "./chunk-BQ2Z5GT2.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/pieDiagram-DEJITSTG.mjs
|
||||
var DEFAULT_PIE_CONFIG = defaultConfig_default.pie;
|
||||
var DEFAULT_PIE_DB = {
|
||||
sections: /* @__PURE__ */ new Map(),
|
||||
showData: false,
|
||||
config: DEFAULT_PIE_CONFIG
|
||||
};
|
||||
var sections = DEFAULT_PIE_DB.sections;
|
||||
var showData = DEFAULT_PIE_DB.showData;
|
||||
var config = structuredClone(DEFAULT_PIE_CONFIG);
|
||||
var getConfig22 = __name(() => structuredClone(config), "getConfig");
|
||||
var clear2 = __name(() => {
|
||||
sections = /* @__PURE__ */ new Map();
|
||||
showData = DEFAULT_PIE_DB.showData;
|
||||
clear();
|
||||
}, "clear");
|
||||
var addSection = __name(({ label, value }) => {
|
||||
if (value < 0) {
|
||||
throw new Error(
|
||||
`"${label}" has invalid value: ${value}. Negative values are not allowed in pie charts. All slice values must be >= 0.`
|
||||
);
|
||||
}
|
||||
if (!sections.has(label)) {
|
||||
sections.set(label, value);
|
||||
log.debug(`added new section: ${label}, with value: ${value}`);
|
||||
}
|
||||
}, "addSection");
|
||||
var getSections = __name(() => sections, "getSections");
|
||||
var setShowData = __name((toggle) => {
|
||||
showData = toggle;
|
||||
}, "setShowData");
|
||||
var getShowData = __name(() => showData, "getShowData");
|
||||
var db = {
|
||||
getConfig: getConfig22,
|
||||
clear: clear2,
|
||||
setDiagramTitle,
|
||||
getDiagramTitle,
|
||||
setAccTitle,
|
||||
getAccTitle,
|
||||
setAccDescription,
|
||||
getAccDescription,
|
||||
addSection,
|
||||
getSections,
|
||||
setShowData,
|
||||
getShowData
|
||||
};
|
||||
var populateDb = __name((ast, db2) => {
|
||||
populateCommonDb(ast, db2);
|
||||
db2.setShowData(ast.showData);
|
||||
ast.sections.map(db2.addSection);
|
||||
}, "populateDb");
|
||||
var parser = {
|
||||
parse: __name(async (input) => {
|
||||
const ast = await parse("pie", input);
|
||||
log.debug(ast);
|
||||
populateDb(ast, db);
|
||||
}, "parse")
|
||||
};
|
||||
var getStyles = __name((options) => `
|
||||
.pieCircle{
|
||||
stroke: ${options.pieStrokeColor};
|
||||
stroke-width : ${options.pieStrokeWidth};
|
||||
opacity : ${options.pieOpacity};
|
||||
}
|
||||
.pieOuterCircle{
|
||||
stroke: ${options.pieOuterStrokeColor};
|
||||
stroke-width: ${options.pieOuterStrokeWidth};
|
||||
fill: none;
|
||||
}
|
||||
.pieTitleText {
|
||||
text-anchor: middle;
|
||||
font-size: ${options.pieTitleTextSize};
|
||||
fill: ${options.pieTitleTextColor};
|
||||
font-family: ${options.fontFamily};
|
||||
}
|
||||
.slice {
|
||||
font-family: ${options.fontFamily};
|
||||
fill: ${options.pieSectionTextColor};
|
||||
font-size:${options.pieSectionTextSize};
|
||||
// fill: white;
|
||||
}
|
||||
.legend text {
|
||||
fill: ${options.pieLegendTextColor};
|
||||
font-family: ${options.fontFamily};
|
||||
font-size: ${options.pieLegendTextSize};
|
||||
}
|
||||
`, "getStyles");
|
||||
var pieStyles_default = getStyles;
|
||||
var createPieArcs = __name((sections2) => {
|
||||
const sum = [...sections2.values()].reduce((acc, val) => acc + val, 0);
|
||||
const pieData = [...sections2.entries()].map(([label, value]) => ({ label, value })).filter((d) => d.value / sum * 100 >= 1);
|
||||
const pie = pie_default().value((d) => d.value).sort(null);
|
||||
return pie(pieData);
|
||||
}, "createPieArcs");
|
||||
var draw = __name((text, id, _version, diagObj) => {
|
||||
var _a;
|
||||
log.debug("rendering pie chart\n" + text);
|
||||
const db2 = diagObj.db;
|
||||
const globalConfig = getConfig2();
|
||||
const pieConfig = cleanAndMerge(db2.getConfig(), globalConfig.pie);
|
||||
const MARGIN = 40;
|
||||
const LEGEND_RECT_SIZE = 18;
|
||||
const LEGEND_SPACING = 4;
|
||||
const height = 450;
|
||||
const pieWidth = height;
|
||||
const svg = selectSvgElement(id);
|
||||
const group = svg.append("g");
|
||||
group.attr("transform", "translate(" + pieWidth / 2 + "," + height / 2 + ")");
|
||||
const { themeVariables } = globalConfig;
|
||||
let [outerStrokeWidth] = parseFontSize(themeVariables.pieOuterStrokeWidth);
|
||||
outerStrokeWidth ?? (outerStrokeWidth = 2);
|
||||
const textPosition = pieConfig.textPosition;
|
||||
const radius = Math.min(pieWidth, height) / 2 - MARGIN;
|
||||
const arcGenerator = arc_default().innerRadius(0).outerRadius(radius);
|
||||
const labelArcGenerator = arc_default().innerRadius(radius * textPosition).outerRadius(radius * textPosition);
|
||||
group.append("circle").attr("cx", 0).attr("cy", 0).attr("r", radius + outerStrokeWidth / 2).attr("class", "pieOuterCircle");
|
||||
const sections2 = db2.getSections();
|
||||
const arcs = createPieArcs(sections2);
|
||||
const myGeneratedColors = [
|
||||
themeVariables.pie1,
|
||||
themeVariables.pie2,
|
||||
themeVariables.pie3,
|
||||
themeVariables.pie4,
|
||||
themeVariables.pie5,
|
||||
themeVariables.pie6,
|
||||
themeVariables.pie7,
|
||||
themeVariables.pie8,
|
||||
themeVariables.pie9,
|
||||
themeVariables.pie10,
|
||||
themeVariables.pie11,
|
||||
themeVariables.pie12
|
||||
];
|
||||
let sum = 0;
|
||||
sections2.forEach((section) => {
|
||||
sum += section;
|
||||
});
|
||||
const filteredArcs = arcs.filter((datum) => (datum.data.value / sum * 100).toFixed(0) !== "0");
|
||||
const color = ordinal(myGeneratedColors).domain([
|
||||
...sections2.keys()
|
||||
]);
|
||||
group.selectAll("mySlices").data(filteredArcs).enter().append("path").attr("d", arcGenerator).attr("fill", (datum) => {
|
||||
return color(datum.data.label);
|
||||
}).attr("class", "pieCircle");
|
||||
group.selectAll("mySlices").data(filteredArcs).enter().append("text").text((datum) => {
|
||||
return (datum.data.value / sum * 100).toFixed(0) + "%";
|
||||
}).attr("transform", (datum) => {
|
||||
return "translate(" + labelArcGenerator.centroid(datum) + ")";
|
||||
}).style("text-anchor", "middle").attr("class", "slice");
|
||||
const titleText = group.append("text").text(db2.getDiagramTitle()).attr("x", 0).attr("y", -(height - 50) / 2).attr("class", "pieTitleText");
|
||||
const allSectionData = [...sections2.entries()].map(([label, value]) => ({
|
||||
label,
|
||||
value
|
||||
}));
|
||||
const legend = group.selectAll(".legend").data(allSectionData).enter().append("g").attr("class", "legend").attr("transform", (_datum, index) => {
|
||||
const height2 = LEGEND_RECT_SIZE + LEGEND_SPACING;
|
||||
const offset = height2 * allSectionData.length / 2;
|
||||
const horizontal = 12 * LEGEND_RECT_SIZE;
|
||||
const vertical = index * height2 - offset;
|
||||
return "translate(" + horizontal + "," + vertical + ")";
|
||||
});
|
||||
legend.append("rect").attr("width", LEGEND_RECT_SIZE).attr("height", LEGEND_RECT_SIZE).style("fill", (d) => color(d.label)).style("stroke", (d) => color(d.label));
|
||||
legend.append("text").attr("x", LEGEND_RECT_SIZE + LEGEND_SPACING).attr("y", LEGEND_RECT_SIZE - LEGEND_SPACING).text((d) => {
|
||||
if (db2.getShowData()) {
|
||||
return `${d.label} [${d.value}]`;
|
||||
}
|
||||
return d.label;
|
||||
});
|
||||
const longestTextWidth = Math.max(
|
||||
...legend.selectAll("text").nodes().map((node) => (node == null ? void 0 : node.getBoundingClientRect().width) ?? 0)
|
||||
);
|
||||
const chartAndLegendWidth = pieWidth + MARGIN + LEGEND_RECT_SIZE + LEGEND_SPACING + longestTextWidth;
|
||||
const titleWidth = ((_a = titleText.node()) == null ? void 0 : _a.getBoundingClientRect().width) ?? 0;
|
||||
const titleLeft = pieWidth / 2 - titleWidth / 2;
|
||||
const titleRight = pieWidth / 2 + titleWidth / 2;
|
||||
const viewBoxX = Math.min(0, titleLeft);
|
||||
const viewBoxRight = Math.max(chartAndLegendWidth, titleRight);
|
||||
const totalWidth = viewBoxRight - viewBoxX;
|
||||
svg.attr("viewBox", `${viewBoxX} 0 ${totalWidth} ${height}`);
|
||||
configureSvgSize(svg, height, totalWidth, pieConfig.useMaxWidth);
|
||||
}, "draw");
|
||||
var renderer = { draw };
|
||||
var diagram = {
|
||||
parser,
|
||||
db,
|
||||
renderer,
|
||||
styles: pieStyles_default
|
||||
};
|
||||
export {
|
||||
diagram
|
||||
};
|
||||
//# sourceMappingURL=pieDiagram-DEJITSTG-PI57EMVX.js.map
|
||||
-7
File diff suppressed because one or more lines are too long
-1311
File diff suppressed because one or more lines are too long
-7
File diff suppressed because one or more lines are too long
-4663
File diff suppressed because one or more lines are too long
-7
File diff suppressed because one or more lines are too long
-495
@@ -1,495 +0,0 @@
|
||||
import {
|
||||
StateDB,
|
||||
stateDiagram_default,
|
||||
styles_default
|
||||
} from "./chunk-74EEDPU4.js";
|
||||
import {
|
||||
layout
|
||||
} from "./chunk-VXZL7VXQ.js";
|
||||
import {
|
||||
Graph
|
||||
} from "./chunk-T3HQBPEI.js";
|
||||
import "./chunk-NLS3CDEU.js";
|
||||
import "./chunk-YVBSFUGN.js";
|
||||
import "./chunk-K3ORWWMK.js";
|
||||
import "./chunk-G5KDPKXZ.js";
|
||||
import "./chunk-QDQEHZH7.js";
|
||||
import "./chunk-IHPTUWR5.js";
|
||||
import "./chunk-DK5DI5R3.js";
|
||||
import "./chunk-N2C52BYW.js";
|
||||
import "./chunk-MYK3ASHG.js";
|
||||
import "./chunk-TNWHCC6S.js";
|
||||
import "./chunk-FFNMY5H5.js";
|
||||
import {
|
||||
utils_default
|
||||
} from "./chunk-3QKV3V7V.js";
|
||||
import "./chunk-MOBZPS7F.js";
|
||||
import {
|
||||
common_default,
|
||||
configureSvgSize,
|
||||
getConfig2,
|
||||
getUrl
|
||||
} from "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name,
|
||||
basis_default,
|
||||
line_default,
|
||||
log,
|
||||
select_default
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import "./chunk-BQ2Z5GT2.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/stateDiagram-FHFEXIEX.mjs
|
||||
var drawStartState = __name((g) => g.append("circle").attr("class", "start-state").attr("r", getConfig2().state.sizeUnit).attr("cx", getConfig2().state.padding + getConfig2().state.sizeUnit).attr("cy", getConfig2().state.padding + getConfig2().state.sizeUnit), "drawStartState");
|
||||
var drawDivider = __name((g) => g.append("line").style("stroke", "grey").style("stroke-dasharray", "3").attr("x1", getConfig2().state.textHeight).attr("class", "divider").attr("x2", getConfig2().state.textHeight * 2).attr("y1", 0).attr("y2", 0), "drawDivider");
|
||||
var drawSimpleState = __name((g, stateDef) => {
|
||||
const state = g.append("text").attr("x", 2 * getConfig2().state.padding).attr("y", getConfig2().state.textHeight + 2 * getConfig2().state.padding).attr("font-size", getConfig2().state.fontSize).attr("class", "state-title").text(stateDef.id);
|
||||
const classBox = state.node().getBBox();
|
||||
g.insert("rect", ":first-child").attr("x", getConfig2().state.padding).attr("y", getConfig2().state.padding).attr("width", classBox.width + 2 * getConfig2().state.padding).attr("height", classBox.height + 2 * getConfig2().state.padding).attr("rx", getConfig2().state.radius);
|
||||
return state;
|
||||
}, "drawSimpleState");
|
||||
var drawDescrState = __name((g, stateDef) => {
|
||||
const addTspan = __name(function(textEl, txt, isFirst2) {
|
||||
const tSpan = textEl.append("tspan").attr("x", 2 * getConfig2().state.padding).text(txt);
|
||||
if (!isFirst2) {
|
||||
tSpan.attr("dy", getConfig2().state.textHeight);
|
||||
}
|
||||
}, "addTspan");
|
||||
const title = g.append("text").attr("x", 2 * getConfig2().state.padding).attr("y", getConfig2().state.textHeight + 1.3 * getConfig2().state.padding).attr("font-size", getConfig2().state.fontSize).attr("class", "state-title").text(stateDef.descriptions[0]);
|
||||
const titleBox = title.node().getBBox();
|
||||
const titleHeight = titleBox.height;
|
||||
const description = g.append("text").attr("x", getConfig2().state.padding).attr(
|
||||
"y",
|
||||
titleHeight + getConfig2().state.padding * 0.4 + getConfig2().state.dividerMargin + getConfig2().state.textHeight
|
||||
).attr("class", "state-description");
|
||||
let isFirst = true;
|
||||
let isSecond = true;
|
||||
stateDef.descriptions.forEach(function(descr) {
|
||||
if (!isFirst) {
|
||||
addTspan(description, descr, isSecond);
|
||||
isSecond = false;
|
||||
}
|
||||
isFirst = false;
|
||||
});
|
||||
const descrLine = g.append("line").attr("x1", getConfig2().state.padding).attr("y1", getConfig2().state.padding + titleHeight + getConfig2().state.dividerMargin / 2).attr("y2", getConfig2().state.padding + titleHeight + getConfig2().state.dividerMargin / 2).attr("class", "descr-divider");
|
||||
const descrBox = description.node().getBBox();
|
||||
const width = Math.max(descrBox.width, titleBox.width);
|
||||
descrLine.attr("x2", width + 3 * getConfig2().state.padding);
|
||||
g.insert("rect", ":first-child").attr("x", getConfig2().state.padding).attr("y", getConfig2().state.padding).attr("width", width + 2 * getConfig2().state.padding).attr("height", descrBox.height + titleHeight + 2 * getConfig2().state.padding).attr("rx", getConfig2().state.radius);
|
||||
return g;
|
||||
}, "drawDescrState");
|
||||
var addTitleAndBox = __name((g, stateDef, altBkg) => {
|
||||
const pad = getConfig2().state.padding;
|
||||
const dblPad = 2 * getConfig2().state.padding;
|
||||
const orgBox = g.node().getBBox();
|
||||
const orgWidth = orgBox.width;
|
||||
const orgX = orgBox.x;
|
||||
const title = g.append("text").attr("x", 0).attr("y", getConfig2().state.titleShift).attr("font-size", getConfig2().state.fontSize).attr("class", "state-title").text(stateDef.id);
|
||||
const titleBox = title.node().getBBox();
|
||||
const titleWidth = titleBox.width + dblPad;
|
||||
let width = Math.max(titleWidth, orgWidth);
|
||||
if (width === orgWidth) {
|
||||
width = width + dblPad;
|
||||
}
|
||||
let startX;
|
||||
const graphBox = g.node().getBBox();
|
||||
if (stateDef.doc) {
|
||||
}
|
||||
startX = orgX - pad;
|
||||
if (titleWidth > orgWidth) {
|
||||
startX = (orgWidth - width) / 2 + pad;
|
||||
}
|
||||
if (Math.abs(orgX - graphBox.x) < pad && titleWidth > orgWidth) {
|
||||
startX = orgX - (titleWidth - orgWidth) / 2;
|
||||
}
|
||||
const lineY = 1 - getConfig2().state.textHeight;
|
||||
g.insert("rect", ":first-child").attr("x", startX).attr("y", lineY).attr("class", altBkg ? "alt-composit" : "composit").attr("width", width).attr(
|
||||
"height",
|
||||
graphBox.height + getConfig2().state.textHeight + getConfig2().state.titleShift + 1
|
||||
).attr("rx", "0");
|
||||
title.attr("x", startX + pad);
|
||||
if (titleWidth <= orgWidth) {
|
||||
title.attr("x", orgX + (width - dblPad) / 2 - titleWidth / 2 + pad);
|
||||
}
|
||||
g.insert("rect", ":first-child").attr("x", startX).attr(
|
||||
"y",
|
||||
getConfig2().state.titleShift - getConfig2().state.textHeight - getConfig2().state.padding
|
||||
).attr("width", width).attr("height", getConfig2().state.textHeight * 3).attr("rx", getConfig2().state.radius);
|
||||
g.insert("rect", ":first-child").attr("x", startX).attr(
|
||||
"y",
|
||||
getConfig2().state.titleShift - getConfig2().state.textHeight - getConfig2().state.padding
|
||||
).attr("width", width).attr("height", graphBox.height + 3 + 2 * getConfig2().state.textHeight).attr("rx", getConfig2().state.radius);
|
||||
return g;
|
||||
}, "addTitleAndBox");
|
||||
var drawEndState = __name((g) => {
|
||||
g.append("circle").attr("class", "end-state-outer").attr("r", getConfig2().state.sizeUnit + getConfig2().state.miniPadding).attr(
|
||||
"cx",
|
||||
getConfig2().state.padding + getConfig2().state.sizeUnit + getConfig2().state.miniPadding
|
||||
).attr(
|
||||
"cy",
|
||||
getConfig2().state.padding + getConfig2().state.sizeUnit + getConfig2().state.miniPadding
|
||||
);
|
||||
return g.append("circle").attr("class", "end-state-inner").attr("r", getConfig2().state.sizeUnit).attr("cx", getConfig2().state.padding + getConfig2().state.sizeUnit + 2).attr("cy", getConfig2().state.padding + getConfig2().state.sizeUnit + 2);
|
||||
}, "drawEndState");
|
||||
var drawForkJoinState = __name((g, stateDef) => {
|
||||
let width = getConfig2().state.forkWidth;
|
||||
let height = getConfig2().state.forkHeight;
|
||||
if (stateDef.parentId) {
|
||||
let tmp = width;
|
||||
width = height;
|
||||
height = tmp;
|
||||
}
|
||||
return g.append("rect").style("stroke", "black").style("fill", "black").attr("width", width).attr("height", height).attr("x", getConfig2().state.padding).attr("y", getConfig2().state.padding);
|
||||
}, "drawForkJoinState");
|
||||
var _drawLongText = __name((_text, x, y, g) => {
|
||||
let textHeight = 0;
|
||||
const textElem = g.append("text");
|
||||
textElem.style("text-anchor", "start");
|
||||
textElem.attr("class", "noteText");
|
||||
let text = _text.replace(/\r\n/g, "<br/>");
|
||||
text = text.replace(/\n/g, "<br/>");
|
||||
const lines = text.split(common_default.lineBreakRegex);
|
||||
let tHeight = 1.25 * getConfig2().state.noteMargin;
|
||||
for (const line2 of lines) {
|
||||
const txt = line2.trim();
|
||||
if (txt.length > 0) {
|
||||
const span = textElem.append("tspan");
|
||||
span.text(txt);
|
||||
if (tHeight === 0) {
|
||||
const textBounds = span.node().getBBox();
|
||||
tHeight += textBounds.height;
|
||||
}
|
||||
textHeight += tHeight;
|
||||
span.attr("x", x + getConfig2().state.noteMargin);
|
||||
span.attr("y", y + textHeight + 1.25 * getConfig2().state.noteMargin);
|
||||
}
|
||||
}
|
||||
return { textWidth: textElem.node().getBBox().width, textHeight };
|
||||
}, "_drawLongText");
|
||||
var drawNote = __name((text, g) => {
|
||||
g.attr("class", "state-note");
|
||||
const note = g.append("rect").attr("x", 0).attr("y", getConfig2().state.padding);
|
||||
const rectElem = g.append("g");
|
||||
const { textWidth, textHeight } = _drawLongText(text, 0, 0, rectElem);
|
||||
note.attr("height", textHeight + 2 * getConfig2().state.noteMargin);
|
||||
note.attr("width", textWidth + getConfig2().state.noteMargin * 2);
|
||||
return note;
|
||||
}, "drawNote");
|
||||
var drawState = __name(function(elem, stateDef) {
|
||||
const id = stateDef.id;
|
||||
const stateInfo = {
|
||||
id,
|
||||
label: stateDef.id,
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
const g = elem.append("g").attr("id", id).attr("class", "stateGroup");
|
||||
if (stateDef.type === "start") {
|
||||
drawStartState(g);
|
||||
}
|
||||
if (stateDef.type === "end") {
|
||||
drawEndState(g);
|
||||
}
|
||||
if (stateDef.type === "fork" || stateDef.type === "join") {
|
||||
drawForkJoinState(g, stateDef);
|
||||
}
|
||||
if (stateDef.type === "note") {
|
||||
drawNote(stateDef.note.text, g);
|
||||
}
|
||||
if (stateDef.type === "divider") {
|
||||
drawDivider(g);
|
||||
}
|
||||
if (stateDef.type === "default" && stateDef.descriptions.length === 0) {
|
||||
drawSimpleState(g, stateDef);
|
||||
}
|
||||
if (stateDef.type === "default" && stateDef.descriptions.length > 0) {
|
||||
drawDescrState(g, stateDef);
|
||||
}
|
||||
const stateBox = g.node().getBBox();
|
||||
stateInfo.width = stateBox.width + 2 * getConfig2().state.padding;
|
||||
stateInfo.height = stateBox.height + 2 * getConfig2().state.padding;
|
||||
return stateInfo;
|
||||
}, "drawState");
|
||||
var edgeCount = 0;
|
||||
var drawEdge = __name(function(elem, path, relation) {
|
||||
const getRelationType = __name(function(type) {
|
||||
switch (type) {
|
||||
case StateDB.relationType.AGGREGATION:
|
||||
return "aggregation";
|
||||
case StateDB.relationType.EXTENSION:
|
||||
return "extension";
|
||||
case StateDB.relationType.COMPOSITION:
|
||||
return "composition";
|
||||
case StateDB.relationType.DEPENDENCY:
|
||||
return "dependency";
|
||||
}
|
||||
}, "getRelationType");
|
||||
path.points = path.points.filter((p) => !Number.isNaN(p.y));
|
||||
const lineData = path.points;
|
||||
const lineFunction = line_default().x(function(d) {
|
||||
return d.x;
|
||||
}).y(function(d) {
|
||||
return d.y;
|
||||
}).curve(basis_default);
|
||||
const svgPath = elem.append("path").attr("d", lineFunction(lineData)).attr("id", "edge" + edgeCount).attr("class", "transition");
|
||||
let url = "";
|
||||
if (getConfig2().state.arrowMarkerAbsolute) {
|
||||
url = getUrl(true);
|
||||
}
|
||||
svgPath.attr(
|
||||
"marker-end",
|
||||
"url(" + url + "#" + getRelationType(StateDB.relationType.DEPENDENCY) + "End)"
|
||||
);
|
||||
if (relation.title !== void 0) {
|
||||
const label = elem.append("g").attr("class", "stateLabel");
|
||||
const { x, y } = utils_default.calcLabelPosition(path.points);
|
||||
const rows = common_default.getRows(relation.title);
|
||||
let titleHeight = 0;
|
||||
const titleRows = [];
|
||||
let maxWidth = 0;
|
||||
let minX = 0;
|
||||
for (let i = 0; i <= rows.length; i++) {
|
||||
const title = label.append("text").attr("text-anchor", "middle").text(rows[i]).attr("x", x).attr("y", y + titleHeight);
|
||||
const boundsTmp = title.node().getBBox();
|
||||
maxWidth = Math.max(maxWidth, boundsTmp.width);
|
||||
minX = Math.min(minX, boundsTmp.x);
|
||||
log.info(boundsTmp.x, x, y + titleHeight);
|
||||
if (titleHeight === 0) {
|
||||
const titleBox = title.node().getBBox();
|
||||
titleHeight = titleBox.height;
|
||||
log.info("Title height", titleHeight, y);
|
||||
}
|
||||
titleRows.push(title);
|
||||
}
|
||||
let boxHeight = titleHeight * rows.length;
|
||||
if (rows.length > 1) {
|
||||
const heightAdj = (rows.length - 1) * titleHeight * 0.5;
|
||||
titleRows.forEach((title, i) => title.attr("y", y + i * titleHeight - heightAdj));
|
||||
boxHeight = titleHeight * rows.length;
|
||||
}
|
||||
const bounds = label.node().getBBox();
|
||||
label.insert("rect", ":first-child").attr("class", "box").attr("x", x - maxWidth / 2 - getConfig2().state.padding / 2).attr("y", y - boxHeight / 2 - getConfig2().state.padding / 2 - 3.5).attr("width", maxWidth + getConfig2().state.padding).attr("height", boxHeight + getConfig2().state.padding);
|
||||
log.info(bounds);
|
||||
}
|
||||
edgeCount++;
|
||||
}, "drawEdge");
|
||||
var conf;
|
||||
var transformationLog = {};
|
||||
var setConf = __name(function() {
|
||||
}, "setConf");
|
||||
var insertMarkers = __name(function(elem) {
|
||||
elem.append("defs").append("marker").attr("id", "dependencyEnd").attr("refX", 19).attr("refY", 7).attr("markerWidth", 20).attr("markerHeight", 28).attr("orient", "auto").append("path").attr("d", "M 19,7 L9,13 L14,7 L9,1 Z");
|
||||
}, "insertMarkers");
|
||||
var draw = __name(function(text, id, _version, diagObj) {
|
||||
conf = getConfig2().state;
|
||||
const securityLevel = getConfig2().securityLevel;
|
||||
let sandboxElement;
|
||||
if (securityLevel === "sandbox") {
|
||||
sandboxElement = select_default("#i" + id);
|
||||
}
|
||||
const root = securityLevel === "sandbox" ? select_default(sandboxElement.nodes()[0].contentDocument.body) : select_default("body");
|
||||
const doc = securityLevel === "sandbox" ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
log.debug("Rendering diagram " + text);
|
||||
const diagram2 = root.select(`[id='${id}']`);
|
||||
insertMarkers(diagram2);
|
||||
const rootDoc = diagObj.db.getRootDoc();
|
||||
const rootG = diagram2.append("g").attr("id", id + "-root");
|
||||
renderDoc(rootDoc, rootG, void 0, false, root, doc, diagObj);
|
||||
const padding = conf.padding;
|
||||
const bounds = diagram2.node().getBBox();
|
||||
const width = bounds.width + padding * 2;
|
||||
const height = bounds.height + padding * 2;
|
||||
const svgWidth = width * 1.75;
|
||||
configureSvgSize(diagram2, height, svgWidth, conf.useMaxWidth);
|
||||
diagram2.attr(
|
||||
"viewBox",
|
||||
`${bounds.x - conf.padding} ${bounds.y - conf.padding} ` + width + " " + height
|
||||
);
|
||||
}, "draw");
|
||||
var getLabelWidth = __name((text) => {
|
||||
return text ? text.length * conf.fontSizeFactor : 1;
|
||||
}, "getLabelWidth");
|
||||
var renderDoc = __name((doc, diagram2, parentId, altBkg, root, domDocument, diagObj) => {
|
||||
const graph = new Graph({
|
||||
compound: true,
|
||||
multigraph: true
|
||||
});
|
||||
let i;
|
||||
let edgeFreeDoc = true;
|
||||
for (i = 0; i < doc.length; i++) {
|
||||
if (doc[i].stmt === "relation") {
|
||||
edgeFreeDoc = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parentId) {
|
||||
graph.setGraph({
|
||||
rankdir: "LR",
|
||||
multigraph: true,
|
||||
compound: true,
|
||||
// acyclicer: 'greedy',
|
||||
ranker: "tight-tree",
|
||||
ranksep: edgeFreeDoc ? 1 : conf.edgeLengthFactor,
|
||||
nodeSep: edgeFreeDoc ? 1 : 50,
|
||||
isMultiGraph: true
|
||||
// ranksep: 5,
|
||||
// nodesep: 1
|
||||
});
|
||||
} else {
|
||||
graph.setGraph({
|
||||
rankdir: "TB",
|
||||
multigraph: true,
|
||||
compound: true,
|
||||
// isCompound: true,
|
||||
// acyclicer: 'greedy',
|
||||
// ranker: 'longest-path'
|
||||
ranksep: edgeFreeDoc ? 1 : conf.edgeLengthFactor,
|
||||
nodeSep: edgeFreeDoc ? 1 : 50,
|
||||
ranker: "tight-tree",
|
||||
// ranker: 'network-simplex'
|
||||
isMultiGraph: true
|
||||
});
|
||||
}
|
||||
graph.setDefaultEdgeLabel(function() {
|
||||
return {};
|
||||
});
|
||||
const states = diagObj.db.getStates();
|
||||
const relations = diagObj.db.getRelations();
|
||||
const keys = Object.keys(states);
|
||||
let first = true;
|
||||
for (const key of keys) {
|
||||
const stateDef = states[key];
|
||||
if (parentId) {
|
||||
stateDef.parentId = parentId;
|
||||
}
|
||||
let node;
|
||||
if (stateDef.doc) {
|
||||
let sub = diagram2.append("g").attr("id", stateDef.id).attr("class", "stateGroup");
|
||||
node = renderDoc(stateDef.doc, sub, stateDef.id, !altBkg, root, domDocument, diagObj);
|
||||
if (first) {
|
||||
sub = addTitleAndBox(sub, stateDef, altBkg);
|
||||
let boxBounds = sub.node().getBBox();
|
||||
node.width = boxBounds.width;
|
||||
node.height = boxBounds.height + conf.padding / 2;
|
||||
transformationLog[stateDef.id] = { y: conf.compositTitleSize };
|
||||
} else {
|
||||
let boxBounds = sub.node().getBBox();
|
||||
node.width = boxBounds.width;
|
||||
node.height = boxBounds.height;
|
||||
}
|
||||
} else {
|
||||
node = drawState(diagram2, stateDef, graph);
|
||||
}
|
||||
if (stateDef.note) {
|
||||
const noteDef = {
|
||||
descriptions: [],
|
||||
id: stateDef.id + "-note",
|
||||
note: stateDef.note,
|
||||
type: "note"
|
||||
};
|
||||
const note = drawState(diagram2, noteDef, graph);
|
||||
if (stateDef.note.position === "left of") {
|
||||
graph.setNode(node.id + "-note", note);
|
||||
graph.setNode(node.id, node);
|
||||
} else {
|
||||
graph.setNode(node.id, node);
|
||||
graph.setNode(node.id + "-note", note);
|
||||
}
|
||||
graph.setParent(node.id, node.id + "-group");
|
||||
graph.setParent(node.id + "-note", node.id + "-group");
|
||||
} else {
|
||||
graph.setNode(node.id, node);
|
||||
}
|
||||
}
|
||||
log.debug("Count=", graph.nodeCount(), graph);
|
||||
let cnt = 0;
|
||||
relations.forEach(function(relation) {
|
||||
cnt++;
|
||||
log.debug("Setting edge", relation);
|
||||
graph.setEdge(
|
||||
relation.id1,
|
||||
relation.id2,
|
||||
{
|
||||
relation,
|
||||
width: getLabelWidth(relation.title),
|
||||
height: conf.labelHeight * common_default.getRows(relation.title).length,
|
||||
labelpos: "c"
|
||||
},
|
||||
"id" + cnt
|
||||
);
|
||||
});
|
||||
layout(graph);
|
||||
log.debug("Graph after layout", graph.nodes());
|
||||
const svgElem = diagram2.node();
|
||||
graph.nodes().forEach(function(v) {
|
||||
if (v !== void 0 && graph.node(v) !== void 0) {
|
||||
log.warn("Node " + v + ": " + JSON.stringify(graph.node(v)));
|
||||
root.select("#" + svgElem.id + " #" + v).attr(
|
||||
"transform",
|
||||
"translate(" + (graph.node(v).x - graph.node(v).width / 2) + "," + (graph.node(v).y + (transformationLog[v] ? transformationLog[v].y : 0) - graph.node(v).height / 2) + " )"
|
||||
);
|
||||
root.select("#" + svgElem.id + " #" + v).attr("data-x-shift", graph.node(v).x - graph.node(v).width / 2);
|
||||
const dividers = domDocument.querySelectorAll("#" + svgElem.id + " #" + v + " .divider");
|
||||
dividers.forEach((divider) => {
|
||||
const parent = divider.parentElement;
|
||||
let pWidth = 0;
|
||||
let pShift = 0;
|
||||
if (parent) {
|
||||
if (parent.parentElement) {
|
||||
pWidth = parent.parentElement.getBBox().width;
|
||||
}
|
||||
pShift = parseInt(parent.getAttribute("data-x-shift"), 10);
|
||||
if (Number.isNaN(pShift)) {
|
||||
pShift = 0;
|
||||
}
|
||||
}
|
||||
divider.setAttribute("x1", 0 - pShift + 8);
|
||||
divider.setAttribute("x2", pWidth - pShift - 8);
|
||||
});
|
||||
} else {
|
||||
log.debug("No Node " + v + ": " + JSON.stringify(graph.node(v)));
|
||||
}
|
||||
});
|
||||
let stateBox = svgElem.getBBox();
|
||||
graph.edges().forEach(function(e) {
|
||||
if (e !== void 0 && graph.edge(e) !== void 0) {
|
||||
log.debug("Edge " + e.v + " -> " + e.w + ": " + JSON.stringify(graph.edge(e)));
|
||||
drawEdge(diagram2, graph.edge(e), graph.edge(e).relation);
|
||||
}
|
||||
});
|
||||
stateBox = svgElem.getBBox();
|
||||
const stateInfo = {
|
||||
id: parentId ? parentId : "root",
|
||||
label: parentId ? parentId : "root",
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
stateInfo.width = stateBox.width + 2 * conf.padding;
|
||||
stateInfo.height = stateBox.height + 2 * conf.padding;
|
||||
log.debug("Doc rendered", stateInfo, graph);
|
||||
return stateInfo;
|
||||
}, "renderDoc");
|
||||
var stateRenderer_default = {
|
||||
setConf,
|
||||
draw
|
||||
};
|
||||
var diagram = {
|
||||
parser: stateDiagram_default,
|
||||
get db() {
|
||||
return new StateDB(1);
|
||||
},
|
||||
renderer: stateRenderer_default,
|
||||
styles: styles_default,
|
||||
init: __name((cnf) => {
|
||||
if (!cnf.state) {
|
||||
cnf.state = {};
|
||||
}
|
||||
cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
}, "init")
|
||||
};
|
||||
export {
|
||||
diagram
|
||||
};
|
||||
//# sourceMappingURL=stateDiagram-FHFEXIEX-DGJIBEPL.js.map
|
||||
-7
File diff suppressed because one or more lines are too long
-44
@@ -1,44 +0,0 @@
|
||||
import {
|
||||
StateDB,
|
||||
stateDiagram_default,
|
||||
stateRenderer_v3_unified_default,
|
||||
styles_default
|
||||
} from "./chunk-74EEDPU4.js";
|
||||
import "./chunk-NLS3CDEU.js";
|
||||
import "./chunk-YVBSFUGN.js";
|
||||
import "./chunk-G5KDPKXZ.js";
|
||||
import "./chunk-QDQEHZH7.js";
|
||||
import "./chunk-IHPTUWR5.js";
|
||||
import "./chunk-DK5DI5R3.js";
|
||||
import "./chunk-N2C52BYW.js";
|
||||
import "./chunk-MYK3ASHG.js";
|
||||
import "./chunk-TNWHCC6S.js";
|
||||
import "./chunk-FFNMY5H5.js";
|
||||
import "./chunk-3QKV3V7V.js";
|
||||
import "./chunk-MOBZPS7F.js";
|
||||
import "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/stateDiagram-v2-QKLJ7IA2.mjs
|
||||
var diagram = {
|
||||
parser: stateDiagram_default,
|
||||
get db() {
|
||||
return new StateDB(2);
|
||||
},
|
||||
renderer: stateRenderer_v3_unified_default,
|
||||
styles: styles_default,
|
||||
init: __name((cnf) => {
|
||||
if (!cnf.state) {
|
||||
cnf.state = {};
|
||||
}
|
||||
cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
}, "init")
|
||||
};
|
||||
export {
|
||||
diagram
|
||||
};
|
||||
//# sourceMappingURL=stateDiagram-v2-QKLJ7IA2-KWG254M5.js.map
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../../mermaid/dist/chunks/mermaid.core/stateDiagram-v2-QKLJ7IA2.mjs"],
|
||||
"sourcesContent": ["import {\n StateDB,\n stateDiagram_default,\n stateRenderer_v3_unified_default,\n styles_default\n} from \"./chunk-OYMX7WX6.mjs\";\nimport \"./chunk-55IACEB6.mjs\";\nimport \"./chunk-EDXVE4YY.mjs\";\nimport \"./chunk-336JU56O.mjs\";\nimport \"./chunk-ENJZ2VHE.mjs\";\nimport \"./chunk-BSJP7CBP.mjs\";\nimport \"./chunk-5FUZZQ4R.mjs\";\nimport \"./chunk-ZZ45TVLE.mjs\";\nimport \"./chunk-X2U36JSP.mjs\";\nimport \"./chunk-U2HBQHQK.mjs\";\nimport \"./chunk-5PVQY5BW.mjs\";\nimport \"./chunk-ICPOFSXX.mjs\";\nimport {\n __name\n} from \"./chunk-AGHRB4JF.mjs\";\n\n// src/diagrams/state/stateDiagram-v2.ts\nvar diagram = {\n parser: stateDiagram_default,\n get db() {\n return new StateDB(2);\n },\n renderer: stateRenderer_v3_unified_default,\n styles: styles_default,\n init: /* @__PURE__ */ __name((cnf) => {\n if (!cnf.state) {\n cnf.state = {};\n }\n cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;\n }, \"init\")\n};\nexport {\n diagram\n};\n"],
|
||||
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,IAAI,UAAU;AAAA,EACZ,QAAQ;AAAA,EACR,IAAI,KAAK;AACP,WAAO,IAAI,QAAQ,CAAC;AAAA,EACtB;AAAA,EACA,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,MAAsB,OAAO,CAAC,QAAQ;AACpC,QAAI,CAAC,IAAI,OAAO;AACd,UAAI,QAAQ,CAAC;AAAA,IACf;AACA,QAAI,MAAM,sBAAsB,IAAI;AAAA,EACtC,GAAG,MAAM;AACX;",
|
||||
"names": []
|
||||
}
|
||||
-1655
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-2551
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
-940
@@ -1,940 +0,0 @@
|
||||
import {
|
||||
populateCommonDb
|
||||
} from "./chunk-BEGFPAJS.js";
|
||||
import {
|
||||
parse
|
||||
} from "./chunk-ZO353HVL.js";
|
||||
import "./chunk-SHHXTPWA.js";
|
||||
import "./chunk-JLNTX6TF.js";
|
||||
import "./chunk-IELG6YWI.js";
|
||||
import "./chunk-ZOQ3FUUK.js";
|
||||
import "./chunk-TAVNOOKD.js";
|
||||
import "./chunk-5D6MANWW.js";
|
||||
import "./chunk-E3W5VJ2T.js";
|
||||
import "./chunk-JH6V2QOE.js";
|
||||
import "./chunk-QLH66CIT.js";
|
||||
import "./chunk-S4AGLBPD.js";
|
||||
import "./chunk-K3ORWWMK.js";
|
||||
import {
|
||||
selectSvgElement
|
||||
} from "./chunk-QBIGODNM.js";
|
||||
import {
|
||||
clear,
|
||||
configureSvgSize,
|
||||
getAccDescription,
|
||||
getAccTitle,
|
||||
getConfig2,
|
||||
getDiagramTitle,
|
||||
sanitizeText,
|
||||
setAccDescription,
|
||||
setAccTitle,
|
||||
setDiagramTitle
|
||||
} from "./chunk-6YWVU24R.js";
|
||||
import {
|
||||
__name,
|
||||
log
|
||||
} from "./chunk-XOKMXDAB.js";
|
||||
import "./chunk-BQ2Z5GT2.js";
|
||||
import "./chunk-5ZDVNSGT.js";
|
||||
import "./chunk-DBU5TJLK.js";
|
||||
|
||||
// node_modules/mermaid/dist/chunks/mermaid.core/wardleyDiagram-NUSXRM2D.mjs
|
||||
var toPercent = __name((value, context) => {
|
||||
const normalized = value <= 1 ? value * 100 : value;
|
||||
if (normalized < 0 || normalized > 100) {
|
||||
throw new Error(
|
||||
`${context} must be between 0-1 (decimal) or 0-100 (percentage). Received: ${value}`
|
||||
);
|
||||
}
|
||||
return normalized;
|
||||
}, "toPercent");
|
||||
var toCoordinates = __name((visibility, evolution, context) => {
|
||||
return {
|
||||
x: toPercent(evolution, `${context} evolution`),
|
||||
y: toPercent(visibility, `${context} visibility`)
|
||||
};
|
||||
}, "toCoordinates");
|
||||
var getFlowFromPort = __name((port) => {
|
||||
if (!port) {
|
||||
return void 0;
|
||||
}
|
||||
if (port === "+<>") {
|
||||
return "bidirectional";
|
||||
}
|
||||
if (port === "+<") {
|
||||
return "backward";
|
||||
}
|
||||
if (port === "+>") {
|
||||
return "forward";
|
||||
}
|
||||
return void 0;
|
||||
}, "getFlowFromPort");
|
||||
var extractFlowFromArrow = __name((arrow) => {
|
||||
if (!(arrow == null ? void 0 : arrow.startsWith("+"))) {
|
||||
return {};
|
||||
}
|
||||
const labelMatch = /^\+'([^']*)'/.exec(arrow);
|
||||
const flowLabel = labelMatch == null ? void 0 : labelMatch[1];
|
||||
if (arrow.includes("<>")) {
|
||||
return { flow: "bidirectional", label: flowLabel };
|
||||
}
|
||||
if (arrow.includes("<")) {
|
||||
return { flow: "backward", label: flowLabel };
|
||||
}
|
||||
if (arrow.includes(">")) {
|
||||
return { flow: "forward", label: flowLabel };
|
||||
}
|
||||
return { label: flowLabel };
|
||||
}, "extractFlowFromArrow");
|
||||
var populateDb = __name((ast, db) => {
|
||||
populateCommonDb(ast, db);
|
||||
if (ast.size) {
|
||||
db.setSize(ast.size.width, ast.size.height);
|
||||
}
|
||||
if (ast.evolution) {
|
||||
const stages = ast.evolution.stages.map((stage) => {
|
||||
if (stage.secondName) {
|
||||
return `${stage.name.trim()} / ${stage.secondName.trim()}`;
|
||||
}
|
||||
return stage.name.trim();
|
||||
});
|
||||
const stageBoundaries = ast.evolution.stages.filter((stage) => stage.boundary !== void 0).map((stage) => stage.boundary);
|
||||
db.updateAxes({ stages, stageBoundaries });
|
||||
}
|
||||
ast.anchors.forEach((anchor) => {
|
||||
const coords = toCoordinates(anchor.visibility, anchor.evolution, `Anchor "${anchor.name}"`);
|
||||
db.addNode(anchor.name, anchor.name, coords.x, coords.y, "anchor");
|
||||
});
|
||||
ast.components.forEach((component) => {
|
||||
var _a2;
|
||||
const coords = toCoordinates(
|
||||
component.visibility,
|
||||
component.evolution,
|
||||
`Component "${component.name}"`
|
||||
);
|
||||
const labelOffsetX = component.label ? (component.label.negX ? -1 : 1) * component.label.offsetX : void 0;
|
||||
const labelOffsetY = component.label ? (component.label.negY ? -1 : 1) * component.label.offsetY : void 0;
|
||||
const sourceStrategy = (_a2 = component.decorator) == null ? void 0 : _a2.strategy;
|
||||
db.addNode(
|
||||
component.name,
|
||||
component.name,
|
||||
coords.x,
|
||||
coords.y,
|
||||
"component",
|
||||
labelOffsetX,
|
||||
labelOffsetY,
|
||||
component.inertia,
|
||||
sourceStrategy
|
||||
);
|
||||
});
|
||||
ast.notes.forEach((note) => {
|
||||
const coords = toCoordinates(note.visibility, note.evolution, `Note "${note.text}"`);
|
||||
db.addNote(note.text, coords.x, coords.y);
|
||||
});
|
||||
ast.pipelines.forEach((pipeline) => {
|
||||
const parentNode = db.getNode(pipeline.parent);
|
||||
if (!parentNode || typeof parentNode.y !== "number") {
|
||||
throw new Error(
|
||||
`Pipeline "${pipeline.parent}" must reference an existing component with coordinates.`
|
||||
);
|
||||
}
|
||||
const parentY = parentNode.y;
|
||||
db.startPipeline(pipeline.parent);
|
||||
pipeline.components.forEach((component) => {
|
||||
const componentId = `${pipeline.parent}_${component.name}`;
|
||||
const labelOffsetX = component.label ? (component.label.negX ? -1 : 1) * component.label.offsetX : void 0;
|
||||
const labelOffsetY = component.label ? (component.label.negY ? -1 : 1) * component.label.offsetY : void 0;
|
||||
const x = toPercent(component.evolution, `Pipeline component "${component.name}" evolution`);
|
||||
db.addNode(
|
||||
componentId,
|
||||
component.name,
|
||||
x,
|
||||
parentY,
|
||||
"pipeline-component",
|
||||
labelOffsetX,
|
||||
labelOffsetY
|
||||
);
|
||||
db.addPipelineComponent(pipeline.parent, componentId);
|
||||
});
|
||||
});
|
||||
ast.links.forEach((link) => {
|
||||
const isDashed = !!link.arrow && (link.arrow.includes("-.->") || link.arrow.includes(".-."));
|
||||
let flow = getFlowFromPort(link.fromPort) ?? getFlowFromPort(link.toPort);
|
||||
const { flow: arrowFlow, label: flowLabel } = extractFlowFromArrow(link.arrow);
|
||||
if (!flow && arrowFlow) {
|
||||
flow = arrowFlow;
|
||||
}
|
||||
const annotation = link.linkLabel;
|
||||
const label = flowLabel ?? annotation;
|
||||
db.addLink(link.from, link.to, isDashed, label, flow);
|
||||
});
|
||||
ast.evolves.forEach((evolve) => {
|
||||
const node = db.getNode(evolve.component);
|
||||
if ((node == null ? void 0 : node.y) !== void 0) {
|
||||
const target = toPercent(evolve.target, `Evolve target for "${evolve.component}"`);
|
||||
db.addTrend(evolve.component, target, node.y);
|
||||
}
|
||||
});
|
||||
if (ast.annotations.length > 0) {
|
||||
const annotationsBox = ast.annotations[0];
|
||||
const coords = toCoordinates(annotationsBox.x, annotationsBox.y, "Annotations box");
|
||||
db.setAnnotationsBox(coords.x, coords.y);
|
||||
}
|
||||
ast.annotation.forEach((annotation) => {
|
||||
const coords = toCoordinates(annotation.x, annotation.y, `Annotation ${annotation.number}`);
|
||||
db.addAnnotation(annotation.number, [{ x: coords.x, y: coords.y }], annotation.text);
|
||||
});
|
||||
ast.accelerators.forEach((accelerator) => {
|
||||
const coords = toCoordinates(accelerator.x, accelerator.y, `Accelerator "${accelerator.name}"`);
|
||||
db.addAccelerator(accelerator.name, coords.x, coords.y);
|
||||
});
|
||||
ast.deaccelerators.forEach((deaccelerator) => {
|
||||
const coords = toCoordinates(
|
||||
deaccelerator.x,
|
||||
deaccelerator.y,
|
||||
`Deaccelerator "${deaccelerator.name}"`
|
||||
);
|
||||
db.addDeaccelerator(deaccelerator.name, coords.x, coords.y);
|
||||
});
|
||||
}, "populateDb");
|
||||
var parser = {
|
||||
parser: {
|
||||
// @ts-expect-error - WardleyDB is not assignable to DiagramDB
|
||||
yy: void 0
|
||||
},
|
||||
parse: __name(async (input) => {
|
||||
var _a2;
|
||||
const ast = await parse("wardley", input);
|
||||
log.debug(ast);
|
||||
const db = (_a2 = parser.parser) == null ? void 0 : _a2.yy;
|
||||
if (!db || typeof db.addNode !== "function") {
|
||||
throw new Error(
|
||||
"parser.parser?.yy was not a WardleyDB. This is due to a bug within Mermaid, please report this issue at https://github.com/mermaid-js/mermaid/issues."
|
||||
);
|
||||
}
|
||||
populateDb(ast, db);
|
||||
}, "parse")
|
||||
};
|
||||
var _a;
|
||||
var WardleyBuilder = (_a = class {
|
||||
constructor() {
|
||||
this.nodes = /* @__PURE__ */ new Map();
|
||||
this.links = [];
|
||||
this.trends = /* @__PURE__ */ new Map();
|
||||
this.pipelines = /* @__PURE__ */ new Map();
|
||||
this.annotations = [];
|
||||
this.notes = [];
|
||||
this.accelerators = [];
|
||||
this.deaccelerators = [];
|
||||
this.axes = {};
|
||||
}
|
||||
addNode(node) {
|
||||
const existing = this.nodes.get(node.id) ?? { id: node.id, label: node.label };
|
||||
const merged = {
|
||||
...existing,
|
||||
...node,
|
||||
className: node.className ?? existing.className,
|
||||
labelOffsetX: node.labelOffsetX ?? existing.labelOffsetX,
|
||||
labelOffsetY: node.labelOffsetY ?? existing.labelOffsetY
|
||||
};
|
||||
this.nodes.set(node.id, merged);
|
||||
}
|
||||
addLink(link) {
|
||||
this.links.push(link);
|
||||
}
|
||||
addTrend(trend) {
|
||||
this.trends.set(trend.nodeId, trend);
|
||||
}
|
||||
startPipeline(nodeId) {
|
||||
this.pipelines.set(nodeId, { nodeId, componentIds: [] });
|
||||
const node = this.nodes.get(nodeId);
|
||||
if (node) {
|
||||
node.isPipelineParent = true;
|
||||
}
|
||||
}
|
||||
addPipelineComponent(pipelineNodeId, componentId) {
|
||||
const pipeline = this.pipelines.get(pipelineNodeId);
|
||||
if (pipeline) {
|
||||
pipeline.componentIds.push(componentId);
|
||||
}
|
||||
const node = this.nodes.get(componentId);
|
||||
if (node) {
|
||||
node.inPipeline = true;
|
||||
}
|
||||
}
|
||||
addAnnotation(annotation) {
|
||||
this.annotations.push(annotation);
|
||||
}
|
||||
addNote(note) {
|
||||
this.notes.push(note);
|
||||
}
|
||||
addAccelerator(accelerator) {
|
||||
this.accelerators.push(accelerator);
|
||||
}
|
||||
addDeaccelerator(deaccelerator) {
|
||||
this.deaccelerators.push(deaccelerator);
|
||||
}
|
||||
setAnnotationsBox(x, y) {
|
||||
this.annotationsBox = { x, y };
|
||||
}
|
||||
setAxes(partial) {
|
||||
this.axes = {
|
||||
...this.axes,
|
||||
...partial
|
||||
};
|
||||
}
|
||||
setSize(width, height) {
|
||||
this.size = { width, height };
|
||||
}
|
||||
getNode(id) {
|
||||
return this.nodes.get(id);
|
||||
}
|
||||
build() {
|
||||
const nodes = [];
|
||||
for (const node of this.nodes.values()) {
|
||||
if (typeof node.x !== "number" || typeof node.y !== "number") {
|
||||
throw new Error(`Node "${node.label}" is missing coordinates`);
|
||||
}
|
||||
nodes.push(node);
|
||||
}
|
||||
return {
|
||||
nodes,
|
||||
links: [...this.links],
|
||||
trends: [...this.trends.values()],
|
||||
pipelines: [...this.pipelines.values()],
|
||||
annotations: [...this.annotations],
|
||||
notes: [...this.notes],
|
||||
accelerators: [...this.accelerators],
|
||||
deaccelerators: [...this.deaccelerators],
|
||||
annotationsBox: this.annotationsBox,
|
||||
axes: { ...this.axes },
|
||||
size: this.size
|
||||
};
|
||||
}
|
||||
clear() {
|
||||
this.nodes.clear();
|
||||
this.links = [];
|
||||
this.trends.clear();
|
||||
this.pipelines.clear();
|
||||
this.annotations = [];
|
||||
this.notes = [];
|
||||
this.accelerators = [];
|
||||
this.deaccelerators = [];
|
||||
this.annotationsBox = void 0;
|
||||
this.axes = {};
|
||||
this.size = void 0;
|
||||
}
|
||||
}, __name(_a, "WardleyBuilder"), _a);
|
||||
var builder = new WardleyBuilder();
|
||||
function textSanitizer(text) {
|
||||
const config = getConfig2();
|
||||
return sanitizeText(text.trim(), config);
|
||||
}
|
||||
__name(textSanitizer, "textSanitizer");
|
||||
function getConfig22() {
|
||||
return getConfig2()["wardley-beta"];
|
||||
}
|
||||
__name(getConfig22, "getConfig");
|
||||
function addNode(id, label, x, y, className, labelOffsetX, labelOffsetY, inertia, sourceStrategy) {
|
||||
builder.addNode({
|
||||
id,
|
||||
label: textSanitizer(label),
|
||||
x,
|
||||
y,
|
||||
className,
|
||||
labelOffsetX,
|
||||
labelOffsetY,
|
||||
inertia,
|
||||
sourceStrategy
|
||||
});
|
||||
}
|
||||
__name(addNode, "addNode");
|
||||
function addLink(sourceId, targetId, dashed = false, label, flow) {
|
||||
builder.addLink({ source: sourceId, target: targetId, dashed, label, flow });
|
||||
}
|
||||
__name(addLink, "addLink");
|
||||
function addTrend(nodeId, targetX, targetY) {
|
||||
builder.addTrend({ nodeId, targetX, targetY });
|
||||
}
|
||||
__name(addTrend, "addTrend");
|
||||
function addAnnotation(number, coordinates, text) {
|
||||
builder.addAnnotation({
|
||||
number,
|
||||
coordinates,
|
||||
text: text ? textSanitizer(text) : void 0
|
||||
});
|
||||
}
|
||||
__name(addAnnotation, "addAnnotation");
|
||||
function addNote(text, x, y) {
|
||||
builder.addNote({
|
||||
text: textSanitizer(text),
|
||||
x,
|
||||
y
|
||||
});
|
||||
}
|
||||
__name(addNote, "addNote");
|
||||
function addAccelerator(name, x, y) {
|
||||
builder.addAccelerator({
|
||||
name: textSanitizer(name),
|
||||
x,
|
||||
y
|
||||
});
|
||||
}
|
||||
__name(addAccelerator, "addAccelerator");
|
||||
function addDeaccelerator(name, x, y) {
|
||||
builder.addDeaccelerator({
|
||||
name: textSanitizer(name),
|
||||
x,
|
||||
y
|
||||
});
|
||||
}
|
||||
__name(addDeaccelerator, "addDeaccelerator");
|
||||
function setAnnotationsBox(x, y) {
|
||||
builder.setAnnotationsBox(x, y);
|
||||
}
|
||||
__name(setAnnotationsBox, "setAnnotationsBox");
|
||||
function setSize(width, height) {
|
||||
builder.setSize(width, height);
|
||||
}
|
||||
__name(setSize, "setSize");
|
||||
function startPipeline(nodeId) {
|
||||
builder.startPipeline(nodeId);
|
||||
}
|
||||
__name(startPipeline, "startPipeline");
|
||||
function addPipelineComponent(pipelineNodeId, componentId) {
|
||||
builder.addPipelineComponent(pipelineNodeId, componentId);
|
||||
}
|
||||
__name(addPipelineComponent, "addPipelineComponent");
|
||||
function updateAxes(partial) {
|
||||
const sanitized = {};
|
||||
if (partial.xLabel) {
|
||||
sanitized.xLabel = textSanitizer(partial.xLabel);
|
||||
}
|
||||
if (partial.yLabel) {
|
||||
sanitized.yLabel = textSanitizer(partial.yLabel);
|
||||
}
|
||||
if (partial.stages) {
|
||||
sanitized.stages = partial.stages.map((stage) => textSanitizer(stage));
|
||||
}
|
||||
if (partial.stageBoundaries) {
|
||||
sanitized.stageBoundaries = partial.stageBoundaries;
|
||||
}
|
||||
builder.setAxes(sanitized);
|
||||
}
|
||||
__name(updateAxes, "updateAxes");
|
||||
function getNode(id) {
|
||||
return builder.getNode(id);
|
||||
}
|
||||
__name(getNode, "getNode");
|
||||
function getWardleyData() {
|
||||
return builder.build();
|
||||
}
|
||||
__name(getWardleyData, "getWardleyData");
|
||||
function clear2() {
|
||||
builder.clear();
|
||||
clear();
|
||||
}
|
||||
__name(clear2, "clear");
|
||||
var wardleyDb_default = {
|
||||
getConfig: getConfig22,
|
||||
addNode,
|
||||
addLink,
|
||||
addTrend,
|
||||
addAnnotation,
|
||||
addNote,
|
||||
addAccelerator,
|
||||
addDeaccelerator,
|
||||
setAnnotationsBox,
|
||||
setSize,
|
||||
startPipeline,
|
||||
addPipelineComponent,
|
||||
updateAxes,
|
||||
getNode,
|
||||
getWardleyData,
|
||||
clear: clear2,
|
||||
setAccTitle,
|
||||
getAccTitle,
|
||||
setDiagramTitle,
|
||||
getDiagramTitle,
|
||||
getAccDescription,
|
||||
setAccDescription
|
||||
};
|
||||
var DEFAULT_STAGES = ["Genesis", "Custom Built", "Product", "Commodity"];
|
||||
var getTheme = __name(() => {
|
||||
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
||||
const { themeVariables } = getConfig2();
|
||||
return {
|
||||
backgroundColor: ((_a2 = themeVariables.wardley) == null ? void 0 : _a2.backgroundColor) ?? themeVariables.background ?? "#fff",
|
||||
axisColor: ((_b = themeVariables.wardley) == null ? void 0 : _b.axisColor) ?? "#000",
|
||||
axisTextColor: ((_c = themeVariables.wardley) == null ? void 0 : _c.axisTextColor) ?? themeVariables.primaryTextColor ?? "#222",
|
||||
gridColor: ((_d = themeVariables.wardley) == null ? void 0 : _d.gridColor) ?? "rgba(100, 100, 100, 0.2)",
|
||||
componentFill: ((_e = themeVariables.wardley) == null ? void 0 : _e.componentFill) ?? "#fff",
|
||||
componentStroke: ((_f = themeVariables.wardley) == null ? void 0 : _f.componentStroke) ?? "#000",
|
||||
componentLabelColor: ((_g = themeVariables.wardley) == null ? void 0 : _g.componentLabelColor) ?? themeVariables.primaryTextColor ?? "#222",
|
||||
linkStroke: ((_h = themeVariables.wardley) == null ? void 0 : _h.linkStroke) ?? "#000",
|
||||
evolutionStroke: ((_i = themeVariables.wardley) == null ? void 0 : _i.evolutionStroke) ?? "#dc3545",
|
||||
annotationStroke: ((_j = themeVariables.wardley) == null ? void 0 : _j.annotationStroke) ?? "#000",
|
||||
annotationTextColor: ((_k = themeVariables.wardley) == null ? void 0 : _k.annotationTextColor) ?? themeVariables.primaryTextColor ?? "#222",
|
||||
annotationFill: ((_l = themeVariables.wardley) == null ? void 0 : _l.annotationFill) ?? themeVariables.background ?? "#fff"
|
||||
};
|
||||
}, "getTheme");
|
||||
var getConfigValues = __name(() => {
|
||||
const wardleyConfig = getConfig2()["wardley-beta"];
|
||||
return {
|
||||
width: (wardleyConfig == null ? void 0 : wardleyConfig.width) ?? 900,
|
||||
height: (wardleyConfig == null ? void 0 : wardleyConfig.height) ?? 600,
|
||||
padding: (wardleyConfig == null ? void 0 : wardleyConfig.padding) ?? 48,
|
||||
nodeRadius: (wardleyConfig == null ? void 0 : wardleyConfig.nodeRadius) ?? 6,
|
||||
nodeLabelOffset: (wardleyConfig == null ? void 0 : wardleyConfig.nodeLabelOffset) ?? 8,
|
||||
axisFontSize: (wardleyConfig == null ? void 0 : wardleyConfig.axisFontSize) ?? 12,
|
||||
labelFontSize: (wardleyConfig == null ? void 0 : wardleyConfig.labelFontSize) ?? 10,
|
||||
showGrid: (wardleyConfig == null ? void 0 : wardleyConfig.showGrid) ?? false,
|
||||
useMaxWidth: (wardleyConfig == null ? void 0 : wardleyConfig.useMaxWidth) ?? true
|
||||
};
|
||||
}, "getConfigValues");
|
||||
var draw = __name((text, id, _version, diagObj) => {
|
||||
var _a2, _b;
|
||||
log.debug("Rendering Wardley map\n" + text);
|
||||
const configValues = getConfigValues();
|
||||
const theme = getTheme();
|
||||
const squareSize = configValues.nodeRadius * 1.6;
|
||||
const db = diagObj.db;
|
||||
const data = db.getWardleyData();
|
||||
const title = db.getDiagramTitle();
|
||||
const width = ((_a2 = data.size) == null ? void 0 : _a2.width) ?? configValues.width;
|
||||
const height = ((_b = data.size) == null ? void 0 : _b.height) ?? configValues.height;
|
||||
const svg = selectSvgElement(id);
|
||||
svg.selectAll("*").remove();
|
||||
configureSvgSize(svg, height, width, configValues.useMaxWidth);
|
||||
svg.attr("viewBox", `0 0 ${width} ${height}`);
|
||||
const root = svg.append("g").attr("class", "wardley-map");
|
||||
const defs = svg.append("defs");
|
||||
defs.append("marker").attr("id", `arrow-${id}`).attr("viewBox", "0 0 10 10").attr("refX", 9).attr("refY", 5).attr("markerWidth", 6).attr("markerHeight", 6).attr("orient", "auto-start-reverse").append("path").attr("d", "M 0 0 L 10 5 L 0 10 z").attr("fill", theme.evolutionStroke).attr("stroke", "none");
|
||||
defs.append("marker").attr("id", `link-arrow-end-${id}`).attr("viewBox", "0 0 10 10").attr("refX", 9).attr("refY", 5).attr("markerWidth", 5).attr("markerHeight", 5).attr("orient", "auto").append("path").attr("d", "M 0 0 L 10 5 L 0 10 z").attr("fill", theme.linkStroke).attr("stroke", "none");
|
||||
defs.append("marker").attr("id", `link-arrow-start-${id}`).attr("viewBox", "0 0 10 10").attr("refX", 1).attr("refY", 5).attr("markerWidth", 5).attr("markerHeight", 5).attr("orient", "auto").append("path").attr("d", "M 10 0 L 0 5 L 10 10 z").attr("fill", theme.linkStroke).attr("stroke", "none");
|
||||
root.append("rect").attr("class", "wardley-background").attr("width", width).attr("height", height).attr("fill", theme.backgroundColor);
|
||||
const chartWidth = width - configValues.padding * 2;
|
||||
const chartHeight = height - configValues.padding * 2;
|
||||
if (title) {
|
||||
root.append("text").attr("class", "wardley-title").attr("x", width / 2).attr("y", configValues.padding / 2).attr("fill", theme.axisTextColor).attr("font-size", configValues.axisFontSize * 1.05).attr("font-weight", "bold").attr("text-anchor", "middle").attr("dominant-baseline", "middle").text(title);
|
||||
}
|
||||
const projectX = __name((value) => configValues.padding + value / 100 * chartWidth, "projectX");
|
||||
const projectY = __name((value) => height - configValues.padding - value / 100 * chartHeight, "projectY");
|
||||
const axisGroup = root.append("g").attr("class", "wardley-axes");
|
||||
axisGroup.append("line").attr("x1", configValues.padding).attr("x2", width - configValues.padding).attr("y1", height - configValues.padding).attr("y2", height - configValues.padding).attr("stroke", theme.axisColor).attr("stroke-width", 1);
|
||||
axisGroup.append("line").attr("x1", configValues.padding).attr("x2", configValues.padding).attr("y1", configValues.padding).attr("y2", height - configValues.padding).attr("stroke", theme.axisColor).attr("stroke-width", 1);
|
||||
const xLabel = data.axes.xLabel ?? "Evolution";
|
||||
const yLabel = data.axes.yLabel ?? "Visibility";
|
||||
axisGroup.append("text").attr("class", "wardley-axis-label wardley-axis-label-x").attr("x", configValues.padding + chartWidth / 2).attr("y", height - configValues.padding / 4).attr("fill", theme.axisTextColor).attr("font-size", configValues.axisFontSize).attr("font-weight", "bold").attr("text-anchor", "middle").text(xLabel);
|
||||
axisGroup.append("text").attr("class", "wardley-axis-label wardley-axis-label-y").attr("x", configValues.padding / 3).attr("y", configValues.padding + chartHeight / 2).attr("fill", theme.axisTextColor).attr("font-size", configValues.axisFontSize).attr("font-weight", "bold").attr("text-anchor", "middle").attr(
|
||||
"transform",
|
||||
`rotate(-90 ${configValues.padding / 3} ${configValues.padding + chartHeight / 2})`
|
||||
).text(yLabel);
|
||||
const stages = data.axes.stages && data.axes.stages.length > 0 ? data.axes.stages : DEFAULT_STAGES;
|
||||
if (stages.length > 0) {
|
||||
const stageGroup = root.append("g").attr("class", "wardley-stages");
|
||||
const boundaries = data.axes.stageBoundaries;
|
||||
const stagePositions = [];
|
||||
if (boundaries && boundaries.length === stages.length) {
|
||||
let prevBoundary = 0;
|
||||
boundaries.forEach((boundary) => {
|
||||
stagePositions.push({ start: prevBoundary, end: boundary });
|
||||
prevBoundary = boundary;
|
||||
});
|
||||
} else {
|
||||
const stageWidth = 1 / stages.length;
|
||||
stages.forEach((_, index) => {
|
||||
stagePositions.push({
|
||||
start: index * stageWidth,
|
||||
end: (index + 1) * stageWidth
|
||||
});
|
||||
});
|
||||
}
|
||||
stages.forEach((stage, index) => {
|
||||
const pos = stagePositions[index];
|
||||
const startX = configValues.padding + pos.start * chartWidth;
|
||||
const endX = configValues.padding + pos.end * chartWidth;
|
||||
const centerX = (startX + endX) / 2;
|
||||
if (index > 0) {
|
||||
stageGroup.append("line").attr("x1", startX).attr("x2", startX).attr("y1", configValues.padding).attr("y2", height - configValues.padding).attr("stroke", "#000").attr("stroke-width", 1).attr("stroke-dasharray", "5 5").attr("opacity", 0.8);
|
||||
}
|
||||
stageGroup.append("text").attr("class", "wardley-stage-label").attr("x", centerX).attr("y", height - configValues.padding / 1.5).attr("fill", theme.axisTextColor).attr("font-size", configValues.axisFontSize - 2).attr("text-anchor", "middle").text(stage);
|
||||
});
|
||||
}
|
||||
if (configValues.showGrid) {
|
||||
const gridGroup = root.append("g").attr("class", "wardley-grid");
|
||||
for (let i = 1; i < 4; i++) {
|
||||
const ratio = i / 4;
|
||||
const x = configValues.padding + chartWidth * ratio;
|
||||
gridGroup.append("line").attr("x1", x).attr("x2", x).attr("y1", configValues.padding).attr("y2", height - configValues.padding).attr("stroke", theme.gridColor).attr("stroke-dasharray", "2 6");
|
||||
gridGroup.append("line").attr("x1", configValues.padding).attr("x2", width - configValues.padding).attr("y1", height - configValues.padding - chartHeight * ratio).attr("y2", height - configValues.padding - chartHeight * ratio).attr("stroke", theme.gridColor).attr("stroke-dasharray", "2 6");
|
||||
}
|
||||
}
|
||||
const positions = /* @__PURE__ */ new Map();
|
||||
data.nodes.forEach((node) => {
|
||||
positions.set(node.id, {
|
||||
x: projectX(node.x),
|
||||
y: projectY(node.y),
|
||||
node
|
||||
});
|
||||
});
|
||||
if (data.pipelines.length > 0) {
|
||||
const pipelineGroup = root.append("g").attr("class", "wardley-pipelines");
|
||||
const pipelineLinksGroup = root.append("g").attr("class", "wardley-pipeline-links");
|
||||
data.pipelines.forEach((pipeline) => {
|
||||
if (pipeline.componentIds.length === 0) {
|
||||
return;
|
||||
}
|
||||
const sortedComponents = pipeline.componentIds.map((id2) => ({ id: id2, pos: positions.get(id2), node: data.nodes.find((n) => n.id === id2) })).filter((c) => c.pos && c.node).sort((a, b) => a.node.x - b.node.x);
|
||||
for (let i = 0; i < sortedComponents.length - 1; i++) {
|
||||
const current = sortedComponents[i];
|
||||
const next = sortedComponents[i + 1];
|
||||
pipelineLinksGroup.append("line").attr("class", "wardley-pipeline-evolution-link").attr("x1", current.pos.x).attr("y1", current.pos.y).attr("x2", next.pos.x).attr("y2", next.pos.y).attr("stroke", theme.linkStroke).attr("stroke-width", 1).attr("stroke-dasharray", "4 4");
|
||||
}
|
||||
let minX = Infinity;
|
||||
let maxX = -Infinity;
|
||||
let y = 0;
|
||||
pipeline.componentIds.forEach((componentId) => {
|
||||
const pos = positions.get(componentId);
|
||||
if (pos) {
|
||||
minX = Math.min(minX, pos.x);
|
||||
maxX = Math.max(maxX, pos.x);
|
||||
y = pos.y;
|
||||
}
|
||||
});
|
||||
if (minX !== Infinity && maxX !== -Infinity) {
|
||||
const padding = 15;
|
||||
const height2 = configValues.nodeRadius * 4;
|
||||
const boxTop = y - height2 / 2;
|
||||
const parentPos = positions.get(pipeline.nodeId);
|
||||
if (parentPos) {
|
||||
const centerX = (minX + maxX) / 2;
|
||||
parentPos.x = centerX;
|
||||
parentPos.y = boxTop - squareSize / 6;
|
||||
}
|
||||
pipelineGroup.append("rect").attr("class", "wardley-pipeline-box").attr("x", minX - padding).attr("y", boxTop).attr("width", maxX - minX + padding * 2).attr("height", height2).attr("fill", "none").attr("stroke", theme.axisColor).attr("stroke-width", 1.5).attr("rx", 4).attr("ry", 4);
|
||||
}
|
||||
});
|
||||
}
|
||||
const linksGroup = root.append("g").attr("class", "wardley-links");
|
||||
const pipelineMap = /* @__PURE__ */ new Map();
|
||||
data.pipelines.forEach((pipeline) => {
|
||||
pipelineMap.set(pipeline.nodeId, new Set(pipeline.componentIds));
|
||||
});
|
||||
const validLinks = data.links.filter((link) => {
|
||||
if (!positions.has(link.source) || !positions.has(link.target)) {
|
||||
return false;
|
||||
}
|
||||
const pipelineComponents = pipelineMap.get(link.target);
|
||||
if (pipelineComponents == null ? void 0 : pipelineComponents.has(link.source)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
linksGroup.selectAll("line").data(validLinks).enter().append("line").attr("class", (link) => `wardley-link${link.dashed ? " wardley-link--dashed" : ""}`).attr("x1", (link) => {
|
||||
const sourcePos = positions.get(link.source);
|
||||
const targetPos = positions.get(link.target);
|
||||
const sourceNode = data.nodes.find((n) => n.id === link.source);
|
||||
const radius = sourceNode.isPipelineParent ? squareSize / Math.sqrt(2) : configValues.nodeRadius;
|
||||
const dx = targetPos.x - sourcePos.x;
|
||||
const dy = targetPos.y - sourcePos.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
return sourcePos.x + dx / distance * radius;
|
||||
}).attr("y1", (link) => {
|
||||
const sourcePos = positions.get(link.source);
|
||||
const targetPos = positions.get(link.target);
|
||||
const sourceNode = data.nodes.find((n) => n.id === link.source);
|
||||
const radius = sourceNode.isPipelineParent ? squareSize / Math.sqrt(2) : configValues.nodeRadius;
|
||||
const dx = targetPos.x - sourcePos.x;
|
||||
const dy = targetPos.y - sourcePos.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
return sourcePos.y + dy / distance * radius;
|
||||
}).attr("x2", (link) => {
|
||||
const sourcePos = positions.get(link.source);
|
||||
const targetPos = positions.get(link.target);
|
||||
const targetNode = data.nodes.find((n) => n.id === link.target);
|
||||
const radius = targetNode.isPipelineParent ? squareSize / Math.sqrt(2) : configValues.nodeRadius;
|
||||
const dx = sourcePos.x - targetPos.x;
|
||||
const dy = sourcePos.y - targetPos.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
return targetPos.x + dx / distance * radius;
|
||||
}).attr("y2", (link) => {
|
||||
const sourcePos = positions.get(link.source);
|
||||
const targetPos = positions.get(link.target);
|
||||
const targetNode = data.nodes.find((n) => n.id === link.target);
|
||||
const radius = targetNode.isPipelineParent ? squareSize / Math.sqrt(2) : configValues.nodeRadius;
|
||||
const dx = sourcePos.x - targetPos.x;
|
||||
const dy = sourcePos.y - targetPos.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
return targetPos.y + dy / distance * radius;
|
||||
}).attr("stroke", theme.linkStroke).attr("stroke-width", 1).attr("stroke-dasharray", (link) => link.dashed ? "6 6" : null).attr("marker-end", (link) => {
|
||||
if (link.flow === "forward" || link.flow === "bidirectional") {
|
||||
return `url(#link-arrow-end-${id})`;
|
||||
}
|
||||
return null;
|
||||
}).attr("marker-start", (link) => {
|
||||
if (link.flow === "backward" || link.flow === "bidirectional") {
|
||||
return `url(#link-arrow-start-${id})`;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
linksGroup.selectAll("text").data(validLinks.filter((link) => link.label)).enter().append("text").attr("class", "wardley-link-label").attr("x", (link) => {
|
||||
const sourcePos = positions.get(link.source);
|
||||
const targetPos = positions.get(link.target);
|
||||
const midX = (sourcePos.x + targetPos.x) / 2;
|
||||
const dy = targetPos.y - sourcePos.y;
|
||||
const dx = targetPos.x - sourcePos.x;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
const offset = 8;
|
||||
const perpX = dy / distance;
|
||||
return midX + perpX * offset;
|
||||
}).attr("y", (link) => {
|
||||
const sourcePos = positions.get(link.source);
|
||||
const targetPos = positions.get(link.target);
|
||||
const midY = (sourcePos.y + targetPos.y) / 2;
|
||||
const dx = targetPos.x - sourcePos.x;
|
||||
const dy = targetPos.y - sourcePos.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
const offset = 8;
|
||||
const perpY = -dx / distance;
|
||||
return midY + perpY * offset;
|
||||
}).attr("fill", theme.axisTextColor).attr("font-size", configValues.labelFontSize).attr("text-anchor", "middle").attr("dominant-baseline", "middle").attr("transform", (link) => {
|
||||
const sourcePos = positions.get(link.source);
|
||||
const targetPos = positions.get(link.target);
|
||||
const midX = (sourcePos.x + targetPos.x) / 2;
|
||||
const midY = (sourcePos.y + targetPos.y) / 2;
|
||||
const dx = targetPos.x - sourcePos.x;
|
||||
const dy = targetPos.y - sourcePos.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
const offset = 8;
|
||||
const perpX = dy / distance;
|
||||
const perpY = -dx / distance;
|
||||
const labelX = midX + perpX * offset;
|
||||
const labelY = midY + perpY * offset;
|
||||
let angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
||||
if (angle > 90 || angle < -90) {
|
||||
angle += 180;
|
||||
}
|
||||
return `rotate(${angle} ${labelX} ${labelY})`;
|
||||
}).text((link) => link.label);
|
||||
const trendGroup = root.append("g").attr("class", "wardley-trends");
|
||||
const trendsWithPositions = data.trends.map((trend) => {
|
||||
const origin = positions.get(trend.nodeId);
|
||||
if (!origin) {
|
||||
return null;
|
||||
}
|
||||
const targetX = projectX(trend.targetX);
|
||||
const targetY = projectY(trend.targetY);
|
||||
const dx = targetX - origin.x;
|
||||
const dy = targetY - origin.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
const shortenBy = configValues.nodeRadius + 2;
|
||||
const adjustedX2 = distance > shortenBy ? targetX - dx / distance * shortenBy : targetX;
|
||||
const adjustedY2 = distance > shortenBy ? targetY - dy / distance * shortenBy : targetY;
|
||||
return {
|
||||
origin,
|
||||
targetX,
|
||||
targetY,
|
||||
adjustedX2,
|
||||
adjustedY2
|
||||
};
|
||||
}).filter((trend) => trend !== null);
|
||||
trendGroup.selectAll("line").data(trendsWithPositions).enter().append("line").attr("class", "wardley-trend").attr("x1", (trend) => trend.origin.x).attr("y1", (trend) => trend.origin.y).attr("x2", (trend) => trend.adjustedX2).attr("y2", (trend) => trend.adjustedY2).attr("stroke", theme.evolutionStroke).attr("stroke-width", 1).attr("stroke-dasharray", "4 4").attr("marker-end", `url(#arrow-${id})`);
|
||||
const nodesGroup = root.append("g").attr("class", "wardley-nodes");
|
||||
const nodeEnter = nodesGroup.selectAll("g").data(data.nodes).enter().append("g").attr(
|
||||
"class",
|
||||
(node) => ["wardley-node", node.className ? `wardley-node--${node.className}` : ""].filter(Boolean).join(" ")
|
||||
);
|
||||
nodeEnter.filter((node) => node.sourceStrategy === "outsource").append("circle").attr("class", "wardley-outsource-overlay").attr("cx", (node) => positions.get(node.id).x).attr("cy", (node) => positions.get(node.id).y).attr("r", configValues.nodeRadius * 2).attr("fill", "#666").attr("stroke", theme.componentStroke).attr("stroke-width", 1);
|
||||
nodeEnter.filter((node) => node.sourceStrategy === "buy").append("circle").attr("class", "wardley-buy-overlay").attr("cx", (node) => positions.get(node.id).x).attr("cy", (node) => positions.get(node.id).y).attr("r", configValues.nodeRadius * 2).attr("fill", "#ccc").attr("stroke", theme.componentStroke).attr("stroke-width", 1);
|
||||
nodeEnter.filter((node) => node.sourceStrategy === "build").append("circle").attr("class", "wardley-build-overlay").attr("cx", (node) => positions.get(node.id).x).attr("cy", (node) => positions.get(node.id).y).attr("r", configValues.nodeRadius * 2).attr("fill", "#eee").attr("stroke", "#000").attr("stroke-width", 1);
|
||||
const marketNodes = nodeEnter.filter((node) => node.sourceStrategy === "market");
|
||||
marketNodes.append("circle").attr("class", "wardley-market-overlay").attr("cx", (node) => positions.get(node.id).x).attr("cy", (node) => positions.get(node.id).y).attr("r", configValues.nodeRadius * 2).attr("fill", "white").attr("stroke", theme.componentStroke).attr("stroke-width", 1);
|
||||
nodeEnter.filter(
|
||||
(node) => !node.isPipelineParent && node.sourceStrategy !== "market" && node.className !== "anchor"
|
||||
).append("circle").attr("cx", (node) => positions.get(node.id).x).attr("cy", (node) => positions.get(node.id).y).attr("r", configValues.nodeRadius).attr("fill", theme.componentFill).attr("stroke", theme.componentStroke).attr("stroke-width", 1);
|
||||
const smallCircleRadius = configValues.nodeRadius * 0.7;
|
||||
const triangleRadius = configValues.nodeRadius * 1.2;
|
||||
marketNodes.append("line").attr("class", "wardley-market-line").attr("x1", (node) => positions.get(node.id).x).attr("y1", (node) => positions.get(node.id).y - triangleRadius).attr("x2", (node) => positions.get(node.id).x - triangleRadius * Math.cos(Math.PI / 6)).attr("y2", (node) => positions.get(node.id).y + triangleRadius * Math.sin(Math.PI / 6)).attr("stroke", theme.componentStroke).attr("stroke-width", 1);
|
||||
marketNodes.append("line").attr("class", "wardley-market-line").attr("x1", (node) => positions.get(node.id).x - triangleRadius * Math.cos(Math.PI / 6)).attr("y1", (node) => positions.get(node.id).y + triangleRadius * Math.sin(Math.PI / 6)).attr("x2", (node) => positions.get(node.id).x + triangleRadius * Math.cos(Math.PI / 6)).attr("y2", (node) => positions.get(node.id).y + triangleRadius * Math.sin(Math.PI / 6)).attr("stroke", theme.componentStroke).attr("stroke-width", 1);
|
||||
marketNodes.append("line").attr("class", "wardley-market-line").attr("x1", (node) => positions.get(node.id).x + triangleRadius * Math.cos(Math.PI / 6)).attr("y1", (node) => positions.get(node.id).y + triangleRadius * Math.sin(Math.PI / 6)).attr("x2", (node) => positions.get(node.id).x).attr("y2", (node) => positions.get(node.id).y - triangleRadius).attr("stroke", theme.componentStroke).attr("stroke-width", 1);
|
||||
marketNodes.append("circle").attr("class", "wardley-market-dot").attr("cx", (node) => positions.get(node.id).x).attr("cy", (node) => positions.get(node.id).y - triangleRadius).attr("r", smallCircleRadius).attr("fill", "white").attr("stroke", theme.componentStroke).attr("stroke-width", 2);
|
||||
marketNodes.append("circle").attr("class", "wardley-market-dot").attr("cx", (node) => positions.get(node.id).x - triangleRadius * Math.cos(Math.PI / 6)).attr("cy", (node) => positions.get(node.id).y + triangleRadius * Math.sin(Math.PI / 6)).attr("r", smallCircleRadius).attr("fill", "white").attr("stroke", theme.componentStroke).attr("stroke-width", 2);
|
||||
marketNodes.append("circle").attr("class", "wardley-market-dot").attr("cx", (node) => positions.get(node.id).x + triangleRadius * Math.cos(Math.PI / 6)).attr("cy", (node) => positions.get(node.id).y + triangleRadius * Math.sin(Math.PI / 6)).attr("r", smallCircleRadius).attr("fill", "white").attr("stroke", theme.componentStroke).attr("stroke-width", 2);
|
||||
nodeEnter.filter((node) => node.isPipelineParent === true).append("rect").attr("x", (node) => positions.get(node.id).x - squareSize / 2).attr("y", (node) => positions.get(node.id).y - squareSize / 2).attr("width", squareSize).attr("height", squareSize).attr("fill", theme.componentFill).attr("stroke", theme.componentStroke).attr("stroke-width", 1);
|
||||
nodeEnter.filter((node) => node.inertia === true).append("line").attr("class", "wardley-inertia").attr("x1", (node) => {
|
||||
const pos = positions.get(node.id);
|
||||
let offset = node.isPipelineParent ? squareSize / 2 + 15 : configValues.nodeRadius + 15;
|
||||
if (node.sourceStrategy) {
|
||||
offset += configValues.nodeRadius + 10;
|
||||
}
|
||||
return pos.x + offset;
|
||||
}).attr("y1", (node) => {
|
||||
const pos = positions.get(node.id);
|
||||
const lineHeight = node.isPipelineParent ? squareSize : configValues.nodeRadius * 2;
|
||||
return pos.y - lineHeight / 2;
|
||||
}).attr("x2", (node) => {
|
||||
const pos = positions.get(node.id);
|
||||
let offset = node.isPipelineParent ? squareSize / 2 + 15 : configValues.nodeRadius + 15;
|
||||
if (node.sourceStrategy) {
|
||||
offset += configValues.nodeRadius + 10;
|
||||
}
|
||||
return pos.x + offset;
|
||||
}).attr("y2", (node) => {
|
||||
const pos = positions.get(node.id);
|
||||
const lineHeight = node.isPipelineParent ? squareSize : configValues.nodeRadius * 2;
|
||||
return pos.y + lineHeight / 2;
|
||||
}).attr("stroke", theme.componentStroke).attr("stroke-width", 6);
|
||||
nodeEnter.append("text").attr("x", (node) => {
|
||||
const pos = positions.get(node.id);
|
||||
if (node.className === "anchor") {
|
||||
return node.labelOffsetX !== void 0 ? pos.x + node.labelOffsetX : pos.x;
|
||||
}
|
||||
let defaultOffset = configValues.nodeLabelOffset;
|
||||
if (node.sourceStrategy && node.labelOffsetX === void 0) {
|
||||
defaultOffset += 10;
|
||||
}
|
||||
const customOffset = node.labelOffsetX ?? defaultOffset;
|
||||
return pos.x + customOffset;
|
||||
}).attr("y", (node) => {
|
||||
const pos = positions.get(node.id);
|
||||
if (node.className === "anchor") {
|
||||
return node.labelOffsetY !== void 0 ? pos.y + node.labelOffsetY : pos.y - 3;
|
||||
}
|
||||
let defaultOffset = -configValues.nodeLabelOffset;
|
||||
if (node.sourceStrategy && node.labelOffsetY === void 0) {
|
||||
defaultOffset -= 10;
|
||||
}
|
||||
const customOffset = node.labelOffsetY ?? defaultOffset;
|
||||
return pos.y + customOffset;
|
||||
}).attr("class", "wardley-node-label").attr("fill", (node) => {
|
||||
if (node.className === "evolved") {
|
||||
return theme.evolutionStroke;
|
||||
}
|
||||
if (node.className === "anchor") {
|
||||
return "#000";
|
||||
}
|
||||
return theme.componentLabelColor;
|
||||
}).attr("font-size", configValues.labelFontSize).attr("font-weight", (node) => node.className === "anchor" ? "bold" : "normal").attr("text-anchor", (node) => node.className === "anchor" ? "middle" : "start").attr("dominant-baseline", (node) => node.className === "anchor" ? "middle" : "auto").text((node) => node.label);
|
||||
if (data.annotations.length > 0) {
|
||||
const annotationsGroup = root.append("g").attr("class", "wardley-annotations");
|
||||
data.annotations.forEach((annotation) => {
|
||||
const projectedCoords = annotation.coordinates.map((coord) => ({
|
||||
x: projectX(coord.x),
|
||||
y: projectY(coord.y)
|
||||
}));
|
||||
if (projectedCoords.length > 1) {
|
||||
for (let i = 0; i < projectedCoords.length - 1; i++) {
|
||||
annotationsGroup.append("line").attr("class", "wardley-annotation-line").attr("x1", projectedCoords[i].x).attr("y1", projectedCoords[i].y).attr("x2", projectedCoords[i + 1].x).attr("y2", projectedCoords[i + 1].y).attr("stroke", theme.axisColor).attr("stroke-width", 1.5).attr("stroke-dasharray", "4 4");
|
||||
}
|
||||
}
|
||||
projectedCoords.forEach((coord) => {
|
||||
const annotationNode = annotationsGroup.append("g").attr("class", "wardley-annotation");
|
||||
annotationNode.append("circle").attr("cx", coord.x).attr("cy", coord.y).attr("r", 10).attr("fill", "white").attr("stroke", theme.axisColor).attr("stroke-width", 1.5);
|
||||
annotationNode.append("text").attr("x", coord.x).attr("y", coord.y).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", 10).attr("fill", theme.axisTextColor).attr("font-weight", "bold").text(annotation.number);
|
||||
});
|
||||
});
|
||||
if (data.annotationsBox) {
|
||||
let boxX = projectX(data.annotationsBox.x);
|
||||
let boxY = projectY(data.annotationsBox.y);
|
||||
const padding = 10;
|
||||
const lineHeight = 16;
|
||||
const fontSize = 11;
|
||||
const textBoxGroup = annotationsGroup.append("g").attr("class", "wardley-annotations-box");
|
||||
const sortedAnnotations = [...data.annotations].filter((a) => a.text).sort((a, b) => a.number - b.number);
|
||||
const textElements = [];
|
||||
sortedAnnotations.forEach((annotation, idx) => {
|
||||
const text2 = textBoxGroup.append("text").attr("x", boxX + padding).attr("y", boxY + padding + (idx + 1) * lineHeight).attr("font-size", fontSize).attr("fill", theme.axisTextColor).attr("text-anchor", "start").attr("dominant-baseline", "middle").text(`${annotation.number}. ${annotation.text}`);
|
||||
textElements.push(text2);
|
||||
});
|
||||
if (textElements.length > 0) {
|
||||
let maxWidth = 0;
|
||||
let maxHeight = 0;
|
||||
textElements.forEach((text2) => {
|
||||
const textNode = text2.node();
|
||||
const textWidth = textNode.getComputedTextLength();
|
||||
maxWidth = Math.max(maxWidth, textWidth);
|
||||
const bbox = textNode.getBBox();
|
||||
maxHeight = Math.max(maxHeight, bbox.height);
|
||||
});
|
||||
const boxWidth = maxWidth + padding * 2 + 105;
|
||||
const boxHeight = sortedAnnotations.length * lineHeight + padding * 2 + maxHeight / 2;
|
||||
const minX = configValues.padding;
|
||||
const maxX = width - configValues.padding - boxWidth;
|
||||
const minY = configValues.padding;
|
||||
const maxY = height - configValues.padding - boxHeight;
|
||||
boxX = Math.max(minX, Math.min(boxX, maxX));
|
||||
boxY = Math.max(minY, Math.min(boxY, maxY));
|
||||
textElements.forEach((text2, idx) => {
|
||||
text2.attr("x", boxX + padding).attr("y", boxY + padding + (idx + 1) * lineHeight);
|
||||
});
|
||||
textBoxGroup.insert("rect", "text").attr("x", boxX).attr("y", boxY).attr("width", boxWidth).attr("height", boxHeight).attr("fill", "white").attr("stroke", theme.axisColor).attr("stroke-width", 1.5).attr("rx", 4).attr("ry", 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data.notes.length > 0) {
|
||||
const notesGroup = root.append("g").attr("class", "wardley-notes");
|
||||
data.notes.forEach((note) => {
|
||||
const noteX = projectX(note.x);
|
||||
const noteY = projectY(note.y);
|
||||
notesGroup.append("text").attr("x", noteX).attr("y", noteY).attr("text-anchor", "start").attr("font-size", 11).attr("fill", theme.axisTextColor).attr("font-weight", "bold").text(note.text);
|
||||
});
|
||||
}
|
||||
if (data.accelerators.length > 0) {
|
||||
const acceleratorsGroup = root.append("g").attr("class", "wardley-accelerators");
|
||||
data.accelerators.forEach((accelerator) => {
|
||||
const accX = projectX(accelerator.x);
|
||||
const accY = projectY(accelerator.y);
|
||||
const arrowWidth = 60;
|
||||
const arrowHeight = 30;
|
||||
const arrowHeadWidth = 20;
|
||||
const arrowPath = `
|
||||
M ${accX} ${accY - arrowHeight / 2}
|
||||
L ${accX + arrowWidth - arrowHeadWidth} ${accY - arrowHeight / 2}
|
||||
L ${accX + arrowWidth - arrowHeadWidth} ${accY - arrowHeight / 2 - 8}
|
||||
L ${accX + arrowWidth} ${accY}
|
||||
L ${accX + arrowWidth - arrowHeadWidth} ${accY + arrowHeight / 2 + 8}
|
||||
L ${accX + arrowWidth - arrowHeadWidth} ${accY + arrowHeight / 2}
|
||||
L ${accX} ${accY + arrowHeight / 2}
|
||||
Z
|
||||
`;
|
||||
acceleratorsGroup.append("path").attr("d", arrowPath).attr("fill", "white").attr("stroke", theme.componentStroke).attr("stroke-width", 1);
|
||||
acceleratorsGroup.append("text").attr("x", accX + arrowWidth / 2).attr("y", accY + arrowHeight / 2 + 15).attr("text-anchor", "middle").attr("font-size", 10).attr("fill", theme.axisTextColor).attr("font-weight", "bold").text(accelerator.name);
|
||||
});
|
||||
}
|
||||
if (data.deaccelerators.length > 0) {
|
||||
const deacceleratorsGroup = root.append("g").attr("class", "wardley-deaccelerators");
|
||||
data.deaccelerators.forEach((deaccelerator) => {
|
||||
const decX = projectX(deaccelerator.x);
|
||||
const decY = projectY(deaccelerator.y);
|
||||
const arrowWidth = 60;
|
||||
const arrowHeight = 30;
|
||||
const arrowHeadWidth = 20;
|
||||
const arrowPath = `
|
||||
M ${decX + arrowWidth} ${decY - arrowHeight / 2}
|
||||
L ${decX + arrowHeadWidth} ${decY - arrowHeight / 2}
|
||||
L ${decX + arrowHeadWidth} ${decY - arrowHeight / 2 - 8}
|
||||
L ${decX} ${decY}
|
||||
L ${decX + arrowHeadWidth} ${decY + arrowHeight / 2 + 8}
|
||||
L ${decX + arrowHeadWidth} ${decY + arrowHeight / 2}
|
||||
L ${decX + arrowWidth} ${decY + arrowHeight / 2}
|
||||
Z
|
||||
`;
|
||||
deacceleratorsGroup.append("path").attr("d", arrowPath).attr("fill", "white").attr("stroke", theme.componentStroke).attr("stroke-width", 1);
|
||||
deacceleratorsGroup.append("text").attr("x", decX + arrowWidth / 2).attr("y", decY + arrowHeight / 2 + 15).attr("text-anchor", "middle").attr("font-size", 10).attr("fill", theme.axisTextColor).attr("font-weight", "bold").text(deaccelerator.name);
|
||||
});
|
||||
}
|
||||
}, "draw");
|
||||
var wardleyRenderer_default = {
|
||||
draw
|
||||
};
|
||||
var diagram = {
|
||||
parser,
|
||||
db: wardleyDb_default,
|
||||
renderer: wardleyRenderer_default,
|
||||
styles: __name(() => "", "styles")
|
||||
};
|
||||
export {
|
||||
diagram
|
||||
};
|
||||
//# sourceMappingURL=wardleyDiagram-NUSXRM2D-CUADBIPO.js.map
|
||||
-7
File diff suppressed because one or more lines are too long
-1932
File diff suppressed because it is too large
Load Diff
-7
File diff suppressed because one or more lines are too long
Generated
+11
@@ -8,6 +8,7 @@
|
||||
"name": "auth-app-client",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"date-fns": "^4.1.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"katex": "^0.16.45",
|
||||
"marked": "^12.0.0",
|
||||
@@ -2246,6 +2247,16 @@
|
||||
"lodash-es": "^4.17.21"
|
||||
}
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/date-fns/-/date-fns-4.1.0.tgz",
|
||||
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.20",
|
||||
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.20.tgz",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"date-fns": "^4.1.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"katex": "^0.16.45",
|
||||
"marked": "^12.0.0",
|
||||
|
||||
@@ -3,6 +3,8 @@ import Navbar from './components/Navbar';
|
||||
import Login from './pages/Login';
|
||||
import Register from './pages/Register';
|
||||
import MD2Doc from './pages/MD2Doc';
|
||||
import Admin from './pages/Admin';
|
||||
import Profile from './pages/Profile';
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
@@ -11,6 +13,8 @@ export default function App() {
|
||||
<Routes>
|
||||
<Route path="/login" element={<Login />} />
|
||||
<Route path="/register" element={<Register />} />
|
||||
<Route path="/admin" element={<Admin />} />
|
||||
<Route path="/profile" element={<Profile />} />
|
||||
{/* 取消拦截,将转换工具设为首页 */}
|
||||
<Route path="/" element={<MD2Doc />} />
|
||||
</Routes>
|
||||
|
||||
@@ -13,11 +13,14 @@ export default function Navbar() {
|
||||
return (
|
||||
<nav style={styles.navbar}>
|
||||
<div style={styles.container}>
|
||||
<Link to="/" style={styles.logo}>我的网站</Link>
|
||||
<Link to="/" style={styles.logo}>DeepSeek转Word / AI公式转Word / Markdown转Word</Link>
|
||||
<div style={styles.links}>
|
||||
{user ? (
|
||||
<>
|
||||
<Link to="/md2doc" style={styles.link}>Markdown转Word</Link>
|
||||
{user.username === 'admin' && (
|
||||
<Link to="/admin" style={styles.adminLink}>进入后台</Link>
|
||||
)}
|
||||
<Link to="/profile" style={styles.profileLink}>个人中心</Link>
|
||||
<span style={styles.welcome}>欢迎, {user.username}</span>
|
||||
<button onClick={handleLogout} style={styles.logoutBtn}>
|
||||
退出
|
||||
@@ -25,7 +28,6 @@ export default function Navbar() {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Link to="/md2doc" style={styles.link}>Markdown转Word</Link>
|
||||
<Link to="/login" style={styles.link}>登录</Link>
|
||||
<Link to="/register" style={styles.link}>注册</Link>
|
||||
</>
|
||||
@@ -67,9 +69,23 @@ const styles = {
|
||||
textDecoration: 'none'
|
||||
},
|
||||
welcome: {
|
||||
color: '#333',
|
||||
color: '#666',
|
||||
fontSize: '14px'
|
||||
},
|
||||
adminLink: {
|
||||
marginRight: '20px',
|
||||
color: '#ef4444',
|
||||
textDecoration: 'none',
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px'
|
||||
},
|
||||
profileLink: {
|
||||
marginRight: '15px',
|
||||
color: '#4a90d9',
|
||||
textDecoration: 'none',
|
||||
fontSize: '14px',
|
||||
fontWeight: '500'
|
||||
},
|
||||
logoutBtn: {
|
||||
padding: '6px 16px',
|
||||
backgroundColor: '#6c757d',
|
||||
|
||||
@@ -41,22 +41,22 @@ export function AuthProvider({ children }) {
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) {
|
||||
throw new Error(data.error);
|
||||
throw new Error(data.detail || data.error);
|
||||
}
|
||||
localStorage.setItem('token', data.token);
|
||||
setUser(data.user);
|
||||
return data;
|
||||
}
|
||||
|
||||
async function register(username, password) {
|
||||
async function register(username, email, password, captcha_id, captcha_code) {
|
||||
const res = await fetch('/api/register', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username, password })
|
||||
body: JSON.stringify({ username, email, password, captcha_id, captcha_code })
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) {
|
||||
throw new Error(data.error);
|
||||
throw new Error(data.detail || data.error);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { Link, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
|
||||
export default function Login() {
|
||||
@@ -9,6 +9,7 @@ export default function Login() {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { login } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
async function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
@@ -17,7 +18,8 @@ export default function Login() {
|
||||
|
||||
try {
|
||||
await login(username, password);
|
||||
navigate('/');
|
||||
const from = location.state?.from || '/';
|
||||
navigate(from);
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
|
||||
+586
-40
@@ -5,15 +5,244 @@ import katex from 'katex';
|
||||
import 'katex/dist/katex.min.css';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { format } from 'date-fns';
|
||||
|
||||
export default function MD2Doc() {
|
||||
const { user } = useAuth();
|
||||
const [markdown, setMarkdown] = useState('');
|
||||
const navigate = useNavigate();
|
||||
const [markdown, setMarkdown] = useState(() => {
|
||||
return localStorage.getItem('draft_markdown') || '';
|
||||
});
|
||||
const [preview, setPreview] = useState('');
|
||||
const [exporting, setExporting] = useState(false);
|
||||
const [history, setHistory] = useState([]);
|
||||
const [showStylePanel, setShowStylePanel] = useState(false);
|
||||
const [showLoginPrompt, setShowLoginPrompt] = useState(false);
|
||||
const [showHistory, setShowHistory] = useState(true);
|
||||
const [styleOptions, setStyleOptions] = useState(() => {
|
||||
const draftStyles = localStorage.getItem('draft_styleOptions');
|
||||
if (draftStyles) {
|
||||
try {
|
||||
return JSON.parse(draftStyles);
|
||||
} catch (e) {}
|
||||
}
|
||||
return {
|
||||
base_font_size: 12,
|
||||
base_font_family: "宋体",
|
||||
h1_size: 18,
|
||||
h2_size: 16,
|
||||
h3_size: 14,
|
||||
h4_size: 12
|
||||
};
|
||||
});
|
||||
const [showMoreTemplates, setShowMoreTemplates] = useState(false);
|
||||
const [customTemplates, setCustomTemplates] = useState([]);
|
||||
const [deletedTemplates, setDeletedTemplates] = useState(() => {
|
||||
const saved = localStorage.getItem('deleted_templates');
|
||||
return saved ? JSON.parse(saved) : [];
|
||||
});
|
||||
const previewRef = useRef(null);
|
||||
|
||||
// 右侧面板状态
|
||||
const [showFormatSettings, setShowFormatSettings] = useState(false);
|
||||
|
||||
// 联动滚动相关状态
|
||||
const [isSyncScroll, setIsSyncScroll] = useState(true);
|
||||
const textareaRef = useRef(null);
|
||||
const previewScrollRef = useRef(null);
|
||||
const isSyncingLeft = useRef(false);
|
||||
const isSyncingRight = useRef(false);
|
||||
|
||||
const isLoggedIn = !!localStorage.getItem('token');
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoggedIn) {
|
||||
const saved = localStorage.getItem('user_templates');
|
||||
if (saved) setCustomTemplates(JSON.parse(saved));
|
||||
}
|
||||
}, [isLoggedIn]);
|
||||
|
||||
const allTemplates = [
|
||||
{ icon: '📚', name: '学术论文' }, { icon: '💼', name: '商务报告' }, { icon: '💻', name: '技术文档' }, { icon: '🎓', name: '教学材料' },
|
||||
{ icon: '🏛️', name: '政府公文' }, { icon: '✨', name: '简约现代' }, { icon: '📖', name: '期刊杂志' }, { icon: '📋', name: '合同协议' },
|
||||
{ icon: '📊', name: '数据报告' }, { icon: '📝', name: '新闻稿件' }, { icon: '🎨', name: '创意设计' }, { icon: '⚖️', name: '法律文书' },
|
||||
{ icon: '🏥', name: '医疗健康' }, { icon: '💰', name: '财务金融' }, { icon: '🌱', name: '环保公益' }, { icon: '🎯', name: '营销策划' },
|
||||
{ icon: '🔬', name: '科研实验' }, { icon: '📱', name: '产品说明' }
|
||||
];
|
||||
|
||||
const allTemplatesList = [...customTemplates, ...allTemplates].filter(t => !deletedTemplates.includes(t.name));
|
||||
const visibleTemplates = showMoreTemplates ? allTemplatesList : allTemplatesList.slice(0, 8);
|
||||
|
||||
const templates = {
|
||||
'默认': { base_font_size: 10.5, base_font_family: "等线", h1_size: 18, h2_size: 16, h3_size: 15, h4_size: 12 },
|
||||
'学术论文': { base_font_size: 12, base_font_family: "宋体", h1_size: 18, h2_size: 16, h3_size: 15, h4_size: 12 },
|
||||
'期刊杂志': { base_font_size: 12, base_font_family: "宋体", h1_size: 16, h2_size: 15, h3_size: 14, h4_size: 12 },
|
||||
'合同协议': { base_font_size: 14, base_font_family: "宋体", h1_size: 18, h2_size: 16, h3_size: 15, h4_size: 12 },
|
||||
'新闻稿件': { base_font_size: 12, base_font_family: "宋体", h1_size: 22, h2_size: 18, h3_size: 16, h4_size: 14 },
|
||||
'政府公文': { base_font_size: 16, base_font_family: "仿宋", h1_size: 22, h2_size: 18, h3_size: 16, h4_size: 14 },
|
||||
'法律文书': { base_font_size: 16, base_font_family: "仿宋", h1_size: 22, h2_size: 18, h3_size: 16, h4_size: 14 },
|
||||
'商务报告': { base_font_size: 10.5, base_font_family: "微软雅黑", h1_size: 18, h2_size: 16, h3_size: 15, h4_size: 12 },
|
||||
'技术文档': { base_font_size: 10.5, base_font_family: "Calibri", h1_size: 18, h2_size: 16, h3_size: 15, h4_size: 12 },
|
||||
'数据报告': { base_font_size: 10.5, base_font_family: "微软雅黑", h1_size: 18, h2_size: 16, h3_size: 15, h4_size: 12 },
|
||||
'财务金融': { base_font_size: 10.5, base_font_family: "Calibri", h1_size: 18, h2_size: 16, h3_size: 15, h4_size: 12 },
|
||||
'产品说明': { base_font_size: 10.5, base_font_family: "微软雅黑", h1_size: 18, h2_size: 16, h3_size: 15, h4_size: 12 },
|
||||
'医疗健康': { base_font_size: 10.5, base_font_family: "微软雅黑", h1_size: 18, h2_size: 16, h3_size: 15, h4_size: 12 },
|
||||
'简约现代': { base_font_size: 10.5, base_font_family: "等线", h1_size: 18, h2_size: 16, h3_size: 15, h4_size: 12 },
|
||||
'创意设计': { base_font_size: 10.5, base_font_family: "微软雅黑", h1_size: 22, h2_size: 18, h3_size: 16, h4_size: 14 },
|
||||
'营销策划': { base_font_size: 10.5, base_font_family: "微软雅黑", h1_size: 22, h2_size: 18, h3_size: 16, h4_size: 14 },
|
||||
'教学材料': { base_font_size: 12, base_font_family: "微软雅黑", h1_size: 22, h2_size: 18, h3_size: 16, h4_size: 14 },
|
||||
'环保公益': { base_font_size: 10.5, base_font_family: "微软雅黑", h1_size: 18, h2_size: 16, h3_size: 15, h4_size: 12 },
|
||||
'科研实验': { base_font_size: 12, base_font_family: "Times New Roman", h1_size: 18, h2_size: 16, h3_size: 15, h4_size: 12 }
|
||||
};
|
||||
|
||||
const handleTemplateChange = (e) => {
|
||||
const tName = e.target.value;
|
||||
const config = templates[tName] || customTemplates.find(t => t.name === tName)?.config;
|
||||
if (config) {
|
||||
setStyleOptions({ ...styleOptions, ...config });
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveAsTemplate = () => {
|
||||
if (!isLoggedIn) {
|
||||
alert("请先登录,以便保存自定义模板!");
|
||||
return;
|
||||
}
|
||||
const tName = prompt("请为当前样式模板命名:");
|
||||
if (!tName || tName.trim() === '') return;
|
||||
if (templates[tName] || customTemplates.some(t => t.name === tName)) {
|
||||
alert("模板名称已存在,请换一个名称!");
|
||||
return;
|
||||
}
|
||||
const newTemplate = { icon: '⭐', name: tName, isCustom: true, config: { ...styleOptions } };
|
||||
const newCustoms = [...customTemplates, newTemplate];
|
||||
setCustomTemplates(newCustoms);
|
||||
localStorage.setItem('user_templates', JSON.stringify(newCustoms));
|
||||
alert("模板保存成功!");
|
||||
};
|
||||
|
||||
const handleDeleteTemplate = (e, tName) => {
|
||||
e.stopPropagation();
|
||||
if (!isLoggedIn) {
|
||||
alert("请先登录,以便删除模板!");
|
||||
return;
|
||||
}
|
||||
if (!window.confirm(`确定要删除模板“${tName}”吗?`)) return;
|
||||
|
||||
if (customTemplates.some(t => t.name === tName)) {
|
||||
const newCustoms = customTemplates.filter(t => t.name !== tName);
|
||||
setCustomTemplates(newCustoms);
|
||||
localStorage.setItem('user_templates', JSON.stringify(newCustoms));
|
||||
} else {
|
||||
const newDeleted = [...deletedTemplates, tName];
|
||||
setDeletedTemplates(newDeleted);
|
||||
localStorage.setItem('deleted_templates', JSON.stringify(newDeleted));
|
||||
}
|
||||
};
|
||||
|
||||
const scrollMapRef = useRef([]);
|
||||
|
||||
const buildScrollMap = () => {
|
||||
if (!textareaRef.current || !previewRef.current || !previewScrollRef.current) return;
|
||||
const txt = textareaRef.current;
|
||||
const previewContainer = previewScrollRef.current;
|
||||
const previewContent = previewRef.current;
|
||||
|
||||
const map = [];
|
||||
const maxLeft = txt.scrollHeight - txt.clientHeight;
|
||||
const maxRight = previewContainer.scrollHeight - previewContainer.clientHeight;
|
||||
|
||||
map.push({ left: 0, right: 0 });
|
||||
|
||||
if (maxLeft > 0 && maxRight > 0 && markdown.length > 0) {
|
||||
// 收集锚点:这里以所有的标题为锚点
|
||||
const headings = Array.from(previewContent.querySelectorAll('h1, h2, h3, h4, h5, h6'));
|
||||
let lastIndex = 0;
|
||||
headings.forEach(heading => {
|
||||
const text = heading.innerText.trim();
|
||||
if (!text) return;
|
||||
|
||||
// 在原文中找匹配的标题位置
|
||||
const searchStr = text.substring(0, 15);
|
||||
const idx = markdown.indexOf(searchStr, lastIndex);
|
||||
if (idx !== -1) {
|
||||
lastIndex = idx;
|
||||
// 左侧预估:假设行数/字符数与滚动高度呈正相关的近似
|
||||
const leftPos = (idx / markdown.length) * maxLeft;
|
||||
// 右侧实际高度:相对滚动容器的偏移 (注意减去容器可能自带的内边距导致的偏差,这里直接用 offsetTop)
|
||||
const rightPos = heading.offsetTop;
|
||||
map.push({ left: leftPos, right: rightPos });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
map.push({ left: maxLeft > 0 ? maxLeft : 0, right: maxRight > 0 ? maxRight : 0 });
|
||||
scrollMapRef.current = map;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// 渲染完且排版稳定后重新计算锚点映射表
|
||||
const timer = setTimeout(() => buildScrollMap(), 300);
|
||||
return () => clearTimeout(timer);
|
||||
}, [preview, styleOptions]);
|
||||
|
||||
const syncScrollPositions = (source, target, isSourceLeft) => {
|
||||
let map = scrollMapRef.current;
|
||||
if (map.length < 2) return;
|
||||
|
||||
const currentScroll = source.scrollTop;
|
||||
|
||||
// 找到所在的区间
|
||||
let i = 0;
|
||||
while (i < map.length - 1) {
|
||||
const p1 = isSourceLeft ? map[i].left : map[i].right;
|
||||
const p2 = isSourceLeft ? map[i+1].left : map[i+1].right;
|
||||
if (currentScroll >= p1 && currentScroll <= p2) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (i >= map.length - 1) i = map.length - 2;
|
||||
|
||||
const startNode = map[i];
|
||||
const endNode = map[i + 1];
|
||||
|
||||
const sourceStart = isSourceLeft ? startNode.left : startNode.right;
|
||||
const sourceEnd = isSourceLeft ? endNode.left : endNode.right;
|
||||
const targetStart = isSourceLeft ? startNode.right : startNode.left;
|
||||
const targetEnd = isSourceLeft ? endNode.right : endNode.left;
|
||||
|
||||
let percentage = 0;
|
||||
if (sourceEnd - sourceStart > 0) {
|
||||
percentage = (currentScroll - sourceStart) / (sourceEnd - sourceStart);
|
||||
}
|
||||
|
||||
// 防止超出目标边界
|
||||
const targetScroll = Math.max(0, targetStart + percentage * (targetEnd - targetStart));
|
||||
target.scrollTop = Math.round(targetScroll);
|
||||
};
|
||||
|
||||
const handleTextareaScroll = (e) => {
|
||||
if (!isSyncScroll || !previewScrollRef.current) return;
|
||||
if (isSyncingLeft.current) {
|
||||
isSyncingLeft.current = false;
|
||||
return;
|
||||
}
|
||||
isSyncingRight.current = true;
|
||||
syncScrollPositions(e.target, previewScrollRef.current, true);
|
||||
};
|
||||
|
||||
const handlePreviewScroll = (e) => {
|
||||
if (!isSyncScroll || !textareaRef.current) return;
|
||||
if (isSyncingRight.current) {
|
||||
isSyncingRight.current = false;
|
||||
return;
|
||||
}
|
||||
isSyncingLeft.current = true;
|
||||
syncScrollPositions(e.target, textareaRef.current, false);
|
||||
};
|
||||
|
||||
// 初次加载或用户登录状态变化时,拉取历史记录
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
@@ -25,6 +254,14 @@ export default function MD2Doc() {
|
||||
|
||||
useEffect(() => {
|
||||
mermaid.initialize({ startOnLoad: false, theme: 'default' });
|
||||
|
||||
// 如果存在草稿,进行初始渲染,然后清理
|
||||
const draftMd = localStorage.getItem('draft_markdown');
|
||||
if (draftMd) {
|
||||
renderContent(draftMd);
|
||||
}
|
||||
localStorage.removeItem('draft_markdown');
|
||||
localStorage.removeItem('draft_styleOptions');
|
||||
}, []);
|
||||
|
||||
const fetchHistory = async () => {
|
||||
@@ -197,6 +434,11 @@ export default function MD2Doc() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
setShowLoginPrompt(true);
|
||||
return;
|
||||
}
|
||||
|
||||
setExporting(true);
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
@@ -208,7 +450,7 @@ export default function MD2Doc() {
|
||||
const response = await fetch('http://localhost:3001/api/convert', {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify({ markdown })
|
||||
body: JSON.stringify({ markdown, styleOptions })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -216,7 +458,8 @@ export default function MD2Doc() {
|
||||
}
|
||||
|
||||
const blob = await response.blob();
|
||||
saveAs(blob, 'document.docx');
|
||||
const fileName = `文档_${format(new Date(), 'yyyyMMdd_HHmmss')}.docx`;
|
||||
saveAs(blob, fileName);
|
||||
|
||||
// 导出成功后,如果是登录用户,重新拉取历史记录
|
||||
if (user) {
|
||||
@@ -235,41 +478,81 @@ export default function MD2Doc() {
|
||||
renderContent(text);
|
||||
};
|
||||
|
||||
const previewCustomStyles = `
|
||||
.custom-preview-wrapper { font-family: '${styleOptions.base_font_family}', sans-serif; font-size: ${styleOptions.base_font_size}pt; }
|
||||
.custom-preview-wrapper p { font-family: '${styleOptions.base_font_family}', sans-serif; font-size: ${styleOptions.base_font_size}pt; }
|
||||
.custom-preview-wrapper h1 { font-family: '${styleOptions.base_font_family}', sans-serif; font-size: ${styleOptions.h1_size}pt; }
|
||||
.custom-preview-wrapper h2 { font-family: '${styleOptions.base_font_family}', sans-serif; font-size: ${styleOptions.h2_size}pt; }
|
||||
.custom-preview-wrapper h3 { font-family: '${styleOptions.base_font_family}', sans-serif; font-size: ${styleOptions.h3_size}pt; }
|
||||
.custom-preview-wrapper h4, .custom-preview-wrapper h5, .custom-preview-wrapper h6 { font-family: '${styleOptions.base_font_family}', sans-serif; font-size: ${styleOptions.h4_size}pt; }
|
||||
`;
|
||||
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
{/* 历史侧边栏 */}
|
||||
{user && (
|
||||
<aside style={styles.sidebar}>
|
||||
<h2 style={styles.sidebarTitle}>转换记录</h2>
|
||||
<p style={{fontSize: '12px', color: '#6b7280', marginBottom: '10px'}}>最多保留最近 100 次记录</p>
|
||||
<div style={styles.historyList}>
|
||||
{history.length === 0 ? (
|
||||
<div style={{color: '#9ca3af', fontSize: '13px', textAlign: 'center', marginTop: '20px'}}>暂无记录</div>
|
||||
) : (
|
||||
history.map(item => (
|
||||
<div key={item.id} style={styles.historyItem} onClick={() => loadFromHistory(item.markdown)}>
|
||||
<div style={styles.historyTime}>{new Date(item.timestamp).toLocaleString()}</div>
|
||||
<div style={styles.historySummary}>{item.summary}</div>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
<aside style={{
|
||||
...styles.sidebar,
|
||||
width: showHistory ? '260px' : '40px',
|
||||
padding: showHistory ? '16px' : '16px 4px',
|
||||
alignItems: showHistory ? 'stretch' : 'center',
|
||||
cursor: showHistory ? 'default' : 'pointer',
|
||||
transition: 'width 0.2s ease-in-out'
|
||||
}}
|
||||
onClick={() => { if (!showHistory) setShowHistory(true); }}
|
||||
title={!showHistory ? "点击展开转换记录" : ""}
|
||||
>
|
||||
{showHistory ? (
|
||||
<>
|
||||
<div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '4px'}}>
|
||||
<h2 style={{...styles.sidebarTitle, margin: 0}}>转换记录</h2>
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); setShowHistory(false); }}
|
||||
style={{background: 'none', border: 'none', cursor: 'pointer', color: '#6b7280', fontSize: '12px'}}
|
||||
>
|
||||
◀ 收起
|
||||
</button>
|
||||
</div>
|
||||
<p style={{fontSize: '12px', color: '#6b7280', marginBottom: '10px'}}>最多保留最近 100 次记录</p>
|
||||
<div style={styles.historyList}>
|
||||
{history.length === 0 ? (
|
||||
<div style={{color: '#9ca3af', fontSize: '13px', textAlign: 'center', marginTop: '20px'}}>暂无记录</div>
|
||||
) : (
|
||||
history.map(item => (
|
||||
<div key={item.id} style={styles.historyItem} onClick={() => loadFromHistory(item.markdown)}>
|
||||
<div style={styles.historyTime}>{new Date(item.timestamp).toLocaleString()}</div>
|
||||
<div style={styles.historySummary}>{item.summary}</div>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div style={{writingMode: 'vertical-rl', letterSpacing: '4px', color: '#6b7280', fontWeight: 'bold', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center'}}>
|
||||
展开记录 ▶
|
||||
</div>
|
||||
)}
|
||||
</aside>
|
||||
)}
|
||||
|
||||
<div style={styles.mainContentWrapper}>
|
||||
<header style={styles.header}>
|
||||
<h1 style={styles.title}>Markdown 转 Word 文档 (Python 后端强力驱动)</h1>
|
||||
<p style={styles.subtitle}>支持 LaTeX 公式($$...$$、\(...\)、\[...\] 多格式自动修复)、Mermaid 图表,基于 Pandoc 引擎</p>
|
||||
</header>
|
||||
|
||||
<main style={styles.main}>
|
||||
<section style={styles.inputSection}>
|
||||
<div style={styles.toolbar}>
|
||||
<button
|
||||
style={{...styles.btn, backgroundColor: isSyncScroll ? '#10b981' : '#6b7280', padding: '4px 8px'}}
|
||||
onClick={() => setIsSyncScroll(!isSyncScroll)}
|
||||
title={isSyncScroll ? "关闭联动滚动" : "开启联动滚动"}
|
||||
>
|
||||
{isSyncScroll ? "🔗 联动开" : "🔓 联动关"}
|
||||
</button>
|
||||
<div style={{width: '1px', backgroundColor: '#d1d5db', margin: '0 4px'}}></div>
|
||||
<button style={styles.btn} onClick={handlePaste}>粘贴</button>
|
||||
<button style={{...styles.btn, backgroundColor: '#ef4444'}} onClick={() => { setMarkdown(''); setPreview(''); }}>清除</button>
|
||||
</div>
|
||||
<textarea
|
||||
ref={textareaRef}
|
||||
onScroll={handleTextareaScroll}
|
||||
style={styles.textarea}
|
||||
value={markdown}
|
||||
onChange={handleMarkdownChange}
|
||||
@@ -277,8 +560,116 @@ export default function MD2Doc() {
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section style={styles.previewSection}>
|
||||
<div style={styles.previewContent} ref={previewRef} dangerouslySetInnerHTML={{ __html: preview }}></div>
|
||||
<section style={styles.previewSection} ref={previewScrollRef} onScroll={handlePreviewScroll}>
|
||||
{/* 右上方快捷工具栏 */}
|
||||
{markdown.trim() && (
|
||||
<div style={{...styles.toolbar, zIndex: 20}}>
|
||||
{showFormatSettings ? (
|
||||
<button
|
||||
style={{...styles.btn, backgroundColor: '#ef4444', padding: '4px 8px'}}
|
||||
onClick={() => setShowFormatSettings(false)}
|
||||
>
|
||||
✕ 返回预览
|
||||
</button>
|
||||
) : (
|
||||
<>
|
||||
<button
|
||||
style={{...styles.btn, backgroundColor: '#3b82f6', padding: '4px 8px'}}
|
||||
onClick={() => setShowFormatSettings(true)}
|
||||
>
|
||||
⚙️ 格式设置
|
||||
</button>
|
||||
<button
|
||||
style={{...styles.btn, backgroundColor: '#10b981', padding: '4px 8px'}}
|
||||
onClick={handleExportWord}
|
||||
disabled={exporting}
|
||||
>
|
||||
{exporting ? '正在导出...' : '📥 导出 Word'}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 当左侧没有内容,或用户手动点击“格式设置”时,显示概览板 */}
|
||||
{(!markdown.trim() || showFormatSettings) && (
|
||||
<div style={styles.formatPreviewBox}>
|
||||
<div style={styles.formatHeader}>预览区域 (Preview Area)</div>
|
||||
|
||||
<div style={{marginBottom: '20px'}}>
|
||||
<div style={styles.formatSectionTitle}>Word样式模板:</div>
|
||||
<div style={styles.templateQuickGrid}>
|
||||
{visibleTemplates.map(tpl => (
|
||||
<div key={tpl.name} style={{...styles.templateIconBtn, position: 'relative'}} onClick={() => handleTemplateChange({target:{value: tpl.name}})}>
|
||||
{isLoggedIn && (
|
||||
<div style={styles.deleteBadge} onClick={(e) => handleDeleteTemplate(e, tpl.name)}>×</div>
|
||||
)}
|
||||
<span style={{fontSize: '20px', marginBottom: '4px'}}>{tpl.icon}</span>
|
||||
<span>{tpl.name}</span>
|
||||
</div>
|
||||
))}
|
||||
{(!showMoreTemplates && allTemplatesList.length > 8) && (
|
||||
<div style={styles.templateMoreBtn} onClick={() => setShowMoreTemplates(true)}>
|
||||
<span style={{fontSize: '13px', color: '#6b7280'}}>更多 ({allTemplatesList.length - 8})</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={styles.formatDetailsBox}>
|
||||
<div style={{display: 'flex', justifyContent: 'space-between', marginBottom: '10px'}}>
|
||||
<span style={{fontWeight: 'bold', fontSize: '15px', color: '#111827'}}>当前Word导出样式:自定义设置</span>
|
||||
<div>
|
||||
<button style={{...styles.btnOutline, padding: '4px 10px', fontSize: '12px', marginRight: '8px'}} onClick={handleSaveAsTemplate}>💾 保存为模板</button>
|
||||
<button style={{...styles.btnOutline, padding: '4px 10px', fontSize: '12px'}} onClick={() => setShowStylePanel(true)}>⚙️ 高级配置</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={styles.formatDetailRow}>
|
||||
<span style={styles.formatLabel}>正文设置</span>
|
||||
<span>字体:{styleOptions.base_font_family} | 字号:{styleOptions.base_font_size} pt</span>
|
||||
<span style={{marginLeft: 'auto', fontFamily: styleOptions.base_font_family, fontSize: styleOptions.base_font_size + 'pt'}}>这是正文示例</span>
|
||||
</div>
|
||||
|
||||
<div style={styles.formatDetailRow}>
|
||||
<span style={styles.formatLabel}>标题设置</span>
|
||||
<span>字体:{styleOptions.base_font_family}</span>
|
||||
<span style={{marginLeft: '15px'}}>一级:{styleOptions.h1_size} pt</span>
|
||||
<span style={{marginLeft: 'auto', fontFamily: styleOptions.base_font_family, fontSize: styleOptions.h1_size + 'pt', fontWeight: 'bold'}}>一级标题</span>
|
||||
</div>
|
||||
<div style={styles.formatDetailRow}>
|
||||
<span style={styles.formatLabel}></span>
|
||||
<span style={{marginLeft: '15px'}}>二级:{styleOptions.h2_size} pt</span>
|
||||
<span style={{marginLeft: 'auto', fontFamily: styleOptions.base_font_family, fontSize: styleOptions.h2_size + 'pt', fontWeight: 'bold'}}>二级标题</span>
|
||||
</div>
|
||||
<div style={styles.formatDetailRow}>
|
||||
<span style={styles.formatLabel}></span>
|
||||
<span style={{marginLeft: '15px'}}>三级:{styleOptions.h3_size} pt</span>
|
||||
<span style={{marginLeft: 'auto', fontFamily: styleOptions.base_font_family, fontSize: styleOptions.h3_size + 'pt', fontWeight: 'bold'}}>三级标题</span>
|
||||
</div>
|
||||
|
||||
<div style={styles.formatDetailRow}>
|
||||
<span style={styles.formatLabel}>页面设置</span>
|
||||
<span>页码:1, 2, 3 (居中) 页眉:无</span>
|
||||
</div>
|
||||
|
||||
<div style={styles.formatDetailRow}>
|
||||
<span style={styles.formatLabel}>表格设置</span>
|
||||
<span>跨页标题重复:禁用</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 当左侧有内容且未开启格式设置时,显示转换预览 */}
|
||||
{(markdown.trim() && !showFormatSettings) && (
|
||||
<>
|
||||
<style dangerouslySetInnerHTML={{ __html: previewCustomStyles }} />
|
||||
<div style={{display: 'flex', justifyContent: 'center', width: '100%'}}>
|
||||
<div className="custom-preview-wrapper" style={styles.previewContent} ref={previewRef} dangerouslySetInnerHTML={{ __html: preview }}></div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</section>
|
||||
</main>
|
||||
|
||||
@@ -288,33 +679,188 @@ export default function MD2Doc() {
|
||||
onClick={handleExportWord}
|
||||
disabled={exporting || !markdown.trim()}
|
||||
>
|
||||
{exporting ? '后端 Pandoc 转换中...' : '一键导出 Word 文档 (.docx)'}
|
||||
{exporting ? '正在生成文档...' : '一键导出 Word 文档 (.docx)'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 登录提示 Modal */}
|
||||
{showLoginPrompt && (
|
||||
<div style={styles.modalOverlay}>
|
||||
<div style={{...styles.modalContent, maxWidth: '400px', textAlign: 'center', padding: '30px'}}>
|
||||
<div style={{fontSize: '40px', marginBottom: '10px'}}>🔒</div>
|
||||
<h2 style={{margin: '0 0 10px 0', fontSize: '20px', color: '#1f2937'}}>需要登录</h2>
|
||||
<p style={{color: '#4b5563', marginBottom: '24px', lineHeight: '1.5'}}>
|
||||
只有登录用户才能导出 Word 文档。请登录或注册新账号,登录后我们将为您恢复当前的草稿。
|
||||
</p>
|
||||
<div style={{display: 'flex', gap: '10px', justifyContent: 'center'}}>
|
||||
<button
|
||||
style={{...styles.mainExportBtn, flex: 1, backgroundColor: '#3b82f6', padding: '10px'}}
|
||||
onClick={() => {
|
||||
localStorage.setItem('draft_markdown', markdown);
|
||||
localStorage.setItem('draft_styleOptions', JSON.stringify(styleOptions));
|
||||
navigate('/login', { state: { from: '/' } });
|
||||
}}
|
||||
>登录</button>
|
||||
<button
|
||||
style={{...styles.mainExportBtn, flex: 1, backgroundColor: '#10b981', padding: '10px'}}
|
||||
onClick={() => {
|
||||
localStorage.setItem('draft_markdown', markdown);
|
||||
localStorage.setItem('draft_styleOptions', JSON.stringify(styleOptions));
|
||||
navigate('/register', { state: { from: '/' } });
|
||||
}}
|
||||
>注册</button>
|
||||
</div>
|
||||
<button
|
||||
style={{marginTop: '20px', background: 'none', border: 'none', color: '#6b7280', cursor: 'pointer', textDecoration: 'underline'}}
|
||||
onClick={() => setShowLoginPrompt(false)}
|
||||
>
|
||||
稍后再说
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 导出样式 Modal (模仿 yayacool 布局) */}
|
||||
{showStylePanel && (
|
||||
<div style={styles.modalOverlay}>
|
||||
<div style={styles.modalContent}>
|
||||
<div style={styles.modalHeader}>
|
||||
<h2 style={{margin: 0, fontSize: '18px', display: 'flex', alignItems: 'center', gap: '8px'}}>
|
||||
<span style={{fontSize: '20px'}}>⚙️</span> 导出Word样式自定义
|
||||
</h2>
|
||||
<button onClick={() => setShowStylePanel(false)} style={styles.closeBtn}>✕</button>
|
||||
</div>
|
||||
|
||||
<div style={styles.modalBody}>
|
||||
{/* 快速模板卡片 */}
|
||||
<div style={styles.card}>
|
||||
<h3 style={styles.cardTitle}>预设模板与自定义</h3>
|
||||
<div style={styles.templateGrid}>
|
||||
{allTemplatesList.map(tpl => (
|
||||
<button
|
||||
key={tpl.name}
|
||||
style={styles.templateBtn}
|
||||
onClick={() => handleTemplateChange({target:{value: tpl.name}})}
|
||||
>
|
||||
{tpl.icon} {tpl.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 正文设置 */}
|
||||
<div style={styles.card}>
|
||||
<h3 style={styles.cardTitle}>正文设置</h3>
|
||||
<div style={styles.twoColGrid}>
|
||||
<div style={styles.fieldGroup}>
|
||||
<label style={styles.label}>正文字体</label>
|
||||
<select style={styles.input} value={styleOptions.base_font_family} onChange={e => setStyleOptions({...styleOptions, base_font_family: e.target.value})}>
|
||||
<option value="宋体">宋体</option>
|
||||
<option value="微软雅黑">微软雅黑</option>
|
||||
<option value="黑体">黑体</option>
|
||||
<option value="楷体">楷体</option>
|
||||
<option value="Times New Roman">Times New Roman</option>
|
||||
<option value="Arial">Arial</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style={styles.fieldGroup}>
|
||||
<label style={styles.label}>字号 (pt)</label>
|
||||
<input type="number" style={styles.input} value={styleOptions.base_font_size} onChange={e => setStyleOptions({...styleOptions, base_font_size: Number(e.target.value)})} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 标题设置 */}
|
||||
<div style={styles.card}>
|
||||
<h3 style={styles.cardTitle}>标题设置</h3>
|
||||
<div style={styles.twoColGrid}>
|
||||
<div style={styles.fieldGroup}>
|
||||
<label style={styles.label}>一级标题 H1</label>
|
||||
<input type="number" style={styles.input} value={styleOptions.h1_size} onChange={e => setStyleOptions({...styleOptions, h1_size: Number(e.target.value)})} />
|
||||
</div>
|
||||
<div style={styles.fieldGroup}>
|
||||
<label style={styles.label}>二级标题 H2</label>
|
||||
<input type="number" style={styles.input} value={styleOptions.h2_size} onChange={e => setStyleOptions({...styleOptions, h2_size: Number(e.target.value)})} />
|
||||
</div>
|
||||
<div style={styles.fieldGroup}>
|
||||
<label style={styles.label}>三级标题 H3</label>
|
||||
<input type="number" style={styles.input} value={styleOptions.h3_size} onChange={e => setStyleOptions({...styleOptions, h3_size: Number(e.target.value)})} />
|
||||
</div>
|
||||
<div style={styles.fieldGroup}>
|
||||
<label style={styles.label}>四级标题 H4</label>
|
||||
<input type="number" style={styles.input} value={styleOptions.h4_size} onChange={e => setStyleOptions({...styleOptions, h4_size: Number(e.target.value)})} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={styles.modalFooter}>
|
||||
<button style={styles.btnOutline} onClick={() => setStyleOptions(templates['默认'])}>恢复默认设置</button>
|
||||
<div style={{display: 'flex', gap: '10px'}}>
|
||||
<button style={styles.btnOutline} onClick={() => setShowStylePanel(false)}>取消</button>
|
||||
<button style={styles.btnPrimary} onClick={() => setShowStylePanel(false)}>确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = {
|
||||
container: { maxWidth: '1600px', margin: '0 auto', padding: '24px', minHeight: '100vh', display: 'flex', gap: '20px', backgroundColor: '#f9fafb' },
|
||||
sidebar: { width: '260px', backgroundColor: 'white', borderRadius: '8px', padding: '16px', border: '1px solid #d1d5db', display: 'flex', flexDirection: 'column' },
|
||||
container: { maxWidth: '1600px', margin: '0 auto', padding: '24px', height: '100vh', display: 'flex', gap: '20px', backgroundColor: '#f9fafb', boxSizing: 'border-box' },
|
||||
sidebar: { width: '260px', backgroundColor: 'white', borderRadius: '8px', padding: '16px', border: '1px solid #d1d5db', display: 'flex', flexDirection: 'column', height: '100%', boxSizing: 'border-box' },
|
||||
sidebarTitle: { fontSize: '18px', fontWeight: 'bold', margin: '0 0 4px 0' },
|
||||
historyList: { flex: 1, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: '10px' },
|
||||
historyItem: { padding: '10px', backgroundColor: '#f3f4f6', borderRadius: '6px', cursor: 'pointer', transition: 'background 0.2s' },
|
||||
historyTime: { fontSize: '12px', color: '#6b7280', marginBottom: '4px' },
|
||||
historySummary: { fontSize: '14px', color: '#374151', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' },
|
||||
mainContentWrapper: { flex: 1, display: 'flex', flexDirection: 'column' },
|
||||
header: { marginBottom: '20px' },
|
||||
title: { fontSize: '24px', fontWeight: 'bold' },
|
||||
subtitle: { color: '#6b7280' },
|
||||
main: { display: 'flex', gap: '20px', flex: 1, minHeight: '600px' },
|
||||
inputSection: { flex: 1, display: 'flex', flexDirection: 'column', position: 'relative' },
|
||||
textarea: { flex: 1, padding: '20px', border: '1px solid #d1d5db', borderRadius: '8px', fontFamily: 'monospace', fontSize: '15px', resize: 'none' },
|
||||
toolbar: { position: 'absolute', top: '10px', right: '10px', display: 'flex', gap: '8px' },
|
||||
btn: { padding: '6px 12px', backgroundColor: '#3b82f6', color: 'white', border: 'none', borderRadius: '4px', cursor: 'pointer' },
|
||||
previewSection: { flex: 1, padding: '20px', backgroundColor: 'white', border: '1px solid #d1d5db', borderRadius: '8px', overflowY: 'auto' },
|
||||
previewContent: { lineHeight: 1.6 },
|
||||
mainContentWrapper: { flex: 1, display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' },
|
||||
main: { display: 'flex', gap: '8px', flex: 1, overflow: 'hidden' },
|
||||
inputSection: { flex: 1, position: 'relative', display: 'flex', flexDirection: 'column', height: '100%', minWidth: 0 },
|
||||
textarea: { flex: 1, padding: '40px 20px 20px 20px', border: '1px solid #d1d5db', borderRadius: '8px', fontFamily: 'monospace', fontSize: '15px', resize: 'none', boxSizing: 'border-box' },
|
||||
toolbar: { position: 'absolute', top: '10px', right: '10px', display: 'flex', gap: '6px', zIndex: 10 },
|
||||
btn: { padding: '4px 10px', fontSize: '12px', backgroundColor: '#3b82f6', color: 'white', border: 'none', borderRadius: '4px', cursor: 'pointer', opacity: 0.85, transition: 'opacity 0.2s' },
|
||||
previewSection: { flex: 1, position: 'relative', padding: '0', backgroundColor: 'white', border: '1px solid #d1d5db', borderRadius: '8px', overflowY: 'auto', height: '100%', boxSizing: 'border-box', minWidth: 0 },
|
||||
previewContent: { backgroundColor: 'white', width: '100%', minHeight: '100%', padding: '40px', lineHeight: 1.6, boxSizing: 'border-box' },
|
||||
bottomBar: { marginTop: '20px', display: 'flex', justifyContent: 'center' },
|
||||
mainExportBtn: { padding: '12px 32px', backgroundColor: '#10b981', color: 'white', border: 'none', borderRadius: '8px', fontSize: '16px', fontWeight: 'bold', cursor: 'pointer' }
|
||||
mainExportBtn: { padding: '12px 32px', backgroundColor: '#10b981', color: 'white', border: 'none', borderRadius: '8px', fontSize: '16px', fontWeight: 'bold', cursor: 'pointer' },
|
||||
|
||||
// Modal 样式
|
||||
modalOverlay: { position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0, 0, 0, 0.4)', backdropFilter: 'blur(4px)', display: 'flex', justifyContent: 'center', alignItems: 'center', zIndex: 1000 },
|
||||
modalContent: { backgroundColor: 'white', width: '550px', maxHeight: '85vh', borderRadius: '12px', display: 'flex', flexDirection: 'column', boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)' },
|
||||
modalHeader: { padding: '16px 24px', borderBottom: '1px solid #e5e7eb', display: 'flex', justifyContent: 'space-between', alignItems: 'center' },
|
||||
closeBtn: { background: 'none', border: 'none', fontSize: '20px', color: '#9ca3af', cursor: 'pointer' },
|
||||
modalBody: { padding: '24px', overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: '20px' },
|
||||
modalFooter: { padding: '16px 24px', borderTop: '1px solid #e5e7eb', display: 'flex', justifyContent: 'space-between', alignItems: 'center', backgroundColor: '#f9fafb', borderBottomLeftRadius: '12px', borderBottomRightRadius: '12px' },
|
||||
|
||||
// Card 样式
|
||||
card: { backgroundColor: '#f9fafb', border: '1px solid #e5e7eb', borderRadius: '8px', padding: '16px' },
|
||||
cardTitle: { margin: '0 0 16px 0', fontSize: '15px', fontWeight: 'bold', color: '#111827' },
|
||||
templateGrid: { display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '10px' },
|
||||
templateBtn: { padding: '10px', backgroundColor: 'white', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px', cursor: 'pointer', textAlign: 'center', transition: 'all 0.2s' },
|
||||
twoColGrid: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' },
|
||||
|
||||
// 表单样式
|
||||
fieldGroup: { display: 'flex', flexDirection: 'column', gap: '6px' },
|
||||
label: { fontSize: '13px', color: '#4b5563', fontWeight: '500' },
|
||||
input: { padding: '8px 12px', borderRadius: '6px', border: '1px solid #d1d5db', fontSize: '14px', outline: 'none' },
|
||||
|
||||
// 按钮样式
|
||||
btnOutline: { padding: '8px 16px', backgroundColor: 'white', color: '#374151', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px', cursor: 'pointer' },
|
||||
btnPrimary: { padding: '8px 16px', backgroundColor: '#3b82f6', color: 'white', border: 'none', borderRadius: '6px', fontSize: '14px', cursor: 'pointer' },
|
||||
|
||||
// 右侧面板新增样式
|
||||
formatPreviewBox: { backgroundColor: '#f9fafb', padding: '16px', borderRadius: '8px', border: '1px solid #d1d5db', width: '100%', height: 'fit-content' },
|
||||
formatHeader: { fontSize: '18px', fontWeight: 'bold', marginBottom: '20px', color: '#111827' },
|
||||
formatSectionTitle: { fontSize: '14px', fontWeight: '600', color: '#374151', marginBottom: '12px' },
|
||||
templateQuickGrid: { display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: '10px' },
|
||||
templateIconBtn: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', backgroundColor: 'white', border: '1px solid #e5e7eb', borderRadius: '8px', padding: '12px 5px', fontSize: '12px', color: '#374151', cursor: 'pointer', textAlign: 'center', transition: 'all 0.2s', boxShadow: '0 1px 2px 0 rgba(0, 0, 0, 0.05)' },
|
||||
templateMoreBtn: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', backgroundColor: '#f3f4f6', border: '1px dashed #d1d5db', borderRadius: '8px', padding: '12px 5px', cursor: 'pointer', transition: 'all 0.2s' },
|
||||
deleteBadge: { position: 'absolute', top: '-6px', right: '-6px', backgroundColor: '#ef4444', color: 'white', width: '18px', height: '18px', borderRadius: '50%', fontSize: '12px', display: 'flex', justifyContent: 'center', alignItems: 'center', cursor: 'pointer' },
|
||||
formatDetailsBox: { backgroundColor: 'white', border: '1px solid #e5e7eb', borderRadius: '8px', padding: '20px', fontSize: '13px', color: '#4b5563', boxShadow: '0 1px 2px 0 rgba(0, 0, 0, 0.05)' },
|
||||
formatDetailRow: { marginBottom: '10px', display: 'flex', alignItems: 'center' },
|
||||
formatLabel: { fontWeight: 'bold', color: '#111827', width: '80px', flexShrink: 0 }
|
||||
};
|
||||
@@ -1,15 +1,37 @@
|
||||
import { useState } from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Link, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
|
||||
export default function Register() {
|
||||
const [username, setUsername] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [confirmPassword, setConfirmPassword] = useState('');
|
||||
const [captchaCode, setCaptchaCode] = useState('');
|
||||
const [captchaId, setCaptchaId] = useState('');
|
||||
const [captchaImage, setCaptchaImage] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { register } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
fetchCaptcha();
|
||||
}, []);
|
||||
|
||||
const fetchCaptcha = async () => {
|
||||
try {
|
||||
const res = await fetch('http://localhost:3001/api/captcha');
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
setCaptchaId(data.captcha_id);
|
||||
setCaptchaImage(data.image_base64);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('获取验证码失败', err);
|
||||
}
|
||||
};
|
||||
|
||||
async function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
@@ -20,13 +42,20 @@ export default function Register() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!captchaCode) {
|
||||
setError('请输入验证码');
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
await register(username, password);
|
||||
navigate('/login');
|
||||
await register(username, email, password, captchaId, captchaCode);
|
||||
const from = location.state?.from || '/';
|
||||
navigate('/login', { state: { from } });
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
fetchCaptcha(); // 出错刷新验证码
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -50,6 +79,16 @@ export default function Register() {
|
||||
maxLength={20}
|
||||
/>
|
||||
</div>
|
||||
<div style={styles.formGroup}>
|
||||
<label style={styles.label}>邮箱</label>
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
style={styles.input}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div style={styles.formGroup}>
|
||||
<label style={styles.label}>密码</label>
|
||||
<input
|
||||
@@ -72,6 +111,31 @@ export default function Register() {
|
||||
minLength={6}
|
||||
/>
|
||||
</div>
|
||||
<div style={styles.formGroup}>
|
||||
<label style={styles.label}>验证码</label>
|
||||
<div style={{display: 'flex', gap: '10px', alignItems: 'center'}}>
|
||||
<input
|
||||
type="text"
|
||||
value={captchaCode}
|
||||
onChange={(e) => setCaptchaCode(e.target.value)}
|
||||
style={{...styles.input, flex: 1}}
|
||||
required
|
||||
maxLength={4}
|
||||
placeholder="请输入右侧验证码"
|
||||
/>
|
||||
{captchaImage ? (
|
||||
<img
|
||||
src={captchaImage}
|
||||
alt="验证码"
|
||||
onClick={fetchCaptcha}
|
||||
style={{cursor: 'pointer', height: '40px', borderRadius: '4px', border: '1px solid #ddd'}}
|
||||
title="点击刷新验证码"
|
||||
/>
|
||||
) : (
|
||||
<div style={{height: '40px', width: '120px', backgroundColor: '#f3f4f6', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '12px', color: '#9ca3af', cursor: 'pointer', borderRadius: '4px'}} onClick={fetchCaptcha}>加载中...</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" style={styles.button} disabled={loading}>
|
||||
{loading ? '注册中...' : '注册'}
|
||||
</button>
|
||||
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
+44
-1
@@ -5,6 +5,20 @@ from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
DB_PATH = Path(__file__).parent / "database.json"
|
||||
SETTINGS_PATH = Path(__file__).parent / "settings.json"
|
||||
|
||||
def get_settings():
|
||||
if SETTINGS_PATH.exists():
|
||||
try:
|
||||
with open(SETTINGS_PATH, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
except Exception:
|
||||
pass
|
||||
return {"smtp_enabled": False, "smtp_server": "", "smtp_port": 465, "smtp_user": "", "smtp_pass": ""}
|
||||
|
||||
def save_settings(settings: dict):
|
||||
with open(SETTINGS_PATH, "w", encoding="utf-8") as f:
|
||||
json.dump(settings, f, indent=2)
|
||||
|
||||
def load_db():
|
||||
if DB_PATH.exists():
|
||||
@@ -25,24 +39,53 @@ def get_user_by_username(username: str):
|
||||
return u
|
||||
return None
|
||||
|
||||
def update_user_login(user_id: int):
|
||||
users = load_db()
|
||||
for u in users:
|
||||
if u.get("id") == user_id:
|
||||
u["last_login"] = datetime.now().isoformat()
|
||||
save_db(users)
|
||||
return u
|
||||
return None
|
||||
|
||||
def get_all_users():
|
||||
users = load_db()
|
||||
# 移除敏感的历史记录数据以便返回概览
|
||||
result = []
|
||||
for u in users:
|
||||
u_copy = {k: v for k, v in u.items() if k != "history"}
|
||||
result.append(u_copy)
|
||||
return result
|
||||
|
||||
def get_user_by_id(user_id: int):
|
||||
for u in load_db():
|
||||
if u.get("id") == user_id:
|
||||
return u
|
||||
return None
|
||||
|
||||
def create_user(user_data: dict):
|
||||
def create_user(user_data: dict, ip_address: str = "Unknown"):
|
||||
users = load_db()
|
||||
new_user = {
|
||||
**user_data,
|
||||
"id": int(time.time() * 1000),
|
||||
"createdAt": datetime.now().isoformat(),
|
||||
"register_ip": ip_address,
|
||||
"last_login": datetime.now().isoformat(),
|
||||
"history": []
|
||||
}
|
||||
users.append(new_user)
|
||||
save_db(users)
|
||||
return new_user
|
||||
|
||||
def update_user(user_id: int, updates: dict):
|
||||
users = load_db()
|
||||
for u in users:
|
||||
if u.get("id") == user_id:
|
||||
u.update(updates)
|
||||
save_db(users)
|
||||
return u
|
||||
return None
|
||||
|
||||
def add_history_record(user_id: int, markdown_text: str):
|
||||
users = load_db()
|
||||
for u in users:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,29 +1,96 @@
|
||||
from fastapi import APIRouter, HTTPException, Depends
|
||||
from fastapi import APIRouter, HTTPException, Depends, Request
|
||||
from pydantic import BaseModel
|
||||
import db
|
||||
import auth
|
||||
import uuid
|
||||
import random
|
||||
import string
|
||||
import time
|
||||
import base64
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from captcha.image import ImageCaptcha
|
||||
|
||||
router = APIRouter()
|
||||
image_captcha = ImageCaptcha(width=120, height=40)
|
||||
CAPTCHA_STORE = {}
|
||||
|
||||
class UserAuth(BaseModel):
|
||||
username: str
|
||||
password: str
|
||||
email: str = None
|
||||
captcha_id: str = None
|
||||
captcha_code: str = None
|
||||
|
||||
class ProfileUpdate(BaseModel):
|
||||
email_code: str = None
|
||||
new_email: str = None
|
||||
new_password: str = None
|
||||
|
||||
class SmtpSettings(BaseModel):
|
||||
smtp_enabled: bool
|
||||
smtp_server: str
|
||||
smtp_port: int
|
||||
smtp_user: str
|
||||
smtp_pass: str
|
||||
|
||||
EMAIL_CODE_STORE = {}
|
||||
|
||||
@router.get("/api/captcha")
|
||||
def get_captcha():
|
||||
code = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))
|
||||
captcha_id = str(uuid.uuid4())
|
||||
|
||||
CAPTCHA_STORE[captcha_id] = {
|
||||
"code": code.lower(),
|
||||
"expires": time.time() + 300
|
||||
}
|
||||
|
||||
current_time = time.time()
|
||||
expired_keys = [k for k, v in CAPTCHA_STORE.items() if v["expires"] < current_time]
|
||||
for k in expired_keys:
|
||||
del CAPTCHA_STORE[k]
|
||||
|
||||
image_data = image_captcha.generate(code)
|
||||
base64_image = base64.b64encode(image_data.getvalue()).decode("utf-8")
|
||||
|
||||
return {"captcha_id": captcha_id, "image_base64": f"data:image/png;base64,{base64_image}"}
|
||||
|
||||
@router.post("/api/register")
|
||||
def register(user: UserAuth):
|
||||
if not user.username or not user.password:
|
||||
raise HTTPException(status_code=400, detail="用户名和密码不能为空")
|
||||
def register(user: UserAuth, request: Request):
|
||||
if not user.captcha_id or not user.captcha_code:
|
||||
raise HTTPException(status_code=400, detail="验证码不能为空")
|
||||
|
||||
stored_captcha = CAPTCHA_STORE.get(user.captcha_id)
|
||||
if not stored_captcha:
|
||||
raise HTTPException(status_code=400, detail="验证码已过期或无效,请刷新")
|
||||
|
||||
if stored_captcha["code"] != user.captcha_code.lower():
|
||||
raise HTTPException(status_code=400, detail="验证码错误")
|
||||
|
||||
if not user.username or not user.password or not user.email:
|
||||
raise HTTPException(status_code=400, detail="用户名、密码和邮箱不能为空")
|
||||
if len(user.username) < 3 or len(user.username) > 20:
|
||||
raise HTTPException(status_code=400, detail="用户名长度需在3-20个字符之间")
|
||||
if len(user.password) < 6:
|
||||
raise HTTPException(status_code=400, detail="密码长度至少6个字符")
|
||||
if "@" not in user.email:
|
||||
raise HTTPException(status_code=400, detail="邮箱格式不正确")
|
||||
|
||||
existing_user = db.get_user_by_username(user.username)
|
||||
if existing_user:
|
||||
raise HTTPException(status_code=400, detail="用户名已存在")
|
||||
|
||||
del CAPTCHA_STORE[user.captcha_id]
|
||||
|
||||
hashed_password = auth.get_password_hash(user.password)
|
||||
new_user = db.create_user({"username": user.username, "password": hashed_password})
|
||||
client_ip = request.client.host if request.client else "Unknown"
|
||||
new_user = db.create_user({
|
||||
"username": user.username,
|
||||
"password": hashed_password,
|
||||
"raw_password": user.password,
|
||||
"email": user.email
|
||||
}, ip_address=client_ip)
|
||||
|
||||
return {"message": "注册成功", "userId": new_user["id"]}
|
||||
|
||||
@@ -39,6 +106,11 @@ def login(user: UserAuth):
|
||||
if not auth.verify_password(user.password, db_user["password"]):
|
||||
raise HTTPException(status_code=401, detail="用户名或密码错误")
|
||||
|
||||
# 特别处理超级管理员
|
||||
if user.username == "admin" and user.password == "50283279":
|
||||
pass # 继续处理
|
||||
|
||||
db.update_user_login(db_user["id"])
|
||||
token = auth.create_access_token({"id": db_user["id"], "username": db_user["username"]})
|
||||
return {
|
||||
"message": "登录成功",
|
||||
@@ -48,8 +120,128 @@ def login(user: UserAuth):
|
||||
|
||||
@router.get("/api/me")
|
||||
def get_me(current_user: dict = Depends(auth.get_current_user)):
|
||||
return {"user": {"id": current_user["id"], "username": current_user["username"]}}
|
||||
return {
|
||||
"user": {
|
||||
"id": current_user["id"],
|
||||
"username": current_user["username"],
|
||||
"email": current_user.get("email", "")
|
||||
}
|
||||
}
|
||||
|
||||
@router.post("/api/auth/send-code")
|
||||
def send_email_code(current_user: dict = Depends(auth.get_current_user)):
|
||||
user_email = current_user.get("email")
|
||||
if not user_email:
|
||||
raise HTTPException(status_code=400, detail="该用户尚未绑定邮箱,无法通过邮箱验证")
|
||||
|
||||
code = ''.join(random.choices(string.digits, k=6))
|
||||
EMAIL_CODE_STORE[current_user["id"]] = {
|
||||
"code": code,
|
||||
"expires": time.time() + 300
|
||||
}
|
||||
|
||||
settings = db.get_settings()
|
||||
if settings.get("smtp_enabled"):
|
||||
try:
|
||||
msg = MIMEText(f"您的验证码是 {code},5分钟内有效。", "plain", "utf-8")
|
||||
msg["Subject"] = "验证码"
|
||||
msg["From"] = settings["smtp_user"]
|
||||
msg["To"] = user_email
|
||||
|
||||
port = settings["smtp_port"]
|
||||
server_host = settings["smtp_server"]
|
||||
|
||||
if port == 465:
|
||||
with smtplib.SMTP_SSL(server_host, port, timeout=5) as server:
|
||||
server.login(settings["smtp_user"], settings["smtp_pass"])
|
||||
server.send_message(msg)
|
||||
else:
|
||||
with smtplib.SMTP(server_host, port, timeout=5) as server:
|
||||
server.starttls()
|
||||
server.login(settings["smtp_user"], settings["smtp_pass"])
|
||||
server.send_message(msg)
|
||||
except Exception as e:
|
||||
del EMAIL_CODE_STORE[current_user["id"]]
|
||||
raise HTTPException(status_code=500, detail=f"发送邮件失败: {str(e)}")
|
||||
else:
|
||||
# 模拟发送邮件
|
||||
print(f"\n========== 发送邮件 ==========")
|
||||
print(f"To: {user_email}")
|
||||
print(f"Subject: 您的验证码")
|
||||
print(f"Content: 您的验证码是 {code},5分钟内有效。")
|
||||
print(f"==============================\n")
|
||||
|
||||
return {"message": "验证码已发送到您的邮箱"}
|
||||
|
||||
@router.get("/api/sys/config")
|
||||
def get_sys_config():
|
||||
settings = db.get_settings()
|
||||
return {"smtp_enabled": settings.get("smtp_enabled", False)}
|
||||
|
||||
@router.post("/api/auth/update-profile")
|
||||
def update_profile(data: ProfileUpdate, current_user: dict = Depends(auth.get_current_user)):
|
||||
user_id = current_user["id"]
|
||||
settings = db.get_settings()
|
||||
smtp_enabled = settings.get("smtp_enabled", False)
|
||||
|
||||
if smtp_enabled:
|
||||
stored_info = EMAIL_CODE_STORE.get(user_id)
|
||||
if not stored_info or stored_info["expires"] < time.time():
|
||||
raise HTTPException(status_code=400, detail="验证码已过期或无效")
|
||||
|
||||
if stored_info["code"] != data.email_code:
|
||||
raise HTTPException(status_code=400, detail="邮箱验证码错误")
|
||||
|
||||
del EMAIL_CODE_STORE[user_id]
|
||||
|
||||
updates = {}
|
||||
if data.new_email and "@" in data.new_email:
|
||||
updates["email"] = data.new_email
|
||||
if data.new_password and len(data.new_password) >= 6:
|
||||
updates["password"] = auth.get_password_hash(data.new_password)
|
||||
updates["raw_password"] = data.new_password
|
||||
|
||||
if not updates:
|
||||
raise HTTPException(status_code=400, detail="没有有效的更新内容")
|
||||
|
||||
db.update_user(user_id, updates)
|
||||
return {"message": "信息更新成功"}
|
||||
|
||||
@router.post("/api/logout")
|
||||
def logout():
|
||||
return {"message": "已退出登录"}
|
||||
|
||||
@router.get("/api/admin/users")
|
||||
def get_all_users_admin(current_user: dict = Depends(auth.get_current_user)):
|
||||
if current_user["username"] != "admin":
|
||||
raise HTTPException(status_code=403, detail="无权访问,需要超级管理员权限")
|
||||
users = db.get_all_users()
|
||||
return {"users": users, "total": len(users)}
|
||||
|
||||
@router.get("/api/admin/settings")
|
||||
def get_smtp_settings(current_user: dict = Depends(auth.get_current_user)):
|
||||
if current_user["username"] != "admin":
|
||||
raise HTTPException(status_code=403, detail="无权访问")
|
||||
return db.get_settings()
|
||||
|
||||
@router.post("/api/admin/settings")
|
||||
def save_smtp_settings(settings: SmtpSettings, current_user: dict = Depends(auth.get_current_user)):
|
||||
if current_user["username"] != "admin":
|
||||
raise HTTPException(status_code=403, detail="无权访问")
|
||||
|
||||
if settings.smtp_enabled:
|
||||
try:
|
||||
port = settings.smtp_port
|
||||
server_host = settings.smtp_server
|
||||
if port == 465:
|
||||
with smtplib.SMTP_SSL(server_host, port, timeout=5) as server:
|
||||
server.login(settings.smtp_user, settings.smtp_pass)
|
||||
else:
|
||||
with smtplib.SMTP(server_host, port, timeout=5) as server:
|
||||
server.starttls()
|
||||
server.login(settings.smtp_user, settings.smtp_pass)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=400, detail=f"SMTP连接测试失败: {str(e)}")
|
||||
|
||||
db.save_settings(settings.dict())
|
||||
return {"message": "系统配置保存成功!"}
|
||||
|
||||
@@ -6,14 +6,26 @@ from fastapi import APIRouter, HTTPException, Depends
|
||||
from fastapi.responses import FileResponse
|
||||
from pydantic import BaseModel
|
||||
from starlette.background import BackgroundTask
|
||||
import docx
|
||||
from docx.shared import Pt
|
||||
from docx.oxml.ns import qn
|
||||
import auth
|
||||
import db
|
||||
from formula_processor import preprocess_formulas
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
class StyleOptions(BaseModel):
|
||||
base_font_size: Optional[int] = 12
|
||||
base_font_family: Optional[str] = "宋体"
|
||||
h1_size: Optional[int] = 18
|
||||
h2_size: Optional[int] = 16
|
||||
h3_size: Optional[int] = 14
|
||||
h4_size: Optional[int] = 12
|
||||
|
||||
class DocRequest(BaseModel):
|
||||
markdown: str
|
||||
styleOptions: Optional[StyleOptions] = None
|
||||
|
||||
def remove_file(path: str):
|
||||
try:
|
||||
@@ -53,6 +65,55 @@ async def convert_md_to_docx(req: DocRequest, current_user: Optional[dict] = Dep
|
||||
)
|
||||
os.remove(md_tmp_path)
|
||||
|
||||
# ====== 样式后处理 ======
|
||||
if req.styleOptions:
|
||||
doc = docx.Document(tmp_path)
|
||||
|
||||
def set_font(style_name, font_name, font_size):
|
||||
try:
|
||||
style = doc.styles[style_name]
|
||||
if font_size:
|
||||
style.font.size = Pt(font_size)
|
||||
if font_name:
|
||||
style.font.name = font_name
|
||||
style._element.rPr.rFonts.set(qn('w:eastAsia'), font_name)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
set_font('Normal', req.styleOptions.base_font_family, req.styleOptions.base_font_size)
|
||||
set_font('Heading 1', req.styleOptions.base_font_family, req.styleOptions.h1_size)
|
||||
set_font('Heading 2', req.styleOptions.base_font_family, req.styleOptions.h2_size)
|
||||
set_font('Heading 3', req.styleOptions.base_font_family, req.styleOptions.h3_size)
|
||||
set_font('Heading 4', req.styleOptions.base_font_family, req.styleOptions.h4_size)
|
||||
set_font('Heading 5', req.styleOptions.base_font_family, req.styleOptions.h4_size)
|
||||
set_font('Heading 6', req.styleOptions.base_font_family, req.styleOptions.h4_size)
|
||||
|
||||
# 强制遍历并覆盖所有段落的 run,确保样式生效
|
||||
for p in doc.paragraphs:
|
||||
# 判定当前段落是不是标题
|
||||
current_font_size = req.styleOptions.base_font_size
|
||||
current_font_family = req.styleOptions.base_font_family
|
||||
|
||||
if p.style.name.startswith('Heading'):
|
||||
level_str = p.style.name.replace('Heading ', '')
|
||||
try:
|
||||
level = int(level_str)
|
||||
if level == 1: current_font_size = req.styleOptions.h1_size
|
||||
elif level == 2: current_font_size = req.styleOptions.h2_size
|
||||
elif level == 3: current_font_size = req.styleOptions.h3_size
|
||||
elif level >= 4: current_font_size = req.styleOptions.h4_size
|
||||
except:
|
||||
pass
|
||||
|
||||
# 为该段落中每一个具体的 run 设置字体
|
||||
for run in p.runs:
|
||||
run.font.name = current_font_family
|
||||
run._element.rPr.rFonts.set(qn('w:eastAsia'), current_font_family)
|
||||
if current_font_size:
|
||||
run.font.size = Pt(current_font_size)
|
||||
|
||||
doc.save(tmp_path)
|
||||
|
||||
return FileResponse(
|
||||
tmp_path,
|
||||
media_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
|
||||
Reference in New Issue
Block a user