@diagrammo/dgmo 0.92.1 → 0.94.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/advanced.d.ts +103 -38
- package/dist/advanced.js +457 -423
- package/dist/block.d.ts +2 -2
- package/dist/block.js +75 -70
- package/dist/{chart-meta-BBqLnv5q.d.ts → chart-meta-BbjsRY7o.d.ts} +2 -2
- package/dist/chart-meta.d.ts +3 -3
- package/dist/chart-meta.js +25 -19
- package/dist/{chart-types-CbXlZFLd.d.ts → chart-types-Cppnp31G.d.ts} +173 -4
- package/dist/{charts-d3-QUUDVETP.js → charts-d3-SZV2SFTM.js} +7 -6
- package/dist/{chunk-ADNIO3XY.js → chunk-2FDQEQID.js} +5 -5
- package/dist/{chunk-QUGC7GWB.js → chunk-2HSHWPTO.js} +15 -15
- package/dist/{chunk-L5NW3PVL.js → chunk-2I4UQG7W.js} +1 -1
- package/dist/{chunk-2YAFDND3.js → chunk-2MS623GW.js} +4 -6
- package/dist/{chunk-73EYNV4O.js → chunk-2XMTZ5JR.js} +4 -6
- package/dist/{chunk-ZJAK6C7Y.js → chunk-3PP746YM.js} +6 -1
- package/dist/{chunk-MDVJYRJT.js → chunk-3TWBMU7K.js} +22 -22
- package/dist/{chunk-FTUMRSGT.js → chunk-3ZP3QC47.js} +8 -288
- package/dist/{chunk-J2E7EUER.js → chunk-4EX4OKGZ.js} +86 -23
- package/dist/{chunk-Y2V5AEVG.js → chunk-4SP6OUO7.js} +1952 -1824
- package/dist/{chunk-HIWHIYLD.js → chunk-4TEPDQHJ.js} +19 -19
- package/dist/{chunk-DEFBUZWV.js → chunk-5HAYT43L.js} +70 -54
- package/dist/{chunk-6WVX4KNP.js → chunk-5ZUZZDW5.js} +97 -297
- package/dist/{chunk-X5BUX2GK.js → chunk-6JCTW74W.js} +7 -5
- package/dist/{chunk-Q6W2K33N.js → chunk-6XLMTAEX.js} +1 -1
- package/dist/{chunk-ONYO5WJW.js → chunk-7IOZ6JE4.js} +21 -21
- package/dist/chunk-7SXV7NUS.js +416 -0
- package/dist/{chunk-NPWVOFB3.js → chunk-7WEYXYLC.js} +1 -1
- package/dist/{chunk-GE7ICBX6.js → chunk-AM42TLSZ.js} +102 -97
- package/dist/{chunk-WLLO3PZ3.js → chunk-AYUSD4Z6.js} +45 -19
- package/dist/{chunk-45QUTYPD.js → chunk-B25IWGDH.js} +69 -20
- package/dist/{chunk-JKST4RTT.js → chunk-BH2SF4TT.js} +6 -6
- package/dist/{chunk-6OIMUSDX.js → chunk-C6G36F5S.js} +9 -9
- package/dist/{chunk-DRFGIOZ6.js → chunk-CIHHTS5B.js} +4 -6
- package/dist/chunk-CYTFO2LF.js +209 -0
- package/dist/{chunk-Q2UFOKPB.js → chunk-DDIOWNHS.js} +22 -22
- package/dist/{chunk-Q6ZQX2HX.js → chunk-DLJJOCIT.js} +4 -6
- package/dist/{chunk-26BBJUBW.js → chunk-DNM3XZCK.js} +4 -6
- package/dist/{chunk-AUS7V54P.js → chunk-ERT7XDQW.js} +1 -1
- package/dist/{chunk-7ENDOHAA.js → chunk-FMAVHTYB.js} +919 -927
- package/dist/{chunk-URQIWIKX.js → chunk-FWVE373X.js} +4 -4
- package/dist/{chunk-VOR32OHN.js → chunk-G3HZ4PGE.js} +13 -15
- package/dist/{chunk-RBFJT23E.js → chunk-GWQRTA5W.js} +6 -6
- package/dist/chunk-GXCDD6NG.js +24 -0
- package/dist/{chunk-3PFMGNOM.js → chunk-HHVIE45A.js} +26 -11
- package/dist/{chunk-MXAP37W6.js → chunk-HI6R27YA.js} +16 -7
- package/dist/{chunk-QQPNCXAO.js → chunk-I37S3EZE.js} +18 -18
- package/dist/{chunk-YITHYQCL.js → chunk-IGJEKO2P.js} +8 -8
- package/dist/{chunk-BZX7QCXJ.js → chunk-IHN6WDEY.js} +15 -15
- package/dist/{chunk-QT3KDDXK.js → chunk-IN7XI6NO.js} +0 -7
- package/dist/{chunk-4QLGGQNO.js → chunk-IZHGT5HD.js} +44 -18
- package/dist/{chunk-5SSTVFPX.js → chunk-JT2BG7LM.js} +5 -7
- package/dist/{chunk-2BJW7FSF.js → chunk-KBEWVCK3.js} +1 -1
- package/dist/{chunk-DUPZ2BBY.js → chunk-KBHT5XEY.js} +143 -6
- package/dist/{chunk-V4D2ZQBE.js → chunk-KRPLP5LP.js} +6 -1
- package/dist/{chunk-QKY6W4NA.js → chunk-KSZB7TIY.js} +25 -25
- package/dist/{chunk-6ZL2XYM7.js → chunk-MLY5ALOV.js} +6 -6
- package/dist/{chunk-VSOZZYLK.js → chunk-NERQSSYD.js} +20 -9
- package/dist/{chunk-OQW4ETJX.js → chunk-NM5V5EKY.js} +6 -1
- package/dist/{chunk-EBSFSOJC.js → chunk-NOQB4KMV.js} +22 -22
- package/dist/{chunk-6BNNLVAR.js → chunk-NPDVWFAQ.js} +6 -1
- package/dist/{chunk-FSJ3ZA6N.js → chunk-OSSTOSXU.js} +12 -12
- package/dist/chunk-P7TRFL4P.js +54 -0
- package/dist/{chunk-A4PNWAUW.js → chunk-PGSGJLUR.js} +6 -1
- package/dist/{chunk-S7W75MIM.js → chunk-QKPOIJBT.js} +23 -5
- package/dist/{chunk-YO6AQU4A.js → chunk-QPQWY5RU.js} +12 -12
- package/dist/{chunk-NREU4JFE.js → chunk-RBVFNUAL.js} +6 -8
- package/dist/{chunk-5EBYPETE.js → chunk-RESEJSCV.js} +3 -5
- package/dist/{chunk-BRSM6Z34.js → chunk-RITTLIDJ.js} +14 -14
- package/dist/{chunk-MX4SZLSV.js → chunk-S5Y3OO3V.js} +16 -8
- package/dist/{chunk-O5WUZGPV.js → chunk-TASRGDYP.js} +18 -18
- package/dist/{chunk-HXULJZA2.js → chunk-TDAGJJPZ.js} +6 -1
- package/dist/chunk-UCHZJJIT.js +421 -0
- package/dist/{chunk-42UJ23H3.js → chunk-UIEKW4SG.js} +1 -0
- package/dist/{chunk-WFA6IULY.js → chunk-URRAWU5D.js} +5 -0
- package/dist/{chunk-IGKFOHBG.js → chunk-VBMRZCMQ.js} +13 -13
- package/dist/{chunk-JRWUHLRP.js → chunk-VDY2GR6U.js} +51 -8
- package/dist/{chunk-EJS3K44P.js → chunk-VGAMBOOC.js} +5 -3
- package/dist/{chunk-B5PEKSRH.js → chunk-VSAKEMDD.js} +6 -1
- package/dist/chunk-WTTIODDV.js +9 -0
- package/dist/{chunk-JLU52ZDT.js → chunk-XJQ6Z3FO.js} +10 -10
- package/dist/{chunk-KTGZDMDX.js → chunk-XKCRKD2B.js} +140 -53
- package/dist/{chunk-LRP5FXST.js → chunk-YQMIKX54.js} +61 -24
- package/dist/{chunk-H5UEVW6Q.js → chunk-ZD3QCNB7.js} +1 -1
- package/dist/clock.js +168 -0
- package/dist/completion-registry.js +3 -1
- package/dist/countdown.js +36 -395
- package/dist/{dgmo-router-4UAPPIKN.js → dgmo-router-E5O7RJSW.js} +50 -43
- package/dist/{dimensions-SCNVYLRF.js → dimensions-DS6FWLRY.js} +3 -3
- package/dist/{d3-BThYBTQk.d.ts → export-context-Ceh3wr0E.d.ts} +2 -8
- package/dist/{flowchart-parser-NA75YQ77.js → flowchart-parser-NZXASOZG.js} +8 -3
- package/dist/{flowchart-renderer-6MGGX4RC.js → flowchart-renderer-PTCRIANF.js} +17 -19
- package/dist/index.d.ts +8 -7
- package/dist/index.js +80 -74
- package/dist/{layout-MBVBAMPA.js → layout-3TSVAGWH.js} +2 -2
- package/dist/layout-ISSBWBH7.js +24 -0
- package/dist/layout-IT4ZTV6C.js +24 -0
- package/dist/{layout-BNLFQHSB.js → layout-U3AH6M7J.js} +9 -10
- package/dist/layout-VC3MXRB4.js +29 -0
- package/dist/layout-VDCJOZSH.js +11 -0
- package/dist/{layout-search-PMYL3VWS.js → layout-search-BBX2BMEF.js} +11 -12
- package/dist/{palettes-IN7ZFRJM.js → palettes-4Y7CL2QL.js} +4 -2
- package/dist/{parser-QYISOAGR.js → parser-4RFY7D52.js} +8 -3
- package/dist/{parser-3MK56JZC.js → parser-4Y6PODW6.js} +2 -2
- package/dist/{parser-GX5YLRIP.js → parser-7QKQ4P4P.js} +8 -3
- package/dist/{parser-2NWH5JUS.js → parser-A3AN76RQ.js} +2 -1
- package/dist/{parser-LCJ76UXS.js → parser-BT4NI6JY.js} +5 -1
- package/dist/{parser-FXDS4JDK.js → parser-F7NDRPMA.js} +2 -2
- package/dist/{parser-BES6LV3G.js → parser-GDLKUBTO.js} +5 -1
- package/dist/{parser-SEUTXN6U.js → parser-KJPPUN4D.js} +2 -2
- package/dist/{parser-SIKL4PLF.js → parser-KMKVFET2.js} +5 -1
- package/dist/{parser-5LW5JDYG.js → parser-NL73FSFI.js} +5 -1
- package/dist/{parser-VA7ZQQTA.js → parser-NUU3DVW4.js} +5 -1
- package/dist/{parser-XZUKNZPB.js → parser-R3LPEQIT.js} +7 -1
- package/dist/{parser-X23GRTQJ.js → parser-RCIEKN7Y.js} +5 -1
- package/dist/{parser-L6RWDXQN.js → parser-TAYRTCPR.js} +8 -3
- package/dist/redraw-AHW7EUUF.js +1698 -0
- package/dist/redraw-STZ4WJAI.js +73 -0
- package/dist/{renderer-LM4ICK6I.js → renderer-2LYX6NHN.js} +4 -5
- package/dist/{renderer-NHTR7IRR.js → renderer-3NLDX7DQ.js} +4 -5
- package/dist/{renderer-TO2NVJP3.js → renderer-4SE7R22T.js} +50 -45
- package/dist/{renderer-3IHQI4A4.js → renderer-53B523PM.js} +11 -10
- package/dist/{renderer-3JY6JAQJ.js → renderer-7OGGV327.js} +5 -6
- package/dist/{renderer-2FVUPBGV.js → renderer-AM7P4LN7.js} +1 -1
- package/dist/{renderer-5VKPB4LL.js → renderer-BXD5KVSR.js} +5 -5
- package/dist/{renderer-OAR5VPH4.js → renderer-DAZWHNLI.js} +2 -2
- package/dist/{renderer-WIU5BJUK.js → renderer-DDWDCM2K.js} +2 -2
- package/dist/{renderer-3QAFDXEY.js → renderer-FMTLSOCX.js} +16 -12
- package/dist/{renderer-JEJT3YET.js → renderer-HX6ICPDX.js} +2 -3
- package/dist/{renderer-NDA2FFYB.js → renderer-ISQJ2ELA.js} +5 -5
- package/dist/{renderer-XGG2UNXT.js → renderer-IXBOT6DU.js} +3 -4
- package/dist/{renderer-S3YCLJKL.js → renderer-J3GPDK73.js} +20 -22
- package/dist/{renderer-DVNMCYHZ.js → renderer-J7ZSTJUE.js} +15 -15
- package/dist/{renderer-ALWVK3EJ.js → renderer-JJ4QW3SK.js} +6 -6
- package/dist/{renderer-RUSFL7WU.js → renderer-JYHA6R2D.js} +8 -7
- package/dist/{renderer-5TZVFQ7K.js → renderer-KJ3V5BYP.js} +7 -8
- package/dist/{renderer-RSK6QFWN.js → renderer-LNP23NSM.js} +7 -9
- package/dist/{renderer-ZHGHTSNG.js → renderer-M5DUMITP.js} +13 -12
- package/dist/{renderer-O6DY46AV.js → renderer-MWZC7TMD.js} +7 -7
- package/dist/{renderer-DC7C5Q3G.js → renderer-NOYLNVTI.js} +2 -2
- package/dist/{renderer-ISSDGK54.js → renderer-O6RP52CQ.js} +3 -3
- package/dist/{renderer-ZGY7P4BM.js → renderer-OUDHH5MV.js} +19 -22
- package/dist/{renderer-QGIHLZOJ.js → renderer-PHLCYVSN.js} +9 -10
- package/dist/{renderer-VPIELEE5.js → renderer-QTPWRRJ7.js} +8 -9
- package/dist/{renderer-LQP3AGEJ.js → renderer-RUSQJFFC.js} +3 -4
- package/dist/{renderer-MM27BSBO.js → renderer-TINHO2IO.js} +3 -4
- package/dist/{renderer-7ZZG5HR3.js → renderer-UTEEJDGB.js} +9 -9
- package/dist/{renderer-J5FKF423.js → renderer-W4MUMXJE.js} +7 -4
- package/dist/{renderer-XO57LTU4.js → renderer-WPN2SXGT.js} +5 -5
- package/dist/{renderer-ZZ6MWVB7.js → renderer-XCLARXCK.js} +4 -4
- package/dist/{renderer-J666LZXJ.js → renderer-XOWDERU2.js} +8 -8
- package/dist/{state-parser-TIR2ORJY.js → state-parser-KPVW5CRI.js} +8 -3
- package/dist/{state-renderer-G6SUXU4J.js → state-renderer-ZVEI265C.js} +18 -21
- package/dist/{tag-groups-DsoVpAY-.d.ts → tag-groups-DydewK3D.d.ts} +2 -173
- package/dist/{themes-DRNjxX7Q.d.ts → themes-DzIH3Hjv.d.ts} +3 -2
- package/docs/ai-integration.md +1 -1
- package/docs/language-reference.md +23 -2
- package/gallery/fixtures/whiteboard.dgmo +3 -0
- package/package.json +2 -6
- package/dist/chunk-3Y63RFJL.js +0 -75
- package/dist/chunk-5DH3KYFH.js +0 -20
- package/dist/chunk-O753JUEZ.js +0 -67
- package/dist/chunk-RJNZHFNG.js +0 -51
- package/dist/chunk-Z6DXWULM.js +0 -23
- package/dist/layout-5USEVQBY.js +0 -25
- package/dist/layout-J3AGFZZ7.js +0 -10
- package/dist/layout-S3RLVPH4.js +0 -25
- package/dist/layout-WRG4APSJ.js +0 -32
- package/dist/{chunk-DGUGE67L.js → chunk-CDYV46JE.js} +3 -3
- package/dist/{chunk-TKAB3FTK.js → chunk-DRQSB72S.js} +11 -11
- package/dist/{chunk-ZKP77MB3.js → chunk-FVTYJUXR.js} +5 -5
- package/dist/{chunk-MA42PIGJ.js → chunk-H5NVCOEJ.js} +4 -4
- package/dist/{chunk-BEA4D7OS.js → chunk-IXHWS2HI.js} +3 -3
- package/dist/{chunk-SOHZDW6N.js → chunk-UXNA2H2V.js} +3 -3
- package/dist/{chunk-NO3UX6AP.js → chunk-V2NQV7VL.js} +4 -4
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "./chunk-
|
|
2
|
+
renderDataChartD3
|
|
3
|
+
} from "./chunk-YQMIKX54.js";
|
|
4
4
|
import {
|
|
5
5
|
REGISTRY_BY_ID,
|
|
6
|
-
choosePalette,
|
|
7
|
-
extractPaletteDirective,
|
|
8
6
|
getRenderCategory,
|
|
9
7
|
parseArc,
|
|
10
8
|
parseDgmo,
|
|
@@ -14,46 +12,69 @@ import {
|
|
|
14
12
|
parseVenn,
|
|
15
13
|
parseVisualization,
|
|
16
14
|
parseWordcloud
|
|
17
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-5ZUZZDW5.js";
|
|
16
|
+
import {
|
|
17
|
+
parseChart,
|
|
18
|
+
parseFunctionChart,
|
|
19
|
+
parseFunnel,
|
|
20
|
+
parseHeatmap,
|
|
21
|
+
parseSankey,
|
|
22
|
+
parseScatter
|
|
23
|
+
} from "./chunk-H6BT45SN.js";
|
|
24
|
+
import {
|
|
25
|
+
parsePyramid
|
|
26
|
+
} from "./chunk-3PP746YM.js";
|
|
27
|
+
import {
|
|
28
|
+
parseRing
|
|
29
|
+
} from "./chunk-NM5V5EKY.js";
|
|
30
|
+
import {
|
|
31
|
+
parseTreemap
|
|
32
|
+
} from "./chunk-3KVUFHUJ.js";
|
|
18
33
|
import {
|
|
19
34
|
MAP_DX
|
|
20
35
|
} from "./chunk-EOYPX6SF.js";
|
|
21
36
|
import {
|
|
22
|
-
|
|
23
|
-
} from "./chunk-
|
|
37
|
+
computeQuadrantPointLabels
|
|
38
|
+
} from "./chunk-KMU65FYM.js";
|
|
24
39
|
import {
|
|
25
|
-
|
|
26
|
-
} from "./chunk-
|
|
40
|
+
parseVersionControl
|
|
41
|
+
} from "./chunk-2ZW4NBYX.js";
|
|
27
42
|
import {
|
|
28
|
-
|
|
29
|
-
} from "./chunk-
|
|
43
|
+
parseMap
|
|
44
|
+
} from "./chunk-AULZD45V.js";
|
|
30
45
|
import {
|
|
31
|
-
|
|
32
|
-
} from "./chunk-
|
|
46
|
+
parseSketch
|
|
47
|
+
} from "./chunk-WZBZXZ6T.js";
|
|
33
48
|
import {
|
|
34
|
-
|
|
35
|
-
} from "./chunk-
|
|
49
|
+
parseWhiteboard
|
|
50
|
+
} from "./chunk-5HAYT43L.js";
|
|
36
51
|
import {
|
|
37
|
-
|
|
38
|
-
} from "./chunk-
|
|
52
|
+
parseSwimlane
|
|
53
|
+
} from "./chunk-J7Q4AB23.js";
|
|
39
54
|
import {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
parseFunnel,
|
|
43
|
-
parseHeatmap,
|
|
44
|
-
parseSankey,
|
|
45
|
-
parseScatter
|
|
46
|
-
} from "./chunk-H6BT45SN.js";
|
|
55
|
+
parseMindmap
|
|
56
|
+
} from "./chunk-XIUGSUE4.js";
|
|
47
57
|
import {
|
|
48
|
-
|
|
49
|
-
} from "./chunk-
|
|
58
|
+
parseTechRadar
|
|
59
|
+
} from "./chunk-EBVVMUAA.js";
|
|
50
60
|
import {
|
|
51
|
-
|
|
52
|
-
} from "./chunk-
|
|
61
|
+
parseKanban
|
|
62
|
+
} from "./chunk-LKZCUFOW.js";
|
|
53
63
|
import {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
64
|
+
parseInfra
|
|
65
|
+
} from "./chunk-UXNA2H2V.js";
|
|
66
|
+
import {
|
|
67
|
+
parseJourneyMap
|
|
68
|
+
} from "./chunk-PGSGJLUR.js";
|
|
69
|
+
import {
|
|
70
|
+
parseGoal
|
|
71
|
+
} from "./chunk-7PJBJ2DU.js";
|
|
72
|
+
import {
|
|
73
|
+
parseEventLine
|
|
74
|
+
} from "./chunk-3GUEYQGL.js";
|
|
75
|
+
import {
|
|
76
|
+
renderTimeline
|
|
77
|
+
} from "./chunk-TASRGDYP.js";
|
|
57
78
|
import {
|
|
58
79
|
EXPORT_HEIGHT,
|
|
59
80
|
EXPORT_WIDTH,
|
|
@@ -65,34 +86,34 @@ import {
|
|
|
65
86
|
renderChartTitle,
|
|
66
87
|
resolveExportPalette,
|
|
67
88
|
showTooltip
|
|
68
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-6XLMTAEX.js";
|
|
69
90
|
import {
|
|
70
|
-
|
|
71
|
-
} from "./chunk-
|
|
91
|
+
parseTimelineDate
|
|
92
|
+
} from "./chunk-BQO24BDM.js";
|
|
72
93
|
import {
|
|
73
|
-
|
|
74
|
-
} from "./chunk-
|
|
94
|
+
parseFamily
|
|
95
|
+
} from "./chunk-R6EGUTIV.js";
|
|
75
96
|
import {
|
|
76
|
-
|
|
77
|
-
} from "./chunk-
|
|
97
|
+
parseGantt
|
|
98
|
+
} from "./chunk-PVWIBKV2.js";
|
|
78
99
|
import {
|
|
79
|
-
|
|
80
|
-
} from "./chunk-
|
|
100
|
+
parseClock
|
|
101
|
+
} from "./chunk-NXU4N5WT.js";
|
|
81
102
|
import {
|
|
82
|
-
|
|
83
|
-
} from "./chunk-
|
|
103
|
+
parseCountdown
|
|
104
|
+
} from "./chunk-KBEWVCK3.js";
|
|
84
105
|
import {
|
|
85
|
-
|
|
86
|
-
} from "./chunk-
|
|
106
|
+
parseCycle
|
|
107
|
+
} from "./chunk-NPDVWFAQ.js";
|
|
87
108
|
import {
|
|
88
|
-
|
|
89
|
-
} from "./chunk-
|
|
109
|
+
parseBracket
|
|
110
|
+
} from "./chunk-2WQ3YZMN.js";
|
|
90
111
|
import {
|
|
91
|
-
|
|
92
|
-
} from "./chunk-
|
|
112
|
+
layoutBracket
|
|
113
|
+
} from "./chunk-ZI6WC24V.js";
|
|
93
114
|
import {
|
|
94
|
-
|
|
95
|
-
} from "./chunk-
|
|
115
|
+
parseC4
|
|
116
|
+
} from "./chunk-IXHWS2HI.js";
|
|
96
117
|
import {
|
|
97
118
|
parseBlock
|
|
98
119
|
} from "./chunk-BRGRIZQB.js";
|
|
@@ -100,83 +121,64 @@ import {
|
|
|
100
121
|
isBlockNode
|
|
101
122
|
} from "./chunk-XSVWUOUZ.js";
|
|
102
123
|
import {
|
|
103
|
-
|
|
104
|
-
} from "./chunk-
|
|
105
|
-
import {
|
|
106
|
-
parseMap
|
|
107
|
-
} from "./chunk-AULZD45V.js";
|
|
124
|
+
parseBody
|
|
125
|
+
} from "./chunk-JXGSTBW6.js";
|
|
108
126
|
import {
|
|
109
127
|
parseBoxesAndLines
|
|
110
|
-
} from "./chunk-
|
|
111
|
-
import {
|
|
112
|
-
parseSketch
|
|
113
|
-
} from "./chunk-WZBZXZ6T.js";
|
|
114
|
-
import {
|
|
115
|
-
parseWhiteboard
|
|
116
|
-
} from "./chunk-DEFBUZWV.js";
|
|
117
|
-
import {
|
|
118
|
-
parseSwimlane
|
|
119
|
-
} from "./chunk-J7Q4AB23.js";
|
|
120
|
-
import {
|
|
121
|
-
parseFamily
|
|
122
|
-
} from "./chunk-R6EGUTIV.js";
|
|
128
|
+
} from "./chunk-2XMTZ5JR.js";
|
|
123
129
|
import {
|
|
124
|
-
|
|
125
|
-
} from "./chunk-
|
|
130
|
+
ScaleContext
|
|
131
|
+
} from "./chunk-24YPR5EH.js";
|
|
126
132
|
import {
|
|
127
|
-
|
|
128
|
-
} from "./chunk-
|
|
133
|
+
legendInlineSupported
|
|
134
|
+
} from "./chunk-UIEKW4SG.js";
|
|
129
135
|
import {
|
|
130
|
-
|
|
131
|
-
|
|
136
|
+
GRID_DASH,
|
|
137
|
+
scaleDash
|
|
138
|
+
} from "./chunk-XCKNFFKM.js";
|
|
132
139
|
import {
|
|
133
|
-
|
|
134
|
-
} from "./chunk-
|
|
140
|
+
compactNumber
|
|
141
|
+
} from "./chunk-JILEYZ2V.js";
|
|
135
142
|
import {
|
|
136
|
-
|
|
137
|
-
} from "./chunk-
|
|
143
|
+
parseRaci
|
|
144
|
+
} from "./chunk-KRPLP5LP.js";
|
|
138
145
|
import {
|
|
139
|
-
|
|
140
|
-
} from "./chunk-
|
|
146
|
+
parseLiveLink
|
|
147
|
+
} from "./chunk-KBDMEOLI.js";
|
|
141
148
|
import {
|
|
142
|
-
|
|
143
|
-
} from "./chunk-
|
|
149
|
+
parseSequenceDgmo
|
|
150
|
+
} from "./chunk-VSAKEMDD.js";
|
|
144
151
|
import {
|
|
145
|
-
|
|
146
|
-
} from "./chunk-
|
|
152
|
+
parseOrg
|
|
153
|
+
} from "./chunk-5OTA2PUH.js";
|
|
147
154
|
import {
|
|
148
|
-
|
|
149
|
-
} from "./chunk-
|
|
155
|
+
parseSitemap
|
|
156
|
+
} from "./chunk-ZECJ7Q6C.js";
|
|
150
157
|
import {
|
|
151
158
|
parsePert
|
|
152
159
|
} from "./chunk-CDM6XMOT.js";
|
|
153
|
-
import {
|
|
154
|
-
parseLiveLink
|
|
155
|
-
} from "./chunk-KBDMEOLI.js";
|
|
156
|
-
import {
|
|
157
|
-
getPalette
|
|
158
|
-
} from "./chunk-7ENDOHAA.js";
|
|
159
|
-
import {
|
|
160
|
-
parseSequenceDgmo
|
|
161
|
-
} from "./chunk-B5PEKSRH.js";
|
|
162
160
|
import {
|
|
163
161
|
parseFlowchart
|
|
164
|
-
} from "./chunk-
|
|
162
|
+
} from "./chunk-DNM3XZCK.js";
|
|
165
163
|
import {
|
|
166
164
|
parseState
|
|
167
|
-
} from "./chunk-
|
|
165
|
+
} from "./chunk-2MS623GW.js";
|
|
168
166
|
import {
|
|
169
|
-
|
|
170
|
-
|
|
167
|
+
choosePalette,
|
|
168
|
+
extractPaletteDirective
|
|
169
|
+
} from "./chunk-CYTFO2LF.js";
|
|
171
170
|
import {
|
|
172
171
|
parseERDiagram
|
|
173
|
-
} from "./chunk-
|
|
172
|
+
} from "./chunk-CIHHTS5B.js";
|
|
174
173
|
import {
|
|
175
|
-
|
|
176
|
-
} from "./chunk-
|
|
174
|
+
parseClassDiagram
|
|
175
|
+
} from "./chunk-DLJJOCIT.js";
|
|
177
176
|
import {
|
|
178
|
-
|
|
179
|
-
} from "./chunk-
|
|
177
|
+
getPalette
|
|
178
|
+
} from "./chunk-FMAVHTYB.js";
|
|
179
|
+
import {
|
|
180
|
+
FONT_FAMILY
|
|
181
|
+
} from "./chunk-ICLB27PZ.js";
|
|
180
182
|
import {
|
|
181
183
|
parseWireframe
|
|
182
184
|
} from "./chunk-GI5R5B3S.js";
|
|
@@ -198,209 +200,19 @@ import {
|
|
|
198
200
|
makeDgmoError
|
|
199
201
|
} from "./chunk-BYU54C3S.js";
|
|
200
202
|
|
|
201
|
-
// src/
|
|
203
|
+
// src/arc/renderer.ts
|
|
202
204
|
import * as d3Scale from "d3-scale";
|
|
203
|
-
import * as
|
|
205
|
+
import * as d3Selection from "d3-selection";
|
|
204
206
|
import * as d3Array from "d3-array";
|
|
205
|
-
function
|
|
206
|
-
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
for (const item of sorted) {
|
|
211
|
-
const halfH = item.height / 2;
|
|
212
|
-
let top = Math.max(item.naturalY - halfH, prevBottom + minGap);
|
|
213
|
-
if (maxY !== void 0) {
|
|
214
|
-
top = Math.min(top, maxY - item.height);
|
|
215
|
-
}
|
|
216
|
-
adjustedY[item.idx] = top + halfH;
|
|
217
|
-
prevBottom = top + item.height;
|
|
218
|
-
}
|
|
219
|
-
return adjustedY;
|
|
220
|
-
}
|
|
221
|
-
var SLOPE_MARGIN = { top: 80, bottom: 40, left: 80 };
|
|
222
|
-
var SLOPE_LABEL_FONT_SIZE = 14;
|
|
223
|
-
function renderSlopeChart(container, parsed, palette, isDark, onClickItem, exportDims) {
|
|
224
|
-
const { periods, data } = parsed;
|
|
225
|
-
const title = parsed.noTitle ? null : parsed.title;
|
|
226
|
-
if (data.length === 0 || periods.length < 2) return;
|
|
227
|
-
const init = initD3Chart(container, palette, exportDims);
|
|
228
|
-
if (!init) return;
|
|
229
|
-
const { svg, width, height, textColor, mutedColor, bgColor, colors } = init;
|
|
230
|
-
const idealWidth = SLOPE_MARGIN.left + periods.length * 100 + 150;
|
|
231
|
-
const ctx = exportDims ? ScaleContext.identity() : ScaleContext.from(width, idealWidth);
|
|
232
|
-
const sMarginTop = ctx.aesthetic(SLOPE_MARGIN.top);
|
|
233
|
-
const sMarginBottom = ctx.aesthetic(SLOPE_MARGIN.bottom);
|
|
234
|
-
const sMarginLeft = ctx.aesthetic(SLOPE_MARGIN.left);
|
|
235
|
-
const sLabelFontSize = ctx.text(SLOPE_LABEL_FONT_SIZE);
|
|
236
|
-
const sPeriodFont = ctx.text(18);
|
|
237
|
-
const sValueFont = ctx.text(16);
|
|
238
|
-
const sPeriodHeaderY = ctx.structural(15);
|
|
239
|
-
const sDash = scaleDash(GRID_DASH, (n) => ctx.structural(n));
|
|
240
|
-
const sLineStroke = ctx.structural(2.5);
|
|
241
|
-
const sHitWidth = ctx.structural(14);
|
|
242
|
-
const sPointR = ctx.structural(4);
|
|
243
|
-
const sPointStroke = ctx.structural(1.5);
|
|
244
|
-
const sValueLabelXOff = ctx.structural(10);
|
|
245
|
-
const sLabelGap = ctx.structural(10);
|
|
246
|
-
svg.attr("preserveAspectRatio", "xMidYMin meet");
|
|
247
|
-
if (ctx.isBelowFloor) {
|
|
248
|
-
svg.attr("width", "100%");
|
|
207
|
+
function orderArcNodes(links, order, groups) {
|
|
208
|
+
const nodeSet = /* @__PURE__ */ new Set();
|
|
209
|
+
for (const link of links) {
|
|
210
|
+
nodeSet.add(link.source);
|
|
211
|
+
nodeSet.add(link.target);
|
|
249
212
|
}
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
return
|
|
253
|
-
}, "");
|
|
254
|
-
const estimatedLabelWidth = measureText(maxLabelText, sLabelFontSize);
|
|
255
|
-
const maxRightMargin = Math.floor(width * 0.35);
|
|
256
|
-
const rightMargin = Math.min(
|
|
257
|
-
Math.max(estimatedLabelWidth + ctx.aesthetic(30), ctx.aesthetic(120)),
|
|
258
|
-
maxRightMargin
|
|
259
|
-
);
|
|
260
|
-
const innerWidth = width - sMarginLeft - rightMargin;
|
|
261
|
-
const innerHeight = height - sMarginTop - sMarginBottom;
|
|
262
|
-
const allValues2 = data.flatMap((d) => d.values);
|
|
263
|
-
const [minVal, maxVal] = d3Array.extent(allValues2);
|
|
264
|
-
const valuePadding = (maxVal - minVal) * 0.1 || 1;
|
|
265
|
-
const yScale = d3Scale.scaleLinear().domain([minVal - valuePadding, maxVal + valuePadding]).range([innerHeight, 0]);
|
|
266
|
-
const xScale = d3Scale.scalePoint().domain(periods).range([0, innerWidth]).padding(0);
|
|
267
|
-
const g = svg.append("g").attr("transform", `translate(${sMarginLeft},${sMarginTop})`);
|
|
268
|
-
const tooltip = createTooltip(container, palette, isDark);
|
|
269
|
-
renderChartTitle(
|
|
270
|
-
svg,
|
|
271
|
-
title,
|
|
272
|
-
parsed.titleLineNumber,
|
|
273
|
-
width,
|
|
274
|
-
textColor,
|
|
275
|
-
onClickItem
|
|
276
|
-
);
|
|
277
|
-
for (const period of periods) {
|
|
278
|
-
const x = xScale(period);
|
|
279
|
-
g.append("text").attr("x", x).attr("y", -sPeriodHeaderY).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", sPeriodFont).attr("font-weight", "bold").text(period);
|
|
280
|
-
g.append("line").attr("x1", x).attr("y1", 0).attr("x2", x).attr("y2", innerHeight).attr("stroke", mutedColor).attr("stroke-width", 1).attr("stroke-dasharray", sDash);
|
|
281
|
-
}
|
|
282
|
-
const lineGen = d3Shape.line().x((_d, i) => xScale(periods[i])).y((d) => yScale(d));
|
|
283
|
-
const seriesInfo = data.map((item, idx) => {
|
|
284
|
-
const color = item.color ?? colors[idx % colors.length];
|
|
285
|
-
const firstVal = item.values[0];
|
|
286
|
-
const lastVal = item.values[item.values.length - 1];
|
|
287
|
-
const absChange = lastVal - firstVal;
|
|
288
|
-
const pctChange = firstVal !== 0 ? absChange / firstVal * 100 : null;
|
|
289
|
-
const sign = absChange > 0 ? "+" : "";
|
|
290
|
-
const tipLines = [`${sign}${parseFloat(absChange.toFixed(2))}`];
|
|
291
|
-
if (pctChange !== null) tipLines.push(`${sign}${pctChange.toFixed(1)}%`);
|
|
292
|
-
const tipHtml = tipLines.join("<br>");
|
|
293
|
-
const lastX = xScale(periods[periods.length - 1]);
|
|
294
|
-
const labelText = `${lastVal} \u2014 ${item.label}`;
|
|
295
|
-
const availableWidth = rightMargin - ctx.aesthetic(15);
|
|
296
|
-
let labelLineCount = 1;
|
|
297
|
-
let wrappedLines = null;
|
|
298
|
-
if (measureText(labelText, sLabelFontSize) > availableWidth) {
|
|
299
|
-
const lines = wrapTextToWidth(labelText, sLabelFontSize, availableWidth);
|
|
300
|
-
labelLineCount = lines.length;
|
|
301
|
-
wrappedLines = lines;
|
|
302
|
-
}
|
|
303
|
-
const lineHeight = sLabelFontSize * 1.2;
|
|
304
|
-
const labelHeight = labelLineCount === 1 ? sLabelFontSize : labelLineCount * lineHeight;
|
|
305
|
-
return {
|
|
306
|
-
item,
|
|
307
|
-
idx,
|
|
308
|
-
color,
|
|
309
|
-
firstVal,
|
|
310
|
-
lastVal,
|
|
311
|
-
tipHtml,
|
|
312
|
-
lastX,
|
|
313
|
-
labelText,
|
|
314
|
-
wrappedLines,
|
|
315
|
-
labelHeight
|
|
316
|
-
};
|
|
317
|
-
});
|
|
318
|
-
const leftLabelHeight = sValueFont * 1.25;
|
|
319
|
-
const leftLabelCollisions = /* @__PURE__ */ new Map();
|
|
320
|
-
for (let pi = 0; pi < periods.length - 1; pi++) {
|
|
321
|
-
const entries = data.map((item) => ({
|
|
322
|
-
// pi is in-bounds by loop guard against periods.length, and each data row has periods.length values.
|
|
323
|
-
naturalY: yScale(item.values[pi]),
|
|
324
|
-
height: leftLabelHeight
|
|
325
|
-
}));
|
|
326
|
-
leftLabelCollisions.set(
|
|
327
|
-
pi,
|
|
328
|
-
resolveVerticalCollisions(entries, 4, innerHeight)
|
|
329
|
-
);
|
|
330
|
-
}
|
|
331
|
-
const rightEntries = seriesInfo.map((si) => ({
|
|
332
|
-
naturalY: yScale(si.lastVal),
|
|
333
|
-
height: Math.max(si.labelHeight, sLabelFontSize * 1.4)
|
|
334
|
-
}));
|
|
335
|
-
const rightAdjustedY = resolveVerticalCollisions(
|
|
336
|
-
rightEntries,
|
|
337
|
-
4,
|
|
338
|
-
innerHeight
|
|
339
|
-
);
|
|
340
|
-
data.forEach((item, idx) => {
|
|
341
|
-
const si = seriesInfo[idx];
|
|
342
|
-
const color = si.color;
|
|
343
|
-
const seriesG = g.append("g").attr("class", "slope-series").attr("data-line-number", String(item.lineNumber));
|
|
344
|
-
seriesG.append("path").datum(item.values).attr("fill", "none").attr("stroke", color).attr("stroke-width", sLineStroke).attr("d", lineGen);
|
|
345
|
-
seriesG.append("path").datum(item.values).attr("fill", "none").attr("stroke", "transparent").attr("stroke-width", sHitWidth).attr("d", lineGen).style("cursor", onClickItem ? "pointer" : "default").on(
|
|
346
|
-
"mouseenter",
|
|
347
|
-
(event) => showTooltip(tooltip, si.tipHtml, event)
|
|
348
|
-
).on(
|
|
349
|
-
"mousemove",
|
|
350
|
-
(event) => showTooltip(tooltip, si.tipHtml, event)
|
|
351
|
-
).on("mouseleave", () => hideTooltip(tooltip)).on("click", () => {
|
|
352
|
-
if (onClickItem && item.lineNumber) onClickItem(item.lineNumber);
|
|
353
|
-
});
|
|
354
|
-
item.values.forEach((val, i) => {
|
|
355
|
-
const x = xScale(periods[i]);
|
|
356
|
-
const y = yScale(val);
|
|
357
|
-
seriesG.append("circle").attr("cx", x).attr("cy", y).attr("r", sPointR).attr("fill", color).attr("stroke", bgColor).attr("stroke-width", sPointStroke).style("cursor", onClickItem ? "pointer" : "default").on(
|
|
358
|
-
"mouseenter",
|
|
359
|
-
(event) => showTooltip(tooltip, si.tipHtml, event)
|
|
360
|
-
).on(
|
|
361
|
-
"mousemove",
|
|
362
|
-
(event) => showTooltip(tooltip, si.tipHtml, event)
|
|
363
|
-
).on("mouseleave", () => hideTooltip(tooltip)).on("click", () => {
|
|
364
|
-
if (onClickItem && item.lineNumber) onClickItem(item.lineNumber);
|
|
365
|
-
});
|
|
366
|
-
const isFirst = i === 0;
|
|
367
|
-
const isLast = i === periods.length - 1;
|
|
368
|
-
if (!isLast) {
|
|
369
|
-
const adjustedY = leftLabelCollisions.get(i)[idx];
|
|
370
|
-
seriesG.append("text").attr("x", isFirst ? x - sValueLabelXOff : x).attr("y", adjustedY).attr("dy", "0.35em").attr("text-anchor", isFirst ? "end" : "middle").attr("fill", color).attr("font-size", sValueFont).text(val.toString());
|
|
371
|
-
}
|
|
372
|
-
});
|
|
373
|
-
const adjustedLastY = rightAdjustedY[idx];
|
|
374
|
-
const labelEl = seriesG.append("text").attr("x", si.lastX + sLabelGap).attr("y", adjustedLastY).attr("text-anchor", "start").attr("fill", color).attr("font-size", sLabelFontSize).attr("font-weight", "normal");
|
|
375
|
-
if (!si.wrappedLines) {
|
|
376
|
-
labelEl.attr("dy", "0.35em").text(si.labelText);
|
|
377
|
-
} else {
|
|
378
|
-
const lineHeight = sLabelFontSize * 1.2;
|
|
379
|
-
const totalHeight = (si.wrappedLines.length - 1) * lineHeight;
|
|
380
|
-
const startDy = -totalHeight / 2;
|
|
381
|
-
si.wrappedLines.forEach((line2, li) => {
|
|
382
|
-
labelEl.append("tspan").attr("x", si.lastX + sLabelGap).attr(
|
|
383
|
-
"dy",
|
|
384
|
-
li === 0 ? `${startDy + sLabelFontSize * 0.35}px` : `${lineHeight}px`
|
|
385
|
-
).text(line2);
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// src/arc/renderer.ts
|
|
392
|
-
import * as d3Scale2 from "d3-scale";
|
|
393
|
-
import * as d3Selection from "d3-selection";
|
|
394
|
-
import * as d3Array2 from "d3-array";
|
|
395
|
-
function orderArcNodes(links, order, groups) {
|
|
396
|
-
const nodeSet = /* @__PURE__ */ new Set();
|
|
397
|
-
for (const link of links) {
|
|
398
|
-
nodeSet.add(link.source);
|
|
399
|
-
nodeSet.add(link.target);
|
|
400
|
-
}
|
|
401
|
-
const allNodes = Array.from(nodeSet);
|
|
402
|
-
if (order === "name") {
|
|
403
|
-
return allNodes.slice().sort((a, b) => a.localeCompare(b));
|
|
213
|
+
const allNodes = Array.from(nodeSet);
|
|
214
|
+
if (order === "name") {
|
|
215
|
+
return allNodes.slice().sort((a, b) => a.localeCompare(b));
|
|
404
216
|
}
|
|
405
217
|
if (order === "degree") {
|
|
406
218
|
const degree = /* @__PURE__ */ new Map();
|
|
@@ -556,8 +368,8 @@ function renderArcDiagram(container, parsed, palette, isDark, onClickItem, expor
|
|
|
556
368
|
groupNodeSets.set(group.name, new Set(group.nodes));
|
|
557
369
|
}
|
|
558
370
|
const values = links.map((l) => l.value);
|
|
559
|
-
const [minVal, maxVal] =
|
|
560
|
-
const strokeScale =
|
|
371
|
+
const [minVal, maxVal] = d3Array.extent(values);
|
|
372
|
+
const strokeScale = d3Scale.scaleLinear().domain([minVal, maxVal]).range([sStrokeMin, sStrokeMax]);
|
|
561
373
|
const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
|
|
562
374
|
renderChartTitle(
|
|
563
375
|
svg,
|
|
@@ -642,7 +454,7 @@ function renderArcDiagram(container, parsed, palette, isDark, onClickItem, expor
|
|
|
642
454
|
return g2 ? groupColorByName.get(g2) : void 0;
|
|
643
455
|
};
|
|
644
456
|
if (isVertical) {
|
|
645
|
-
const yScale =
|
|
457
|
+
const yScale = d3Scale.scalePoint().domain(nodes).range([0, innerHeight]).padding(0.5);
|
|
646
458
|
const baseX = innerWidth / 2;
|
|
647
459
|
if (arcNodeGroups.length > 0) {
|
|
648
460
|
const bandPad = (yScale.step?.() ?? 20) * 0.4;
|
|
@@ -702,7 +514,7 @@ function renderArcDiagram(container, parsed, palette, isDark, onClickItem, expor
|
|
|
702
514
|
nodeG.append("text").attr("x", baseX - sNodeLabelXOffset).attr("y", y).attr("dy", "0.35em").attr("text-anchor", "end").attr("fill", textColor).attr("font-size", sNodeLabelFont).text(node);
|
|
703
515
|
}
|
|
704
516
|
} else {
|
|
705
|
-
const xScale =
|
|
517
|
+
const xScale = d3Scale.scalePoint().domain(nodes).range([0, innerWidth]).padding(0.5);
|
|
706
518
|
const arcStep = xScale.step();
|
|
707
519
|
const widestLabelChars = Math.max(...nodes.map((n) => n.length));
|
|
708
520
|
const labelWidthPx = widestLabelChars * sNodeLabelFont * 0.6;
|
|
@@ -827,175 +639,541 @@ function renderArcDiagram(container, parsed, palette, isDark, onClickItem, expor
|
|
|
827
639
|
}
|
|
828
640
|
}
|
|
829
641
|
|
|
830
|
-
// src/
|
|
642
|
+
// src/quadrant/renderer.ts
|
|
643
|
+
import * as d3Scale2 from "d3-scale";
|
|
831
644
|
import * as d3Selection2 from "d3-selection";
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
return typeof canvas.getContext === "function" && !!canvas.getContext("2d");
|
|
843
|
-
} catch {
|
|
844
|
-
return false;
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
function estimateWordWidth(text, size) {
|
|
848
|
-
return measureText(text, size, { bold: true });
|
|
849
|
-
}
|
|
850
|
-
function layoutWordsNoCanvas(words, width, height, padding, rotateFn) {
|
|
851
|
-
const sorted = [...words].sort((a, b) => b.size - a.size);
|
|
852
|
-
const placed = [];
|
|
853
|
-
const maxR = Math.sqrt(width * width + height * height) / 2;
|
|
854
|
-
const aspect = width > 0 ? height / width : 1;
|
|
855
|
-
for (const w of sorted) {
|
|
856
|
-
const rotate = rotateFn();
|
|
857
|
-
const rawW = estimateWordWidth(w.text, w.size) + padding * 2;
|
|
858
|
-
const rawH = w.size + padding * 2;
|
|
859
|
-
const rad = rotate * Math.PI / 180;
|
|
860
|
-
const cos = Math.abs(Math.cos(rad));
|
|
861
|
-
const sin = Math.abs(Math.sin(rad));
|
|
862
|
-
const halfW = (rawW * cos + rawH * sin) / 2;
|
|
863
|
-
const halfH = (rawW * sin + rawH * cos) / 2;
|
|
864
|
-
let spot = null;
|
|
865
|
-
for (let t = 0; t < 4e3; t++) {
|
|
866
|
-
const a = t * 0.25;
|
|
867
|
-
const r = a * 1.4;
|
|
868
|
-
if (r > maxR) break;
|
|
869
|
-
const x = Math.cos(a) * r;
|
|
870
|
-
const y = Math.sin(a) * r * aspect;
|
|
871
|
-
if (x - halfW < -width / 2 || x + halfW > width / 2 || y - halfH < -height / 2 || y + halfH > height / 2) {
|
|
872
|
-
continue;
|
|
873
|
-
}
|
|
874
|
-
let collides = false;
|
|
875
|
-
for (const p of placed) {
|
|
876
|
-
if (Math.abs(x - p.x) < halfW + p.halfW && Math.abs(y - p.y) < halfH + p.halfH) {
|
|
877
|
-
collides = true;
|
|
878
|
-
break;
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
if (!collides) {
|
|
882
|
-
spot = { x, y };
|
|
883
|
-
break;
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
if (!spot) continue;
|
|
887
|
-
placed.push({ ...w, rotate, x: spot.x, y: spot.y, halfW, halfH });
|
|
888
|
-
}
|
|
889
|
-
return placed;
|
|
890
|
-
}
|
|
891
|
-
function renderWordCloud(container, parsed, palette, _isDark, onClickItem, exportDims) {
|
|
892
|
-
const { words, cloudOptions } = parsed;
|
|
645
|
+
function renderQuadrant(container, parsed, palette, isDark, onClickItem, exportDims) {
|
|
646
|
+
const {
|
|
647
|
+
quadrantLabels,
|
|
648
|
+
quadrantPoints,
|
|
649
|
+
quadrantXAxis,
|
|
650
|
+
quadrantYAxis,
|
|
651
|
+
quadrantTitleLineNumber,
|
|
652
|
+
quadrantXAxisLineNumber,
|
|
653
|
+
quadrantYAxisLineNumber
|
|
654
|
+
} = parsed;
|
|
893
655
|
const title = parsed.noTitle ? null : parsed.title;
|
|
894
|
-
if (
|
|
656
|
+
if (quadrantPoints.length === 0) return;
|
|
895
657
|
const init = initD3Chart(container, palette, exportDims);
|
|
896
658
|
if (!init) return;
|
|
897
|
-
const { svg, width, height, textColor
|
|
898
|
-
const
|
|
659
|
+
const { svg, width, height, textColor } = init;
|
|
660
|
+
const borderColor = palette.border;
|
|
661
|
+
const idealWidth = 600;
|
|
899
662
|
const ctx = exportDims ? ScaleContext.identity() : ScaleContext.from(width, idealWidth);
|
|
900
|
-
const sTitleHeight = title ? ctx.aesthetic(40) : 0;
|
|
901
|
-
const cloudHeight = height - sTitleHeight;
|
|
902
|
-
const sPadding = ctx.structural(2);
|
|
903
663
|
svg.attr("preserveAspectRatio", "xMidYMid meet");
|
|
904
664
|
if (ctx.isBelowFloor) {
|
|
905
665
|
svg.attr("width", "100%");
|
|
906
666
|
}
|
|
907
|
-
const
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
const
|
|
914
|
-
const
|
|
915
|
-
|
|
916
|
-
|
|
667
|
+
const defaultColors = [
|
|
668
|
+
palette.colors.blue,
|
|
669
|
+
palette.colors.green,
|
|
670
|
+
palette.colors.yellow,
|
|
671
|
+
palette.colors.purple
|
|
672
|
+
];
|
|
673
|
+
const hasXAxis = !!quadrantXAxis;
|
|
674
|
+
const hasYAxis = !!quadrantYAxis;
|
|
675
|
+
const margin = {
|
|
676
|
+
top: title ? ctx.aesthetic(60) : ctx.aesthetic(30),
|
|
677
|
+
right: ctx.aesthetic(30),
|
|
678
|
+
bottom: hasXAxis ? ctx.aesthetic(70) : ctx.aesthetic(40),
|
|
679
|
+
left: hasYAxis ? ctx.aesthetic(80) : ctx.aesthetic(40)
|
|
917
680
|
};
|
|
918
|
-
const
|
|
681
|
+
const chartWidth = width - margin.left - margin.right;
|
|
682
|
+
const chartHeight = height - margin.top - margin.bottom;
|
|
683
|
+
const xScale = d3Scale2.scaleLinear().domain([0, 1]).range([0, chartWidth]);
|
|
684
|
+
const yScale = d3Scale2.scaleLinear().domain([0, 1]).range([chartHeight, 0]);
|
|
919
685
|
renderChartTitle(
|
|
920
686
|
svg,
|
|
921
687
|
title,
|
|
922
|
-
|
|
688
|
+
quadrantTitleLineNumber,
|
|
923
689
|
width,
|
|
924
690
|
textColor,
|
|
925
691
|
onClickItem
|
|
926
692
|
);
|
|
927
|
-
const
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
const sized = words.map((w) => ({ ...w, size: fontSize(w.weight) }));
|
|
932
|
-
const draw = (layoutWords) => {
|
|
933
|
-
g.selectAll("text").data(layoutWords).join("text").style("font-size", (d) => `${d.size}px`).style("font-family", FONT_FAMILY).style("font-weight", "bold").style("fill", (_d, i) => colors[i % colors.length]).style(
|
|
934
|
-
"cursor",
|
|
935
|
-
(d) => onClickItem && d.lineNumber ? "pointer" : "default"
|
|
936
|
-
).attr("text-anchor", "middle").attr("transform", (d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`).attr("data-line-number", (d) => {
|
|
937
|
-
const ln = d.lineNumber;
|
|
938
|
-
return ln ? String(ln) : null;
|
|
939
|
-
}).text((d) => d.text).on("click", (_event, d) => {
|
|
940
|
-
const ln = d.lineNumber;
|
|
941
|
-
if (onClickItem && ln) onClickItem(ln);
|
|
942
|
-
});
|
|
693
|
+
const chartG = svg.append("g").attr("transform", `translate(${margin.left}, ${margin.top})`);
|
|
694
|
+
const bg = themeBaseBg(palette, isDark);
|
|
695
|
+
const getQuadrantColor = (label, defaultIdx) => {
|
|
696
|
+
return label?.color ?? defaultColors[defaultIdx % defaultColors.length];
|
|
943
697
|
};
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
698
|
+
const getQuadrantFill = (label, defaultIdx) => {
|
|
699
|
+
return mix(getQuadrantColor(label, defaultIdx), bg, 30);
|
|
700
|
+
};
|
|
701
|
+
const quadrantDefs = [
|
|
702
|
+
{
|
|
703
|
+
position: "top-left",
|
|
704
|
+
x: 0,
|
|
705
|
+
y: 0,
|
|
706
|
+
w: chartWidth / 2,
|
|
707
|
+
h: chartHeight / 2,
|
|
708
|
+
labelX: chartWidth / 4,
|
|
709
|
+
labelY: chartHeight / 4,
|
|
710
|
+
label: quadrantLabels.topLeft,
|
|
711
|
+
colorIdx: 1
|
|
712
|
+
// green
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
position: "top-right",
|
|
716
|
+
x: chartWidth / 2,
|
|
717
|
+
y: 0,
|
|
718
|
+
w: chartWidth / 2,
|
|
719
|
+
h: chartHeight / 2,
|
|
720
|
+
labelX: chartWidth * 3 / 4,
|
|
721
|
+
labelY: chartHeight / 4,
|
|
722
|
+
label: quadrantLabels.topRight,
|
|
723
|
+
colorIdx: 0
|
|
724
|
+
// blue
|
|
725
|
+
},
|
|
726
|
+
{
|
|
727
|
+
position: "bottom-left",
|
|
728
|
+
x: 0,
|
|
729
|
+
y: chartHeight / 2,
|
|
730
|
+
w: chartWidth / 2,
|
|
731
|
+
h: chartHeight / 2,
|
|
732
|
+
labelX: chartWidth / 4,
|
|
733
|
+
labelY: chartHeight * 3 / 4,
|
|
734
|
+
label: quadrantLabels.bottomLeft,
|
|
735
|
+
colorIdx: 2
|
|
736
|
+
// yellow
|
|
737
|
+
},
|
|
738
|
+
{
|
|
739
|
+
position: "bottom-right",
|
|
740
|
+
x: chartWidth / 2,
|
|
741
|
+
y: chartHeight / 2,
|
|
742
|
+
w: chartWidth / 2,
|
|
743
|
+
h: chartHeight / 2,
|
|
744
|
+
labelX: chartWidth * 3 / 4,
|
|
745
|
+
labelY: chartHeight * 3 / 4,
|
|
746
|
+
label: quadrantLabels.bottomRight,
|
|
747
|
+
colorIdx: 3
|
|
748
|
+
// purple
|
|
958
749
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
750
|
+
];
|
|
751
|
+
const quadrantRects = chartG.selectAll("rect.quadrant").data(quadrantDefs).enter().append("rect").attr("class", "quadrant").attr("x", (d) => d.x).attr("y", (d) => d.y).attr("width", (d) => d.w).attr("height", (d) => d.h).attr("fill", (d) => getQuadrantFill(d.label, d.colorIdx)).attr("stroke", (d) => getQuadrantColor(d.label, d.colorIdx)).attr("stroke-width", ctx.structural(2));
|
|
752
|
+
const shadowColor = isDark ? "rgba(0,0,0,0.55)" : "rgba(0,0,0,0.4)";
|
|
753
|
+
const quadrantLabelColor = mix(textColor, bg, 35);
|
|
754
|
+
const LABEL_MAX_FONT = ctx.text(48);
|
|
755
|
+
const LABEL_MIN_FONT = ctx.text(14);
|
|
756
|
+
const LABEL_PAD = ctx.aesthetic(40);
|
|
757
|
+
const quadrantLabelLayout = (text, qw2, qh2) => {
|
|
758
|
+
const availW = qw2 - LABEL_PAD;
|
|
759
|
+
const availH = qh2 - LABEL_PAD;
|
|
760
|
+
if (measureText(text, LABEL_MAX_FONT, { bold: true }) <= availW) {
|
|
761
|
+
const fs = Math.min(LABEL_MAX_FONT, availH);
|
|
762
|
+
return {
|
|
763
|
+
lines: [text],
|
|
764
|
+
fontSize: Math.max(LABEL_MIN_FONT, Math.round(fs))
|
|
765
|
+
};
|
|
964
766
|
}
|
|
965
|
-
const
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
767
|
+
const wrapLines = (fs) => wrapTextToWidth(text, fs, availW, { bold: true });
|
|
768
|
+
let lo = LABEL_MIN_FONT;
|
|
769
|
+
let hi = LABEL_MAX_FONT;
|
|
770
|
+
let bestLines = wrapLines(lo);
|
|
771
|
+
let bestFs = lo;
|
|
772
|
+
while (lo <= hi) {
|
|
773
|
+
const mid = Math.round((lo + hi) / 2);
|
|
774
|
+
const lines = wrapLines(mid);
|
|
775
|
+
const totalH = lines.length * mid * 1.2;
|
|
776
|
+
const maxLineW = Math.max(
|
|
777
|
+
...lines.map((l) => measureText(l, mid, { bold: true }))
|
|
778
|
+
);
|
|
779
|
+
if (maxLineW <= availW && totalH <= availH) {
|
|
780
|
+
bestFs = mid;
|
|
781
|
+
bestLines = lines;
|
|
782
|
+
lo = mid + 1;
|
|
783
|
+
} else {
|
|
784
|
+
hi = mid - 1;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
return { lines: bestLines, fontSize: Math.max(LABEL_MIN_FONT, bestFs) };
|
|
788
|
+
};
|
|
789
|
+
const qw = chartWidth / 2;
|
|
790
|
+
const qh = chartHeight / 2;
|
|
791
|
+
const quadrantDefsWithLabel = quadrantDefs.filter((d) => d.label !== null);
|
|
792
|
+
const labelLayouts = new Map(
|
|
793
|
+
quadrantDefsWithLabel.map((d) => [
|
|
794
|
+
d.label.text,
|
|
795
|
+
quadrantLabelLayout(d.label.text, qw, qh)
|
|
796
|
+
])
|
|
797
|
+
);
|
|
798
|
+
const renderWatermarkOriginal = (textEl, d) => {
|
|
799
|
+
const layout = labelLayouts.get(d.label.text);
|
|
800
|
+
const el = d3Selection2.select(textEl);
|
|
801
|
+
el.text(null).attr("font-size", layout.fontSize).attr("font-weight", "bold");
|
|
802
|
+
if (layout.lines.length === 1) {
|
|
803
|
+
el.text(layout.lines[0]);
|
|
804
|
+
} else {
|
|
805
|
+
const lineH = layout.fontSize * 1.2;
|
|
806
|
+
const totalH = layout.lines.length * lineH;
|
|
807
|
+
const startY = -totalH / 2 + lineH / 2;
|
|
808
|
+
layout.lines.forEach((line2, i) => {
|
|
809
|
+
el.append("tspan").attr("x", d.labelX).attr("dy", i === 0 ? `${startY}px` : `${lineH}px`).text(line2);
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
const quadrantLabelTexts = chartG.selectAll("text.quadrant-label").data(quadrantDefsWithLabel).enter().append("text").attr("class", "quadrant-label").attr("x", (d) => d.labelX).attr("y", (d) => d.labelY).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("fill", quadrantLabelColor).attr(
|
|
814
|
+
"data-line-number",
|
|
815
|
+
(d) => d.label?.lineNumber ? String(d.label.lineNumber) : null
|
|
816
|
+
).style(
|
|
817
|
+
"cursor",
|
|
818
|
+
(d) => onClickItem && d.label?.lineNumber ? "pointer" : "default"
|
|
819
|
+
).each(function(d) {
|
|
820
|
+
renderWatermarkOriginal(this, d);
|
|
821
|
+
});
|
|
822
|
+
if (onClickItem) {
|
|
823
|
+
quadrantLabelTexts.on("click", (_, d) => {
|
|
824
|
+
if (d.label?.lineNumber) onClickItem(d.label.lineNumber);
|
|
825
|
+
}).on("mouseenter", function() {
|
|
826
|
+
d3Selection2.select(this).attr("opacity", 0.7);
|
|
827
|
+
}).on("mouseleave", function() {
|
|
828
|
+
d3Selection2.select(this).attr("opacity", 1);
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
const sAxisFont = ctx.text(18);
|
|
832
|
+
const sAxisPad = ctx.aesthetic(20);
|
|
833
|
+
const sAxisX = ctx.aesthetic(22);
|
|
834
|
+
if (quadrantXAxis) {
|
|
835
|
+
const xLowLabel = svg.append("text").attr("class", "quadrant-axis-label").attr("x", margin.left + chartWidth / 4).attr("y", height - sAxisPad).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", sAxisFont).attr(
|
|
836
|
+
"data-line-number",
|
|
837
|
+
quadrantXAxisLineNumber ? String(quadrantXAxisLineNumber) : null
|
|
838
|
+
).style(
|
|
839
|
+
"cursor",
|
|
840
|
+
onClickItem && quadrantXAxisLineNumber ? "pointer" : "default"
|
|
841
|
+
).text(quadrantXAxis[0]);
|
|
842
|
+
const xHighLabel = svg.append("text").attr("class", "quadrant-axis-label").attr("x", margin.left + chartWidth * 3 / 4).attr("y", height - sAxisPad).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", sAxisFont).attr(
|
|
843
|
+
"data-line-number",
|
|
844
|
+
quadrantXAxisLineNumber ? String(quadrantXAxisLineNumber) : null
|
|
845
|
+
).style(
|
|
846
|
+
"cursor",
|
|
847
|
+
onClickItem && quadrantXAxisLineNumber ? "pointer" : "default"
|
|
848
|
+
).text(quadrantXAxis[1]);
|
|
849
|
+
if (onClickItem && quadrantXAxisLineNumber) {
|
|
850
|
+
[xLowLabel, xHighLabel].forEach((label) => {
|
|
851
|
+
label.on("click", () => onClickItem(quadrantXAxisLineNumber)).on("mouseenter", function() {
|
|
852
|
+
d3Selection2.select(this).attr("opacity", 0.7);
|
|
853
|
+
}).on("mouseleave", function() {
|
|
854
|
+
d3Selection2.select(this).attr("opacity", 1);
|
|
855
|
+
});
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
if (quadrantYAxis) {
|
|
860
|
+
const yMidBottom = margin.top + chartHeight * 3 / 4;
|
|
861
|
+
const yMidTop = margin.top + chartHeight / 4;
|
|
862
|
+
const yLowLabel = svg.append("text").attr("class", "quadrant-axis-label").attr("x", sAxisX).attr("y", yMidBottom).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", sAxisFont).attr("transform", `rotate(-90, ${sAxisX}, ${yMidBottom})`).attr(
|
|
863
|
+
"data-line-number",
|
|
864
|
+
quadrantYAxisLineNumber ? String(quadrantYAxisLineNumber) : null
|
|
865
|
+
).style(
|
|
866
|
+
"cursor",
|
|
867
|
+
onClickItem && quadrantYAxisLineNumber ? "pointer" : "default"
|
|
868
|
+
).text(quadrantYAxis[0]);
|
|
869
|
+
const yHighLabel = svg.append("text").attr("class", "quadrant-axis-label").attr("x", sAxisX).attr("y", yMidTop).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", sAxisFont).attr("transform", `rotate(-90, ${sAxisX}, ${yMidTop})`).attr(
|
|
870
|
+
"data-line-number",
|
|
871
|
+
quadrantYAxisLineNumber ? String(quadrantYAxisLineNumber) : null
|
|
872
|
+
).style(
|
|
873
|
+
"cursor",
|
|
874
|
+
onClickItem && quadrantYAxisLineNumber ? "pointer" : "default"
|
|
875
|
+
).text(quadrantYAxis[1]);
|
|
876
|
+
if (onClickItem && quadrantYAxisLineNumber) {
|
|
877
|
+
[yLowLabel, yHighLabel].forEach((label) => {
|
|
878
|
+
label.on("click", () => onClickItem(quadrantYAxisLineNumber)).on("mouseenter", function() {
|
|
879
|
+
d3Selection2.select(this).attr("opacity", 0.7);
|
|
880
|
+
}).on("mouseleave", function() {
|
|
881
|
+
d3Selection2.select(this).attr("opacity", 1);
|
|
882
|
+
});
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
chartG.append("line").attr("x1", chartWidth / 2).attr("y1", 0).attr("x2", chartWidth / 2).attr("y2", chartHeight).attr("stroke", borderColor).attr("stroke-width", 1);
|
|
887
|
+
chartG.append("line").attr("x1", 0).attr("y1", chartHeight / 2).attr("x2", chartWidth).attr("y2", chartHeight / 2).attr("stroke", borderColor).attr("stroke-width", 1);
|
|
888
|
+
const getPointQuadrant = (x, y) => {
|
|
889
|
+
if (x >= 0.5 && y >= 0.5) return "top-right";
|
|
890
|
+
if (x < 0.5 && y >= 0.5) return "top-left";
|
|
891
|
+
if (x < 0.5 && y < 0.5) return "bottom-left";
|
|
892
|
+
return "bottom-right";
|
|
893
|
+
};
|
|
894
|
+
const POINT_RADIUS = ctx.structural(6);
|
|
895
|
+
const POINT_LABEL_FONT_SIZE = ctx.text(12);
|
|
896
|
+
const quadrantLabelObstacles = quadrantDefsWithLabel.map((d) => {
|
|
897
|
+
const layout = labelLayouts.get(d.label.text);
|
|
898
|
+
const totalW = Math.max(
|
|
899
|
+
...layout.lines.map((l) => measureText(l, layout.fontSize))
|
|
900
|
+
);
|
|
901
|
+
const totalH = layout.lines.length * layout.fontSize * 1.2;
|
|
902
|
+
return {
|
|
903
|
+
x: d.labelX - totalW / 2,
|
|
904
|
+
y: d.labelY - totalH / 2,
|
|
905
|
+
w: totalW,
|
|
906
|
+
h: totalH
|
|
978
907
|
};
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
908
|
+
});
|
|
909
|
+
const pointPixels = quadrantPoints.map((point) => ({
|
|
910
|
+
label: point.label,
|
|
911
|
+
cx: xScale(point.x),
|
|
912
|
+
cy: yScale(point.y)
|
|
913
|
+
}));
|
|
914
|
+
const placedPointLabels = computeQuadrantPointLabels(
|
|
915
|
+
pointPixels,
|
|
916
|
+
{ left: 0, top: 0, right: chartWidth, bottom: chartHeight },
|
|
917
|
+
quadrantLabelObstacles,
|
|
918
|
+
POINT_RADIUS,
|
|
919
|
+
POINT_LABEL_FONT_SIZE,
|
|
920
|
+
// Point labels are drawn at 700 here.
|
|
921
|
+
true
|
|
922
|
+
);
|
|
923
|
+
const pointsG = chartG.append("g").attr("class", "points");
|
|
924
|
+
quadrantPoints.forEach((point, i) => {
|
|
925
|
+
const cx = xScale(point.x);
|
|
926
|
+
const cy = yScale(point.y);
|
|
927
|
+
const quadrant = getPointQuadrant(point.x, point.y);
|
|
928
|
+
const quadDef = quadrantDefs.find((d) => d.position === quadrant);
|
|
929
|
+
const pointColor = quadDef?.label?.color ?? defaultColors[quadDef?.colorIdx ?? 0];
|
|
930
|
+
const placed = placedPointLabels[i];
|
|
931
|
+
const pointG = pointsG.append("g").attr("class", "point-group").attr("data-line-number", String(point.lineNumber)).attr("data-quadrant", quadrant);
|
|
932
|
+
if (placed.connectorLine) {
|
|
933
|
+
pointG.append("line").attr("x1", placed.connectorLine.x1).attr("y1", placed.connectorLine.y1).attr("x2", placed.connectorLine.x2).attr("y2", placed.connectorLine.y2).attr("stroke", pointColor).attr("stroke-width", 1).attr("opacity", 0.5);
|
|
934
|
+
}
|
|
935
|
+
pointG.append("circle").attr("cx", cx).attr("cy", cy).attr("r", POINT_RADIUS).attr("fill", bg).attr("stroke", pointColor).attr("stroke-width", ctx.structural(2));
|
|
936
|
+
const labelText = pointG.append("text").attr("x", placed.x).attr("y", placed.y).attr("text-anchor", placed.anchor).attr("dominant-baseline", "central").attr("fill", textColor).attr("font-size", POINT_LABEL_FONT_SIZE).attr("font-weight", "bold").style("text-shadow", `0 1px 2px ${shadowColor}`).style("transition", "y 120ms ease-out");
|
|
937
|
+
labelText.append("tspan").text(point.label);
|
|
938
|
+
const coordsTspan = labelText.append("tspan").attr("class", "point-coords").attr("x", placed.x).attr("dy", `${POINT_LABEL_FONT_SIZE}px`).attr("font-size", ctx.text(10)).attr("font-weight", "normal").attr("visibility", "hidden").text(`${point.x.toFixed(2)}, ${point.y.toFixed(2)}`);
|
|
939
|
+
const COORDS_LINE_H = ctx.structural(14);
|
|
940
|
+
const bumpDy = placed.y < cy ? -COORDS_LINE_H : COORDS_LINE_H;
|
|
941
|
+
pointG.style("cursor", onClickItem ? "pointer" : "default").on("mouseenter", () => {
|
|
942
|
+
pointG.select("circle").attr("r", ctx.structural(8));
|
|
943
|
+
labelText.attr("y", placed.y + bumpDy);
|
|
944
|
+
coordsTspan.attr("visibility", "visible");
|
|
945
|
+
quadrantRects.attr(
|
|
946
|
+
"opacity",
|
|
947
|
+
(qd) => qd.position === quadrant ? 1 : 0.3
|
|
948
|
+
);
|
|
949
|
+
quadrantLabelTexts.attr(
|
|
950
|
+
"opacity",
|
|
951
|
+
(qd) => qd.position === quadrant ? 1 : 0.3
|
|
952
|
+
);
|
|
953
|
+
pointsG.selectAll("g.point-group").filter((_, j) => j !== i).attr("opacity", 0.3);
|
|
954
|
+
}).on("mouseleave", () => {
|
|
955
|
+
pointG.select("circle").attr("r", POINT_RADIUS);
|
|
956
|
+
labelText.attr("y", placed.y);
|
|
957
|
+
coordsTspan.attr("visibility", "hidden");
|
|
958
|
+
quadrantRects.attr("opacity", 1);
|
|
959
|
+
quadrantLabelTexts.attr("opacity", 1);
|
|
960
|
+
pointsG.selectAll("g.point-group").attr("opacity", 1);
|
|
961
|
+
}).on("click", () => {
|
|
962
|
+
if (onClickItem && point.lineNumber) onClickItem(point.lineNumber);
|
|
963
|
+
});
|
|
964
|
+
});
|
|
965
|
+
quadrantRects.style("cursor", onClickItem ? "pointer" : "default").on("mouseenter", function(_, d) {
|
|
966
|
+
quadrantRects.attr(
|
|
967
|
+
"opacity",
|
|
968
|
+
(qd) => qd.position === d.position ? 1 : 0.3
|
|
985
969
|
);
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
970
|
+
quadrantLabelTexts.attr(
|
|
971
|
+
"opacity",
|
|
972
|
+
(qd) => qd.position === d.position ? 1 : 0.3
|
|
973
|
+
);
|
|
974
|
+
pointsG.selectAll("g.point-group").each(function(_2, i) {
|
|
975
|
+
const pt = quadrantPoints[i];
|
|
976
|
+
const ptQuad = getPointQuadrant(pt.x, pt.y);
|
|
977
|
+
d3Selection2.select(this).attr("opacity", ptQuad === d.position ? 1 : 0.2);
|
|
978
|
+
});
|
|
979
|
+
}).on("mouseleave", () => {
|
|
980
|
+
quadrantRects.attr("opacity", 1);
|
|
981
|
+
quadrantLabelTexts.attr("opacity", 1);
|
|
982
|
+
pointsG.selectAll("g.point-group").attr("opacity", 1);
|
|
983
|
+
}).on("click", (_, d) => {
|
|
984
|
+
if (onClickItem && d.label?.lineNumber) {
|
|
985
|
+
onClickItem(d.label.lineNumber);
|
|
986
|
+
}
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
// src/slope/renderer.ts
|
|
991
|
+
import * as d3Scale3 from "d3-scale";
|
|
992
|
+
import * as d3Shape from "d3-shape";
|
|
993
|
+
import * as d3Array2 from "d3-array";
|
|
994
|
+
function resolveVerticalCollisions(items, minGap, maxY) {
|
|
995
|
+
if (items.length === 0) return [];
|
|
996
|
+
const sorted = items.map((it, i) => ({ ...it, idx: i })).sort((a, b) => a.naturalY - b.naturalY);
|
|
997
|
+
const adjustedY = new Array(items.length);
|
|
998
|
+
let prevBottom = -Infinity;
|
|
999
|
+
for (const item of sorted) {
|
|
1000
|
+
const halfH = item.height / 2;
|
|
1001
|
+
let top = Math.max(item.naturalY - halfH, prevBottom + minGap);
|
|
1002
|
+
if (maxY !== void 0) {
|
|
1003
|
+
top = Math.min(top, maxY - item.height);
|
|
1004
|
+
}
|
|
1005
|
+
adjustedY[item.idx] = top + halfH;
|
|
1006
|
+
prevBottom = top + item.height;
|
|
1007
|
+
}
|
|
1008
|
+
return adjustedY;
|
|
1009
|
+
}
|
|
1010
|
+
var SLOPE_MARGIN = { top: 80, bottom: 40, left: 80 };
|
|
1011
|
+
var SLOPE_LABEL_FONT_SIZE = 14;
|
|
1012
|
+
function renderSlopeChart(container, parsed, palette, isDark, onClickItem, exportDims) {
|
|
1013
|
+
const { periods, data } = parsed;
|
|
1014
|
+
const title = parsed.noTitle ? null : parsed.title;
|
|
1015
|
+
if (data.length === 0 || periods.length < 2) return;
|
|
1016
|
+
const init = initD3Chart(container, palette, exportDims);
|
|
1017
|
+
if (!init) return;
|
|
1018
|
+
const { svg, width, height, textColor, mutedColor, bgColor, colors } = init;
|
|
1019
|
+
const idealWidth = SLOPE_MARGIN.left + periods.length * 100 + 150;
|
|
1020
|
+
const ctx = exportDims ? ScaleContext.identity() : ScaleContext.from(width, idealWidth);
|
|
1021
|
+
const sMarginTop = ctx.aesthetic(SLOPE_MARGIN.top);
|
|
1022
|
+
const sMarginBottom = ctx.aesthetic(SLOPE_MARGIN.bottom);
|
|
1023
|
+
const sMarginLeft = ctx.aesthetic(SLOPE_MARGIN.left);
|
|
1024
|
+
const sLabelFontSize = ctx.text(SLOPE_LABEL_FONT_SIZE);
|
|
1025
|
+
const sPeriodFont = ctx.text(18);
|
|
1026
|
+
const sValueFont = ctx.text(16);
|
|
1027
|
+
const sPeriodHeaderY = ctx.structural(15);
|
|
1028
|
+
const sDash = scaleDash(GRID_DASH, (n) => ctx.structural(n));
|
|
1029
|
+
const sLineStroke = ctx.structural(2.5);
|
|
1030
|
+
const sHitWidth = ctx.structural(14);
|
|
1031
|
+
const sPointR = ctx.structural(4);
|
|
1032
|
+
const sPointStroke = ctx.structural(1.5);
|
|
1033
|
+
const sValueLabelXOff = ctx.structural(10);
|
|
1034
|
+
const sLabelGap = ctx.structural(10);
|
|
1035
|
+
svg.attr("preserveAspectRatio", "xMidYMin meet");
|
|
1036
|
+
if (ctx.isBelowFloor) {
|
|
1037
|
+
svg.attr("width", "100%");
|
|
1038
|
+
}
|
|
1039
|
+
const maxLabelText = data.reduce((longest, item) => {
|
|
1040
|
+
const text = `${item.values[item.values.length - 1]} \u2014 ${item.label}`;
|
|
1041
|
+
return text.length > longest.length ? text : longest;
|
|
1042
|
+
}, "");
|
|
1043
|
+
const estimatedLabelWidth = measureText(maxLabelText, sLabelFontSize);
|
|
1044
|
+
const maxRightMargin = Math.floor(width * 0.35);
|
|
1045
|
+
const rightMargin = Math.min(
|
|
1046
|
+
Math.max(estimatedLabelWidth + ctx.aesthetic(30), ctx.aesthetic(120)),
|
|
1047
|
+
maxRightMargin
|
|
1048
|
+
);
|
|
1049
|
+
const innerWidth = width - sMarginLeft - rightMargin;
|
|
1050
|
+
const innerHeight = height - sMarginTop - sMarginBottom;
|
|
1051
|
+
const allValues2 = data.flatMap((d) => d.values);
|
|
1052
|
+
const [minVal, maxVal] = d3Array2.extent(allValues2);
|
|
1053
|
+
const valuePadding = (maxVal - minVal) * 0.1 || 1;
|
|
1054
|
+
const yScale = d3Scale3.scaleLinear().domain([minVal - valuePadding, maxVal + valuePadding]).range([innerHeight, 0]);
|
|
1055
|
+
const xScale = d3Scale3.scalePoint().domain(periods).range([0, innerWidth]).padding(0);
|
|
1056
|
+
const g = svg.append("g").attr("transform", `translate(${sMarginLeft},${sMarginTop})`);
|
|
1057
|
+
const tooltip = createTooltip(container, palette, isDark);
|
|
1058
|
+
renderChartTitle(
|
|
1059
|
+
svg,
|
|
1060
|
+
title,
|
|
1061
|
+
parsed.titleLineNumber,
|
|
1062
|
+
width,
|
|
1063
|
+
textColor,
|
|
1064
|
+
onClickItem
|
|
1065
|
+
);
|
|
1066
|
+
for (const period of periods) {
|
|
1067
|
+
const x = xScale(period);
|
|
1068
|
+
g.append("text").attr("x", x).attr("y", -sPeriodHeaderY).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", sPeriodFont).attr("font-weight", "bold").text(period);
|
|
1069
|
+
g.append("line").attr("x1", x).attr("y1", 0).attr("x2", x).attr("y2", innerHeight).attr("stroke", mutedColor).attr("stroke-width", 1).attr("stroke-dasharray", sDash);
|
|
1070
|
+
}
|
|
1071
|
+
const lineGen = d3Shape.line().x((_d, i) => xScale(periods[i])).y((d) => yScale(d));
|
|
1072
|
+
const seriesInfo = data.map((item, idx) => {
|
|
1073
|
+
const color = item.color ?? colors[idx % colors.length];
|
|
1074
|
+
const firstVal = item.values[0];
|
|
1075
|
+
const lastVal = item.values[item.values.length - 1];
|
|
1076
|
+
const absChange = lastVal - firstVal;
|
|
1077
|
+
const pctChange = firstVal !== 0 ? absChange / firstVal * 100 : null;
|
|
1078
|
+
const sign = absChange > 0 ? "+" : "";
|
|
1079
|
+
const tipLines = [`${sign}${parseFloat(absChange.toFixed(2))}`];
|
|
1080
|
+
if (pctChange !== null) tipLines.push(`${sign}${pctChange.toFixed(1)}%`);
|
|
1081
|
+
const tipHtml = tipLines.join("<br>");
|
|
1082
|
+
const lastX = xScale(periods[periods.length - 1]);
|
|
1083
|
+
const labelText = `${lastVal} \u2014 ${item.label}`;
|
|
1084
|
+
const availableWidth = rightMargin - ctx.aesthetic(15);
|
|
1085
|
+
let labelLineCount = 1;
|
|
1086
|
+
let wrappedLines = null;
|
|
1087
|
+
if (measureText(labelText, sLabelFontSize) > availableWidth) {
|
|
1088
|
+
const lines = wrapTextToWidth(labelText, sLabelFontSize, availableWidth);
|
|
1089
|
+
labelLineCount = lines.length;
|
|
1090
|
+
wrappedLines = lines;
|
|
1091
|
+
}
|
|
1092
|
+
const lineHeight = sLabelFontSize * 1.2;
|
|
1093
|
+
const labelHeight = labelLineCount === 1 ? sLabelFontSize : labelLineCount * lineHeight;
|
|
1094
|
+
return {
|
|
1095
|
+
item,
|
|
1096
|
+
idx,
|
|
1097
|
+
color,
|
|
1098
|
+
firstVal,
|
|
1099
|
+
lastVal,
|
|
1100
|
+
tipHtml,
|
|
1101
|
+
lastX,
|
|
1102
|
+
labelText,
|
|
1103
|
+
wrappedLines,
|
|
1104
|
+
labelHeight
|
|
993
1105
|
};
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1106
|
+
});
|
|
1107
|
+
const leftLabelHeight = sValueFont * 1.25;
|
|
1108
|
+
const leftLabelCollisions = /* @__PURE__ */ new Map();
|
|
1109
|
+
for (let pi = 0; pi < periods.length - 1; pi++) {
|
|
1110
|
+
const entries = data.map((item) => ({
|
|
1111
|
+
// pi is in-bounds by loop guard against periods.length, and each data row has periods.length values.
|
|
1112
|
+
naturalY: yScale(item.values[pi]),
|
|
1113
|
+
height: leftLabelHeight
|
|
1114
|
+
}));
|
|
1115
|
+
leftLabelCollisions.set(
|
|
1116
|
+
pi,
|
|
1117
|
+
resolveVerticalCollisions(entries, 4, innerHeight)
|
|
1118
|
+
);
|
|
1119
|
+
}
|
|
1120
|
+
const rightEntries = seriesInfo.map((si) => ({
|
|
1121
|
+
naturalY: yScale(si.lastVal),
|
|
1122
|
+
height: Math.max(si.labelHeight, sLabelFontSize * 1.4)
|
|
1123
|
+
}));
|
|
1124
|
+
const rightAdjustedY = resolveVerticalCollisions(
|
|
1125
|
+
rightEntries,
|
|
1126
|
+
4,
|
|
1127
|
+
innerHeight
|
|
1128
|
+
);
|
|
1129
|
+
data.forEach((item, idx) => {
|
|
1130
|
+
const si = seriesInfo[idx];
|
|
1131
|
+
const color = si.color;
|
|
1132
|
+
const seriesG = g.append("g").attr("class", "slope-series").attr("data-line-number", String(item.lineNumber));
|
|
1133
|
+
seriesG.append("path").datum(item.values).attr("fill", "none").attr("stroke", color).attr("stroke-width", sLineStroke).attr("d", lineGen);
|
|
1134
|
+
seriesG.append("path").datum(item.values).attr("fill", "none").attr("stroke", "transparent").attr("stroke-width", sHitWidth).attr("d", lineGen).style("cursor", onClickItem ? "pointer" : "default").on(
|
|
1135
|
+
"mouseenter",
|
|
1136
|
+
(event) => showTooltip(tooltip, si.tipHtml, event)
|
|
1137
|
+
).on(
|
|
1138
|
+
"mousemove",
|
|
1139
|
+
(event) => showTooltip(tooltip, si.tipHtml, event)
|
|
1140
|
+
).on("mouseleave", () => hideTooltip(tooltip)).on("click", () => {
|
|
1141
|
+
if (onClickItem && item.lineNumber) onClickItem(item.lineNumber);
|
|
1142
|
+
});
|
|
1143
|
+
item.values.forEach((val, i) => {
|
|
1144
|
+
const x = xScale(periods[i]);
|
|
1145
|
+
const y = yScale(val);
|
|
1146
|
+
seriesG.append("circle").attr("cx", x).attr("cy", y).attr("r", sPointR).attr("fill", color).attr("stroke", bgColor).attr("stroke-width", sPointStroke).style("cursor", onClickItem ? "pointer" : "default").on(
|
|
1147
|
+
"mouseenter",
|
|
1148
|
+
(event) => showTooltip(tooltip, si.tipHtml, event)
|
|
1149
|
+
).on(
|
|
1150
|
+
"mousemove",
|
|
1151
|
+
(event) => showTooltip(tooltip, si.tipHtml, event)
|
|
1152
|
+
).on("mouseleave", () => hideTooltip(tooltip)).on("click", () => {
|
|
1153
|
+
if (onClickItem && item.lineNumber) onClickItem(item.lineNumber);
|
|
1154
|
+
});
|
|
1155
|
+
const isFirst = i === 0;
|
|
1156
|
+
const isLast = i === periods.length - 1;
|
|
1157
|
+
if (!isLast) {
|
|
1158
|
+
const adjustedY = leftLabelCollisions.get(i)[idx];
|
|
1159
|
+
seriesG.append("text").attr("x", isFirst ? x - sValueLabelXOff : x).attr("y", adjustedY).attr("dy", "0.35em").attr("text-anchor", isFirst ? "end" : "middle").attr("fill", color).attr("font-size", sValueFont).text(val.toString());
|
|
1160
|
+
}
|
|
1161
|
+
});
|
|
1162
|
+
const adjustedLastY = rightAdjustedY[idx];
|
|
1163
|
+
const labelEl = seriesG.append("text").attr("x", si.lastX + sLabelGap).attr("y", adjustedLastY).attr("text-anchor", "start").attr("fill", color).attr("font-size", sLabelFontSize).attr("font-weight", "normal");
|
|
1164
|
+
if (!si.wrappedLines) {
|
|
1165
|
+
labelEl.attr("dy", "0.35em").text(si.labelText);
|
|
1166
|
+
} else {
|
|
1167
|
+
const lineHeight = sLabelFontSize * 1.2;
|
|
1168
|
+
const totalHeight = (si.wrappedLines.length - 1) * lineHeight;
|
|
1169
|
+
const startDy = -totalHeight / 2;
|
|
1170
|
+
si.wrappedLines.forEach((line2, li) => {
|
|
1171
|
+
labelEl.append("tspan").attr("x", si.lastX + sLabelGap).attr(
|
|
1172
|
+
"dy",
|
|
1173
|
+
li === 0 ? `${startDy + sLabelFontSize * 0.35}px` : `${lineHeight}px`
|
|
1174
|
+
).text(line2);
|
|
1175
|
+
});
|
|
997
1176
|
}
|
|
998
|
-
cloud().size([width, cloudHeight]).words(sized).padding(2).rotate(rotateFn).fontSize((d) => d.size).font(FONT_FAMILY).on("end", draw).start();
|
|
999
1177
|
});
|
|
1000
1178
|
}
|
|
1001
1179
|
|
|
@@ -1465,985 +1643,484 @@ function renderVenn(container, parsed, palette, _isDark, onClickItem, exportDims
|
|
|
1465
1643
|
sy /= excluded.length;
|
|
1466
1644
|
const dx = centroid.x - sx;
|
|
1467
1645
|
const dy = centroid.y - sy;
|
|
1468
|
-
const m = Math.sqrt(dx * dx + dy * dy);
|
|
1469
|
-
if (m >= 1e-6) {
|
|
1470
|
-
const nx = Math.abs(dx / m) < 1e-9 ? 0 : dx / m;
|
|
1471
|
-
const ny = Math.abs(dy / m) < 1e-9 ? 0 : dy / m;
|
|
1472
|
-
return { x: nx, y: ny };
|
|
1473
|
-
}
|
|
1474
|
-
}
|
|
1475
|
-
if (n === 3) return { x: 0, y: -1 };
|
|
1476
|
-
return { x: 0, y: 1 };
|
|
1477
|
-
}
|
|
1478
|
-
function lensExit(c0, dir, idxs) {
|
|
1479
|
-
let minT = Infinity;
|
|
1480
|
-
for (const i of idxs) {
|
|
1481
|
-
const c = circles[i];
|
|
1482
|
-
const dx = c0.x - c.x;
|
|
1483
|
-
const dy = c0.y - c.y;
|
|
1484
|
-
const B = dx * dir.x + dy * dir.y;
|
|
1485
|
-
const C = dx * dx + dy * dy - c.r * c.r;
|
|
1486
|
-
const disc = B * B - C;
|
|
1487
|
-
if (disc < 0) continue;
|
|
1488
|
-
const t = -B + Math.sqrt(disc);
|
|
1489
|
-
if (t > 0 && t < minT) minT = t;
|
|
1490
|
-
}
|
|
1491
|
-
if (!isFinite(minT)) return { x: c0.x, y: c0.y };
|
|
1492
|
-
return { x: c0.x + dir.x * minT, y: c0.y + dir.y * minT };
|
|
1493
|
-
}
|
|
1494
|
-
function unionExit(c0, dir, idxs) {
|
|
1495
|
-
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
1496
|
-
for (const c of circles) {
|
|
1497
|
-
minX = Math.min(minX, c.x - c.r);
|
|
1498
|
-
maxX = Math.max(maxX, c.x + c.r);
|
|
1499
|
-
minY = Math.min(minY, c.y - c.r);
|
|
1500
|
-
maxY = Math.max(maxY, c.y + c.r);
|
|
1501
|
-
}
|
|
1502
|
-
const STEP = 3;
|
|
1503
|
-
const MAX_ITERS = 400;
|
|
1504
|
-
const axisAligned = dir.x === 0 || dir.y === 0;
|
|
1505
|
-
let p = { x: c0.x, y: c0.y };
|
|
1506
|
-
let leftOverlap = false;
|
|
1507
|
-
for (let i = 0; i < MAX_ITERS; i++) {
|
|
1508
|
-
const next = { x: p.x + dir.x * STEP, y: p.y + dir.y * STEP };
|
|
1509
|
-
p = next;
|
|
1510
|
-
if (!leftOverlap) {
|
|
1511
|
-
leftOverlap = !idxs.every((ci) => pointInCircle(next, circles[ci]));
|
|
1512
|
-
if (!leftOverlap) continue;
|
|
1513
|
-
}
|
|
1514
|
-
const insideAny = circles.some((c) => pointInCircle(next, c));
|
|
1515
|
-
if (insideAny) continue;
|
|
1516
|
-
if (axisAligned) {
|
|
1517
|
-
const passedX = dir.x > 0 ? next.x >= maxX : next.x <= minX;
|
|
1518
|
-
const passedY = dir.y > 0 ? next.y >= maxY : next.y <= minY;
|
|
1519
|
-
if (dir.x !== 0 && !passedX) continue;
|
|
1520
|
-
if (dir.y !== 0 && !passedY) continue;
|
|
1521
|
-
}
|
|
1522
|
-
break;
|
|
1523
|
-
}
|
|
1524
|
-
return p;
|
|
1525
|
-
}
|
|
1526
|
-
for (const ov of vennOverlaps) {
|
|
1527
|
-
if (!ov.label) continue;
|
|
1528
|
-
const idxs = ov.sets.map((s) => vennSets.findIndex((vs) => vs.name === s));
|
|
1529
|
-
if (idxs.some((idx) => idx < 0)) continue;
|
|
1530
|
-
const lines = wrappedOverlapLabels.get(ov) ?? [ov.label];
|
|
1531
|
-
const inside = circles.map((_, j) => idxs.includes(j));
|
|
1532
|
-
const centroid = regionCentroid(circles, inside);
|
|
1533
|
-
const dir = overlapOutwardDir(centroid, idxs);
|
|
1534
|
-
const isTriple = idxs.length === 3 && n === 3;
|
|
1535
|
-
const padBoost = isTriple && dir.y < 0 ? 32 : 0;
|
|
1536
|
-
const leaderPad = OVERLAP_LEADER_PAD + padBoost;
|
|
1537
|
-
const lensPt = lensExit(centroid, dir, idxs);
|
|
1538
|
-
const farExit = unionExit(centroid, dir, idxs);
|
|
1539
|
-
const stubEndX = farExit.x + dir.x * leaderPad;
|
|
1540
|
-
const stubEndY = farExit.y + dir.y * leaderPad;
|
|
1541
|
-
const horizontal = Math.abs(dir.x) >= Math.abs(dir.y);
|
|
1542
|
-
let textAnchor;
|
|
1543
|
-
let baseline = "central";
|
|
1544
|
-
if (horizontal) {
|
|
1545
|
-
textAnchor = dir.x >= 0 ? "start" : "end";
|
|
1546
|
-
} else {
|
|
1547
|
-
textAnchor = "middle";
|
|
1548
|
-
baseline = dir.y >= 0 ? "hanging" : "auto";
|
|
1549
|
-
}
|
|
1550
|
-
let textX, textY;
|
|
1551
|
-
if (horizontal) {
|
|
1552
|
-
const sign = dir.x >= 0 ? 1 : -1;
|
|
1553
|
-
textX = stubEndX + sign * OVERLAP_TEXT_GAP;
|
|
1554
|
-
textY = stubEndY;
|
|
1555
|
-
} else {
|
|
1556
|
-
const sign = dir.y >= 0 ? 1 : -1;
|
|
1557
|
-
textX = stubEndX;
|
|
1558
|
-
textY = stubEndY + sign * OVERLAP_TEXT_GAP;
|
|
1559
|
-
}
|
|
1560
|
-
const blockW = lines.reduce(
|
|
1561
|
-
(m, l) => Math.max(m, measureText(l, OVERLAP_FONT, { bold: true })),
|
|
1562
|
-
0
|
|
1563
|
-
);
|
|
1564
|
-
const blockH = lines.length * OVERLAP_LINE_H;
|
|
1565
|
-
if (textAnchor === "start") textX = Math.min(textX, width - blockW - 4);
|
|
1566
|
-
else if (textAnchor === "end") textX = Math.max(textX, blockW + 4);
|
|
1567
|
-
else
|
|
1568
|
-
textX = Math.max(blockW / 2 + 4, Math.min(width - blockW / 2 - 4, textX));
|
|
1569
|
-
let topY, bottomY;
|
|
1570
|
-
if (baseline === "hanging") {
|
|
1571
|
-
topY = textY;
|
|
1572
|
-
bottomY = textY + blockH;
|
|
1573
|
-
} else if (baseline === "auto") {
|
|
1574
|
-
bottomY = textY;
|
|
1575
|
-
topY = textY - blockH;
|
|
1576
|
-
} else {
|
|
1577
|
-
topY = textY - blockH / 2;
|
|
1578
|
-
bottomY = textY + blockH / 2;
|
|
1579
|
-
}
|
|
1580
|
-
if (topY < sTitleHeight + 6) textY += sTitleHeight + 6 - topY;
|
|
1581
|
-
else if (bottomY > height - 4) textY -= bottomY - (height - 4);
|
|
1582
|
-
const startY = baseline === "hanging" ? textY : baseline === "auto" ? textY - (lines.length - 1) * OVERLAP_LINE_H : textY - (lines.length - 1) * OVERLAP_LINE_H / 2;
|
|
1583
|
-
const leaderStartX = isTriple ? centroid.x : lensPt.x;
|
|
1584
|
-
const leaderStartY = isTriple ? centroid.y : lensPt.y;
|
|
1585
|
-
let tinted = setColors[idxs[0]];
|
|
1586
|
-
for (let k = 1; k < idxs.length; k++) {
|
|
1587
|
-
const pct = k / (k + 1) * 100;
|
|
1588
|
-
tinted = mix(tinted, setColors[idxs[k]], pct);
|
|
1589
|
-
}
|
|
1590
|
-
const overlapColor = mix(tinted, textColor, 90);
|
|
1591
|
-
const ovKey = [...idxs].sort((a, b) => a - b).join("-");
|
|
1592
|
-
const ovLabelG = labelGroup.append("g").style("cursor", "default").on("mouseenter", () => showRegionOverlay(idxs)).on("mouseleave", () => hideAllOverlays());
|
|
1593
|
-
registerLabel(ovKey, ovLabelG);
|
|
1594
|
-
const labelRects = setLabelBBoxes.filter((b) => b !== null);
|
|
1595
|
-
const segments = clipLineByRects(
|
|
1596
|
-
leaderStartX,
|
|
1597
|
-
leaderStartY,
|
|
1598
|
-
stubEndX,
|
|
1599
|
-
stubEndY,
|
|
1600
|
-
labelRects,
|
|
1601
|
-
4
|
|
1602
|
-
);
|
|
1603
|
-
for (const seg of segments) {
|
|
1604
|
-
ovLabelG.append("line").attr("x1", seg.x1).attr("y1", seg.y1).attr("x2", seg.x2).attr("y2", seg.y2).attr("stroke", overlapColor).attr("stroke-width", ctx.structural(1.25)).attr("opacity", 0.85);
|
|
1605
|
-
}
|
|
1606
|
-
const textEl = ovLabelG.append("text").attr("text-anchor", textAnchor).attr("dominant-baseline", baseline).attr("fill", overlapColor).attr("font-size", OVERLAP_FONT).attr("font-weight", "bold");
|
|
1607
|
-
lines.forEach((line2, i) => {
|
|
1608
|
-
const tspan = textEl.append("tspan").attr("x", textX);
|
|
1609
|
-
if (i === 0) tspan.attr("y", startY);
|
|
1610
|
-
else tspan.attr("dy", OVERLAP_LINE_H);
|
|
1611
|
-
tspan.text(line2);
|
|
1612
|
-
});
|
|
1613
|
-
}
|
|
1614
|
-
const hoverGroup = svg.append("g");
|
|
1615
|
-
circles.forEach((c, i) => {
|
|
1616
|
-
hoverGroup.append("circle").attr("cx", c.x).attr("cy", c.y).attr("r", c.r).attr("fill", "transparent").attr("stroke", "none").attr("class", "venn-hit-target").attr("data-line-number", String(vennSets[i].lineNumber)).style("cursor", onClickItem ? "pointer" : "default").style("outline-solid", "none").on("mouseenter", () => {
|
|
1617
|
-
showRegionOverlay([i]);
|
|
1618
|
-
}).on("mouseleave", () => {
|
|
1619
|
-
hideAllOverlays();
|
|
1620
|
-
}).on("click", function() {
|
|
1621
|
-
this.blur?.();
|
|
1622
|
-
if (onClickItem && vennSets[i].lineNumber)
|
|
1623
|
-
onClickItem(vennSets[i].lineNumber);
|
|
1624
|
-
});
|
|
1625
|
-
});
|
|
1626
|
-
const overlayR = scaledR * 0.35;
|
|
1627
|
-
const subsets = [];
|
|
1628
|
-
if (n === 2) {
|
|
1629
|
-
subsets.push({
|
|
1630
|
-
idxs: [0, 1],
|
|
1631
|
-
sets: [vennSets[0].name, vennSets[1].name].sort()
|
|
1632
|
-
});
|
|
1633
|
-
} else {
|
|
1634
|
-
for (let a = 0; a < n; a++) {
|
|
1635
|
-
for (let b = a + 1; b < n; b++) {
|
|
1636
|
-
subsets.push({
|
|
1637
|
-
idxs: [a, b],
|
|
1638
|
-
sets: [vennSets[a].name, vennSets[b].name].sort()
|
|
1639
|
-
});
|
|
1646
|
+
const m = Math.sqrt(dx * dx + dy * dy);
|
|
1647
|
+
if (m >= 1e-6) {
|
|
1648
|
+
const nx = Math.abs(dx / m) < 1e-9 ? 0 : dx / m;
|
|
1649
|
+
const ny = Math.abs(dy / m) < 1e-9 ? 0 : dy / m;
|
|
1650
|
+
return { x: nx, y: ny };
|
|
1640
1651
|
}
|
|
1641
1652
|
}
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
sets: [vennSets[0].name, vennSets[1].name, vennSets[2].name].sort()
|
|
1645
|
-
});
|
|
1646
|
-
}
|
|
1647
|
-
for (const subset of subsets) {
|
|
1648
|
-
const { idxs, sets } = subset;
|
|
1649
|
-
const inside = circles.map((_, j) => idxs.includes(j));
|
|
1650
|
-
const centroid = regionCentroid(circles, inside);
|
|
1651
|
-
const declaredOv = vennOverlaps.find(
|
|
1652
|
-
(ov) => ov.sets.length === sets.length && ov.sets.every((s, k) => s === sets[k])
|
|
1653
|
-
);
|
|
1654
|
-
hoverGroup.append("circle").attr("cx", centroid.x).attr("cy", centroid.y).attr("r", overlayR).attr("fill", "transparent").attr("stroke", "none").attr("class", "venn-hit-target").attr("data-line-number", declaredOv ? String(declaredOv.lineNumber) : "").style("cursor", onClickItem && declaredOv ? "pointer" : "default").style("outline-solid", "none").on("mouseenter", () => {
|
|
1655
|
-
showRegionOverlay(idxs);
|
|
1656
|
-
}).on("mouseleave", () => {
|
|
1657
|
-
hideAllOverlays();
|
|
1658
|
-
}).on("click", function() {
|
|
1659
|
-
this.blur?.();
|
|
1660
|
-
if (onClickItem && declaredOv) onClickItem(declaredOv.lineNumber);
|
|
1661
|
-
});
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
|
-
|
|
1665
|
-
// src/quadrant/renderer.ts
|
|
1666
|
-
import * as d3Scale3 from "d3-scale";
|
|
1667
|
-
import * as d3Selection3 from "d3-selection";
|
|
1668
|
-
function renderQuadrant(container, parsed, palette, isDark, onClickItem, exportDims) {
|
|
1669
|
-
const {
|
|
1670
|
-
quadrantLabels,
|
|
1671
|
-
quadrantPoints,
|
|
1672
|
-
quadrantXAxis,
|
|
1673
|
-
quadrantYAxis,
|
|
1674
|
-
quadrantTitleLineNumber,
|
|
1675
|
-
quadrantXAxisLineNumber,
|
|
1676
|
-
quadrantYAxisLineNumber
|
|
1677
|
-
} = parsed;
|
|
1678
|
-
const title = parsed.noTitle ? null : parsed.title;
|
|
1679
|
-
if (quadrantPoints.length === 0) return;
|
|
1680
|
-
const init = initD3Chart(container, palette, exportDims);
|
|
1681
|
-
if (!init) return;
|
|
1682
|
-
const { svg, width, height, textColor } = init;
|
|
1683
|
-
const borderColor = palette.border;
|
|
1684
|
-
const idealWidth = 600;
|
|
1685
|
-
const ctx = exportDims ? ScaleContext.identity() : ScaleContext.from(width, idealWidth);
|
|
1686
|
-
svg.attr("preserveAspectRatio", "xMidYMid meet");
|
|
1687
|
-
if (ctx.isBelowFloor) {
|
|
1688
|
-
svg.attr("width", "100%");
|
|
1653
|
+
if (n === 3) return { x: 0, y: -1 };
|
|
1654
|
+
return { x: 0, y: 1 };
|
|
1689
1655
|
}
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
left: hasYAxis ? ctx.aesthetic(80) : ctx.aesthetic(40)
|
|
1703
|
-
};
|
|
1704
|
-
const chartWidth = width - margin.left - margin.right;
|
|
1705
|
-
const chartHeight = height - margin.top - margin.bottom;
|
|
1706
|
-
const xScale = d3Scale3.scaleLinear().domain([0, 1]).range([0, chartWidth]);
|
|
1707
|
-
const yScale = d3Scale3.scaleLinear().domain([0, 1]).range([chartHeight, 0]);
|
|
1708
|
-
renderChartTitle(
|
|
1709
|
-
svg,
|
|
1710
|
-
title,
|
|
1711
|
-
quadrantTitleLineNumber,
|
|
1712
|
-
width,
|
|
1713
|
-
textColor,
|
|
1714
|
-
onClickItem
|
|
1715
|
-
);
|
|
1716
|
-
const chartG = svg.append("g").attr("transform", `translate(${margin.left}, ${margin.top})`);
|
|
1717
|
-
const bg = themeBaseBg(palette, isDark);
|
|
1718
|
-
const getQuadrantColor = (label, defaultIdx) => {
|
|
1719
|
-
return label?.color ?? defaultColors[defaultIdx % defaultColors.length];
|
|
1720
|
-
};
|
|
1721
|
-
const getQuadrantFill = (label, defaultIdx) => {
|
|
1722
|
-
return mix(getQuadrantColor(label, defaultIdx), bg, 30);
|
|
1723
|
-
};
|
|
1724
|
-
const quadrantDefs = [
|
|
1725
|
-
{
|
|
1726
|
-
position: "top-left",
|
|
1727
|
-
x: 0,
|
|
1728
|
-
y: 0,
|
|
1729
|
-
w: chartWidth / 2,
|
|
1730
|
-
h: chartHeight / 2,
|
|
1731
|
-
labelX: chartWidth / 4,
|
|
1732
|
-
labelY: chartHeight / 4,
|
|
1733
|
-
label: quadrantLabels.topLeft,
|
|
1734
|
-
colorIdx: 1
|
|
1735
|
-
// green
|
|
1736
|
-
},
|
|
1737
|
-
{
|
|
1738
|
-
position: "top-right",
|
|
1739
|
-
x: chartWidth / 2,
|
|
1740
|
-
y: 0,
|
|
1741
|
-
w: chartWidth / 2,
|
|
1742
|
-
h: chartHeight / 2,
|
|
1743
|
-
labelX: chartWidth * 3 / 4,
|
|
1744
|
-
labelY: chartHeight / 4,
|
|
1745
|
-
label: quadrantLabels.topRight,
|
|
1746
|
-
colorIdx: 0
|
|
1747
|
-
// blue
|
|
1748
|
-
},
|
|
1749
|
-
{
|
|
1750
|
-
position: "bottom-left",
|
|
1751
|
-
x: 0,
|
|
1752
|
-
y: chartHeight / 2,
|
|
1753
|
-
w: chartWidth / 2,
|
|
1754
|
-
h: chartHeight / 2,
|
|
1755
|
-
labelX: chartWidth / 4,
|
|
1756
|
-
labelY: chartHeight * 3 / 4,
|
|
1757
|
-
label: quadrantLabels.bottomLeft,
|
|
1758
|
-
colorIdx: 2
|
|
1759
|
-
// yellow
|
|
1760
|
-
},
|
|
1761
|
-
{
|
|
1762
|
-
position: "bottom-right",
|
|
1763
|
-
x: chartWidth / 2,
|
|
1764
|
-
y: chartHeight / 2,
|
|
1765
|
-
w: chartWidth / 2,
|
|
1766
|
-
h: chartHeight / 2,
|
|
1767
|
-
labelX: chartWidth * 3 / 4,
|
|
1768
|
-
labelY: chartHeight * 3 / 4,
|
|
1769
|
-
label: quadrantLabels.bottomRight,
|
|
1770
|
-
colorIdx: 3
|
|
1771
|
-
// purple
|
|
1656
|
+
function lensExit(c0, dir, idxs) {
|
|
1657
|
+
let minT = Infinity;
|
|
1658
|
+
for (const i of idxs) {
|
|
1659
|
+
const c = circles[i];
|
|
1660
|
+
const dx = c0.x - c.x;
|
|
1661
|
+
const dy = c0.y - c.y;
|
|
1662
|
+
const B = dx * dir.x + dy * dir.y;
|
|
1663
|
+
const C = dx * dx + dy * dy - c.r * c.r;
|
|
1664
|
+
const disc = B * B - C;
|
|
1665
|
+
if (disc < 0) continue;
|
|
1666
|
+
const t = -B + Math.sqrt(disc);
|
|
1667
|
+
if (t > 0 && t < minT) minT = t;
|
|
1772
1668
|
}
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
if (measureText(text, LABEL_MAX_FONT, { bold: true }) <= availW) {
|
|
1784
|
-
const fs = Math.min(LABEL_MAX_FONT, availH);
|
|
1785
|
-
return {
|
|
1786
|
-
lines: [text],
|
|
1787
|
-
fontSize: Math.max(LABEL_MIN_FONT, Math.round(fs))
|
|
1788
|
-
};
|
|
1669
|
+
if (!isFinite(minT)) return { x: c0.x, y: c0.y };
|
|
1670
|
+
return { x: c0.x + dir.x * minT, y: c0.y + dir.y * minT };
|
|
1671
|
+
}
|
|
1672
|
+
function unionExit(c0, dir, idxs) {
|
|
1673
|
+
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
1674
|
+
for (const c of circles) {
|
|
1675
|
+
minX = Math.min(minX, c.x - c.r);
|
|
1676
|
+
maxX = Math.max(maxX, c.x + c.r);
|
|
1677
|
+
minY = Math.min(minY, c.y - c.r);
|
|
1678
|
+
maxY = Math.max(maxY, c.y + c.r);
|
|
1789
1679
|
}
|
|
1790
|
-
const
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
let
|
|
1794
|
-
let
|
|
1795
|
-
|
|
1796
|
-
const
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1680
|
+
const STEP = 3;
|
|
1681
|
+
const MAX_ITERS = 400;
|
|
1682
|
+
const axisAligned = dir.x === 0 || dir.y === 0;
|
|
1683
|
+
let p = { x: c0.x, y: c0.y };
|
|
1684
|
+
let leftOverlap = false;
|
|
1685
|
+
for (let i = 0; i < MAX_ITERS; i++) {
|
|
1686
|
+
const next = { x: p.x + dir.x * STEP, y: p.y + dir.y * STEP };
|
|
1687
|
+
p = next;
|
|
1688
|
+
if (!leftOverlap) {
|
|
1689
|
+
leftOverlap = !idxs.every((ci) => pointInCircle(next, circles[ci]));
|
|
1690
|
+
if (!leftOverlap) continue;
|
|
1691
|
+
}
|
|
1692
|
+
const insideAny = circles.some((c) => pointInCircle(next, c));
|
|
1693
|
+
if (insideAny) continue;
|
|
1694
|
+
if (axisAligned) {
|
|
1695
|
+
const passedX = dir.x > 0 ? next.x >= maxX : next.x <= minX;
|
|
1696
|
+
const passedY = dir.y > 0 ? next.y >= maxY : next.y <= minY;
|
|
1697
|
+
if (dir.x !== 0 && !passedX) continue;
|
|
1698
|
+
if (dir.y !== 0 && !passedY) continue;
|
|
1808
1699
|
}
|
|
1700
|
+
break;
|
|
1809
1701
|
}
|
|
1810
|
-
return
|
|
1811
|
-
}
|
|
1812
|
-
const
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
const
|
|
1823
|
-
const
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1702
|
+
return p;
|
|
1703
|
+
}
|
|
1704
|
+
for (const ov of vennOverlaps) {
|
|
1705
|
+
if (!ov.label) continue;
|
|
1706
|
+
const idxs = ov.sets.map((s) => vennSets.findIndex((vs) => vs.name === s));
|
|
1707
|
+
if (idxs.some((idx) => idx < 0)) continue;
|
|
1708
|
+
const lines = wrappedOverlapLabels.get(ov) ?? [ov.label];
|
|
1709
|
+
const inside = circles.map((_, j) => idxs.includes(j));
|
|
1710
|
+
const centroid = regionCentroid(circles, inside);
|
|
1711
|
+
const dir = overlapOutwardDir(centroid, idxs);
|
|
1712
|
+
const isTriple = idxs.length === 3 && n === 3;
|
|
1713
|
+
const padBoost = isTriple && dir.y < 0 ? 32 : 0;
|
|
1714
|
+
const leaderPad = OVERLAP_LEADER_PAD + padBoost;
|
|
1715
|
+
const lensPt = lensExit(centroid, dir, idxs);
|
|
1716
|
+
const farExit = unionExit(centroid, dir, idxs);
|
|
1717
|
+
const stubEndX = farExit.x + dir.x * leaderPad;
|
|
1718
|
+
const stubEndY = farExit.y + dir.y * leaderPad;
|
|
1719
|
+
const horizontal = Math.abs(dir.x) >= Math.abs(dir.y);
|
|
1720
|
+
let textAnchor;
|
|
1721
|
+
let baseline = "central";
|
|
1722
|
+
if (horizontal) {
|
|
1723
|
+
textAnchor = dir.x >= 0 ? "start" : "end";
|
|
1724
|
+
} else {
|
|
1725
|
+
textAnchor = "middle";
|
|
1726
|
+
baseline = dir.y >= 0 ? "hanging" : "auto";
|
|
1727
|
+
}
|
|
1728
|
+
let textX, textY;
|
|
1729
|
+
if (horizontal) {
|
|
1730
|
+
const sign = dir.x >= 0 ? 1 : -1;
|
|
1731
|
+
textX = stubEndX + sign * OVERLAP_TEXT_GAP;
|
|
1732
|
+
textY = stubEndY;
|
|
1827
1733
|
} else {
|
|
1828
|
-
const
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
layout.lines.forEach((line2, i) => {
|
|
1832
|
-
el.append("tspan").attr("x", d.labelX).attr("dy", i === 0 ? `${startY}px` : `${lineH}px`).text(line2);
|
|
1833
|
-
});
|
|
1734
|
+
const sign = dir.y >= 0 ? 1 : -1;
|
|
1735
|
+
textX = stubEndX;
|
|
1736
|
+
textY = stubEndY + sign * OVERLAP_TEXT_GAP;
|
|
1834
1737
|
}
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
"
|
|
1841
|
-
(
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
const sAxisFont = ctx.text(18);
|
|
1855
|
-
const sAxisPad = ctx.aesthetic(20);
|
|
1856
|
-
const sAxisX = ctx.aesthetic(22);
|
|
1857
|
-
if (quadrantXAxis) {
|
|
1858
|
-
const xLowLabel = svg.append("text").attr("class", "quadrant-axis-label").attr("x", margin.left + chartWidth / 4).attr("y", height - sAxisPad).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", sAxisFont).attr(
|
|
1859
|
-
"data-line-number",
|
|
1860
|
-
quadrantXAxisLineNumber ? String(quadrantXAxisLineNumber) : null
|
|
1861
|
-
).style(
|
|
1862
|
-
"cursor",
|
|
1863
|
-
onClickItem && quadrantXAxisLineNumber ? "pointer" : "default"
|
|
1864
|
-
).text(quadrantXAxis[0]);
|
|
1865
|
-
const xHighLabel = svg.append("text").attr("class", "quadrant-axis-label").attr("x", margin.left + chartWidth * 3 / 4).attr("y", height - sAxisPad).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", sAxisFont).attr(
|
|
1866
|
-
"data-line-number",
|
|
1867
|
-
quadrantXAxisLineNumber ? String(quadrantXAxisLineNumber) : null
|
|
1868
|
-
).style(
|
|
1869
|
-
"cursor",
|
|
1870
|
-
onClickItem && quadrantXAxisLineNumber ? "pointer" : "default"
|
|
1871
|
-
).text(quadrantXAxis[1]);
|
|
1872
|
-
if (onClickItem && quadrantXAxisLineNumber) {
|
|
1873
|
-
[xLowLabel, xHighLabel].forEach((label) => {
|
|
1874
|
-
label.on("click", () => onClickItem(quadrantXAxisLineNumber)).on("mouseenter", function() {
|
|
1875
|
-
d3Selection3.select(this).attr("opacity", 0.7);
|
|
1876
|
-
}).on("mouseleave", function() {
|
|
1877
|
-
d3Selection3.select(this).attr("opacity", 1);
|
|
1878
|
-
});
|
|
1879
|
-
});
|
|
1738
|
+
const blockW = lines.reduce(
|
|
1739
|
+
(m, l) => Math.max(m, measureText(l, OVERLAP_FONT, { bold: true })),
|
|
1740
|
+
0
|
|
1741
|
+
);
|
|
1742
|
+
const blockH = lines.length * OVERLAP_LINE_H;
|
|
1743
|
+
if (textAnchor === "start") textX = Math.min(textX, width - blockW - 4);
|
|
1744
|
+
else if (textAnchor === "end") textX = Math.max(textX, blockW + 4);
|
|
1745
|
+
else
|
|
1746
|
+
textX = Math.max(blockW / 2 + 4, Math.min(width - blockW / 2 - 4, textX));
|
|
1747
|
+
let topY, bottomY;
|
|
1748
|
+
if (baseline === "hanging") {
|
|
1749
|
+
topY = textY;
|
|
1750
|
+
bottomY = textY + blockH;
|
|
1751
|
+
} else if (baseline === "auto") {
|
|
1752
|
+
bottomY = textY;
|
|
1753
|
+
topY = textY - blockH;
|
|
1754
|
+
} else {
|
|
1755
|
+
topY = textY - blockH / 2;
|
|
1756
|
+
bottomY = textY + blockH / 2;
|
|
1880
1757
|
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
const
|
|
1884
|
-
const
|
|
1885
|
-
const
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
onClickItem && quadrantYAxisLineNumber ? "pointer" : "default"
|
|
1891
|
-
).text(quadrantYAxis[0]);
|
|
1892
|
-
const yHighLabel = svg.append("text").attr("class", "quadrant-axis-label").attr("x", sAxisX).attr("y", yMidTop).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", sAxisFont).attr("transform", `rotate(-90, ${sAxisX}, ${yMidTop})`).attr(
|
|
1893
|
-
"data-line-number",
|
|
1894
|
-
quadrantYAxisLineNumber ? String(quadrantYAxisLineNumber) : null
|
|
1895
|
-
).style(
|
|
1896
|
-
"cursor",
|
|
1897
|
-
onClickItem && quadrantYAxisLineNumber ? "pointer" : "default"
|
|
1898
|
-
).text(quadrantYAxis[1]);
|
|
1899
|
-
if (onClickItem && quadrantYAxisLineNumber) {
|
|
1900
|
-
[yLowLabel, yHighLabel].forEach((label) => {
|
|
1901
|
-
label.on("click", () => onClickItem(quadrantYAxisLineNumber)).on("mouseenter", function() {
|
|
1902
|
-
d3Selection3.select(this).attr("opacity", 0.7);
|
|
1903
|
-
}).on("mouseleave", function() {
|
|
1904
|
-
d3Selection3.select(this).attr("opacity", 1);
|
|
1905
|
-
});
|
|
1906
|
-
});
|
|
1758
|
+
if (topY < sTitleHeight + 6) textY += sTitleHeight + 6 - topY;
|
|
1759
|
+
else if (bottomY > height - 4) textY -= bottomY - (height - 4);
|
|
1760
|
+
const startY = baseline === "hanging" ? textY : baseline === "auto" ? textY - (lines.length - 1) * OVERLAP_LINE_H : textY - (lines.length - 1) * OVERLAP_LINE_H / 2;
|
|
1761
|
+
const leaderStartX = isTriple ? centroid.x : lensPt.x;
|
|
1762
|
+
const leaderStartY = isTriple ? centroid.y : lensPt.y;
|
|
1763
|
+
let tinted = setColors[idxs[0]];
|
|
1764
|
+
for (let k = 1; k < idxs.length; k++) {
|
|
1765
|
+
const pct = k / (k + 1) * 100;
|
|
1766
|
+
tinted = mix(tinted, setColors[idxs[k]], pct);
|
|
1907
1767
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
const layout = labelLayouts.get(d.label.text);
|
|
1921
|
-
const totalW = Math.max(
|
|
1922
|
-
...layout.lines.map((l) => measureText(l, layout.fontSize))
|
|
1768
|
+
const overlapColor = mix(tinted, textColor, 90);
|
|
1769
|
+
const ovKey = [...idxs].sort((a, b) => a - b).join("-");
|
|
1770
|
+
const ovLabelG = labelGroup.append("g").style("cursor", "default").on("mouseenter", () => showRegionOverlay(idxs)).on("mouseleave", () => hideAllOverlays());
|
|
1771
|
+
registerLabel(ovKey, ovLabelG);
|
|
1772
|
+
const labelRects = setLabelBBoxes.filter((b) => b !== null);
|
|
1773
|
+
const segments = clipLineByRects(
|
|
1774
|
+
leaderStartX,
|
|
1775
|
+
leaderStartY,
|
|
1776
|
+
stubEndX,
|
|
1777
|
+
stubEndY,
|
|
1778
|
+
labelRects,
|
|
1779
|
+
4
|
|
1923
1780
|
);
|
|
1924
|
-
const
|
|
1925
|
-
|
|
1926
|
-
x: d.labelX - totalW / 2,
|
|
1927
|
-
y: d.labelY - totalH / 2,
|
|
1928
|
-
w: totalW,
|
|
1929
|
-
h: totalH
|
|
1930
|
-
};
|
|
1931
|
-
});
|
|
1932
|
-
const pointPixels = quadrantPoints.map((point) => ({
|
|
1933
|
-
label: point.label,
|
|
1934
|
-
cx: xScale(point.x),
|
|
1935
|
-
cy: yScale(point.y)
|
|
1936
|
-
}));
|
|
1937
|
-
const placedPointLabels = computeQuadrantPointLabels(
|
|
1938
|
-
pointPixels,
|
|
1939
|
-
{ left: 0, top: 0, right: chartWidth, bottom: chartHeight },
|
|
1940
|
-
quadrantLabelObstacles,
|
|
1941
|
-
POINT_RADIUS,
|
|
1942
|
-
POINT_LABEL_FONT_SIZE,
|
|
1943
|
-
// Point labels are drawn at 700 here.
|
|
1944
|
-
true
|
|
1945
|
-
);
|
|
1946
|
-
const pointsG = chartG.append("g").attr("class", "points");
|
|
1947
|
-
quadrantPoints.forEach((point, i) => {
|
|
1948
|
-
const cx = xScale(point.x);
|
|
1949
|
-
const cy = yScale(point.y);
|
|
1950
|
-
const quadrant = getPointQuadrant(point.x, point.y);
|
|
1951
|
-
const quadDef = quadrantDefs.find((d) => d.position === quadrant);
|
|
1952
|
-
const pointColor = quadDef?.label?.color ?? defaultColors[quadDef?.colorIdx ?? 0];
|
|
1953
|
-
const placed = placedPointLabels[i];
|
|
1954
|
-
const pointG = pointsG.append("g").attr("class", "point-group").attr("data-line-number", String(point.lineNumber)).attr("data-quadrant", quadrant);
|
|
1955
|
-
if (placed.connectorLine) {
|
|
1956
|
-
pointG.append("line").attr("x1", placed.connectorLine.x1).attr("y1", placed.connectorLine.y1).attr("x2", placed.connectorLine.x2).attr("y2", placed.connectorLine.y2).attr("stroke", pointColor).attr("stroke-width", 1).attr("opacity", 0.5);
|
|
1781
|
+
for (const seg of segments) {
|
|
1782
|
+
ovLabelG.append("line").attr("x1", seg.x1).attr("y1", seg.y1).attr("x2", seg.x2).attr("y2", seg.y2).attr("stroke", overlapColor).attr("stroke-width", ctx.structural(1.25)).attr("opacity", 0.85);
|
|
1957
1783
|
}
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
(qd) => qd.position === quadrant ? 1 : 0.3
|
|
1971
|
-
);
|
|
1972
|
-
quadrantLabelTexts.attr(
|
|
1973
|
-
"opacity",
|
|
1974
|
-
(qd) => qd.position === quadrant ? 1 : 0.3
|
|
1975
|
-
);
|
|
1976
|
-
pointsG.selectAll("g.point-group").filter((_, j) => j !== i).attr("opacity", 0.3);
|
|
1784
|
+
const textEl = ovLabelG.append("text").attr("text-anchor", textAnchor).attr("dominant-baseline", baseline).attr("fill", overlapColor).attr("font-size", OVERLAP_FONT).attr("font-weight", "bold");
|
|
1785
|
+
lines.forEach((line2, i) => {
|
|
1786
|
+
const tspan = textEl.append("tspan").attr("x", textX);
|
|
1787
|
+
if (i === 0) tspan.attr("y", startY);
|
|
1788
|
+
else tspan.attr("dy", OVERLAP_LINE_H);
|
|
1789
|
+
tspan.text(line2);
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1792
|
+
const hoverGroup = svg.append("g");
|
|
1793
|
+
circles.forEach((c, i) => {
|
|
1794
|
+
hoverGroup.append("circle").attr("cx", c.x).attr("cy", c.y).attr("r", c.r).attr("fill", "transparent").attr("stroke", "none").attr("class", "venn-hit-target").attr("data-line-number", String(vennSets[i].lineNumber)).style("cursor", onClickItem ? "pointer" : "default").style("outline-solid", "none").on("mouseenter", () => {
|
|
1795
|
+
showRegionOverlay([i]);
|
|
1977
1796
|
}).on("mouseleave", () => {
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
pointsG.selectAll("g.point-group").attr("opacity", 1);
|
|
1984
|
-
}).on("click", () => {
|
|
1985
|
-
if (onClickItem && point.lineNumber) onClickItem(point.lineNumber);
|
|
1797
|
+
hideAllOverlays();
|
|
1798
|
+
}).on("click", function() {
|
|
1799
|
+
this.blur?.();
|
|
1800
|
+
if (onClickItem && vennSets[i].lineNumber)
|
|
1801
|
+
onClickItem(vennSets[i].lineNumber);
|
|
1986
1802
|
});
|
|
1987
1803
|
});
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
"opacity",
|
|
1995
|
-
(qd) => qd.position === d.position ? 1 : 0.3
|
|
1996
|
-
);
|
|
1997
|
-
pointsG.selectAll("g.point-group").each(function(_2, i) {
|
|
1998
|
-
const pt = quadrantPoints[i];
|
|
1999
|
-
const ptQuad = getPointQuadrant(pt.x, pt.y);
|
|
2000
|
-
d3Selection3.select(this).attr("opacity", ptQuad === d.position ? 1 : 0.2);
|
|
1804
|
+
const overlayR = scaledR * 0.35;
|
|
1805
|
+
const subsets = [];
|
|
1806
|
+
if (n === 2) {
|
|
1807
|
+
subsets.push({
|
|
1808
|
+
idxs: [0, 1],
|
|
1809
|
+
sets: [vennSets[0].name, vennSets[1].name].sort()
|
|
2001
1810
|
});
|
|
2002
|
-
}
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
1811
|
+
} else {
|
|
1812
|
+
for (let a = 0; a < n; a++) {
|
|
1813
|
+
for (let b = a + 1; b < n; b++) {
|
|
1814
|
+
subsets.push({
|
|
1815
|
+
idxs: [a, b],
|
|
1816
|
+
sets: [vennSets[a].name, vennSets[b].name].sort()
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
2009
1819
|
}
|
|
2010
|
-
|
|
1820
|
+
subsets.push({
|
|
1821
|
+
idxs: [0, 1, 2],
|
|
1822
|
+
sets: [vennSets[0].name, vennSets[1].name, vennSets[2].name].sort()
|
|
1823
|
+
});
|
|
1824
|
+
}
|
|
1825
|
+
for (const subset of subsets) {
|
|
1826
|
+
const { idxs, sets } = subset;
|
|
1827
|
+
const inside = circles.map((_, j) => idxs.includes(j));
|
|
1828
|
+
const centroid = regionCentroid(circles, inside);
|
|
1829
|
+
const declaredOv = vennOverlaps.find(
|
|
1830
|
+
(ov) => ov.sets.length === sets.length && ov.sets.every((s, k) => s === sets[k])
|
|
1831
|
+
);
|
|
1832
|
+
hoverGroup.append("circle").attr("cx", centroid.x).attr("cy", centroid.y).attr("r", overlayR).attr("fill", "transparent").attr("stroke", "none").attr("class", "venn-hit-target").attr("data-line-number", declaredOv ? String(declaredOv.lineNumber) : "").style("cursor", onClickItem && declaredOv ? "pointer" : "default").style("outline-solid", "none").on("mouseenter", () => {
|
|
1833
|
+
showRegionOverlay(idxs);
|
|
1834
|
+
}).on("mouseleave", () => {
|
|
1835
|
+
hideAllOverlays();
|
|
1836
|
+
}).on("click", function() {
|
|
1837
|
+
this.blur?.();
|
|
1838
|
+
if (onClickItem && declaredOv) onClickItem(declaredOv.lineNumber);
|
|
1839
|
+
});
|
|
1840
|
+
}
|
|
2011
1841
|
}
|
|
2012
1842
|
|
|
2013
|
-
// src/
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
1843
|
+
// src/wordcloud/renderer.ts
|
|
1844
|
+
import * as d3Selection3 from "d3-selection";
|
|
1845
|
+
import cloud from "d3-cloud";
|
|
1846
|
+
function getRotateFn(mode) {
|
|
1847
|
+
if (mode === "mixed") return () => Math.random() > 0.5 ? 0 : 90;
|
|
1848
|
+
if (mode === "angled") return () => Math.round(Math.random() * 30 - 15);
|
|
1849
|
+
return () => 0;
|
|
1850
|
+
}
|
|
1851
|
+
function hasCanvas2d() {
|
|
2017
1852
|
try {
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
return
|
|
1853
|
+
if (typeof document === "undefined") return false;
|
|
1854
|
+
const canvas = document.createElement("canvas");
|
|
1855
|
+
return typeof canvas.getContext === "function" && !!canvas.getContext("2d");
|
|
1856
|
+
} catch {
|
|
1857
|
+
return false;
|
|
2021
1858
|
}
|
|
2022
1859
|
}
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
state: exportState,
|
|
2043
|
-
"tech-radar": exportTechRadar,
|
|
2044
|
-
"journey-map": exportJourneyMap,
|
|
2045
|
-
cycle: exportCycle,
|
|
2046
|
-
map: exportMap,
|
|
2047
|
-
pyramid: exportPyramid,
|
|
2048
|
-
ring: exportRing,
|
|
2049
|
-
treemap: exportTreemap,
|
|
2050
|
-
block: exportBlock,
|
|
2051
|
-
goal: exportGoal,
|
|
2052
|
-
countdown: exportCountdown,
|
|
2053
|
-
clock: exportClock,
|
|
2054
|
-
bracket: exportBracket,
|
|
2055
|
-
raci: exportRaci,
|
|
2056
|
-
body: exportBody,
|
|
2057
|
-
"live-link": exportLiveLink,
|
|
2058
|
-
// D3 visualizations — own handler per type (Story 109.2). Only `sequence`
|
|
2059
|
-
// still falls through to exportVisualization (no chart-type of its own).
|
|
2060
|
-
slope: exportSlope,
|
|
2061
|
-
arc: exportArc,
|
|
2062
|
-
timeline: exportTimeline,
|
|
2063
|
-
"event-line": exportEventLine,
|
|
2064
|
-
wordcloud: exportWordcloud,
|
|
2065
|
-
venn: exportVenn,
|
|
2066
|
-
quadrant: exportQuadrant
|
|
2067
|
-
};
|
|
2068
|
-
function resolveArcChordOverride(content, detectedType, palette) {
|
|
2069
|
-
if (detectedType === "arc") {
|
|
2070
|
-
const p = parseArc(content, palette);
|
|
2071
|
-
if (!p.error && p.layout === "chord" && p.links.length) {
|
|
2072
|
-
const emitted = [
|
|
2073
|
-
`chord ${p.title ?? ""}`.trimEnd(),
|
|
2074
|
-
// §1.9 fill family survives the layout re-emit so the circular
|
|
2075
|
-
// renderer honors fill-solid / fill-outline authored on the arc.
|
|
2076
|
-
...p.fillMode ? [`fill-${p.fillMode}`] : [],
|
|
2077
|
-
...p.links.map((l) => `${l.source} -> ${l.target} ${l.value}`)
|
|
2078
|
-
].join("\n");
|
|
2079
|
-
return { content: emitted, type: "chord" };
|
|
2080
|
-
}
|
|
1860
|
+
function estimateWordWidth(text, size) {
|
|
1861
|
+
return measureText(text, size, { bold: true });
|
|
1862
|
+
}
|
|
1863
|
+
var WORD_ASCENT = 0.78;
|
|
1864
|
+
var WORD_DESCENT = 0.22;
|
|
1865
|
+
var CLOUD_SHRINK = 0.9;
|
|
1866
|
+
var CLOUD_SHRINK_TRIES = 6;
|
|
1867
|
+
function layoutWordsNoCanvas(words, width, height, padding, rotateFn) {
|
|
1868
|
+
let placed = [];
|
|
1869
|
+
for (let attempt = 0, scale = 1; attempt <= CLOUD_SHRINK_TRIES; attempt++) {
|
|
1870
|
+
placed = packWords(
|
|
1871
|
+
words.map((w) => ({ ...w, size: w.size * scale })),
|
|
1872
|
+
width,
|
|
1873
|
+
height,
|
|
1874
|
+
padding,
|
|
1875
|
+
rotateFn
|
|
1876
|
+
);
|
|
1877
|
+
if (placed.length === words.length) break;
|
|
1878
|
+
scale *= CLOUD_SHRINK;
|
|
2081
1879
|
}
|
|
2082
|
-
return
|
|
1880
|
+
return placed;
|
|
2083
1881
|
}
|
|
2084
|
-
|
|
2085
|
-
const
|
|
2086
|
-
const
|
|
2087
|
-
const
|
|
2088
|
-
const
|
|
2089
|
-
const
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
const
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
1882
|
+
function packWords(words, width, height, padding, rotateFn) {
|
|
1883
|
+
const sorted = [...words].sort((a, b) => b.size - a.size);
|
|
1884
|
+
const placed = [];
|
|
1885
|
+
const maxR = Math.sqrt(width * width + height * height) / 2;
|
|
1886
|
+
const aspect = width > 0 ? height / width : 1;
|
|
1887
|
+
for (const w of sorted) {
|
|
1888
|
+
const rotate = rotateFn();
|
|
1889
|
+
const rawW = estimateWordWidth(w.text, w.size) + padding * 2;
|
|
1890
|
+
const rawH = (WORD_ASCENT + WORD_DESCENT) * w.size + padding * 2;
|
|
1891
|
+
const rad = rotate * Math.PI / 180;
|
|
1892
|
+
const cos = Math.abs(Math.cos(rad));
|
|
1893
|
+
const sin = Math.abs(Math.sin(rad));
|
|
1894
|
+
const halfW = (rawW * cos + rawH * sin) / 2;
|
|
1895
|
+
const halfH = (rawW * sin + rawH * cos) / 2;
|
|
1896
|
+
const off = (WORD_DESCENT - WORD_ASCENT) / 2 * w.size;
|
|
1897
|
+
const offX = -off * Math.sin(rad);
|
|
1898
|
+
const offY = off * Math.cos(rad);
|
|
1899
|
+
let spot = null;
|
|
1900
|
+
for (let t = 0; t < 4e3; t++) {
|
|
1901
|
+
const a = t * 0.25;
|
|
1902
|
+
const r = a * 1.4;
|
|
1903
|
+
if (r > maxR) break;
|
|
1904
|
+
const x = Math.cos(a) * r;
|
|
1905
|
+
const y = Math.sin(a) * r * aspect;
|
|
1906
|
+
const cx = x + offX;
|
|
1907
|
+
const cy = y + offY;
|
|
1908
|
+
if (cx - halfW < -width / 2 || cx + halfW > width / 2 || cy - halfH < -height / 2 || cy + halfH > height / 2) {
|
|
1909
|
+
continue;
|
|
1910
|
+
}
|
|
1911
|
+
let collides = false;
|
|
1912
|
+
for (const p of placed) {
|
|
1913
|
+
if (Math.abs(cx - p.cx) < halfW + p.halfW && Math.abs(cy - p.cy) < halfH + p.halfH) {
|
|
1914
|
+
collides = true;
|
|
1915
|
+
break;
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
if (!collides) {
|
|
1919
|
+
spot = { x, y };
|
|
1920
|
+
break;
|
|
1921
|
+
}
|
|
2098
1922
|
}
|
|
1923
|
+
if (!spot) continue;
|
|
1924
|
+
placed.push({
|
|
1925
|
+
...w,
|
|
1926
|
+
rotate,
|
|
1927
|
+
x: spot.x,
|
|
1928
|
+
y: spot.y,
|
|
1929
|
+
cx: spot.x + offX,
|
|
1930
|
+
cy: spot.y + offY,
|
|
1931
|
+
halfW,
|
|
1932
|
+
halfH
|
|
1933
|
+
});
|
|
2099
1934
|
}
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
1935
|
+
return placed;
|
|
1936
|
+
}
|
|
1937
|
+
function renderWordCloud(container, parsed, palette, _isDark, onClickItem, exportDims) {
|
|
1938
|
+
const { words, cloudOptions } = parsed;
|
|
1939
|
+
const title = parsed.noTitle ? null : parsed.title;
|
|
1940
|
+
if (words.length === 0) return;
|
|
1941
|
+
const init = initD3Chart(container, palette, exportDims);
|
|
1942
|
+
if (!init) return;
|
|
1943
|
+
const { svg, width, height, textColor, colors } = init;
|
|
1944
|
+
const idealWidth = Math.max(400, words.length * 30);
|
|
1945
|
+
const ctx = exportDims ? ScaleContext.identity() : ScaleContext.from(width, idealWidth);
|
|
1946
|
+
const sTitleHeight = title ? ctx.aesthetic(40) : 0;
|
|
1947
|
+
const cloudHeight = height - sTitleHeight;
|
|
1948
|
+
const sPadding = ctx.structural(2);
|
|
1949
|
+
svg.attr("preserveAspectRatio", "xMidYMid meet");
|
|
1950
|
+
if (ctx.isBelowFloor) {
|
|
1951
|
+
svg.attr("width", "100%");
|
|
1952
|
+
}
|
|
1953
|
+
const { minSize, maxSize } = cloudOptions;
|
|
1954
|
+
const sMinSize = ctx.text(minSize);
|
|
1955
|
+
const sMaxSize = ctx.text(maxSize);
|
|
1956
|
+
const weights = words.map((w) => w.weight);
|
|
1957
|
+
const minWeight = Math.min(...weights);
|
|
1958
|
+
const maxWeight = Math.max(...weights);
|
|
1959
|
+
const range = maxWeight - minWeight || 1;
|
|
1960
|
+
const fontSize = (weight) => {
|
|
1961
|
+
const t = (weight - minWeight) / range;
|
|
1962
|
+
return sMinSize + Math.sqrt(t) * (sMaxSize - sMinSize);
|
|
2116
1963
|
};
|
|
2117
|
-
const
|
|
2118
|
-
|
|
1964
|
+
const rotateFn = getRotateFn(cloudOptions.rotate);
|
|
1965
|
+
renderChartTitle(
|
|
1966
|
+
svg,
|
|
1967
|
+
title,
|
|
1968
|
+
parsed.titleLineNumber,
|
|
1969
|
+
width,
|
|
1970
|
+
textColor,
|
|
1971
|
+
onClickItem
|
|
1972
|
+
);
|
|
1973
|
+
const g = svg.append("g").attr(
|
|
1974
|
+
"transform",
|
|
1975
|
+
`translate(${width / 2},${sTitleHeight + cloudHeight / 2})`
|
|
1976
|
+
);
|
|
1977
|
+
const sized = words.map((w) => ({ ...w, size: fontSize(w.weight) }));
|
|
1978
|
+
const draw = (layoutWords) => {
|
|
1979
|
+
g.selectAll("text").data(layoutWords).join("text").style("font-size", (d) => `${d.size}px`).style("font-family", FONT_FAMILY).style("font-weight", "bold").style("fill", (_d, i) => colors[i % colors.length]).style(
|
|
1980
|
+
"cursor",
|
|
1981
|
+
(d) => onClickItem && d.lineNumber ? "pointer" : "default"
|
|
1982
|
+
).attr("text-anchor", "middle").attr("transform", (d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`).attr("data-line-number", (d) => {
|
|
1983
|
+
const ln = d.lineNumber;
|
|
1984
|
+
return ln ? String(ln) : null;
|
|
1985
|
+
}).text((d) => d.text).on("click", (_event, d) => {
|
|
1986
|
+
const ln = d.lineNumber;
|
|
1987
|
+
if (onClickItem && ln) onClickItem(ln);
|
|
1988
|
+
});
|
|
1989
|
+
};
|
|
1990
|
+
if (!hasCanvas2d()) {
|
|
1991
|
+
draw(layoutWordsNoCanvas(sized, width, cloudHeight, sPadding, rotateFn));
|
|
1992
|
+
return;
|
|
1993
|
+
}
|
|
1994
|
+
cloud().size([width, cloudHeight]).words(sized).padding(sPadding).rotate(rotateFn).fontSize((d) => d.size).font(FONT_FAMILY).on("end", draw).start();
|
|
1995
|
+
}
|
|
1996
|
+
function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
|
|
1997
|
+
return new Promise((resolve) => {
|
|
1998
|
+
d3Selection3.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
1999
|
+
const { words, cloudOptions } = parsed;
|
|
2000
|
+
const title = parsed.noTitle ? null : parsed.title;
|
|
2001
|
+
if (words.length === 0) {
|
|
2002
|
+
resolve();
|
|
2003
|
+
return;
|
|
2004
|
+
}
|
|
2005
|
+
const width = exportDims?.width ?? container.clientWidth;
|
|
2006
|
+
const height = exportDims?.height ?? container.clientHeight;
|
|
2007
|
+
if (width <= 0 || height <= 0) {
|
|
2008
|
+
resolve();
|
|
2009
|
+
return;
|
|
2010
|
+
}
|
|
2011
|
+
const titleHeight = title ? 40 : 0;
|
|
2012
|
+
const cloudHeight = height - titleHeight;
|
|
2013
|
+
const textColor = palette.text;
|
|
2014
|
+
const bgColor = palette.bg;
|
|
2015
|
+
const colors = getSeriesColors(palette);
|
|
2016
|
+
const { minSize, maxSize } = cloudOptions;
|
|
2017
|
+
const weights = words.map((w) => w.weight);
|
|
2018
|
+
const minWeight = Math.min(...weights);
|
|
2019
|
+
const maxWeight = Math.max(...weights);
|
|
2020
|
+
const range = maxWeight - minWeight || 1;
|
|
2021
|
+
const fontSize = (weight) => {
|
|
2022
|
+
const t = (weight - minWeight) / range;
|
|
2023
|
+
return minSize + Math.sqrt(t) * (maxSize - minSize);
|
|
2024
|
+
};
|
|
2025
|
+
const rotateFn = getRotateFn(cloudOptions.rotate);
|
|
2026
|
+
const svg = d3Selection3.select(container).append("svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("preserveAspectRatio", "xMidYMid meet").style("background", bgColor);
|
|
2027
|
+
renderChartTitle(svg, title, parsed.titleLineNumber, width, textColor);
|
|
2028
|
+
const g = svg.append("g").attr(
|
|
2029
|
+
"transform",
|
|
2030
|
+
`translate(${width / 2},${titleHeight + cloudHeight / 2})`
|
|
2031
|
+
);
|
|
2032
|
+
const sized = words.map((w) => ({ ...w, size: fontSize(w.weight) }));
|
|
2033
|
+
const draw = (layoutWords) => {
|
|
2034
|
+
g.selectAll("text").data(layoutWords).join("text").style("font-size", (d) => `${d.size}px`).style("font-family", FONT_FAMILY).style("font-weight", "bold").style("fill", (_d, i) => colors[i % colors.length]).attr("text-anchor", "middle").attr(
|
|
2035
|
+
"transform",
|
|
2036
|
+
(d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`
|
|
2037
|
+
).text((d) => d.text);
|
|
2038
|
+
resolve();
|
|
2039
|
+
};
|
|
2040
|
+
if (!hasCanvas2d()) {
|
|
2041
|
+
draw(layoutWordsNoCanvas(sized, width, cloudHeight, 2, rotateFn));
|
|
2042
|
+
return;
|
|
2043
|
+
}
|
|
2044
|
+
cloud().size([width, cloudHeight]).words(sized).padding(2).rotate(rotateFn).fontSize((d) => d.size).font(FONT_FAMILY).on("end", draw).start();
|
|
2045
|
+
});
|
|
2119
2046
|
}
|
|
2047
|
+
|
|
2048
|
+
// src/utils/export-context.ts
|
|
2120
2049
|
function ctxTagOverride(ctx) {
|
|
2121
2050
|
return ctx.viewState?.tag ?? ctx.options?.tagGroup;
|
|
2122
2051
|
}
|
|
2123
|
-
async function exportEventLine(ctx) {
|
|
2124
|
-
const { content, theme, palette } = ctx;
|
|
2125
|
-
const { parseEventLine: parseEventLine2 } = await import("./parser-YG625J5H.js");
|
|
2126
|
-
const { renderEventLineForExport } = await import("./renderer-DVNMCYHZ.js");
|
|
2127
|
-
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2128
|
-
const parsed = parseEventLine2(content, effectivePalette);
|
|
2129
|
-
if (parsed.error || parsed.events.length === 0) return "";
|
|
2130
|
-
const container = createExportContainer(ctx.width, ctx.height);
|
|
2131
|
-
renderEventLineForExport(
|
|
2132
|
-
container,
|
|
2133
|
-
parsed,
|
|
2134
|
-
effectivePalette,
|
|
2135
|
-
ctx.isDark,
|
|
2136
|
-
{ width: ctx.width, height: ctx.height },
|
|
2137
|
-
ctxTagOverride(ctx),
|
|
2138
|
-
/* @__PURE__ */ new Date()
|
|
2139
|
-
);
|
|
2140
|
-
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2141
|
-
}
|
|
2142
|
-
async function exportBody(ctx) {
|
|
2143
|
-
const { content, theme, palette } = ctx;
|
|
2144
|
-
const { parseBody: parseBody2 } = await import("./parser-PEZ7RN43.js");
|
|
2145
|
-
const { renderBodyForExport } = await import("./renderer-2FVUPBGV.js");
|
|
2146
|
-
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2147
|
-
const parsed = parseBody2(content, effectivePalette);
|
|
2148
|
-
if (parsed.error) return "";
|
|
2149
|
-
const container = createExportContainer(ctx.width, ctx.height);
|
|
2150
|
-
renderBodyForExport(
|
|
2151
|
-
container,
|
|
2152
|
-
parsed,
|
|
2153
|
-
effectivePalette,
|
|
2154
|
-
ctx.isDark,
|
|
2155
|
-
{ width: ctx.width, height: ctx.height },
|
|
2156
|
-
ctxTagOverride(ctx)
|
|
2157
|
-
);
|
|
2158
|
-
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2159
|
-
}
|
|
2160
|
-
async function exportVersionControl(ctx) {
|
|
2161
|
-
const { content, theme, palette } = ctx;
|
|
2162
|
-
const { parseVersionControl: parseVersionControl2 } = await import("./parser-5UZV32ZI.js");
|
|
2163
|
-
const { renderVersionControlForExport } = await import("./renderer-DC7C5Q3G.js");
|
|
2164
|
-
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2165
|
-
const parsed = parseVersionControl2(content, effectivePalette);
|
|
2166
|
-
if (parsed.error || parsed.nodes.length === 0) return "";
|
|
2167
|
-
const container = createExportContainer(ctx.width, ctx.height);
|
|
2168
|
-
renderVersionControlForExport(
|
|
2169
|
-
container,
|
|
2170
|
-
parsed,
|
|
2171
|
-
effectivePalette,
|
|
2172
|
-
ctx.isDark,
|
|
2173
|
-
{
|
|
2174
|
-
width: ctx.width,
|
|
2175
|
-
height: ctx.height
|
|
2176
|
-
}
|
|
2177
|
-
);
|
|
2178
|
-
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2179
|
-
}
|
|
2180
2052
|
function unionHiddenAttributes(hideOption, ha) {
|
|
2181
2053
|
const sourceHidden = hideOption ? hideOption.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean) : [];
|
|
2182
2054
|
const union = /* @__PURE__ */ new Set([...sourceHidden, ...ha ?? []]);
|
|
2183
2055
|
return union.size > 0 ? union : void 0;
|
|
2184
2056
|
}
|
|
2185
|
-
|
|
2186
|
-
const
|
|
2187
|
-
const
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2193
|
-
const orgParsed = parseOrg2(content, effectivePalette);
|
|
2194
|
-
if (orgParsed.error) return "";
|
|
2195
|
-
const collapsedNodes = unionCollapsedOrgNodes(orgParsed, viewState?.cg);
|
|
2196
|
-
const activeTagGroup = resolveActiveTagGroup(
|
|
2197
|
-
orgParsed.tagGroups,
|
|
2198
|
-
orgParsed.options["active-tag"],
|
|
2199
|
-
ctxTagOverride(ctx)
|
|
2200
|
-
);
|
|
2201
|
-
const hiddenAttributes = unionHiddenAttributes(
|
|
2202
|
-
orgParsed.options["hide"],
|
|
2203
|
-
viewState?.ha
|
|
2204
|
-
);
|
|
2205
|
-
const collapseResult = collapsedNodes && collapsedNodes.size > 0 ? collapseOrgTree(orgParsed, collapsedNodes) : { parsed: orgParsed, hiddenCounts: /* @__PURE__ */ new Map() };
|
|
2206
|
-
const { hiddenCounts } = collapseResult;
|
|
2207
|
-
let effectiveParsed = collapseResult.parsed;
|
|
2208
|
-
let ancestorPath;
|
|
2209
|
-
const focusName = orgParsed.options["focus"];
|
|
2210
|
-
if (focusName) {
|
|
2211
|
-
const focusId = findOrgNodeIdByName(effectiveParsed.roots, focusName);
|
|
2212
|
-
const focused = focusId ? focusOrgTree(effectiveParsed, focusId) : null;
|
|
2213
|
-
if (focused) {
|
|
2214
|
-
effectiveParsed = focused.parsed;
|
|
2215
|
-
ancestorPath = focused.ancestorPath;
|
|
2216
|
-
}
|
|
2217
|
-
}
|
|
2218
|
-
const orgLayout = layoutOrg(
|
|
2219
|
-
effectiveParsed,
|
|
2220
|
-
hiddenCounts.size > 0 ? hiddenCounts : void 0,
|
|
2221
|
-
activeTagGroup,
|
|
2222
|
-
hiddenAttributes,
|
|
2223
|
-
false
|
|
2224
|
-
// expandAllLegend off — collapsed-by-default per §1.3
|
|
2225
|
-
);
|
|
2226
|
-
const PADDING = 20;
|
|
2227
|
-
const titleOffset = effectiveParsed.title ? 30 : 0;
|
|
2228
|
-
const rootIds = new Set(effectiveParsed.roots.map((r) => r.id));
|
|
2229
|
-
const rootTop = orgLayout.nodes.find((n) => rootIds.has(n.id))?.y ?? orgLayout.containers.find((c) => rootIds.has(c.nodeId))?.y ?? 0;
|
|
2230
|
-
const trailReserve = ancestorTrailReserve(ancestorPath?.length ?? 0, rootTop);
|
|
2231
|
-
const exportWidth = orgLayout.width + PADDING * 2;
|
|
2232
|
-
const exportHeight = orgLayout.height + PADDING * 2 + titleOffset + trailReserve;
|
|
2233
|
-
const container = createExportContainer(exportWidth, exportHeight);
|
|
2234
|
-
renderOrg(
|
|
2235
|
-
container,
|
|
2236
|
-
effectiveParsed,
|
|
2237
|
-
orgLayout,
|
|
2238
|
-
effectivePalette,
|
|
2239
|
-
isDark,
|
|
2240
|
-
void 0,
|
|
2241
|
-
{ width: exportWidth, height: exportHeight },
|
|
2242
|
-
activeTagGroup,
|
|
2243
|
-
hiddenAttributes,
|
|
2244
|
-
ancestorPath,
|
|
2245
|
-
exportMode
|
|
2246
|
-
);
|
|
2247
|
-
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2248
|
-
}
|
|
2249
|
-
async function exportSitemap(ctx) {
|
|
2250
|
-
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
2251
|
-
const { parseSitemap: parseSitemap2 } = await import("./parser-6TDWUKM5.js");
|
|
2252
|
-
const { layoutSitemap } = await import("./layout-ND26WVX2.js");
|
|
2253
|
-
const { collapseSitemapTree } = await import("./collapse-TCVK3RPO.js");
|
|
2254
|
-
const { renderSitemap } = await import("./renderer-J666LZXJ.js");
|
|
2255
|
-
const isDark = ctx.isDark;
|
|
2256
|
-
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2257
|
-
const sitemapParsed = parseSitemap2(content, effectivePalette);
|
|
2258
|
-
if (sitemapParsed.error || sitemapParsed.roots.length === 0) return "";
|
|
2259
|
-
const collapsedNodes = viewState?.cg ? new Set(viewState.cg) : void 0;
|
|
2260
|
-
const activeTagGroup = resolveActiveTagGroup(
|
|
2261
|
-
sitemapParsed.tagGroups,
|
|
2262
|
-
sitemapParsed.options["active-tag"],
|
|
2263
|
-
ctxTagOverride(ctx)
|
|
2264
|
-
);
|
|
2265
|
-
const hiddenAttributes = unionHiddenAttributes(
|
|
2266
|
-
sitemapParsed.options["hide"],
|
|
2267
|
-
viewState?.ha
|
|
2268
|
-
);
|
|
2269
|
-
const { parsed: effectiveParsed, hiddenCounts } = collapsedNodes && collapsedNodes.size > 0 ? collapseSitemapTree(sitemapParsed, collapsedNodes) : { parsed: sitemapParsed, hiddenCounts: /* @__PURE__ */ new Map() };
|
|
2270
|
-
const sitemapLayout = layoutSitemap(
|
|
2271
|
-
effectiveParsed,
|
|
2272
|
-
hiddenCounts.size > 0 ? hiddenCounts : void 0,
|
|
2273
|
-
activeTagGroup,
|
|
2274
|
-
hiddenAttributes,
|
|
2275
|
-
true
|
|
2276
|
-
);
|
|
2277
|
-
const PADDING = 20;
|
|
2278
|
-
const titleOffset = effectiveParsed.title ? 30 : 0;
|
|
2279
|
-
const {
|
|
2280
|
-
LEGEND_HEIGHT: SITEMAP_LEGEND_HEIGHT,
|
|
2281
|
-
LEGEND_GROUP_GAP: SITEMAP_LEGEND_GROUP_GAP
|
|
2282
|
-
} = await import("./legend-constants-55MFBXYF.js");
|
|
2283
|
-
const suppressedLegendBand = sitemapLayout.legend.length > 0 && effectiveParsed.options["no-legend"] === "on" ? SITEMAP_LEGEND_HEIGHT + SITEMAP_LEGEND_GROUP_GAP : 0;
|
|
2284
|
-
const exportWidth = sitemapLayout.width + PADDING * 2;
|
|
2285
|
-
const exportHeight = sitemapLayout.height + PADDING * 2 + titleOffset - suppressedLegendBand;
|
|
2286
|
-
const container = createExportContainer(exportWidth, exportHeight);
|
|
2287
|
-
renderSitemap(
|
|
2288
|
-
container,
|
|
2289
|
-
effectiveParsed,
|
|
2290
|
-
sitemapLayout,
|
|
2291
|
-
effectivePalette,
|
|
2292
|
-
isDark,
|
|
2293
|
-
void 0,
|
|
2294
|
-
{ width: exportWidth, height: exportHeight },
|
|
2295
|
-
activeTagGroup,
|
|
2296
|
-
hiddenAttributes,
|
|
2297
|
-
exportMode
|
|
2298
|
-
);
|
|
2299
|
-
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2300
|
-
}
|
|
2301
|
-
async function exportKanban(ctx) {
|
|
2302
|
-
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
2303
|
-
const { parseKanban: parseKanban2 } = await import("./parser-KLCSFQ3J.js");
|
|
2304
|
-
const { renderKanban } = await import("./renderer-5TZVFQ7K.js");
|
|
2305
|
-
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2306
|
-
const kanbanParsed = parseKanban2(content, effectivePalette);
|
|
2307
|
-
if (kanbanParsed.error || kanbanParsed.columns.length === 0) return "";
|
|
2308
|
-
const container = document.createElement("div");
|
|
2309
|
-
container.style.position = "absolute";
|
|
2310
|
-
container.style.left = "-9999px";
|
|
2311
|
-
document.body.appendChild(container);
|
|
2312
|
-
const kanbanCollapsedLanes = viewState?.cl ? new Set(viewState.cl) : void 0;
|
|
2313
|
-
const sourceCollapsedColumns = kanbanParsed.columns.filter((c) => c.collapsed).map((c) => c.id);
|
|
2314
|
-
const kanbanCollapsedColumns = viewState?.cc || sourceCollapsedColumns.length > 0 ? /* @__PURE__ */ new Set([...sourceCollapsedColumns, ...viewState?.cc ?? []]) : void 0;
|
|
2315
|
-
renderKanban(container, kanbanParsed, effectivePalette, ctx.isDark, {
|
|
2316
|
-
activeTagGroup: resolveActiveTagGroup(
|
|
2317
|
-
kanbanParsed.tagGroups,
|
|
2318
|
-
kanbanParsed.options["active-tag"],
|
|
2319
|
-
ctxTagOverride(ctx)
|
|
2320
|
-
),
|
|
2321
|
-
currentSwimlaneGroup: viewState?.swim ?? kanbanParsed.options["lane-by"] ?? null,
|
|
2322
|
-
...kanbanCollapsedLanes !== void 0 && {
|
|
2323
|
-
collapsedLanes: kanbanCollapsedLanes
|
|
2324
|
-
},
|
|
2325
|
-
...kanbanCollapsedColumns !== void 0 && {
|
|
2326
|
-
collapsedColumns: kanbanCollapsedColumns
|
|
2327
|
-
},
|
|
2328
|
-
...viewState?.cm !== void 0 && { compactMeta: viewState.cm },
|
|
2329
|
-
exportMode
|
|
2330
|
-
});
|
|
2331
|
-
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2332
|
-
}
|
|
2333
|
-
async function exportClass(ctx) {
|
|
2334
|
-
const { content, theme, palette, exportMode } = ctx;
|
|
2335
|
-
const { parseClassDiagram: parseClassDiagram2 } = await import("./parser-L6RWDXQN.js");
|
|
2336
|
-
const { layoutClassDiagram } = await import("./layout-S3RLVPH4.js");
|
|
2337
|
-
const { renderClassDiagram } = await import("./renderer-ZGY7P4BM.js");
|
|
2338
|
-
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2339
|
-
const classParsed = parseClassDiagram2(content, effectivePalette);
|
|
2340
|
-
if (classParsed.error || classParsed.classes.length === 0) return "";
|
|
2341
|
-
const classLayout = layoutClassDiagram(classParsed);
|
|
2342
|
-
const PADDING = 20;
|
|
2343
|
-
const titleOffset = classParsed.title ? 40 : 0;
|
|
2344
|
-
const exportWidth = classLayout.width + PADDING * 2;
|
|
2345
|
-
const exportHeight = classLayout.height + PADDING * 2 + titleOffset;
|
|
2346
|
-
const container = createExportContainer(exportWidth, exportHeight);
|
|
2347
|
-
renderClassDiagram(
|
|
2348
|
-
container,
|
|
2349
|
-
classParsed,
|
|
2350
|
-
classLayout,
|
|
2351
|
-
effectivePalette,
|
|
2352
|
-
ctx.isDark,
|
|
2353
|
-
void 0,
|
|
2354
|
-
{ width: exportWidth, height: exportHeight },
|
|
2355
|
-
void 0,
|
|
2356
|
-
exportMode
|
|
2357
|
-
);
|
|
2358
|
-
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2057
|
+
function beginVizExport(ctx) {
|
|
2058
|
+
const container = createExportContainer(ctx.width, ctx.height);
|
|
2059
|
+
const dims = {
|
|
2060
|
+
width: ctx.width,
|
|
2061
|
+
height: ctx.height
|
|
2062
|
+
};
|
|
2063
|
+
return { container, dims };
|
|
2359
2064
|
}
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
const {
|
|
2364
|
-
const
|
|
2065
|
+
|
|
2066
|
+
// src/arc/export.ts
|
|
2067
|
+
async function exportArc(ctx) {
|
|
2068
|
+
const { content, theme, palette } = ctx;
|
|
2069
|
+
const parsed = parseArc(content, palette);
|
|
2070
|
+
if (parsed.error || parsed.links.length === 0) return "";
|
|
2365
2071
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2366
|
-
const
|
|
2367
|
-
|
|
2368
|
-
const erLayout = layoutERDiagram(erParsed);
|
|
2369
|
-
const PADDING = 20;
|
|
2370
|
-
const titleOffset = erParsed.title ? 40 : 0;
|
|
2371
|
-
const exportWidth = erLayout.width + PADDING * 2;
|
|
2372
|
-
const exportHeight = erLayout.height + PADDING * 2 + titleOffset;
|
|
2373
|
-
const container = createExportContainer(exportWidth, exportHeight);
|
|
2374
|
-
renderERDiagram(
|
|
2072
|
+
const { container, dims } = beginVizExport(ctx);
|
|
2073
|
+
renderArcDiagram(
|
|
2375
2074
|
container,
|
|
2376
|
-
|
|
2377
|
-
erLayout,
|
|
2075
|
+
parsed,
|
|
2378
2076
|
effectivePalette,
|
|
2379
2077
|
ctx.isDark,
|
|
2380
2078
|
void 0,
|
|
2381
|
-
|
|
2382
|
-
resolveActiveTagGroup(
|
|
2383
|
-
erParsed.tagGroups,
|
|
2384
|
-
erParsed.options["active-tag"],
|
|
2385
|
-
ctxTagOverride(ctx)
|
|
2386
|
-
),
|
|
2387
|
-
// Semantic colors are on by default; the source `no-semantic-colors` flag
|
|
2388
|
-
// suppresses them. An interactive `viewState.sem` overrides source.
|
|
2389
|
-
viewState?.sem ?? (erParsed.options["no-semantic-colors"] === "on" ? false : void 0),
|
|
2390
|
-
exportMode
|
|
2079
|
+
dims
|
|
2391
2080
|
);
|
|
2392
2081
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2393
2082
|
}
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
const
|
|
2398
|
-
const
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
const
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2083
|
+
|
|
2084
|
+
// src/block/export.ts
|
|
2085
|
+
async function exportBlock(ctx) {
|
|
2086
|
+
const { content, theme, palette } = ctx;
|
|
2087
|
+
const { parseBlock: parseBlock2 } = await import("./parser-TUAEX6ML.js");
|
|
2088
|
+
const { renderBlockForExport } = await import("./renderer-ISQJ2ELA.js");
|
|
2089
|
+
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2090
|
+
const blockParsed = parseBlock2(content, effectivePalette);
|
|
2091
|
+
if (blockParsed.error || blockParsed.top.rows.length === 0) return "";
|
|
2092
|
+
const container = createExportContainer(ctx.width, ctx.height);
|
|
2093
|
+
renderBlockForExport(container, blockParsed, effectivePalette, ctx.isDark, {
|
|
2094
|
+
width: ctx.width,
|
|
2095
|
+
height: ctx.height
|
|
2407
2096
|
});
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
const
|
|
2414
|
-
|
|
2097
|
+
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
// src/body/export.ts
|
|
2101
|
+
async function exportBody(ctx) {
|
|
2102
|
+
const { content, theme, palette } = ctx;
|
|
2103
|
+
const { parseBody: parseBody2 } = await import("./parser-PEZ7RN43.js");
|
|
2104
|
+
const { renderBodyForExport } = await import("./renderer-AM7P4LN7.js");
|
|
2105
|
+
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2106
|
+
const parsed = parseBody2(content, effectivePalette);
|
|
2107
|
+
if (parsed.error) return "";
|
|
2108
|
+
const container = createExportContainer(ctx.width, ctx.height);
|
|
2109
|
+
renderBodyForExport(
|
|
2415
2110
|
container,
|
|
2416
2111
|
parsed,
|
|
2417
|
-
skLayout,
|
|
2418
2112
|
effectivePalette,
|
|
2419
2113
|
ctx.isDark,
|
|
2420
|
-
{
|
|
2421
|
-
|
|
2422
|
-
...exportMode !== void 0 && { exportMode },
|
|
2423
|
-
...viewState?.hd !== void 0 && { hideDescriptions: viewState.hd }
|
|
2424
|
-
}
|
|
2114
|
+
{ width: ctx.width, height: ctx.height },
|
|
2115
|
+
ctxTagOverride(ctx)
|
|
2425
2116
|
);
|
|
2426
2117
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2427
2118
|
}
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
const { parseWhiteboard: parseWhiteboard2 } = await import("./parser-XZUKNZPB.js");
|
|
2431
|
-
const effectivePalette = await resolveExportPalette(theme, ctx.palette);
|
|
2432
|
-
const parsed = parseWhiteboard2(content, effectivePalette);
|
|
2433
|
-
if (parsed.error || parsed.elements.length === 0) return "";
|
|
2434
|
-
const { renderWhiteboard } = await import("./renderer-ZHGHTSNG.js");
|
|
2435
|
-
const container = createExportContainer(1, 1);
|
|
2436
|
-
const resolveImage = ctx.options?.resolveImage;
|
|
2437
|
-
const showNotes = ctx.options?.showNotes;
|
|
2438
|
-
renderWhiteboard(container, parsed, effectivePalette, ctx.isDark, {
|
|
2439
|
-
...resolveImage !== void 0 && { resolveImage },
|
|
2440
|
-
...showNotes !== void 0 && { showNotes }
|
|
2441
|
-
});
|
|
2442
|
-
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2443
|
-
}
|
|
2119
|
+
|
|
2120
|
+
// src/boxes-and-lines/export.ts
|
|
2444
2121
|
async function exportBoxesAndLines(ctx) {
|
|
2445
2122
|
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
2446
|
-
const { parseBoxesAndLines: parseBoxesAndLines2 } = await import("./parser-
|
|
2123
|
+
const { parseBoxesAndLines: parseBoxesAndLines2 } = await import("./parser-7QKQ4P4P.js");
|
|
2447
2124
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2448
2125
|
const blParsed = parseBoxesAndLines2(content, effectivePalette);
|
|
2449
2126
|
if (blParsed.error || blParsed.nodes.length === 0) return "";
|
|
@@ -2454,8 +2131,8 @@ async function exportBoxesAndLines(ctx) {
|
|
|
2454
2131
|
blHiddenTagValues.set(k, new Set(v));
|
|
2455
2132
|
}
|
|
2456
2133
|
}
|
|
2457
|
-
const { renderBoxesAndLinesForExport } = await import("./renderer-
|
|
2458
|
-
const { layoutBoxesAndLines } = await import("./layout-
|
|
2134
|
+
const { renderBoxesAndLinesForExport } = await import("./renderer-LNP23NSM.js");
|
|
2135
|
+
const { layoutBoxesAndLines } = await import("./layout-U3AH6M7J.js");
|
|
2459
2136
|
const blLayout = await layoutBoxesAndLines(blParsed);
|
|
2460
2137
|
const PADDING = 20;
|
|
2461
2138
|
const titleOffset = blParsed.title ? 40 : 0;
|
|
@@ -2482,311 +2159,246 @@ async function exportBoxesAndLines(ctx) {
|
|
|
2482
2159
|
);
|
|
2483
2160
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2484
2161
|
}
|
|
2485
|
-
|
|
2162
|
+
|
|
2163
|
+
// src/bracket/export.ts
|
|
2164
|
+
async function exportBracket(ctx) {
|
|
2486
2165
|
const { content, theme, palette } = ctx;
|
|
2487
|
-
const {
|
|
2488
|
-
const {
|
|
2489
|
-
const { renderSwimlaneForExport } = await import("./renderer-OAR5VPH4.js");
|
|
2166
|
+
const { parseBracket: parseBracket2 } = await import("./parser-RTWPFKXG.js");
|
|
2167
|
+
const { renderBracketForExport, bracketExportDimensions } = await import("./renderer-2LYX6NHN.js");
|
|
2490
2168
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2491
|
-
const
|
|
2492
|
-
if (
|
|
2493
|
-
const
|
|
2494
|
-
const
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
renderSwimlaneForExport(
|
|
2500
|
-
container,
|
|
2501
|
-
swimParsed,
|
|
2502
|
-
swimLayout,
|
|
2503
|
-
effectivePalette,
|
|
2504
|
-
ctx.isDark,
|
|
2505
|
-
{
|
|
2506
|
-
exportDims: { width: exportWidth, height: exportHeight },
|
|
2507
|
-
activeTagGroup: resolveActiveTagGroup(
|
|
2508
|
-
swimParsed.tagGroups,
|
|
2509
|
-
swimParsed.options["active-tag"],
|
|
2510
|
-
ctxTagOverride(ctx)
|
|
2511
|
-
),
|
|
2512
|
-
exportMode: ctx.exportMode
|
|
2513
|
-
}
|
|
2514
|
-
);
|
|
2169
|
+
const parsed = parseBracket2(content, effectivePalette);
|
|
2170
|
+
if (parsed.error) return "";
|
|
2171
|
+
const { width, height } = bracketExportDimensions(parsed, effectivePalette);
|
|
2172
|
+
const container = createExportContainer(width, height);
|
|
2173
|
+
renderBracketForExport(container, parsed, effectivePalette, ctx.isDark, {
|
|
2174
|
+
width,
|
|
2175
|
+
height
|
|
2176
|
+
});
|
|
2515
2177
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2516
2178
|
}
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
const {
|
|
2521
|
-
const {
|
|
2179
|
+
|
|
2180
|
+
// src/c4/export.ts
|
|
2181
|
+
async function exportC4(ctx) {
|
|
2182
|
+
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
2183
|
+
const { parseC4: parseC42 } = await import("./parser-4Y6PODW6.js");
|
|
2184
|
+
const {
|
|
2185
|
+
layoutC4Context,
|
|
2186
|
+
layoutC4Containers,
|
|
2187
|
+
layoutC4Components,
|
|
2188
|
+
layoutC4Deployment
|
|
2189
|
+
} = await import("./layout-JTIRCKAW.js");
|
|
2190
|
+
const { renderC4Context, renderC4Containers } = await import("./renderer-QTPWRRJ7.js");
|
|
2522
2191
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2523
|
-
const
|
|
2524
|
-
if (
|
|
2525
|
-
const
|
|
2192
|
+
const c4Parsed = parseC42(content, effectivePalette);
|
|
2193
|
+
if (c4Parsed.error || c4Parsed.elements.length === 0) return "";
|
|
2194
|
+
const c4Level = ctx.options?.c4Level ?? viewState?.c4l ?? "context";
|
|
2195
|
+
const c4System = ctx.options?.c4System ?? viewState?.c4s;
|
|
2196
|
+
const c4Container = ctx.options?.c4Container ?? viewState?.c4c;
|
|
2197
|
+
const c4Layout = c4Level === "deployment" ? layoutC4Deployment(c4Parsed) : c4Level === "components" && c4System && c4Container ? layoutC4Components(c4Parsed, c4System, c4Container) : c4Level === "containers" && c4System ? layoutC4Containers(c4Parsed, c4System) : layoutC4Context(c4Parsed);
|
|
2198
|
+
if (c4Layout.nodes.length === 0) return "";
|
|
2526
2199
|
const PADDING = 20;
|
|
2527
|
-
const titleOffset =
|
|
2528
|
-
const exportWidth =
|
|
2529
|
-
const exportHeight =
|
|
2200
|
+
const titleOffset = c4Parsed.title ? 40 : 0;
|
|
2201
|
+
const exportWidth = c4Layout.width + PADDING * 2;
|
|
2202
|
+
const exportHeight = c4Layout.height + PADDING * 2 + titleOffset;
|
|
2530
2203
|
const container = createExportContainer(exportWidth, exportHeight);
|
|
2531
|
-
|
|
2204
|
+
const renderFn = c4Level === "deployment" || c4Level === "components" && c4System && c4Container || c4Level === "containers" && c4System ? renderC4Containers : renderC4Context;
|
|
2205
|
+
renderFn(
|
|
2532
2206
|
container,
|
|
2533
|
-
|
|
2534
|
-
|
|
2207
|
+
c4Parsed,
|
|
2208
|
+
c4Layout,
|
|
2535
2209
|
effectivePalette,
|
|
2536
2210
|
ctx.isDark,
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
}
|
|
2211
|
+
void 0,
|
|
2212
|
+
{ width: exportWidth, height: exportHeight },
|
|
2213
|
+
resolveActiveTagGroup(
|
|
2214
|
+
c4Parsed.tagGroups,
|
|
2215
|
+
c4Parsed.options["active-tag"],
|
|
2216
|
+
ctxTagOverride(ctx)
|
|
2217
|
+
),
|
|
2218
|
+
exportMode
|
|
2546
2219
|
);
|
|
2547
2220
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2548
2221
|
}
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
const {
|
|
2553
|
-
const {
|
|
2554
|
-
const {
|
|
2555
|
-
const
|
|
2222
|
+
|
|
2223
|
+
// src/class/export.ts
|
|
2224
|
+
async function exportClass(ctx) {
|
|
2225
|
+
const { content, theme, palette, exportMode } = ctx;
|
|
2226
|
+
const { parseClassDiagram: parseClassDiagram2 } = await import("./parser-TAYRTCPR.js");
|
|
2227
|
+
const { layoutClassDiagram } = await import("./layout-IT4ZTV6C.js");
|
|
2228
|
+
const { renderClassDiagram } = await import("./renderer-OUDHH5MV.js");
|
|
2556
2229
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2557
|
-
const
|
|
2558
|
-
if (
|
|
2559
|
-
const
|
|
2560
|
-
const collectCollapsed = (nodes) => {
|
|
2561
|
-
for (const n of nodes) {
|
|
2562
|
-
if (n.collapsed) collapsedNodes.add(n.id);
|
|
2563
|
-
if (n.children.length) collectCollapsed(n.children);
|
|
2564
|
-
}
|
|
2565
|
-
};
|
|
2566
|
-
collectCollapsed(mmParsed.roots);
|
|
2567
|
-
const activeTagGroup = resolveActiveTagGroup(
|
|
2568
|
-
mmParsed.tagGroups,
|
|
2569
|
-
mmParsed.options["active-tag"],
|
|
2570
|
-
ctxTagOverride(ctx)
|
|
2571
|
-
);
|
|
2572
|
-
const hideDescriptions = mmParsed.options["no-descriptions"] === "true" || viewState?.hd === true;
|
|
2573
|
-
const { roots: effectiveRoots, hiddenCounts } = collapsedNodes && collapsedNodes.size > 0 ? collapseMindmapTree(mmParsed.roots, collapsedNodes) : { roots: mmParsed.roots, hiddenCounts: /* @__PURE__ */ new Map() };
|
|
2574
|
-
const effectiveParsed = { ...mmParsed, roots: effectiveRoots };
|
|
2575
|
-
const mmLayout = layoutMindmap(effectiveParsed, effectivePalette, {
|
|
2576
|
-
interactive: false,
|
|
2577
|
-
...hiddenCounts.size > 0 && { hiddenCounts },
|
|
2578
|
-
activeTagGroup,
|
|
2579
|
-
hideDescriptions
|
|
2580
|
-
});
|
|
2230
|
+
const classParsed = parseClassDiagram2(content, effectivePalette);
|
|
2231
|
+
if (classParsed.error || classParsed.classes.length === 0) return "";
|
|
2232
|
+
const classLayout = layoutClassDiagram(classParsed);
|
|
2581
2233
|
const PADDING = 20;
|
|
2582
|
-
const titleOffset =
|
|
2583
|
-
const exportWidth =
|
|
2584
|
-
const exportHeight =
|
|
2234
|
+
const titleOffset = classParsed.title ? 40 : 0;
|
|
2235
|
+
const exportWidth = classLayout.width + PADDING * 2;
|
|
2236
|
+
const exportHeight = classLayout.height + PADDING * 2 + titleOffset;
|
|
2585
2237
|
const container = createExportContainer(exportWidth, exportHeight);
|
|
2586
|
-
|
|
2587
|
-
renderMindmap(
|
|
2238
|
+
renderClassDiagram(
|
|
2588
2239
|
container,
|
|
2589
|
-
|
|
2590
|
-
|
|
2240
|
+
classParsed,
|
|
2241
|
+
classLayout,
|
|
2591
2242
|
effectivePalette,
|
|
2592
|
-
isDark,
|
|
2243
|
+
ctx.isDark,
|
|
2593
2244
|
void 0,
|
|
2594
2245
|
{ width: exportWidth, height: exportHeight },
|
|
2595
2246
|
void 0,
|
|
2596
|
-
|
|
2597
|
-
colorByDepth ? null : activeTagGroup,
|
|
2598
|
-
colorByDepth ? { colorByDepth: true, exportMode } : { exportMode }
|
|
2247
|
+
exportMode
|
|
2599
2248
|
);
|
|
2600
2249
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2601
2250
|
}
|
|
2602
|
-
|
|
2251
|
+
|
|
2252
|
+
// src/clock/export.ts
|
|
2253
|
+
async function exportClock(ctx) {
|
|
2603
2254
|
const { content, theme, palette } = ctx;
|
|
2604
|
-
const {
|
|
2605
|
-
const {
|
|
2606
|
-
const { renderWireframe } = await import("./renderer-36446HSH.js");
|
|
2255
|
+
const { parseClock: parseClock2 } = await import("./parser-K2DI26SC.js");
|
|
2256
|
+
const { renderClockForExport } = await import("./renderer-DDWDCM2K.js");
|
|
2607
2257
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2608
|
-
const
|
|
2609
|
-
if (
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2258
|
+
const parsed = parseClock2(content, effectivePalette);
|
|
2259
|
+
if (parsed.error) return "";
|
|
2260
|
+
const container = createExportContainer(ctx.width, ctx.height);
|
|
2261
|
+
renderClockForExport(container, parsed, effectivePalette, ctx.isDark, {
|
|
2262
|
+
width: ctx.width,
|
|
2263
|
+
height: ctx.height
|
|
2264
|
+
});
|
|
2265
|
+
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
// src/countdown/export.ts
|
|
2269
|
+
async function exportCountdown(ctx) {
|
|
2270
|
+
const { content, theme, palette } = ctx;
|
|
2271
|
+
const { parseCountdown: parseCountdown2 } = await import("./parser-KJPPUN4D.js");
|
|
2272
|
+
const { renderCountdownForExport } = await import("./renderer-3NLDX7DQ.js");
|
|
2273
|
+
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2274
|
+
const parsed = parseCountdown2(content, effectivePalette);
|
|
2275
|
+
if (parsed.error) return "";
|
|
2276
|
+
const container = createExportContainer(ctx.width, ctx.height);
|
|
2277
|
+
renderCountdownForExport(container, parsed, effectivePalette, ctx.isDark, {
|
|
2278
|
+
width: ctx.width,
|
|
2279
|
+
height: ctx.height
|
|
2280
|
+
});
|
|
2281
|
+
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
// src/cycle/export.ts
|
|
2285
|
+
async function exportCycle(ctx) {
|
|
2286
|
+
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
2287
|
+
const { parseCycle: parseCycle2 } = await import("./parser-RCIEKN7Y.js");
|
|
2288
|
+
const { renderCycleForExport } = await import("./renderer-7OGGV327.js");
|
|
2289
|
+
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2290
|
+
const cycleParsed = parseCycle2(content);
|
|
2291
|
+
if (cycleParsed.error || cycleParsed.nodes.length === 0) return "";
|
|
2292
|
+
const container = createExportContainer(ctx.width, ctx.height);
|
|
2293
|
+
renderCycleForExport(
|
|
2616
2294
|
container,
|
|
2617
|
-
|
|
2618
|
-
wireframeLayout,
|
|
2295
|
+
cycleParsed,
|
|
2619
2296
|
effectivePalette,
|
|
2620
2297
|
ctx.isDark,
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2298
|
+
{ width: ctx.width, height: ctx.height },
|
|
2299
|
+
viewState,
|
|
2300
|
+
exportMode
|
|
2624
2301
|
);
|
|
2625
2302
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2626
2303
|
}
|
|
2627
|
-
|
|
2304
|
+
|
|
2305
|
+
// src/er/export.ts
|
|
2306
|
+
async function exportEr(ctx) {
|
|
2628
2307
|
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
2629
|
-
const {
|
|
2630
|
-
const {
|
|
2631
|
-
|
|
2632
|
-
layoutC4Containers,
|
|
2633
|
-
layoutC4Components,
|
|
2634
|
-
layoutC4Deployment
|
|
2635
|
-
} = await import("./layout-JTIRCKAW.js");
|
|
2636
|
-
const { renderC4Context, renderC4Containers } = await import("./renderer-VPIELEE5.js");
|
|
2308
|
+
const { parseERDiagram: parseERDiagram2 } = await import("./parser-4RFY7D52.js");
|
|
2309
|
+
const { layoutERDiagram } = await import("./layout-ISSBWBH7.js");
|
|
2310
|
+
const { renderERDiagram } = await import("./renderer-J3GPDK73.js");
|
|
2637
2311
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2638
|
-
const
|
|
2639
|
-
if (
|
|
2640
|
-
const
|
|
2641
|
-
const c4System = ctx.options?.c4System ?? viewState?.c4s;
|
|
2642
|
-
const c4Container = ctx.options?.c4Container ?? viewState?.c4c;
|
|
2643
|
-
const c4Layout = c4Level === "deployment" ? layoutC4Deployment(c4Parsed) : c4Level === "components" && c4System && c4Container ? layoutC4Components(c4Parsed, c4System, c4Container) : c4Level === "containers" && c4System ? layoutC4Containers(c4Parsed, c4System) : layoutC4Context(c4Parsed);
|
|
2644
|
-
if (c4Layout.nodes.length === 0) return "";
|
|
2312
|
+
const erParsed = parseERDiagram2(content, effectivePalette);
|
|
2313
|
+
if (erParsed.error || erParsed.tables.length === 0) return "";
|
|
2314
|
+
const erLayout = layoutERDiagram(erParsed);
|
|
2645
2315
|
const PADDING = 20;
|
|
2646
|
-
const titleOffset =
|
|
2647
|
-
const exportWidth =
|
|
2648
|
-
const exportHeight =
|
|
2316
|
+
const titleOffset = erParsed.title ? 40 : 0;
|
|
2317
|
+
const exportWidth = erLayout.width + PADDING * 2;
|
|
2318
|
+
const exportHeight = erLayout.height + PADDING * 2 + titleOffset;
|
|
2649
2319
|
const container = createExportContainer(exportWidth, exportHeight);
|
|
2650
|
-
|
|
2651
|
-
renderFn(
|
|
2320
|
+
renderERDiagram(
|
|
2652
2321
|
container,
|
|
2653
|
-
|
|
2654
|
-
|
|
2322
|
+
erParsed,
|
|
2323
|
+
erLayout,
|
|
2655
2324
|
effectivePalette,
|
|
2656
2325
|
ctx.isDark,
|
|
2657
2326
|
void 0,
|
|
2658
2327
|
{ width: exportWidth, height: exportHeight },
|
|
2659
2328
|
resolveActiveTagGroup(
|
|
2660
|
-
|
|
2661
|
-
|
|
2329
|
+
erParsed.tagGroups,
|
|
2330
|
+
erParsed.options["active-tag"],
|
|
2662
2331
|
ctxTagOverride(ctx)
|
|
2663
2332
|
),
|
|
2333
|
+
// Semantic colors are on by default; the source `no-semantic-colors` flag
|
|
2334
|
+
// suppresses them. An interactive `viewState.sem` overrides source.
|
|
2335
|
+
viewState?.sem ?? (erParsed.options["no-semantic-colors"] === "on" ? false : void 0),
|
|
2664
2336
|
exportMode
|
|
2665
2337
|
);
|
|
2666
2338
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2667
2339
|
}
|
|
2668
|
-
|
|
2340
|
+
|
|
2341
|
+
// src/event-line/export.ts
|
|
2342
|
+
async function exportEventLine(ctx) {
|
|
2669
2343
|
const { content, theme, palette } = ctx;
|
|
2670
|
-
const {
|
|
2671
|
-
const {
|
|
2672
|
-
const { renderFlowchart } = await import("./flowchart-renderer-6MGGX4RC.js");
|
|
2344
|
+
const { parseEventLine: parseEventLine2 } = await import("./parser-YG625J5H.js");
|
|
2345
|
+
const { renderEventLineForExport } = await import("./renderer-J7ZSTJUE.js");
|
|
2673
2346
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2674
|
-
const
|
|
2675
|
-
if (
|
|
2676
|
-
const layout = layoutGraph(fcParsed);
|
|
2347
|
+
const parsed = parseEventLine2(content, effectivePalette);
|
|
2348
|
+
if (parsed.error || parsed.events.length === 0) return "";
|
|
2677
2349
|
const container = createExportContainer(ctx.width, ctx.height);
|
|
2678
|
-
|
|
2350
|
+
renderEventLineForExport(
|
|
2679
2351
|
container,
|
|
2680
|
-
|
|
2681
|
-
layout,
|
|
2352
|
+
parsed,
|
|
2682
2353
|
effectivePalette,
|
|
2683
2354
|
ctx.isDark,
|
|
2684
|
-
|
|
2685
|
-
|
|
2355
|
+
{ width: ctx.width, height: ctx.height },
|
|
2356
|
+
ctxTagOverride(ctx),
|
|
2357
|
+
/* @__PURE__ */ new Date()
|
|
2686
2358
|
);
|
|
2687
2359
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2688
2360
|
}
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
const {
|
|
2693
|
-
const {
|
|
2694
|
-
const {
|
|
2361
|
+
|
|
2362
|
+
// src/family/export.ts
|
|
2363
|
+
async function exportFamily(ctx) {
|
|
2364
|
+
const { content, theme, palette } = ctx;
|
|
2365
|
+
const { parseFamily: parseFamily2 } = await import("./parser-EAQPZX2B.js");
|
|
2366
|
+
const { layoutFamily } = await import("./layout-3TSVAGWH.js");
|
|
2367
|
+
const { renderFamilyForExport } = await import("./renderer-XCLARXCK.js");
|
|
2695
2368
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2696
|
-
const
|
|
2697
|
-
if (
|
|
2698
|
-
const
|
|
2699
|
-
const
|
|
2700
|
-
const
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
ctxTagOverride(ctx)
|
|
2704
|
-
);
|
|
2705
|
-
const showInfraTitle = !!infraParsed.title && infraParsed.options["no-title"] !== "on";
|
|
2706
|
-
const titleOffset = showInfraTitle ? 40 : 0;
|
|
2707
|
-
const infraTagGroups = [...infraParsed.tagGroups];
|
|
2708
|
-
const legendGroups = computeInfraLegendGroups(
|
|
2709
|
-
infraLayout.nodes,
|
|
2710
|
-
infraTagGroups,
|
|
2711
|
-
effectivePalette
|
|
2712
|
-
);
|
|
2713
|
-
const legendOffset = legendGroups.length > 0 && infraParsed.options["no-legend"] !== "on" ? 28 : 0;
|
|
2714
|
-
const exportWidth = infraLayout.width;
|
|
2715
|
-
const exportHeight = infraLayout.height + titleOffset + legendOffset;
|
|
2369
|
+
const parsed = parseFamily2(content, effectivePalette);
|
|
2370
|
+
if (parsed.error || parsed.persons.size === 0) return "";
|
|
2371
|
+
const layout = layoutFamily(parsed);
|
|
2372
|
+
const PADDING = 20;
|
|
2373
|
+
const titleOffset = parsed.title ? 40 : 0;
|
|
2374
|
+
const exportWidth = layout.width + PADDING * 2;
|
|
2375
|
+
const exportHeight = layout.height + PADDING * 2 + titleOffset;
|
|
2716
2376
|
const container = createExportContainer(exportWidth, exportHeight);
|
|
2717
|
-
|
|
2718
|
-
container,
|
|
2719
|
-
infraLayout,
|
|
2720
|
-
effectivePalette,
|
|
2721
|
-
ctx.isDark,
|
|
2722
|
-
showInfraTitle ? infraParsed.title : null,
|
|
2723
|
-
showInfraTitle ? infraParsed.titleLineNumber : null,
|
|
2724
|
-
infraTagGroups,
|
|
2725
|
-
activeTagGroup,
|
|
2726
|
-
false,
|
|
2727
|
-
null,
|
|
2728
|
-
null,
|
|
2729
|
-
true,
|
|
2730
|
-
viewState?.cg ? new Set(viewState.cg) : null
|
|
2731
|
-
);
|
|
2732
|
-
const infraSvg = container.querySelector("svg");
|
|
2733
|
-
if (infraSvg) {
|
|
2734
|
-
infraSvg.setAttribute("width", String(exportWidth));
|
|
2735
|
-
infraSvg.setAttribute("height", String(exportHeight));
|
|
2736
|
-
}
|
|
2737
|
-
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2738
|
-
}
|
|
2739
|
-
async function exportPert(ctx) {
|
|
2740
|
-
const { content, theme, palette, viewState } = ctx;
|
|
2741
|
-
const { parsePert: parsePert2 } = await import("./parser-2IKPQVKX.js");
|
|
2742
|
-
const { analyzePert } = await import("./analyzer-G7PGOT3V.js");
|
|
2743
|
-
const { layoutPert } = await import("./layout-KV27UW25.js");
|
|
2744
|
-
const { renderPert, measurePertAnalysisBlock } = await import("./renderer-O6DY46AV.js");
|
|
2745
|
-
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2746
|
-
const pertParsed = parsePert2(content, { palette: effectivePalette });
|
|
2747
|
-
if (pertParsed.error || pertParsed.activities.length === 0) return "";
|
|
2748
|
-
const pertResolved = analyzePert(pertParsed);
|
|
2749
|
-
const pertLayout = layoutPert(pertResolved);
|
|
2750
|
-
const hasTitle = !!pertParsed.title && !pertParsed.options.noTitle;
|
|
2751
|
-
const hasSubtitle = pertResolved.projectSubtitle !== null;
|
|
2752
|
-
const titleHeight = hasTitle ? 80 : hasSubtitle ? 50 : 0;
|
|
2753
|
-
const PERT_PADDING = 20;
|
|
2754
|
-
const analysisOn = viewState?.an ?? !pertParsed.options.noAnalysis;
|
|
2755
|
-
const fieldLabelsOn = viewState?.fl === true;
|
|
2756
|
-
const exportW = pertLayout.width + PERT_PADDING * 2;
|
|
2757
|
-
const analysisMeasured = measurePertAnalysisBlock(
|
|
2758
|
-
pertResolved,
|
|
2759
|
-
exportW - 2 * PERT_PADDING,
|
|
2760
|
-
{
|
|
2761
|
-
showTornado: analysisOn,
|
|
2762
|
-
showScurve: analysisOn,
|
|
2763
|
-
showFieldLegend: fieldLabelsOn
|
|
2764
|
-
}
|
|
2765
|
-
);
|
|
2766
|
-
const exportH = pertLayout.height + PERT_PADDING * 2 + titleHeight + analysisMeasured.height;
|
|
2767
|
-
const container = createExportContainer(exportW, exportH);
|
|
2768
|
-
renderPert(
|
|
2377
|
+
renderFamilyForExport(
|
|
2769
2378
|
container,
|
|
2770
|
-
|
|
2771
|
-
|
|
2379
|
+
parsed,
|
|
2380
|
+
layout,
|
|
2772
2381
|
effectivePalette,
|
|
2773
2382
|
ctx.isDark,
|
|
2774
2383
|
{
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2384
|
+
exportDims: { width: exportWidth, height: exportHeight },
|
|
2385
|
+
activeTagGroup: resolveActiveTagGroup(
|
|
2386
|
+
parsed.tagGroups,
|
|
2387
|
+
parsed.options["active-tag"],
|
|
2388
|
+
ctxTagOverride(ctx)
|
|
2389
|
+
),
|
|
2390
|
+
exportMode: ctx.exportMode
|
|
2781
2391
|
}
|
|
2782
2392
|
);
|
|
2783
2393
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2784
2394
|
}
|
|
2395
|
+
|
|
2396
|
+
// src/gantt/export.ts
|
|
2785
2397
|
async function exportGantt(ctx) {
|
|
2786
2398
|
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
2787
|
-
const { parseGantt: parseGantt2 } = await import("./parser-
|
|
2399
|
+
const { parseGantt: parseGantt2 } = await import("./parser-A3AN76RQ.js");
|
|
2788
2400
|
const { calculateSchedule } = await import("./calculator-BNH3GSJE.js");
|
|
2789
|
-
const { renderGantt } = await import("./renderer-
|
|
2401
|
+
const { renderGantt } = await import("./renderer-JYHA6R2D.js");
|
|
2790
2402
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2791
2403
|
const ganttParsed = parseGantt2(content, effectivePalette);
|
|
2792
2404
|
const resolved = calculateSchedule(ganttParsed);
|
|
@@ -2825,11 +2437,50 @@ async function exportGantt(ctx) {
|
|
|
2825
2437
|
);
|
|
2826
2438
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2827
2439
|
}
|
|
2440
|
+
|
|
2441
|
+
// src/goal/export.ts
|
|
2442
|
+
async function exportGoal(ctx) {
|
|
2443
|
+
const { content, theme, palette } = ctx;
|
|
2444
|
+
const { parseGoal: parseGoal2 } = await import("./parser-3QIFY5IN.js");
|
|
2445
|
+
const { renderGoalForExport } = await import("./renderer-HX6ICPDX.js");
|
|
2446
|
+
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2447
|
+
const parsed = parseGoal2(content, effectivePalette);
|
|
2448
|
+
if (parsed.error) return "";
|
|
2449
|
+
const container = createExportContainer(ctx.width, ctx.height);
|
|
2450
|
+
renderGoalForExport(container, parsed, effectivePalette, ctx.isDark, {
|
|
2451
|
+
width: ctx.width,
|
|
2452
|
+
height: ctx.height
|
|
2453
|
+
});
|
|
2454
|
+
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2455
|
+
}
|
|
2456
|
+
|
|
2457
|
+
// src/graph/export.ts
|
|
2458
|
+
async function exportFlowchart(ctx) {
|
|
2459
|
+
const { content, theme, palette } = ctx;
|
|
2460
|
+
const { parseFlowchart: parseFlowchart2 } = await import("./flowchart-parser-NZXASOZG.js");
|
|
2461
|
+
const { layoutGraph } = await import("./layout-VC3MXRB4.js");
|
|
2462
|
+
const { renderFlowchart } = await import("./flowchart-renderer-PTCRIANF.js");
|
|
2463
|
+
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2464
|
+
const fcParsed = parseFlowchart2(content, effectivePalette);
|
|
2465
|
+
if (fcParsed.error || fcParsed.nodes.length === 0) return "";
|
|
2466
|
+
const layout = layoutGraph(fcParsed);
|
|
2467
|
+
const container = createExportContainer(ctx.width, ctx.height);
|
|
2468
|
+
renderFlowchart(
|
|
2469
|
+
container,
|
|
2470
|
+
fcParsed,
|
|
2471
|
+
layout,
|
|
2472
|
+
effectivePalette,
|
|
2473
|
+
ctx.isDark,
|
|
2474
|
+
void 0,
|
|
2475
|
+
{ width: ctx.width, height: ctx.height }
|
|
2476
|
+
);
|
|
2477
|
+
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2478
|
+
}
|
|
2828
2479
|
async function exportState(ctx) {
|
|
2829
2480
|
const { content, theme, palette, viewState } = ctx;
|
|
2830
|
-
const { parseState: parseState2 } = await import("./state-parser-
|
|
2831
|
-
const { layoutGraph } = await import("./layout-
|
|
2832
|
-
const { renderState } = await import("./state-renderer-
|
|
2481
|
+
const { parseState: parseState2 } = await import("./state-parser-KPVW5CRI.js");
|
|
2482
|
+
const { layoutGraph } = await import("./layout-VC3MXRB4.js");
|
|
2483
|
+
const { renderState } = await import("./state-renderer-ZVEI265C.js");
|
|
2833
2484
|
const { collapseStateGroups } = await import("./state-collapse-SE2G4K4I.js");
|
|
2834
2485
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2835
2486
|
const stateParsed = parseState2(content, effectivePalette);
|
|
@@ -2864,31 +2515,64 @@ async function exportState(ctx) {
|
|
|
2864
2515
|
);
|
|
2865
2516
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2866
2517
|
}
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
const {
|
|
2518
|
+
|
|
2519
|
+
// src/infra/export.ts
|
|
2520
|
+
async function exportInfra(ctx) {
|
|
2521
|
+
const { content, theme, palette, viewState } = ctx;
|
|
2522
|
+
const { parseInfra: parseInfra2 } = await import("./parser-F7NDRPMA.js");
|
|
2523
|
+
const { computeInfra } = await import("./compute-II4G44IK.js");
|
|
2524
|
+
const { layoutInfra } = await import("./layout-2WESJYRE.js");
|
|
2525
|
+
const { renderInfra, computeInfraLegendGroups } = await import("./renderer-UTEEJDGB.js");
|
|
2871
2526
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2872
|
-
const
|
|
2873
|
-
if (
|
|
2874
|
-
const
|
|
2875
|
-
const
|
|
2876
|
-
const
|
|
2877
|
-
|
|
2527
|
+
const infraParsed = parseInfra2(content);
|
|
2528
|
+
if (infraParsed.error || infraParsed.nodes.length === 0) return "";
|
|
2529
|
+
const infraComputed = computeInfra(infraParsed);
|
|
2530
|
+
const infraLayout = layoutInfra(infraComputed);
|
|
2531
|
+
const activeTagGroup = resolveActiveTagGroup(
|
|
2532
|
+
infraParsed.tagGroups,
|
|
2533
|
+
infraParsed.options["active-tag"],
|
|
2534
|
+
ctxTagOverride(ctx)
|
|
2535
|
+
);
|
|
2536
|
+
const showInfraTitle = !!infraParsed.title && infraParsed.options["no-title"] !== "on";
|
|
2537
|
+
const titleOffset = showInfraTitle ? 40 : 0;
|
|
2538
|
+
const infraTagGroups = [...infraParsed.tagGroups];
|
|
2539
|
+
const legendGroups = computeInfraLegendGroups(
|
|
2540
|
+
infraLayout.nodes,
|
|
2541
|
+
infraTagGroups,
|
|
2542
|
+
effectivePalette
|
|
2543
|
+
);
|
|
2544
|
+
const legendOffset = legendGroups.length > 0 && infraParsed.options["no-legend"] !== "on" ? 28 : 0;
|
|
2545
|
+
const exportWidth = infraLayout.width;
|
|
2546
|
+
const exportHeight = infraLayout.height + titleOffset + legendOffset;
|
|
2547
|
+
const container = createExportContainer(exportWidth, exportHeight);
|
|
2548
|
+
renderInfra(
|
|
2878
2549
|
container,
|
|
2879
|
-
|
|
2550
|
+
infraLayout,
|
|
2880
2551
|
effectivePalette,
|
|
2881
|
-
ctx.isDark,
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2552
|
+
ctx.isDark,
|
|
2553
|
+
showInfraTitle ? infraParsed.title : null,
|
|
2554
|
+
showInfraTitle ? infraParsed.titleLineNumber : null,
|
|
2555
|
+
infraTagGroups,
|
|
2556
|
+
activeTagGroup,
|
|
2557
|
+
false,
|
|
2558
|
+
null,
|
|
2559
|
+
null,
|
|
2560
|
+
true,
|
|
2561
|
+
viewState?.cg ? new Set(viewState.cg) : null
|
|
2885
2562
|
);
|
|
2563
|
+
const infraSvg = container.querySelector("svg");
|
|
2564
|
+
if (infraSvg) {
|
|
2565
|
+
infraSvg.setAttribute("width", String(exportWidth));
|
|
2566
|
+
infraSvg.setAttribute("height", String(exportHeight));
|
|
2567
|
+
}
|
|
2886
2568
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2887
2569
|
}
|
|
2570
|
+
|
|
2571
|
+
// src/journey-map/export.ts
|
|
2888
2572
|
async function exportJourneyMap(ctx) {
|
|
2889
2573
|
const { content, theme, palette, exportMode } = ctx;
|
|
2890
|
-
const { parseJourneyMap: parseJourneyMap2 } = await import("./parser-
|
|
2891
|
-
const { renderJourneyMap } = await import("./renderer-
|
|
2574
|
+
const { parseJourneyMap: parseJourneyMap2 } = await import("./parser-NL73FSFI.js");
|
|
2575
|
+
const { renderJourneyMap } = await import("./renderer-53B523PM.js");
|
|
2892
2576
|
const { layoutJourneyMap } = await import("./layout-HFBK5UEG.js");
|
|
2893
2577
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2894
2578
|
const jmParsed = parseJourneyMap2(content, effectivePalette);
|
|
@@ -2907,31 +2591,66 @@ async function exportJourneyMap(ctx) {
|
|
|
2907
2591
|
});
|
|
2908
2592
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2909
2593
|
}
|
|
2910
|
-
|
|
2594
|
+
|
|
2595
|
+
// src/kanban/export.ts
|
|
2596
|
+
async function exportKanban(ctx) {
|
|
2911
2597
|
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
2912
|
-
const {
|
|
2913
|
-
const {
|
|
2598
|
+
const { parseKanban: parseKanban2 } = await import("./parser-KLCSFQ3J.js");
|
|
2599
|
+
const { renderKanban } = await import("./renderer-KJ3V5BYP.js");
|
|
2914
2600
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2915
|
-
const
|
|
2916
|
-
if (
|
|
2917
|
-
const container =
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2601
|
+
const kanbanParsed = parseKanban2(content, effectivePalette);
|
|
2602
|
+
if (kanbanParsed.error || kanbanParsed.columns.length === 0) return "";
|
|
2603
|
+
const container = document.createElement("div");
|
|
2604
|
+
container.style.position = "absolute";
|
|
2605
|
+
container.style.left = "-9999px";
|
|
2606
|
+
document.body.appendChild(container);
|
|
2607
|
+
const kanbanCollapsedLanes = viewState?.cl ? new Set(viewState.cl) : void 0;
|
|
2608
|
+
const sourceCollapsedColumns = kanbanParsed.columns.filter((c) => c.collapsed).map((c) => c.id);
|
|
2609
|
+
const kanbanCollapsedColumns = viewState?.cc || sourceCollapsedColumns.length > 0 ? /* @__PURE__ */ new Set([...sourceCollapsedColumns, ...viewState?.cc ?? []]) : void 0;
|
|
2610
|
+
renderKanban(container, kanbanParsed, effectivePalette, ctx.isDark, {
|
|
2611
|
+
activeTagGroup: resolveActiveTagGroup(
|
|
2612
|
+
kanbanParsed.tagGroups,
|
|
2613
|
+
kanbanParsed.options["active-tag"],
|
|
2614
|
+
ctxTagOverride(ctx)
|
|
2615
|
+
),
|
|
2616
|
+
currentSwimlaneGroup: viewState?.swim ?? kanbanParsed.options["lane-by"] ?? null,
|
|
2617
|
+
...kanbanCollapsedLanes !== void 0 && {
|
|
2618
|
+
collapsedLanes: kanbanCollapsedLanes
|
|
2619
|
+
},
|
|
2620
|
+
...kanbanCollapsedColumns !== void 0 && {
|
|
2621
|
+
collapsedColumns: kanbanCollapsedColumns
|
|
2622
|
+
},
|
|
2623
|
+
...viewState?.cm !== void 0 && { compactMeta: viewState.cm },
|
|
2925
2624
|
exportMode
|
|
2926
|
-
);
|
|
2625
|
+
});
|
|
2927
2626
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2928
2627
|
}
|
|
2628
|
+
|
|
2629
|
+
// src/live-link/export.ts
|
|
2630
|
+
async function exportLiveLink(ctx) {
|
|
2631
|
+
const { content, theme, palette } = ctx;
|
|
2632
|
+
const { parseLiveLink: parseLiveLink2 } = await import("./parser-GMQJISZ6.js");
|
|
2633
|
+
const { renderLiveLinkCard } = await import("./renderer-4SE7R22T.js");
|
|
2634
|
+
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2635
|
+
return renderLiveLinkCard(parseLiveLink2(content), effectivePalette, theme);
|
|
2636
|
+
}
|
|
2637
|
+
|
|
2638
|
+
// src/map/export.ts
|
|
2639
|
+
async function resolveMapDataSource(source) {
|
|
2640
|
+
if (source === void 0) return {};
|
|
2641
|
+
if (typeof source !== "function") return { data: source };
|
|
2642
|
+
try {
|
|
2643
|
+
return { data: await source() };
|
|
2644
|
+
} catch (e) {
|
|
2645
|
+
return { reason: e instanceof Error ? e.message : String(e) };
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2929
2648
|
async function exportMap(ctx) {
|
|
2930
2649
|
const { content, theme, palette, options } = ctx;
|
|
2931
2650
|
const { parseMap: parseMap2 } = await import("./parser-EFF22GYO.js");
|
|
2932
2651
|
const { resolveMap } = await import("./resolver-33K6MBCT.js");
|
|
2933
|
-
const { renderMapForExport } = await import("./renderer-
|
|
2934
|
-
const { mapExportDimensions } = await import("./dimensions-
|
|
2652
|
+
const { renderMapForExport } = await import("./renderer-BXD5KVSR.js");
|
|
2653
|
+
const { mapExportDimensions } = await import("./dimensions-DS6FWLRY.js");
|
|
2935
2654
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2936
2655
|
const mapParsed = parseMap2(content, effectivePalette);
|
|
2937
2656
|
const { data: mapData, reason } = await resolveMapDataSource(
|
|
@@ -2962,166 +2681,376 @@ async function exportMap(ctx) {
|
|
|
2962
2681
|
);
|
|
2963
2682
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2964
2683
|
}
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
const {
|
|
2684
|
+
|
|
2685
|
+
// src/mindmap/export.ts
|
|
2686
|
+
async function exportMindmap(ctx) {
|
|
2687
|
+
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
2688
|
+
const { parseMindmap: parseMindmap2 } = await import("./parser-KKF6Y5MM.js");
|
|
2689
|
+
const { layoutMindmap } = await import("./layout-RH3N46HP.js");
|
|
2690
|
+
const { collapseMindmapTree } = await import("./collapse-BSPH3BFM.js");
|
|
2691
|
+
const { renderMindmap } = await import("./renderer-PHLCYVSN.js");
|
|
2692
|
+
const isDark = ctx.isDark;
|
|
2969
2693
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2970
|
-
const
|
|
2971
|
-
if (
|
|
2972
|
-
const
|
|
2973
|
-
|
|
2694
|
+
const mmParsed = parseMindmap2(content, effectivePalette);
|
|
2695
|
+
if (mmParsed.error) return "";
|
|
2696
|
+
const collapsedNodes = new Set(viewState?.cg ?? []);
|
|
2697
|
+
const collectCollapsed = (nodes) => {
|
|
2698
|
+
for (const n of nodes) {
|
|
2699
|
+
if (n.collapsed) collapsedNodes.add(n.id);
|
|
2700
|
+
if (n.children.length) collectCollapsed(n.children);
|
|
2701
|
+
}
|
|
2702
|
+
};
|
|
2703
|
+
collectCollapsed(mmParsed.roots);
|
|
2704
|
+
const activeTagGroup = resolveActiveTagGroup(
|
|
2705
|
+
mmParsed.tagGroups,
|
|
2706
|
+
mmParsed.options["active-tag"],
|
|
2707
|
+
ctxTagOverride(ctx)
|
|
2708
|
+
);
|
|
2709
|
+
const hideDescriptions = mmParsed.options["no-descriptions"] === "true" || viewState?.hd === true;
|
|
2710
|
+
const { roots: effectiveRoots, hiddenCounts } = collapsedNodes && collapsedNodes.size > 0 ? collapseMindmapTree(mmParsed.roots, collapsedNodes) : { roots: mmParsed.roots, hiddenCounts: /* @__PURE__ */ new Map() };
|
|
2711
|
+
const effectiveParsed = { ...mmParsed, roots: effectiveRoots };
|
|
2712
|
+
const mmLayout = layoutMindmap(effectiveParsed, effectivePalette, {
|
|
2713
|
+
interactive: false,
|
|
2714
|
+
...hiddenCounts.size > 0 && { hiddenCounts },
|
|
2715
|
+
activeTagGroup,
|
|
2716
|
+
hideDescriptions
|
|
2717
|
+
});
|
|
2718
|
+
const PADDING = 20;
|
|
2719
|
+
const titleOffset = effectiveParsed.title ? 30 : 0;
|
|
2720
|
+
const exportWidth = mmLayout.width + PADDING * 2;
|
|
2721
|
+
const exportHeight = mmLayout.height + PADDING * 2 + titleOffset;
|
|
2722
|
+
const container = createExportContainer(exportWidth, exportHeight);
|
|
2723
|
+
const colorByDepth = viewState?.cbd ?? mmParsed.options["color-by-depth"] === "on";
|
|
2724
|
+
renderMindmap(
|
|
2974
2725
|
container,
|
|
2975
|
-
|
|
2726
|
+
effectiveParsed,
|
|
2727
|
+
mmLayout,
|
|
2976
2728
|
effectivePalette,
|
|
2977
|
-
|
|
2978
|
-
|
|
2729
|
+
isDark,
|
|
2730
|
+
void 0,
|
|
2731
|
+
{ width: exportWidth, height: exportHeight },
|
|
2732
|
+
void 0,
|
|
2733
|
+
hideDescriptions,
|
|
2734
|
+
colorByDepth ? null : activeTagGroup,
|
|
2735
|
+
colorByDepth ? { colorByDepth: true, exportMode } : { exportMode }
|
|
2979
2736
|
);
|
|
2980
2737
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2981
2738
|
}
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
const {
|
|
2739
|
+
|
|
2740
|
+
// src/org/export.ts
|
|
2741
|
+
async function exportOrg(ctx) {
|
|
2742
|
+
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
2743
|
+
const { parseOrg: parseOrg2, findOrgNodeIdByName } = await import("./parser-BJ7RJNUM.js");
|
|
2744
|
+
const { layoutOrg } = await import("./layout-MXHR3P35.js");
|
|
2745
|
+
const { collapseOrgTree, focusOrgTree, unionCollapsedOrgNodes } = await import("./collapse-VNYYXMUI.js");
|
|
2746
|
+
const { renderOrg, ancestorTrailReserve } = await import("./renderer-JJ4QW3SK.js");
|
|
2747
|
+
const isDark = ctx.isDark;
|
|
2986
2748
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2987
|
-
const
|
|
2988
|
-
if (
|
|
2989
|
-
const
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2749
|
+
const orgParsed = parseOrg2(content, effectivePalette);
|
|
2750
|
+
if (orgParsed.error) return "";
|
|
2751
|
+
const collapsedNodes = unionCollapsedOrgNodes(orgParsed, viewState?.cg);
|
|
2752
|
+
const activeTagGroup = resolveActiveTagGroup(
|
|
2753
|
+
orgParsed.tagGroups,
|
|
2754
|
+
orgParsed.options["active-tag"],
|
|
2755
|
+
ctxTagOverride(ctx)
|
|
2756
|
+
);
|
|
2757
|
+
const hiddenAttributes = unionHiddenAttributes(
|
|
2758
|
+
orgParsed.options["hide"],
|
|
2759
|
+
viewState?.ha
|
|
2760
|
+
);
|
|
2761
|
+
const collapseResult = collapsedNodes && collapsedNodes.size > 0 ? collapseOrgTree(orgParsed, collapsedNodes) : { parsed: orgParsed, hiddenCounts: /* @__PURE__ */ new Map() };
|
|
2762
|
+
const { hiddenCounts } = collapseResult;
|
|
2763
|
+
let effectiveParsed = collapseResult.parsed;
|
|
2764
|
+
let ancestorPath;
|
|
2765
|
+
const focusName = orgParsed.options["focus"];
|
|
2766
|
+
if (focusName) {
|
|
2767
|
+
const focusId = findOrgNodeIdByName(effectiveParsed.roots, focusName);
|
|
2768
|
+
const focused = focusId ? focusOrgTree(effectiveParsed, focusId) : null;
|
|
2769
|
+
if (focused) {
|
|
2770
|
+
effectiveParsed = focused.parsed;
|
|
2771
|
+
ancestorPath = focused.ancestorPath;
|
|
2772
|
+
}
|
|
2773
|
+
}
|
|
2774
|
+
const orgLayout = layoutOrg(
|
|
2775
|
+
effectiveParsed,
|
|
2776
|
+
hiddenCounts.size > 0 ? hiddenCounts : void 0,
|
|
2777
|
+
activeTagGroup,
|
|
2778
|
+
hiddenAttributes,
|
|
2779
|
+
false
|
|
2780
|
+
// expandAllLegend off — collapsed-by-default per §1.3
|
|
2781
|
+
);
|
|
2782
|
+
const PADDING = 20;
|
|
2783
|
+
const titleOffset = effectiveParsed.title ? 30 : 0;
|
|
2784
|
+
const rootIds = new Set(effectiveParsed.roots.map((r) => r.id));
|
|
2785
|
+
const rootTop = orgLayout.nodes.find((n) => rootIds.has(n.id))?.y ?? orgLayout.containers.find((c) => rootIds.has(c.nodeId))?.y ?? 0;
|
|
2786
|
+
const trailReserve = ancestorTrailReserve(ancestorPath?.length ?? 0, rootTop);
|
|
2787
|
+
const exportWidth = orgLayout.width + PADDING * 2;
|
|
2788
|
+
const exportHeight = orgLayout.height + PADDING * 2 + titleOffset + trailReserve;
|
|
2789
|
+
const container = createExportContainer(exportWidth, exportHeight);
|
|
2790
|
+
renderOrg(
|
|
2791
|
+
container,
|
|
2792
|
+
effectiveParsed,
|
|
2793
|
+
orgLayout,
|
|
2794
|
+
effectivePalette,
|
|
2795
|
+
isDark,
|
|
2796
|
+
void 0,
|
|
2797
|
+
{ width: exportWidth, height: exportHeight },
|
|
2798
|
+
activeTagGroup,
|
|
2799
|
+
hiddenAttributes,
|
|
2800
|
+
ancestorPath,
|
|
2801
|
+
exportMode
|
|
2802
|
+
);
|
|
2994
2803
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
2995
2804
|
}
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2805
|
+
|
|
2806
|
+
// src/pert/export.ts
|
|
2807
|
+
async function exportPert(ctx) {
|
|
2808
|
+
const { content, theme, palette, viewState } = ctx;
|
|
2809
|
+
const { parsePert: parsePert2 } = await import("./parser-2IKPQVKX.js");
|
|
2810
|
+
const { analyzePert } = await import("./analyzer-G7PGOT3V.js");
|
|
2811
|
+
const { layoutPert } = await import("./layout-KV27UW25.js");
|
|
2812
|
+
const { renderPert, measurePertAnalysisBlock } = await import("./renderer-MWZC7TMD.js");
|
|
2999
2813
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3000
|
-
const
|
|
3001
|
-
if (
|
|
3002
|
-
const
|
|
3003
|
-
const
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
2814
|
+
const pertParsed = parsePert2(content, { palette: effectivePalette });
|
|
2815
|
+
if (pertParsed.error || pertParsed.activities.length === 0) return "";
|
|
2816
|
+
const pertResolved = analyzePert(pertParsed);
|
|
2817
|
+
const pertLayout = layoutPert(pertResolved);
|
|
2818
|
+
const hasTitle = !!pertParsed.title && !pertParsed.options.noTitle;
|
|
2819
|
+
const hasSubtitle = pertResolved.projectSubtitle !== null;
|
|
2820
|
+
const titleHeight = hasTitle ? 80 : hasSubtitle ? 50 : 0;
|
|
2821
|
+
const PERT_PADDING = 20;
|
|
2822
|
+
const analysisOn = viewState?.an ?? !pertParsed.options.noAnalysis;
|
|
2823
|
+
const fieldLabelsOn = viewState?.fl === true;
|
|
2824
|
+
const exportW = pertLayout.width + PERT_PADDING * 2;
|
|
2825
|
+
const analysisMeasured = measurePertAnalysisBlock(
|
|
2826
|
+
pertResolved,
|
|
2827
|
+
exportW - 2 * PERT_PADDING,
|
|
2828
|
+
{
|
|
2829
|
+
showTornado: analysisOn,
|
|
2830
|
+
showScurve: analysisOn,
|
|
2831
|
+
showFieldLegend: fieldLabelsOn
|
|
2832
|
+
}
|
|
2833
|
+
);
|
|
2834
|
+
const exportH = pertLayout.height + PERT_PADDING * 2 + titleHeight + analysisMeasured.height;
|
|
2835
|
+
const container = createExportContainer(exportW, exportH);
|
|
2836
|
+
renderPert(
|
|
2837
|
+
container,
|
|
2838
|
+
pertResolved,
|
|
2839
|
+
pertLayout,
|
|
2840
|
+
effectivePalette,
|
|
2841
|
+
ctx.isDark,
|
|
2842
|
+
{
|
|
2843
|
+
title: hasTitle ? pertParsed.title : null,
|
|
2844
|
+
subtitle: pertResolved.projectSubtitle,
|
|
2845
|
+
exportDims: { width: exportW, height: exportH },
|
|
2846
|
+
showTornado: analysisOn,
|
|
2847
|
+
showScurve: analysisOn,
|
|
2848
|
+
showFieldLegend: fieldLabelsOn
|
|
2849
|
+
}
|
|
2850
|
+
);
|
|
3023
2851
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3024
2852
|
}
|
|
3025
|
-
|
|
2853
|
+
|
|
2854
|
+
// src/pyramid/export.ts
|
|
2855
|
+
async function exportPyramid(ctx) {
|
|
3026
2856
|
const { content, theme, palette } = ctx;
|
|
3027
|
-
const {
|
|
3028
|
-
const {
|
|
2857
|
+
const { parsePyramid: parsePyramid2 } = await import("./parser-NUU3DVW4.js");
|
|
2858
|
+
const { renderPyramidForExport } = await import("./renderer-IXBOT6DU.js");
|
|
3029
2859
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3030
|
-
|
|
2860
|
+
const pyramidParsed = parsePyramid2(content);
|
|
2861
|
+
if (pyramidParsed.error || pyramidParsed.layers.length === 0) return "";
|
|
2862
|
+
const container = createExportContainer(ctx.width, ctx.height);
|
|
2863
|
+
renderPyramidForExport(
|
|
2864
|
+
container,
|
|
2865
|
+
pyramidParsed,
|
|
2866
|
+
effectivePalette,
|
|
2867
|
+
ctx.isDark,
|
|
2868
|
+
{ width: ctx.width, height: ctx.height }
|
|
2869
|
+
);
|
|
2870
|
+
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3031
2871
|
}
|
|
3032
|
-
|
|
2872
|
+
|
|
2873
|
+
// src/quadrant/export.ts
|
|
2874
|
+
async function exportQuadrant(ctx) {
|
|
3033
2875
|
const { content, theme, palette } = ctx;
|
|
3034
|
-
const
|
|
3035
|
-
|
|
2876
|
+
const parsed = parseQuadrant(content, palette);
|
|
2877
|
+
if (parsed.error || parsed.quadrantPoints.length === 0) return "";
|
|
3036
2878
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3037
|
-
const
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
2879
|
+
const { container, dims } = beginVizExport(ctx);
|
|
2880
|
+
renderQuadrant(
|
|
2881
|
+
container,
|
|
2882
|
+
parsed,
|
|
2883
|
+
effectivePalette,
|
|
2884
|
+
ctx.isDark,
|
|
2885
|
+
void 0,
|
|
2886
|
+
dims
|
|
2887
|
+
);
|
|
3044
2888
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3045
2889
|
}
|
|
3046
|
-
|
|
2890
|
+
|
|
2891
|
+
// src/raci/export.ts
|
|
2892
|
+
async function exportRaci(ctx) {
|
|
3047
2893
|
const { content, theme, palette } = ctx;
|
|
3048
|
-
const {
|
|
3049
|
-
const {
|
|
2894
|
+
const { parseRaci: parseRaci2 } = await import("./parser-GDLKUBTO.js");
|
|
2895
|
+
const { renderRaciForExport } = await import("./renderer-W4MUMXJE.js");
|
|
3050
2896
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3051
|
-
const
|
|
3052
|
-
if (
|
|
2897
|
+
const raciParsed = parseRaci2(content, effectivePalette);
|
|
2898
|
+
if (raciParsed.error) return "";
|
|
3053
2899
|
const container = createExportContainer(ctx.width, ctx.height);
|
|
3054
|
-
|
|
2900
|
+
renderRaciForExport(container, raciParsed, effectivePalette, ctx.isDark, {
|
|
3055
2901
|
width: ctx.width,
|
|
3056
2902
|
height: ctx.height
|
|
3057
2903
|
});
|
|
3058
2904
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3059
2905
|
}
|
|
3060
|
-
|
|
2906
|
+
|
|
2907
|
+
// src/ring/export.ts
|
|
2908
|
+
async function exportRing(ctx) {
|
|
3061
2909
|
const { content, theme, palette } = ctx;
|
|
3062
|
-
const {
|
|
3063
|
-
const {
|
|
2910
|
+
const { parseRing: parseRing2 } = await import("./parser-KMKVFET2.js");
|
|
2911
|
+
const { renderRingForExport } = await import("./renderer-RUSQJFFC.js");
|
|
3064
2912
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3065
|
-
const
|
|
3066
|
-
if (
|
|
2913
|
+
const ringParsed = parseRing2(content);
|
|
2914
|
+
if (ringParsed.error || ringParsed.layers.length === 0) return "";
|
|
3067
2915
|
const container = createExportContainer(ctx.width, ctx.height);
|
|
3068
|
-
|
|
2916
|
+
renderRingForExport(container, ringParsed, effectivePalette, ctx.isDark, {
|
|
3069
2917
|
width: ctx.width,
|
|
3070
2918
|
height: ctx.height
|
|
3071
2919
|
});
|
|
3072
2920
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3073
2921
|
}
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
const {
|
|
2922
|
+
|
|
2923
|
+
// src/sequence/export.ts
|
|
2924
|
+
async function exportVisualization(ctx) {
|
|
2925
|
+
const { content, theme, palette, viewState } = ctx;
|
|
2926
|
+
const parsed = parseVisualization(content, palette);
|
|
2927
|
+
if (parsed.type !== "sequence") {
|
|
2928
|
+
if (parsed.error) {
|
|
2929
|
+
const looksLikeSequence = /->|~>|<-/.test(content);
|
|
2930
|
+
if (!looksLikeSequence) return "";
|
|
2931
|
+
} else {
|
|
2932
|
+
return "";
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
3078
2935
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3079
|
-
const
|
|
3080
|
-
if (parsed.error) return "";
|
|
2936
|
+
const isDark = ctx.isDark;
|
|
3081
2937
|
const container = createExportContainer(ctx.width, ctx.height);
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
2938
|
+
const { parseSequenceDgmo: parseSequenceDgmo2 } = await import("./parser-BT4NI6JY.js");
|
|
2939
|
+
const { renderSequenceDiagram } = await import("./renderer-FMTLSOCX.js");
|
|
2940
|
+
const seqParsed = parseSequenceDgmo2(content, effectivePalette);
|
|
2941
|
+
if (seqParsed.error || seqParsed.participants.length === 0) return "";
|
|
2942
|
+
const collapsedSections = viewState?.cs ? new Set(viewState.cs) : void 0;
|
|
2943
|
+
const collapsedGroups = viewState?.cg ? new Set(viewState.cg.map(Number).filter((n) => Number.isFinite(n))) : void 0;
|
|
2944
|
+
const seqActiveTagGroup = ctxTagOverride(ctx);
|
|
2945
|
+
renderSequenceDiagram(
|
|
2946
|
+
container,
|
|
2947
|
+
seqParsed,
|
|
2948
|
+
effectivePalette,
|
|
2949
|
+
isDark,
|
|
2950
|
+
void 0,
|
|
2951
|
+
{
|
|
2952
|
+
exportWidth: ctx.width,
|
|
2953
|
+
...seqActiveTagGroup !== void 0 && {
|
|
2954
|
+
activeTagGroup: seqActiveTagGroup
|
|
2955
|
+
},
|
|
2956
|
+
...collapsedSections !== void 0 && { collapsedSections },
|
|
2957
|
+
...collapsedGroups !== void 0 && { collapsedGroups }
|
|
2958
|
+
}
|
|
2959
|
+
);
|
|
3086
2960
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3087
2961
|
}
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
const {
|
|
2962
|
+
|
|
2963
|
+
// src/sitemap/export.ts
|
|
2964
|
+
async function exportSitemap(ctx) {
|
|
2965
|
+
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
2966
|
+
const { parseSitemap: parseSitemap2 } = await import("./parser-6TDWUKM5.js");
|
|
2967
|
+
const { layoutSitemap } = await import("./layout-ND26WVX2.js");
|
|
2968
|
+
const { collapseSitemapTree } = await import("./collapse-TCVK3RPO.js");
|
|
2969
|
+
const { renderSitemap } = await import("./renderer-XOWDERU2.js");
|
|
2970
|
+
const isDark = ctx.isDark;
|
|
3092
2971
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3093
|
-
const
|
|
3094
|
-
if (
|
|
3095
|
-
const
|
|
3096
|
-
const
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
2972
|
+
const sitemapParsed = parseSitemap2(content, effectivePalette);
|
|
2973
|
+
if (sitemapParsed.error || sitemapParsed.roots.length === 0) return "";
|
|
2974
|
+
const collapsedNodes = viewState?.cg ? new Set(viewState.cg) : void 0;
|
|
2975
|
+
const activeTagGroup = resolveActiveTagGroup(
|
|
2976
|
+
sitemapParsed.tagGroups,
|
|
2977
|
+
sitemapParsed.options["active-tag"],
|
|
2978
|
+
ctxTagOverride(ctx)
|
|
2979
|
+
);
|
|
2980
|
+
const hiddenAttributes = unionHiddenAttributes(
|
|
2981
|
+
sitemapParsed.options["hide"],
|
|
2982
|
+
viewState?.ha
|
|
2983
|
+
);
|
|
2984
|
+
const { parsed: effectiveParsed, hiddenCounts } = collapsedNodes && collapsedNodes.size > 0 ? collapseSitemapTree(sitemapParsed, collapsedNodes) : { parsed: sitemapParsed, hiddenCounts: /* @__PURE__ */ new Map() };
|
|
2985
|
+
const sitemapLayout = layoutSitemap(
|
|
2986
|
+
effectiveParsed,
|
|
2987
|
+
hiddenCounts.size > 0 ? hiddenCounts : void 0,
|
|
2988
|
+
activeTagGroup,
|
|
2989
|
+
hiddenAttributes,
|
|
2990
|
+
true
|
|
2991
|
+
);
|
|
2992
|
+
const PADDING = 20;
|
|
2993
|
+
const titleOffset = effectiveParsed.title ? 30 : 0;
|
|
2994
|
+
const {
|
|
2995
|
+
LEGEND_HEIGHT: SITEMAP_LEGEND_HEIGHT,
|
|
2996
|
+
LEGEND_GROUP_GAP: SITEMAP_LEGEND_GROUP_GAP
|
|
2997
|
+
} = await import("./legend-constants-55MFBXYF.js");
|
|
2998
|
+
const suppressedLegendBand = sitemapLayout.legend.length > 0 && effectiveParsed.options["no-legend"] === "on" ? SITEMAP_LEGEND_HEIGHT + SITEMAP_LEGEND_GROUP_GAP : 0;
|
|
2999
|
+
const exportWidth = sitemapLayout.width + PADDING * 2;
|
|
3000
|
+
const exportHeight = sitemapLayout.height + PADDING * 2 + titleOffset - suppressedLegendBand;
|
|
3001
|
+
const container = createExportContainer(exportWidth, exportHeight);
|
|
3002
|
+
renderSitemap(
|
|
3003
|
+
container,
|
|
3004
|
+
effectiveParsed,
|
|
3005
|
+
sitemapLayout,
|
|
3006
|
+
effectivePalette,
|
|
3007
|
+
isDark,
|
|
3008
|
+
void 0,
|
|
3009
|
+
{ width: exportWidth, height: exportHeight },
|
|
3010
|
+
activeTagGroup,
|
|
3011
|
+
hiddenAttributes,
|
|
3012
|
+
exportMode
|
|
3013
|
+
);
|
|
3101
3014
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3102
3015
|
}
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
const {
|
|
3107
|
-
const
|
|
3108
|
-
const
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3016
|
+
|
|
3017
|
+
// src/sketch/export.ts
|
|
3018
|
+
async function exportSketch(ctx) {
|
|
3019
|
+
const { content, theme, viewState, exportMode } = ctx;
|
|
3020
|
+
const { parseSketch: parseSketch2 } = await import("./parser-YHDGKPZI.js");
|
|
3021
|
+
const effectivePalette = await resolveExportPalette(theme, ctx.palette);
|
|
3022
|
+
const parsed = parseSketch2(content, effectivePalette);
|
|
3023
|
+
if (parsed.error || parsed.nodes.length === 0 && parsed.boxes.length === 0) {
|
|
3024
|
+
return "";
|
|
3025
|
+
}
|
|
3026
|
+
const { layoutSketch } = await import("./layout-D4L44NRG.js");
|
|
3027
|
+
const { renderSketchForExport } = await import("./renderer-WPN2SXGT.js");
|
|
3028
|
+
const collapsedBoxes = viewState?.cg ? new Set(viewState.cg) : void 0;
|
|
3029
|
+
const skLayout = layoutSketch(parsed, {
|
|
3030
|
+
...collapsedBoxes !== void 0 && { collapsedBoxes }
|
|
3114
3031
|
});
|
|
3032
|
+
const PADDING = 20;
|
|
3033
|
+
const titleOffset = parsed.title ? 40 : 0;
|
|
3034
|
+
const exportWidth = skLayout.width + PADDING * 2;
|
|
3035
|
+
const exportHeight = skLayout.height + PADDING * 2 + titleOffset;
|
|
3036
|
+
const container = createExportContainer(exportWidth, exportHeight);
|
|
3037
|
+
const skTagOverride = ctxTagOverride(ctx);
|
|
3038
|
+
renderSketchForExport(
|
|
3039
|
+
container,
|
|
3040
|
+
parsed,
|
|
3041
|
+
skLayout,
|
|
3042
|
+
effectivePalette,
|
|
3043
|
+
ctx.isDark,
|
|
3044
|
+
{
|
|
3045
|
+
...skTagOverride !== void 0 && { activeTagGroup: skTagOverride },
|
|
3046
|
+
...exportMode !== void 0 && { exportMode },
|
|
3047
|
+
...viewState?.hd !== void 0 && { hideDescriptions: viewState.hd }
|
|
3048
|
+
}
|
|
3049
|
+
);
|
|
3115
3050
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3116
3051
|
}
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
const dims = {
|
|
3120
|
-
width: ctx.width,
|
|
3121
|
-
height: ctx.height
|
|
3122
|
-
};
|
|
3123
|
-
return { container, dims };
|
|
3124
|
-
}
|
|
3052
|
+
|
|
3053
|
+
// src/slope/export.ts
|
|
3125
3054
|
async function exportSlope(ctx) {
|
|
3126
3055
|
const { content, theme, palette } = ctx;
|
|
3127
3056
|
const parsed = parseSlope(content, palette);
|
|
@@ -3138,22 +3067,65 @@ async function exportSlope(ctx) {
|
|
|
3138
3067
|
);
|
|
3139
3068
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3140
3069
|
}
|
|
3141
|
-
|
|
3070
|
+
|
|
3071
|
+
// src/swimlane/export.ts
|
|
3072
|
+
async function exportSwimlane(ctx) {
|
|
3142
3073
|
const { content, theme, palette } = ctx;
|
|
3143
|
-
const
|
|
3144
|
-
|
|
3074
|
+
const { parseSwimlane: parseSwimlane2 } = await import("./parser-H5OODY5N.js");
|
|
3075
|
+
const { layoutSwimlane } = await import("./layout-VDCJOZSH.js");
|
|
3076
|
+
const { renderSwimlaneForExport } = await import("./renderer-DAZWHNLI.js");
|
|
3145
3077
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3146
|
-
const
|
|
3147
|
-
|
|
3078
|
+
const swimParsed = parseSwimlane2(content, effectivePalette);
|
|
3079
|
+
if (swimParsed.error || swimParsed.nodes.length === 0) return "";
|
|
3080
|
+
const swimLayout = layoutSwimlane(swimParsed);
|
|
3081
|
+
const PADDING = 20;
|
|
3082
|
+
const titleOffset = swimParsed.title ? 40 : 0;
|
|
3083
|
+
const exportWidth = swimLayout.width + PADDING * 2;
|
|
3084
|
+
const exportHeight = swimLayout.height + PADDING * 2 + titleOffset;
|
|
3085
|
+
const container = createExportContainer(exportWidth, exportHeight);
|
|
3086
|
+
renderSwimlaneForExport(
|
|
3087
|
+
container,
|
|
3088
|
+
swimParsed,
|
|
3089
|
+
swimLayout,
|
|
3090
|
+
effectivePalette,
|
|
3091
|
+
ctx.isDark,
|
|
3092
|
+
{
|
|
3093
|
+
exportDims: { width: exportWidth, height: exportHeight },
|
|
3094
|
+
activeTagGroup: resolveActiveTagGroup(
|
|
3095
|
+
swimParsed.tagGroups,
|
|
3096
|
+
swimParsed.options["active-tag"],
|
|
3097
|
+
ctxTagOverride(ctx)
|
|
3098
|
+
),
|
|
3099
|
+
exportMode: ctx.exportMode
|
|
3100
|
+
}
|
|
3101
|
+
);
|
|
3102
|
+
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3103
|
+
}
|
|
3104
|
+
|
|
3105
|
+
// src/tech-radar/export.ts
|
|
3106
|
+
async function exportTechRadar(ctx) {
|
|
3107
|
+
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
3108
|
+
const { parseTechRadar: parseTechRadar2 } = await import("./parser-3LT3ZUUC.js");
|
|
3109
|
+
const { renderTechRadarForExport } = await import("./renderer-TINHO2IO.js");
|
|
3110
|
+
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3111
|
+
const radarParsed = parseTechRadar2(content);
|
|
3112
|
+
if (radarParsed.error || radarParsed.quadrants.length === 0) return "";
|
|
3113
|
+
const RADAR_EXPORT_W = ctx.requestedWidth ?? 1300;
|
|
3114
|
+
const RADAR_EXPORT_H = ctx.requestedHeight ?? 1500;
|
|
3115
|
+
const container = createExportContainer(RADAR_EXPORT_W, RADAR_EXPORT_H);
|
|
3116
|
+
renderTechRadarForExport(
|
|
3148
3117
|
container,
|
|
3149
|
-
|
|
3118
|
+
radarParsed,
|
|
3150
3119
|
effectivePalette,
|
|
3151
3120
|
ctx.isDark,
|
|
3152
|
-
|
|
3153
|
-
|
|
3121
|
+
{ width: RADAR_EXPORT_W, height: RADAR_EXPORT_H },
|
|
3122
|
+
viewState,
|
|
3123
|
+
exportMode
|
|
3154
3124
|
);
|
|
3155
3125
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3156
3126
|
}
|
|
3127
|
+
|
|
3128
|
+
// src/timeline/export.ts
|
|
3157
3129
|
async function exportTimeline(ctx) {
|
|
3158
3130
|
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
3159
3131
|
const parsed = parseTimeline(content, palette);
|
|
@@ -3181,21 +3153,39 @@ async function exportTimeline(ctx) {
|
|
|
3181
3153
|
);
|
|
3182
3154
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3183
3155
|
}
|
|
3184
|
-
|
|
3156
|
+
|
|
3157
|
+
// src/treemap/export.ts
|
|
3158
|
+
async function exportTreemap(ctx) {
|
|
3185
3159
|
const { content, theme, palette } = ctx;
|
|
3186
|
-
const
|
|
3187
|
-
if (parsed.error || parsed.words.length === 0) return "";
|
|
3160
|
+
const { parseTreemap: parseTreemap2 } = await import("./parser-LTRQASGB.js");
|
|
3188
3161
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3189
|
-
const
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3162
|
+
const treemapParsed = parseTreemap2(content, effectivePalette);
|
|
3163
|
+
if (treemapParsed.error || treemapParsed.roots.length === 0) return "";
|
|
3164
|
+
const container = createExportContainer(ctx.width, ctx.height);
|
|
3165
|
+
const dims = { width: ctx.width, height: ctx.height };
|
|
3166
|
+
if (treemapParsed.options.radial) {
|
|
3167
|
+
const { renderTreemapRadialForExport } = await import("./renderer-radial-WFUX3Z3C.js");
|
|
3168
|
+
renderTreemapRadialForExport(
|
|
3169
|
+
container,
|
|
3170
|
+
treemapParsed,
|
|
3171
|
+
effectivePalette,
|
|
3172
|
+
ctx.isDark,
|
|
3173
|
+
dims
|
|
3174
|
+
);
|
|
3175
|
+
} else {
|
|
3176
|
+
const { renderTreemapForExport } = await import("./renderer-O6RP52CQ.js");
|
|
3177
|
+
renderTreemapForExport(
|
|
3178
|
+
container,
|
|
3179
|
+
treemapParsed,
|
|
3180
|
+
effectivePalette,
|
|
3181
|
+
ctx.isDark,
|
|
3182
|
+
dims
|
|
3183
|
+
);
|
|
3184
|
+
}
|
|
3197
3185
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3198
3186
|
}
|
|
3187
|
+
|
|
3188
|
+
// src/venn/export.ts
|
|
3199
3189
|
async function exportVenn(ctx) {
|
|
3200
3190
|
const { content, theme, palette } = ctx;
|
|
3201
3191
|
const parsed = parseVenn(content, palette);
|
|
@@ -3205,61 +3195,190 @@ async function exportVenn(ctx) {
|
|
|
3205
3195
|
renderVenn(container, parsed, effectivePalette, ctx.isDark, void 0, dims);
|
|
3206
3196
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3207
3197
|
}
|
|
3208
|
-
|
|
3198
|
+
|
|
3199
|
+
// src/version-control/export.ts
|
|
3200
|
+
async function exportVersionControl(ctx) {
|
|
3209
3201
|
const { content, theme, palette } = ctx;
|
|
3210
|
-
const
|
|
3211
|
-
|
|
3202
|
+
const { parseVersionControl: parseVersionControl2 } = await import("./parser-5UZV32ZI.js");
|
|
3203
|
+
const { renderVersionControlForExport } = await import("./renderer-NOYLNVTI.js");
|
|
3212
3204
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3213
|
-
const
|
|
3214
|
-
|
|
3205
|
+
const parsed = parseVersionControl2(content, effectivePalette);
|
|
3206
|
+
if (parsed.error || parsed.nodes.length === 0) return "";
|
|
3207
|
+
const container = createExportContainer(ctx.width, ctx.height);
|
|
3208
|
+
renderVersionControlForExport(
|
|
3215
3209
|
container,
|
|
3216
3210
|
parsed,
|
|
3217
3211
|
effectivePalette,
|
|
3218
3212
|
ctx.isDark,
|
|
3219
|
-
|
|
3220
|
-
|
|
3213
|
+
{
|
|
3214
|
+
width: ctx.width,
|
|
3215
|
+
height: ctx.height
|
|
3216
|
+
}
|
|
3221
3217
|
);
|
|
3222
3218
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3223
3219
|
}
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3220
|
+
|
|
3221
|
+
// src/whiteboard/export.ts
|
|
3222
|
+
async function exportWhiteboard(ctx) {
|
|
3223
|
+
const { content, theme } = ctx;
|
|
3224
|
+
const { parseWhiteboard: parseWhiteboard2 } = await import("./parser-R3LPEQIT.js");
|
|
3225
|
+
const effectivePalette = await resolveExportPalette(theme, ctx.palette);
|
|
3226
|
+
const parsed = parseWhiteboard2(content, effectivePalette);
|
|
3227
|
+
if (parsed.error || parsed.elements.length === 0) return "";
|
|
3228
|
+
const { renderWhiteboard } = await import("./renderer-M5DUMITP.js");
|
|
3229
|
+
const container = createExportContainer(1, 1);
|
|
3230
|
+
const resolveImage = ctx.options?.resolveImage;
|
|
3231
|
+
const showNotes = ctx.options?.showNotes;
|
|
3232
|
+
renderWhiteboard(container, parsed, effectivePalette, ctx.isDark, {
|
|
3233
|
+
...resolveImage !== void 0 && { resolveImage },
|
|
3234
|
+
...showNotes !== void 0 && { showNotes }
|
|
3235
|
+
});
|
|
3236
|
+
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3237
|
+
}
|
|
3238
|
+
|
|
3239
|
+
// src/wireframe/export.ts
|
|
3240
|
+
async function exportWireframe(ctx) {
|
|
3241
|
+
const { content, theme, palette } = ctx;
|
|
3242
|
+
const { parseWireframe: parseWireframe2 } = await import("./parser-4TBSWULQ.js");
|
|
3243
|
+
const { layoutWireframe } = await import("./layout-HF3PMI4H.js");
|
|
3244
|
+
const { renderWireframe } = await import("./renderer-36446HSH.js");
|
|
3235
3245
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3236
|
-
const
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
const
|
|
3240
|
-
const
|
|
3241
|
-
|
|
3242
|
-
const
|
|
3243
|
-
|
|
3244
|
-
const seqActiveTagGroup = ctxTagOverride(ctx);
|
|
3245
|
-
renderSequenceDiagram(
|
|
3246
|
+
const wireframeParsed = parseWireframe2(content);
|
|
3247
|
+
if (wireframeParsed.error || wireframeParsed.roots.length === 0 && wireframeParsed.modals.length === 0)
|
|
3248
|
+
return "";
|
|
3249
|
+
const wireframeLayout = layoutWireframe(wireframeParsed);
|
|
3250
|
+
const exportWidth = wireframeLayout.width;
|
|
3251
|
+
const exportHeight = wireframeLayout.height;
|
|
3252
|
+
const container = createExportContainer(exportWidth, exportHeight);
|
|
3253
|
+
renderWireframe(
|
|
3246
3254
|
container,
|
|
3247
|
-
|
|
3255
|
+
wireframeParsed,
|
|
3256
|
+
wireframeLayout,
|
|
3248
3257
|
effectivePalette,
|
|
3249
|
-
isDark,
|
|
3258
|
+
ctx.isDark,
|
|
3250
3259
|
void 0,
|
|
3251
|
-
{
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3260
|
+
{ width: exportWidth, height: exportHeight },
|
|
3261
|
+
theme
|
|
3262
|
+
);
|
|
3263
|
+
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3264
|
+
}
|
|
3265
|
+
|
|
3266
|
+
// src/wordcloud/export.ts
|
|
3267
|
+
async function exportWordcloud(ctx) {
|
|
3268
|
+
const { content, theme, palette } = ctx;
|
|
3269
|
+
const parsed = parseWordcloud(content, palette);
|
|
3270
|
+
if (parsed.error || parsed.words.length === 0) return "";
|
|
3271
|
+
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3272
|
+
const { container, dims } = beginVizExport(ctx);
|
|
3273
|
+
await renderWordCloudAsync(
|
|
3274
|
+
container,
|
|
3275
|
+
parsed,
|
|
3276
|
+
effectivePalette,
|
|
3277
|
+
ctx.isDark,
|
|
3278
|
+
dims
|
|
3259
3279
|
);
|
|
3260
3280
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
3261
3281
|
}
|
|
3262
3282
|
|
|
3283
|
+
// src/d3.ts
|
|
3284
|
+
var DIAGRAM_EXPORT_HANDLERS = {
|
|
3285
|
+
org: exportOrg,
|
|
3286
|
+
sitemap: exportSitemap,
|
|
3287
|
+
kanban: exportKanban,
|
|
3288
|
+
class: exportClass,
|
|
3289
|
+
er: exportEr,
|
|
3290
|
+
"boxes-and-lines": exportBoxesAndLines,
|
|
3291
|
+
sketch: exportSketch,
|
|
3292
|
+
whiteboard: exportWhiteboard,
|
|
3293
|
+
swimlane: exportSwimlane,
|
|
3294
|
+
family: exportFamily,
|
|
3295
|
+
"version-control": exportVersionControl,
|
|
3296
|
+
mindmap: exportMindmap,
|
|
3297
|
+
wireframe: exportWireframe,
|
|
3298
|
+
c4: exportC4,
|
|
3299
|
+
flowchart: exportFlowchart,
|
|
3300
|
+
infra: exportInfra,
|
|
3301
|
+
pert: exportPert,
|
|
3302
|
+
gantt: exportGantt,
|
|
3303
|
+
state: exportState,
|
|
3304
|
+
"tech-radar": exportTechRadar,
|
|
3305
|
+
"journey-map": exportJourneyMap,
|
|
3306
|
+
cycle: exportCycle,
|
|
3307
|
+
map: exportMap,
|
|
3308
|
+
pyramid: exportPyramid,
|
|
3309
|
+
ring: exportRing,
|
|
3310
|
+
treemap: exportTreemap,
|
|
3311
|
+
block: exportBlock,
|
|
3312
|
+
goal: exportGoal,
|
|
3313
|
+
countdown: exportCountdown,
|
|
3314
|
+
clock: exportClock,
|
|
3315
|
+
bracket: exportBracket,
|
|
3316
|
+
raci: exportRaci,
|
|
3317
|
+
body: exportBody,
|
|
3318
|
+
"live-link": exportLiveLink,
|
|
3319
|
+
// D3 visualizations — own handler per type (Story 109.2). Only `sequence`
|
|
3320
|
+
// still falls through to exportVisualization (no chart-type of its own).
|
|
3321
|
+
slope: exportSlope,
|
|
3322
|
+
arc: exportArc,
|
|
3323
|
+
timeline: exportTimeline,
|
|
3324
|
+
"event-line": exportEventLine,
|
|
3325
|
+
wordcloud: exportWordcloud,
|
|
3326
|
+
venn: exportVenn,
|
|
3327
|
+
quadrant: exportQuadrant
|
|
3328
|
+
};
|
|
3329
|
+
function resolveArcChordOverride(content, detectedType, palette) {
|
|
3330
|
+
if (detectedType === "arc") {
|
|
3331
|
+
const p = parseArc(content, palette);
|
|
3332
|
+
if (!p.error && p.layout === "chord" && p.links.length) {
|
|
3333
|
+
const emitted = [
|
|
3334
|
+
`chord ${p.title ?? ""}`.trimEnd(),
|
|
3335
|
+
// §1.9 fill family survives the layout re-emit so the circular
|
|
3336
|
+
// renderer honors fill-solid / fill-outline authored on the arc.
|
|
3337
|
+
...p.fillMode ? [`fill-${p.fillMode}`] : [],
|
|
3338
|
+
...p.links.map((l) => `${l.source} -> ${l.target} ${l.value}`)
|
|
3339
|
+
].join("\n");
|
|
3340
|
+
return { content: emitted, type: "chord" };
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
3343
|
+
return null;
|
|
3344
|
+
}
|
|
3345
|
+
async function renderForExport(content, theme, palette, viewState, options) {
|
|
3346
|
+
const exportMode = options?.exportMode ?? false;
|
|
3347
|
+
const { parseDgmoChartType } = await import("./dgmo-router-E5O7RJSW.js");
|
|
3348
|
+
const detectedTypeRaw = parseDgmoChartType(content);
|
|
3349
|
+
const override = resolveArcChordOverride(content, detectedTypeRaw, palette);
|
|
3350
|
+
const renderContent = override?.content ?? content;
|
|
3351
|
+
const detectedType = override?.type ?? detectedTypeRaw;
|
|
3352
|
+
if (detectedType !== null) {
|
|
3353
|
+
const { supportsD3DataChart, renderDataChartD3: renderDataChartD32 } = await import("./charts-d3-SZV2SFTM.js");
|
|
3354
|
+
if (supportsD3DataChart(detectedType)) {
|
|
3355
|
+
return renderDataChartD32(renderContent, theme, palette, {
|
|
3356
|
+
...options?.width !== void 0 && { width: options.width },
|
|
3357
|
+
...options?.height !== void 0 && { height: options.height }
|
|
3358
|
+
});
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
const ctx = {
|
|
3362
|
+
content: renderContent,
|
|
3363
|
+
theme,
|
|
3364
|
+
palette,
|
|
3365
|
+
viewState,
|
|
3366
|
+
options,
|
|
3367
|
+
exportMode,
|
|
3368
|
+
isDark: theme === "dark",
|
|
3369
|
+
// The resolved canvas, and the raw request beside it. A chart whose own
|
|
3370
|
+
// natural size is not EXPORT_WIDTH (tech-radar) needs to tell "the caller
|
|
3371
|
+
// asked for 1200" apart from "nobody asked", which the resolved value
|
|
3372
|
+
// cannot express.
|
|
3373
|
+
requestedWidth: options?.width && options.width > 0 ? Math.round(options.width) : void 0,
|
|
3374
|
+
requestedHeight: options?.height && options.height > 0 ? Math.round(options.height) : void 0,
|
|
3375
|
+
width: options?.width && options.width > 0 ? Math.round(options.width) : EXPORT_WIDTH,
|
|
3376
|
+
height: options?.height && options.height > 0 ? Math.round(options.height) : EXPORT_HEIGHT
|
|
3377
|
+
};
|
|
3378
|
+
const handler = detectedType !== null ? DIAGRAM_EXPORT_HANDLERS[detectedType] : void 0;
|
|
3379
|
+
return (handler ?? exportVisualization)(ctx);
|
|
3380
|
+
}
|
|
3381
|
+
|
|
3263
3382
|
// src/utils/hover-styles.ts
|
|
3264
3383
|
var MAX_HOVER_GROUPS = 40;
|
|
3265
3384
|
var DEFAULT_DIM_OPACITY = 0.4;
|
|
@@ -3592,6 +3711,15 @@ var HOVER_SPECS = {
|
|
|
3592
3711
|
legend: true,
|
|
3593
3712
|
emphasis: "dim"
|
|
3594
3713
|
},
|
|
3714
|
+
// A whiteboard's legend names its colours (#1344); each coloured element
|
|
3715
|
+
// carries its colour's entry.
|
|
3716
|
+
whiteboard: {
|
|
3717
|
+
markSelector: "[data-wb-meaning]",
|
|
3718
|
+
strategy: "enumerated",
|
|
3719
|
+
groupAttr: "data-wb-meaning",
|
|
3720
|
+
emphasis: "dim",
|
|
3721
|
+
legend: true
|
|
3722
|
+
},
|
|
3595
3723
|
sketch: {
|
|
3596
3724
|
markSelector: ".sk-node",
|
|
3597
3725
|
strategy: "connection",
|
|
@@ -4869,12 +4997,12 @@ async function render(source, options) {
|
|
|
4869
4997
|
}
|
|
4870
4998
|
|
|
4871
4999
|
export {
|
|
4872
|
-
renderSlopeChart,
|
|
4873
5000
|
orderArcNodes,
|
|
4874
5001
|
renderArcDiagram,
|
|
4875
|
-
renderWordCloud,
|
|
4876
|
-
renderVenn,
|
|
4877
5002
|
renderQuadrant,
|
|
5003
|
+
renderSlopeChart,
|
|
5004
|
+
renderVenn,
|
|
5005
|
+
renderWordCloud,
|
|
4878
5006
|
renderForExport,
|
|
4879
5007
|
DEFAULT_DIM_OPACITY,
|
|
4880
5008
|
render
|