@zenuml/core 3.47.9 → 3.48.1

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.
Files changed (205) hide show
  1. package/dist/cli/zenuml.mjs +13529 -0
  2. package/dist/cli/zenuml.mjs.map +1 -0
  3. package/dist/cloud-icons-eHuugVSv.js.map +1 -0
  4. package/dist/zenuml.esm.mjs +2153 -2156
  5. package/dist/zenuml.esm.mjs.map +1 -0
  6. package/dist/zenuml.js +82 -82
  7. package/dist/zenuml.js.map +1 -0
  8. package/package.json +18 -5
  9. package/.agents/skills/babysit-pr/SKILL.md +0 -223
  10. package/.agents/skills/babysit-pr/agents/openai.yaml +0 -7
  11. package/.agents/skills/dia-scoring/SKILL.md +0 -139
  12. package/.agents/skills/dia-scoring/agents/openai.yaml +0 -7
  13. package/.agents/skills/dia-scoring/references/selectors-and-keys.md +0 -253
  14. package/.agents/skills/land-pr/SKILL.md +0 -120
  15. package/.agents/skills/propagate-core-release/SKILL.md +0 -205
  16. package/.agents/skills/propagate-core-release/agents/openai.yaml +0 -7
  17. package/.agents/skills/propagate-core-release/references/downstreams.md +0 -42
  18. package/.agents/skills/ship-branch/SKILL.md +0 -105
  19. package/.agents/skills/submit-branch/SKILL.md +0 -76
  20. package/.agents/skills/validate-branch/SKILL.md +0 -72
  21. package/.claude/commands/README.md +0 -162
  22. package/.claude/commands/analyze.md +0 -101
  23. package/.claude/commands/clarify.md +0 -158
  24. package/.claude/commands/code-review.md +0 -322
  25. package/.claude/commands/constitution.md +0 -73
  26. package/.claude/commands/create-docs.md +0 -309
  27. package/.claude/commands/full-context.md +0 -121
  28. package/.claude/commands/gemini-consult.md +0 -164
  29. package/.claude/commands/handoff.md +0 -146
  30. package/.claude/commands/implement.md +0 -56
  31. package/.claude/commands/plan.md +0 -43
  32. package/.claude/commands/refactor.md +0 -188
  33. package/.claude/commands/specify.md +0 -21
  34. package/.claude/commands/tasks.md +0 -62
  35. package/.claude/commands/update-docs.md +0 -314
  36. package/.claude/hooks/README.md +0 -270
  37. package/.claude/hooks/config/sensitive-patterns.json +0 -86
  38. package/.claude/hooks/gemini-context-injector.sh +0 -129
  39. package/.claude/hooks/mcp-security-scan.sh +0 -147
  40. package/.claude/hooks/notify.sh +0 -103
  41. package/.claude/hooks/setup/hook-setup.md +0 -96
  42. package/.claude/hooks/setup/settings.json.template +0 -63
  43. package/.claude/hooks/sounds/complete.wav +0 -0
  44. package/.claude/hooks/sounds/input-needed.wav +0 -0
  45. package/.claude/hooks/subagent-context-injector.sh +0 -65
  46. package/.claude/skills/babysit-pr/SKILL.md +0 -223
  47. package/.claude/skills/babysit-pr/agents/openai.yaml +0 -7
  48. package/.claude/skills/dia-scoring/SKILL.md +0 -139
  49. package/.claude/skills/dia-scoring/agents/openai.yaml +0 -7
  50. package/.claude/skills/dia-scoring/references/selectors-and-keys.md +0 -253
  51. package/.claude/skills/emoji-eval/SKILL.md +0 -187
  52. package/.claude/skills/land-pr/SKILL.md +0 -120
  53. package/.claude/skills/propagate-core-release/SKILL.md +0 -205
  54. package/.claude/skills/propagate-core-release/agents/openai.yaml +0 -7
  55. package/.claude/skills/propagate-core-release/references/downstreams.md +0 -42
  56. package/.claude/skills/ship-branch/SKILL.md +0 -105
  57. package/.claude/skills/submit-branch/SKILL.md +0 -76
  58. package/.claude/skills/validate-branch/SKILL.md +0 -72
  59. package/.claude/skills/zenuml-ux-research/SKILL.md +0 -183
  60. package/.claude/skills/zenuml-ux-research/references/assertion-catalog.md +0 -261
  61. package/.claude/skills/zenuml-ux-research/references/best-practices-overview.md +0 -56
  62. package/.claude/skills/zenuml-ux-research/references/report-template.md +0 -89
  63. package/.claude/skills/zenuml-ux-research/references/scenarios/edit-message-label.md +0 -37
  64. package/.claude/skills/zenuml-ux-research/references/scenarios/insert-message.md +0 -36
  65. package/.claude/skills/zenuml-ux-research/references/scenarios/insert-participant.md +0 -31
  66. package/.claude/skills/zenuml-ux-research/references/scenarios/rename-participant.md +0 -33
  67. package/.claude/skills/zenuml-ux-research/references/scenarios/undo-insert.md +0 -35
  68. package/.devcontainer/devcontainer.json +0 -21
  69. package/.dockerignore +0 -19
  70. package/.eslintrc.js +0 -39
  71. package/.git-blame-ignore-revs +0 -6
  72. package/.kiro/hooks/README.md +0 -38
  73. package/.kiro/hooks/session-sound-notification.js +0 -44
  74. package/.kiro/hooks/session-sound-notification.json +0 -23
  75. package/.mcp.json.example +0 -17
  76. package/.nvmrc +0 -1
  77. package/.prettierignore +0 -4
  78. package/.prettierrc +0 -1
  79. package/.specify/memory/constitution.md +0 -33
  80. package/.specify/scripts/bash/check-prerequisites.sh +0 -166
  81. package/.specify/scripts/bash/common.sh +0 -113
  82. package/.specify/scripts/bash/create-new-feature.sh +0 -97
  83. package/.specify/scripts/bash/setup-plan.sh +0 -60
  84. package/.specify/scripts/bash/update-agent-context.sh +0 -728
  85. package/.specify/templates/agent-file-template.md +0 -23
  86. package/.specify/templates/plan-template.md +0 -219
  87. package/.specify/templates/spec-template.md +0 -116
  88. package/.specify/templates/tasks-template.md +0 -127
  89. package/.storybook/main.ts +0 -25
  90. package/.storybook/preview.ts +0 -29
  91. package/.watchmanconfig +0 -3
  92. package/AGENTS.md +0 -26
  93. package/CLAUDE.md +0 -124
  94. package/DEPLOYMENT.md +0 -62
  95. package/Dockerfile +0 -36
  96. package/IMPLEMENTATION_PLAN.md +0 -163
  97. package/Integration/vanilla-js/index.html +0 -42
  98. package/MCP-ASSISTANT-RULES.md +0 -85
  99. package/README_CN.md +0 -15
  100. package/TUTORIAL.md +0 -116
  101. package/antlr/antlr-4.11.1-complete.jar +0 -0
  102. package/bun.lock +0 -1544
  103. package/bunfig.toml +0 -52
  104. package/docs/UNICODE_SUPPORT.md +0 -179
  105. package/docs/ai-context/deployment-infrastructure.md +0 -21
  106. package/docs/ai-context/docs-overview.md +0 -89
  107. package/docs/ai-context/handoff.md +0 -174
  108. package/docs/ai-context/project-structure.md +0 -160
  109. package/docs/ai-context/system-integration.md +0 -21
  110. package/docs/asciidoc/contributor.adoc +0 -54
  111. package/docs/asciidoc/create-my-own-theme.adoc +0 -149
  112. package/docs/asciidoc/images/creation-component.png +0 -0
  113. package/docs/asciidoc/images/creation-rtl.png +0 -0
  114. package/docs/asciidoc/images/message-arrow-rtl.png +0 -0
  115. package/docs/asciidoc/images/occurrence.png +0 -0
  116. package/docs/asciidoc/images/return-message-conflict.png +0 -0
  117. package/docs/asciidoc/images/shift-up-half-the-height.png +0 -0
  118. package/docs/asciidoc/images/three-layer-info-arch.png +0 -0
  119. package/docs/asciidoc/images/vertical-alignment.svg +0 -1
  120. package/docs/asciidoc/images/vertically-aligning.png +0 -0
  121. package/docs/asciidoc/index.adoc +0 -277
  122. package/docs/asciidoc/theme-debug-web-app.png +0 -0
  123. package/docs/asciidoc/tutorial.adoc +0 -22
  124. package/docs/asciidoc/user-css.png +0 -0
  125. package/docs/async-vs-sync-parser-rules.md +0 -81
  126. package/docs/divider-parser-allow-spaces.md +0 -38
  127. package/docs/highlighting-messages.md +0 -52
  128. package/docs/images/editor-sample.png +0 -0
  129. package/docs/inherited-vs-provided-from.md +0 -64
  130. package/docs/parser/Assignment.md +0 -8
  131. package/docs/parser/PARSER_IMPROVEMENTS_CC.md +0 -425
  132. package/docs/parser/grammar_review_gemini.md +0 -116
  133. package/docs/participants-function.md +0 -25
  134. package/docs/responsive-participant-margin.md +0 -52
  135. package/docs/starter.md +0 -9
  136. package/docs/superpowers/plans/2026-03-27-e2e-test-reorg.md +0 -698
  137. package/docs/superpowers/plans/2026-03-30-emoji-support.md +0 -1220
  138. package/docs/superpowers/plans/2026-03-30-self-correcting-scoring.md +0 -206
  139. package/docs/superpowers/plans/2026-04-15-keyboard-editing-on-diagram.md +0 -1992
  140. package/docs/superpowers/plans/2026-04-15-zenuml-ux-research-skill.md +0 -1452
  141. package/docs/ux-research/.gitkeep +0 -0
  142. package/docs/ux-research/2026-04-15-rename-participant.md +0 -156
  143. package/docs/ux-research/2026-04-18-insert-participant.md +0 -151
  144. package/docs/width-translate-and-offsets.md +0 -62
  145. package/docs/xss.md +0 -59
  146. package/e2e/data/compare-cases.js +0 -1090
  147. package/e2e/data/diff-algorithm.js +0 -199
  148. package/e2e/fixtures/create-message.html +0 -26
  149. package/e2e/fixtures/editable-label.html +0 -35
  150. package/e2e/fixtures/editable-span.html +0 -122
  151. package/e2e/fixtures/empty-diagram.html +0 -23
  152. package/e2e/fixtures/fixture.html +0 -31
  153. package/e2e/fixtures/insert-participant.html +0 -23
  154. package/e2e/fixtures/reorder-cross-fragment.html +0 -31
  155. package/e2e/fixtures/reorder-fragment.html +0 -29
  156. package/e2e/fixtures/reorder-message.html +0 -27
  157. package/e2e/fixtures/svg-test.html +0 -21
  158. package/e2e/fixtures/type-switch.html +0 -29
  159. package/e2e/tools/canonical-history.html +0 -908
  160. package/e2e/tools/compare-case.html +0 -371
  161. package/e2e/tools/compare.html +0 -35
  162. package/e2e/tools/native-diff-ext/background.js +0 -60
  163. package/e2e/tools/native-diff-ext/bridge.js +0 -26
  164. package/e2e/tools/native-diff-ext/content.js +0 -194
  165. package/e2e/tools/svg-preview.html +0 -56
  166. package/embed.html +0 -193
  167. package/eslint.config.mjs +0 -35
  168. package/firebase-debug.log +0 -108
  169. package/iframe-container-demo/diagram.html +0 -124
  170. package/iframe-container-demo/host.html +0 -817
  171. package/index.html +0 -771
  172. package/mermaid-zenuml-async-spa-auth.png +0 -0
  173. package/mermaid-zenuml-async-spa-auth.snapshot.md +0 -96
  174. package/newsletter/unicode-support-announcement.md +0 -134
  175. package/playground/creation.html +0 -53
  176. package/playground/message.html +0 -63
  177. package/playwright.config.ts +0 -40
  178. package/renderer.html +0 -366
  179. package/scripts/analyze-compare-case/collect-data.mjs +0 -1134
  180. package/scripts/analyze-compare-case/config.mjs +0 -102
  181. package/scripts/analyze-compare-case/geometry.mjs +0 -101
  182. package/scripts/analyze-compare-case/native-diff.mjs +0 -224
  183. package/scripts/analyze-compare-case/output.mjs +0 -74
  184. package/scripts/analyze-compare-case/panel-diff.mjs +0 -114
  185. package/scripts/analyze-compare-case/report.mjs +0 -162
  186. package/scripts/analyze-compare-case/residual-scopes.mjs +0 -347
  187. package/scripts/analyze-compare-case/scoring.mjs +0 -829
  188. package/scripts/analyze-compare-case.mjs +0 -149
  189. package/scripts/bump-version.js +0 -117
  190. package/scripts/snapshot-dual.js +0 -173
  191. package/scripts/update-snapshots.js +0 -70
  192. package/skills/dia-scoring/SKILL.md +0 -129
  193. package/skills/dia-scoring/agents/openai.yaml +0 -7
  194. package/skills/dia-scoring/references/selectors-and-keys.md +0 -253
  195. package/tailwind.config.js +0 -126
  196. package/test-compression.html +0 -274
  197. package/test-mermaid-zenuml.html +0 -57
  198. package/test-setup.ts +0 -124
  199. package/test-url-params.html +0 -192
  200. package/tsconfig.app.json +0 -31
  201. package/tsconfig.node.json +0 -24
  202. package/tsconfig.test.json +0 -9
  203. package/vite.config.lib.ts +0 -93
  204. package/vite.config.ts +0 -84
  205. package/wrangler.toml +0 -18
package/index.html DELETED
@@ -1,771 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <!-- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> -->
8
- <!-- <link
9
- rel="preload stylesheet"
10
- as="style"
11
- href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap"
12
- /> -->
13
- <style id="zenumlstyle">
14
- /* Custom styles for the diagram */
15
- </style>
16
- <link
17
- rel="stylesheet"
18
- href="/vendor/highlightjs/github-dark.min.css"
19
- />
20
- <script src="/vendor/codemirror/codemirror.min.js"></script>
21
- <link
22
- rel="stylesheet"
23
- href="/vendor/codemirror/codemirror.min.css"
24
- />
25
- <link
26
- rel="stylesheet"
27
- href="/vendor/codemirror/material-darker.min.css"
28
- />
29
- <title>ZenUML Dev Workbench</title>
30
- <style>
31
- :root {
32
- --bg: #0f172a;
33
- --bg-alt: #111827;
34
- --panel: #ffffff;
35
- --panel-alt: #f8fafc;
36
- --panel-muted: #eef2f7;
37
- --ink: #0f172a;
38
- --muted: #526072;
39
- --line: #d7deea;
40
- --line-strong: #c4cedd;
41
- --accent: #0f766e;
42
- --accent-strong: #115e59;
43
- --danger: #991b1b;
44
- --shadow: 0 18px 48px rgba(15, 23, 42, 0.14);
45
- --radius-lg: 14px;
46
- --radius-md: 10px;
47
- --editor-width: 420px;
48
- }
49
-
50
- * {
51
- box-sizing: border-box;
52
- }
53
-
54
- html,
55
- body {
56
- margin: 0;
57
- min-height: 100%;
58
- }
59
-
60
- body {
61
- font-family:
62
- "SF Pro Text",
63
- "Segoe UI",
64
- system-ui,
65
- sans-serif;
66
- color: var(--ink);
67
- background: linear-gradient(180deg, var(--bg) 0%, var(--bg-alt) 100%);
68
- }
69
-
70
- a {
71
- color: inherit;
72
- }
73
-
74
- code,
75
- .CodeMirror,
76
- .tool-chip,
77
- .tool-button,
78
- .tool-link,
79
- .stats-text,
80
- .toolbar-label {
81
- font-family:
82
- "IBM Plex Mono",
83
- "SFMono-Regular",
84
- "Menlo",
85
- "Monaco",
86
- "Consolas",
87
- monospace;
88
- }
89
-
90
- .app-shell {
91
- min-height: 100vh;
92
- display: grid;
93
- grid-template-rows: auto 1fr;
94
- gap: 12px;
95
- padding: 14px;
96
- }
97
-
98
- .toolbar {
99
- display: grid;
100
- grid-template-columns: minmax(0, 1fr) auto;
101
- align-items: center;
102
- gap: 16px;
103
- padding: 12px 14px;
104
- border: 1px solid rgba(255, 255, 255, 0.08);
105
- border-radius: var(--radius-lg);
106
- background: rgba(15, 23, 42, 0.9);
107
- color: #e5edf8;
108
- box-shadow: var(--shadow);
109
- }
110
-
111
- .toolbar-title {
112
- display: flex;
113
- flex-wrap: wrap;
114
- align-items: baseline;
115
- gap: 12px;
116
- }
117
-
118
- .toolbar-title strong {
119
- font-size: 15px;
120
- font-weight: 700;
121
- letter-spacing: 0.01em;
122
- }
123
-
124
- .toolbar-title span {
125
- color: #9fb1c7;
126
- font-size: 12px;
127
- }
128
-
129
- .toolbar-actions {
130
- display: flex;
131
- align-items: center;
132
- justify-content: flex-end;
133
- flex-wrap: wrap;
134
- gap: 8px;
135
- }
136
-
137
- .toolbar-label {
138
- color: #9fb1c7;
139
- font-size: 11px;
140
- letter-spacing: 0.08em;
141
- text-transform: uppercase;
142
- }
143
-
144
- .workspace {
145
- min-height: 0;
146
- display: grid;
147
- grid-template-columns: minmax(280px, var(--editor-width)) 10px minmax(320px, 1fr) minmax(320px, 1fr);
148
- gap: 12px;
149
- align-items: stretch;
150
- }
151
-
152
- .panel {
153
- display: flex;
154
- flex-direction: column;
155
- min-height: 0;
156
- min-width: 0;
157
- overflow: hidden;
158
- border-radius: var(--radius-lg);
159
- border: 1px solid var(--line);
160
- background: var(--panel);
161
- box-shadow: var(--shadow);
162
- }
163
-
164
- .workspace-resizer {
165
- position: relative;
166
- min-height: 0;
167
- border-radius: 999px;
168
- background: rgba(148, 163, 184, 0.28);
169
- cursor: col-resize;
170
- touch-action: none;
171
- }
172
-
173
- .workspace-resizer::before {
174
- content: "";
175
- position: absolute;
176
- inset: 0;
177
- margin: auto;
178
- width: 4px;
179
- height: 56px;
180
- border-radius: 999px;
181
- background: rgba(15, 118, 110, 0.22);
182
- }
183
-
184
- .workspace-resizer:hover,
185
- .workspace.is-resizing .workspace-resizer {
186
- background: rgba(15, 118, 110, 0.2);
187
- }
188
-
189
- .workspace.is-resizing {
190
- user-select: none;
191
- }
192
-
193
- .panel-header {
194
- display: flex;
195
- align-items: center;
196
- justify-content: space-between;
197
- gap: 14px;
198
- padding: 12px 14px;
199
- border-bottom: 1px solid var(--line);
200
- background: var(--panel-alt);
201
- }
202
-
203
- .panel-title {
204
- display: flex;
205
- flex-direction: column;
206
- gap: 4px;
207
- }
208
-
209
- .panel-title h2,
210
- .panel-title h3 {
211
- margin: 0;
212
- font-size: 14px;
213
- letter-spacing: 0.01em;
214
- }
215
-
216
- .panel-title p {
217
- margin: 0;
218
- color: var(--muted);
219
- font-size: 12px;
220
- line-height: 1.3;
221
- }
222
-
223
- .panel-actions {
224
- display: flex;
225
- align-items: center;
226
- flex-wrap: wrap;
227
- justify-content: flex-end;
228
- gap: 8px;
229
- }
230
-
231
- .tool-button,
232
- .tool-chip,
233
- .tool-link {
234
- display: inline-flex;
235
- align-items: center;
236
- justify-content: center;
237
- appearance: none;
238
- border: 1px solid var(--line);
239
- border-radius: 8px;
240
- padding: 8px 10px;
241
- background: #fff;
242
- color: var(--ink);
243
- cursor: pointer;
244
- text-decoration: none;
245
- transition:
246
- border-color 160ms ease,
247
- background 160ms ease;
248
- font-size: 11px;
249
- letter-spacing: 0.03em;
250
- white-space: nowrap;
251
- }
252
-
253
- .tool-button:hover,
254
- .tool-chip:hover,
255
- .tool-link:hover {
256
- border-color: var(--line-strong);
257
- background: var(--panel-muted);
258
- }
259
-
260
- .toolbar .tool-chip,
261
- .toolbar .tool-link {
262
- background: rgba(15, 23, 42, 0.55);
263
- border-color: rgba(159, 177, 199, 0.25);
264
- color: #e5edf8;
265
- }
266
-
267
- .toolbar .tool-chip:hover,
268
- .toolbar .tool-link:hover {
269
- background: rgba(30, 41, 59, 0.95);
270
- border-color: rgba(191, 209, 230, 0.4);
271
- }
272
-
273
- .tool-chip.is-active {
274
- background: var(--accent);
275
- border-color: var(--accent-strong);
276
- color: #f8fffe;
277
- }
278
-
279
- .tool-button.primary {
280
- background: var(--accent);
281
- border-color: var(--accent-strong);
282
- color: #f8fffe;
283
- }
284
-
285
- .panel-body {
286
- flex: 1;
287
- min-height: 0;
288
- }
289
-
290
- .editor-body {
291
- background: #1d1d1b;
292
- }
293
-
294
- .CodeMirror {
295
- font-size: 14px;
296
- height: 100%;
297
- overflow: hidden;
298
- }
299
-
300
- .CodeMirror-scroll {
301
- padding: 1rem;
302
- }
303
-
304
- .zenuml .CodeMirror .CodeMirror-cursor {
305
- border-color: #fff;
306
- border-left-width: 2px;
307
- }
308
-
309
- .preview-surface {
310
- height: 100%;
311
- overflow: auto;
312
- padding: 12px;
313
- background: var(--panel-muted);
314
- }
315
-
316
- .html-surface {
317
- position: relative;
318
- }
319
-
320
- .preview-stage {
321
- min-height: 100%;
322
- padding: 10px;
323
- border-radius: var(--radius-md);
324
- border: 1px solid var(--line);
325
- background: #fff;
326
- }
327
-
328
- .preview-stage pre {
329
- margin: 0;
330
- }
331
-
332
- .preview-stage svg {
333
- display: block;
334
- }
335
-
336
- .svg-stage {
337
- display: block;
338
- }
339
-
340
- #svg-container {
341
- width: max-content;
342
- margin: 0 auto;
343
- min-width: 100%;
344
- min-height: 100%;
345
- display: grid;
346
- place-items: center;
347
- }
348
-
349
- #svg-container svg {
350
- display: block;
351
- box-shadow: 0 10px 28px rgba(15, 23, 42, 0.08);
352
- }
353
-
354
- .stats-text {
355
- color: #9fb1c7;
356
- font-size: 11px;
357
- }
358
-
359
- .svg-error {
360
- display: grid;
361
- place-items: center;
362
- min-height: 240px;
363
- padding: 20px;
364
- border-radius: var(--radius-md);
365
- border: 1px dashed #d4b4b4;
366
- color: var(--danger);
367
- background: #fff7f7;
368
- text-align: center;
369
- line-height: 1.6;
370
- }
371
-
372
- .workspace.mode-svg,
373
- .workspace.mode-dom {
374
- grid-template-columns: minmax(280px, var(--editor-width)) 10px minmax(720px, 1fr);
375
- }
376
-
377
- .workspace.mode-svg .html-panel,
378
- .workspace.mode-dom .svg-panel {
379
- display: none;
380
- }
381
-
382
- @media (max-width: 1440px) {
383
- .workspace,
384
- .workspace.mode-svg,
385
- .workspace.mode-dom {
386
- grid-template-columns: minmax(280px, var(--editor-width)) 10px minmax(320px, 1fr);
387
- }
388
-
389
- .workspace.mode-split .svg-panel {
390
- grid-column: 3;
391
- }
392
- }
393
-
394
- @media (max-width: 1024px) {
395
- .app-shell {
396
- padding: 10px;
397
- }
398
-
399
- .toolbar {
400
- grid-template-columns: 1fr;
401
- align-items: start;
402
- }
403
-
404
- .workspace,
405
- .workspace.mode-svg,
406
- .workspace.mode-dom {
407
- grid-template-columns: 1fr;
408
- }
409
-
410
- .workspace-resizer {
411
- display: none;
412
- }
413
-
414
- .workspace.mode-split .svg-panel {
415
- grid-column: auto;
416
- }
417
-
418
- .panel {
419
- min-height: 360px;
420
- }
421
- }
422
- </style>
423
- <script src="/vendor/tailwindcss/tailwindcss.js"></script>
424
- </head>
425
- <body>
426
- <div class="app-shell">
427
- <header class="toolbar">
428
- <div class="toolbar-title">
429
- <strong>ZenUML Dev Workbench</strong>
430
- <span>default to native SVG, switch to DOM or split only when needed</span>
431
- </div>
432
- <div class="toolbar-actions">
433
- <span class="toolbar-label">View</span>
434
- <button id="view-svg" class="tool-chip">SVG</button>
435
- <button id="view-dom" class="tool-chip">DOM</button>
436
- <button id="view-split" class="tool-chip">Split</button>
437
- <span class="toolbar-label">Editing</span>
438
- <button class="tool-chip" data-flag="enableParticipantInsertion" title="Toggle ParticipantInsertControls (+ between participants)">+ Participant</button>
439
- <button class="tool-chip" data-flag="enableMessageInsertion" title="Toggle Occurrence drag-to-create + GapHandleZone message handles">+ Message</button>
440
- <button class="tool-chip" data-flag="enableDividerInsertion" title="Toggle GapHandleZone divider button">+ Divider</button>
441
- <button class="tool-chip" data-flag="enableParticipantStyleEditing" title="Toggle ParticipantStylePanel (color/type)">Style Participant</button>
442
- <button id="width-provider-toggle" class="tool-chip"></button>
443
- <span id="svg-stats" class="stats-text">SVG: waiting</span>
444
- <a class="tool-link" href="/e2e/tools/compare.html" target="_blank" rel="noreferrer">
445
- Compare Cases
446
- </a>
447
- <a class="tool-link" href="/e2e/tools/svg-preview.html" target="_blank" rel="noreferrer">
448
- SVG Only
449
- </a>
450
- </div>
451
- </header>
452
-
453
- <main class="workspace mode-svg" id="workspace">
454
- <article class="panel editor-panel">
455
- <div class="panel-header">
456
- <div class="panel-title">
457
- <h2>Editor</h2>
458
- <p>Persisted in <code>localStorage</code>.</p>
459
- </div>
460
- <div class="panel-actions">
461
- <button onclick="loadExample('basic')" class="tool-button">Basic</button>
462
- <button onclick="loadExample('advanced')" class="tool-button">Advanced</button>
463
- <button onclick="clearEditor()" class="tool-button">Clear</button>
464
- <button onclick="exportDiagram()" class="tool-button primary">Export PNG</button>
465
- </div>
466
- </div>
467
- <div class="panel-body editor-body">
468
- <textarea id="text" style="display: none"></textarea>
469
- </div>
470
- </article>
471
-
472
- <div
473
- id="editor-resizer"
474
- class="workspace-resizer"
475
- role="separator"
476
- aria-orientation="vertical"
477
- aria-label="Resize editor"
478
- ></div>
479
-
480
- <article class="panel html-panel">
481
- <div class="panel-header">
482
- <div class="panel-title">
483
- <h3>DOM preview</h3>
484
- <p><code>window.zenUml.render()</code> output.</p>
485
- </div>
486
- </div>
487
- <div class="panel-body preview-surface html-surface">
488
- <div class="preview-stage">
489
- <pre class="zenuml"></pre>
490
- </div>
491
- </div>
492
- </article>
493
-
494
- <article class="panel svg-panel">
495
- <div class="panel-header">
496
- <div class="panel-title">
497
- <h3>Native SVG preview</h3>
498
- <p><code>renderToSvg()</code> output.</p>
499
- </div>
500
- </div>
501
- <div class="panel-body preview-surface svg-surface">
502
- <div class="preview-stage svg-stage">
503
- <div id="svg-container"></div>
504
- </div>
505
- </div>
506
- </article>
507
- </main>
508
- </div>
509
-
510
- <script type="module">
511
- import { waitUntil, debounce } from "./src/utils.ts";
512
- import { createConfig } from "./src/config.ts";
513
- import { toPng } from "html-to-image";
514
- import { renderToSvg } from "./src/svg/renderToSvg.ts";
515
-
516
- const editor = CodeMirror.fromTextArea(document.getElementById("text"), {
517
- lineNumbers: true,
518
- singleCursorHeightPerLine: false,
519
- theme: "material-darker",
520
- mode: "text/plain",
521
- autofocus: true,
522
- });
523
-
524
- const svgContainer = document.getElementById("svg-container");
525
- const svgStats = document.getElementById("svg-stats");
526
- const workspace = document.getElementById("workspace");
527
- const editorResizer = document.getElementById("editor-resizer");
528
- const viewButtons = {
529
- svg: document.getElementById("view-svg"),
530
- dom: document.getElementById("view-dom"),
531
- split: document.getElementById("view-split"),
532
- };
533
- const minEditorWidth = 280;
534
-
535
- function clampEditorWidth(nextWidth) {
536
- const maxEditorWidth = Math.max(minEditorWidth, Math.floor(window.innerWidth * 0.72));
537
- return Math.min(Math.max(nextWidth, minEditorWidth), maxEditorWidth);
538
- }
539
-
540
- function setEditorWidth(nextWidth) {
541
- const clampedWidth = clampEditorWidth(nextWidth);
542
- document.documentElement.style.setProperty("--editor-width", `${clampedWidth}px`);
543
- localStorage.setItem("zenuml-workbench-editor-width", String(clampedWidth));
544
- }
545
-
546
- function setViewMode(mode) {
547
- const validMode = ["svg", "dom", "split"].includes(mode) ? mode : "svg";
548
- workspace.classList.remove("mode-svg", "mode-dom", "mode-split");
549
- workspace.classList.add(`mode-${validMode}`);
550
-
551
- Object.entries(viewButtons).forEach(([key, button]) => {
552
- button.classList.toggle("is-active", key === validMode);
553
- });
554
-
555
- localStorage.setItem("zenuml-workbench-view", validMode);
556
- }
557
-
558
- const FLAG_KEYS = [
559
- "enableParticipantInsertion",
560
- "enableMessageInsertion",
561
- "enableDividerInsertion",
562
- "enableParticipantStyleEditing",
563
- ];
564
- const FLAG_STORAGE_PREFIX = "zenuml-workbench-flag-";
565
-
566
- function readFlag(key) {
567
- const stored = localStorage.getItem(FLAG_STORAGE_PREFIX + key);
568
- // Default ON in the workbench so dev experience matches main.tsx.
569
- return stored === null ? true : stored === "true";
570
- }
571
-
572
- function writeFlag(key, value) {
573
- localStorage.setItem(FLAG_STORAGE_PREFIX + key, String(value));
574
- }
575
-
576
- function readFlags() {
577
- return Object.fromEntries(FLAG_KEYS.map((k) => [k, readFlag(k)]));
578
- }
579
-
580
- function syncFlagButtons() {
581
- document.querySelectorAll("[data-flag]").forEach((btn) => {
582
- btn.classList.toggle("is-active", readFlag(btn.dataset.flag));
583
- });
584
- }
585
-
586
- const updateHtmlPreview = debounce((content) => {
587
- const config = createConfig({
588
- ...readFlags(),
589
- onContentChange: (code) => editor.setValue(code),
590
- });
591
-
592
- window.zenUml.render(content, config).then((r) => {
593
- window.parentLogger
594
- .child({ name: "index.html" })
595
- .debug("render resolved", r);
596
- });
597
- }, 400);
598
-
599
- document.querySelectorAll("[data-flag]").forEach((btn) => {
600
- btn.addEventListener("click", () => {
601
- const key = btn.dataset.flag;
602
- writeFlag(key, !readFlag(key));
603
- syncFlagButtons();
604
- updateHtmlPreview(editor.getValue());
605
- });
606
- });
607
- syncFlagButtons();
608
-
609
- const updateSvgPreview = debounce((content) => {
610
- try {
611
- const t0 = performance.now();
612
- const result = renderToSvg(content);
613
- const dt = (performance.now() - t0).toFixed(1);
614
-
615
- if (!result.svg || result.width === 0 || result.height === 0) {
616
- svgContainer.innerHTML = `
617
- <div class="svg-error">
618
- Native SVG output is empty for the current input.
619
- </div>
620
- `;
621
- svgStats.textContent = "SVG: empty";
622
- return;
623
- }
624
-
625
- svgContainer.innerHTML = result.svg;
626
- svgStats.textContent = `SVG ${result.width}x${result.height} | ${dt}ms`;
627
- } catch (error) {
628
- console.error("Failed to render native SVG preview:", error);
629
- svgContainer.innerHTML = `
630
- <div class="svg-error">
631
- Native SVG preview failed. Check the console for details.
632
- </div>
633
- `;
634
- svgStats.textContent = "SVG: error";
635
- }
636
- }, 180);
637
-
638
- Object.entries(viewButtons).forEach(([mode, button]) => {
639
- button.addEventListener("click", () => setViewMode(mode));
640
- });
641
-
642
- editorResizer.addEventListener("pointerdown", (event) => {
643
- if (window.innerWidth <= 1024) {
644
- return;
645
- }
646
-
647
- event.preventDefault();
648
- workspace.classList.add("is-resizing");
649
- editorResizer.setPointerCapture(event.pointerId);
650
-
651
- const onPointerMove = (moveEvent) => {
652
- setEditorWidth(moveEvent.clientX - workspace.getBoundingClientRect().left);
653
- };
654
-
655
- const stopResize = () => {
656
- workspace.classList.remove("is-resizing");
657
- editorResizer.removeEventListener("pointermove", onPointerMove);
658
- editorResizer.removeEventListener("pointerup", stopResize);
659
- editorResizer.removeEventListener("pointercancel", stopResize);
660
- };
661
-
662
- editorResizer.addEventListener("pointermove", onPointerMove);
663
- editorResizer.addEventListener("pointerup", stopResize);
664
- editorResizer.addEventListener("pointercancel", stopResize);
665
- });
666
-
667
- window.addEventListener("resize", () => {
668
- const savedWidth = Number(localStorage.getItem("zenuml-workbench-editor-width"));
669
- if (savedWidth) {
670
- setEditorWidth(savedWidth);
671
- }
672
- });
673
-
674
- editor.on("change", function (cm) {
675
- const content = cm.getValue();
676
- updateSvgPreview(content);
677
-
678
- waitUntil(
679
- () => window.zenUml,
680
- () => {
681
- updateHtmlPreview(content);
682
- // Save to localStorage
683
- localStorage.setItem("zenuml-cm-code", content);
684
- },
685
- );
686
- });
687
-
688
- // Example data
689
- const examples = {
690
- basic: `Alice -> Bob: Hello Bob!
691
- Bob -> Alice: Hello Alice!`,
692
- advanced: `title Online Shopping
693
- participant Customer
694
- participant WebApp
695
- participant PaymentService
696
- participant Database
697
-
698
- Customer -> WebApp: Browse products
699
- WebApp -> Database: Query products
700
- Database --> WebApp: Return products
701
- WebApp --> Customer: Display products
702
-
703
- Customer -> WebApp: Add to cart
704
- WebApp -> Database: Update cart
705
- Database --> WebApp: Cart updated
706
- WebApp --> Customer: Show cart
707
-
708
- Customer -> WebApp: Checkout
709
- WebApp -> PaymentService: Process payment
710
- PaymentService --> WebApp: Payment confirmed
711
- WebApp -> Database: Create order
712
- Database --> WebApp: Order created
713
- WebApp --> Customer: Order confirmation`,
714
- };
715
-
716
- // Global functions
717
- window.loadExample = function (type) {
718
- editor.setValue(examples[type] || examples.basic);
719
- };
720
-
721
- window.clearEditor = function () {
722
- editor.setValue("");
723
- };
724
-
725
- window.exportDiagram = async function () {
726
- const element = document.querySelector(".zenuml");
727
- if (element) {
728
- try {
729
- const dataUrl = await toPng(element);
730
- const link = document.createElement("a");
731
- link.download = "sequence-diagram.png";
732
- link.href = dataUrl;
733
- link.click();
734
- } catch (error) {
735
- console.error("Failed to export diagram:", error);
736
- }
737
- }
738
- };
739
-
740
- // Load saved code from localStorage or default example
741
- const savedCode = localStorage.getItem("zenuml-cm-code");
742
- if (savedCode) {
743
- editor.setValue(savedCode);
744
- } else {
745
- editor.setValue(examples.basic);
746
- }
747
-
748
- const savedEditorWidth = Number(localStorage.getItem("zenuml-workbench-editor-width"));
749
- if (savedEditorWidth) {
750
- setEditorWidth(savedEditorWidth);
751
- }
752
-
753
- setViewMode(localStorage.getItem("zenuml-workbench-view") || "svg");
754
- </script>
755
- <script type="module">
756
- const params = new URLSearchParams(location.search);
757
- const wp = params.get("WIDTH_PROVIDER") || import.meta.env.VITE_WIDTH_PROVIDER || "browser";
758
- const toggle = document.getElementById("width-provider-toggle");
759
- const isCanvas = wp === "canvas";
760
- toggle.textContent = "WIDTH: " + wp;
761
- toggle.classList.toggle("is-active", isCanvas);
762
- toggle.title = "Click to switch to " + (isCanvas ? "browser" : "canvas");
763
- toggle.addEventListener("click", () => {
764
- const next = isCanvas ? "browser" : "canvas";
765
- params.set("WIDTH_PROVIDER", next);
766
- location.search = params.toString();
767
- });
768
- </script>
769
- <script type="module" src="/src/main.tsx"></script>
770
- </body>
771
- </html>