antri_cli 1.57.6 → 1.57.7
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/cli/shortcuts.d.ts.map +1 -1
- package/dist/cli/shortcuts.js +12 -10
- package/dist/cli/shortcuts.js.map +1 -1
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +17 -12
- package/dist/core/agent.js.map +1 -1
- package/dist/core/artifactManager.d.ts +1 -0
- package/dist/core/artifactManager.d.ts.map +1 -1
- package/dist/core/artifactManager.js +372 -292
- package/dist/core/artifactManager.js.map +1 -1
- package/dist/core/updater.d.ts +1 -1
- package/dist/core/updater.js +1 -1
- package/dist/desktop/public/index.html +1 -1
- package/dist/desktop/server.d.ts.map +1 -1
- package/dist/desktop/server.js +3 -624
- package/dist/desktop/server.js.map +1 -1
- package/package.json +1 -1
|
@@ -45,23 +45,34 @@ export class ArtifactManager {
|
|
|
45
45
|
saveArtifact(artifact) {
|
|
46
46
|
this.ensureDirectory();
|
|
47
47
|
this.artifacts.set(artifact.id, artifact);
|
|
48
|
-
// Also write a standalone file for
|
|
48
|
+
// Also write a standalone HTML file for instant browser viewing
|
|
49
49
|
try {
|
|
50
|
-
const
|
|
51
|
-
const filePath = path.join(this.baseDir, `${artifact.id}
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
const fullHtml = this.getArtifactHtml(artifact);
|
|
51
|
+
const filePath = path.join(this.baseDir, `${artifact.id}.html`);
|
|
52
|
+
fs.writeFileSync(filePath, fullHtml, 'utf-8');
|
|
53
|
+
}
|
|
54
|
+
catch { }
|
|
55
|
+
this.persistIndex();
|
|
56
|
+
return artifact;
|
|
57
|
+
}
|
|
58
|
+
getArtifactHtml(artifact) {
|
|
59
|
+
if (artifact.type === 'html') {
|
|
60
|
+
let content = artifact.content.trim();
|
|
61
|
+
if (!content.toLowerCase().includes('<!doctype html>') && !content.toLowerCase().includes('<html')) {
|
|
62
|
+
content = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>${artifact.title}</title><style>body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;background:#0f172a;color:#f8fafc;padding:16px;}</style></head><body>${content}</body></html>`;
|
|
54
63
|
}
|
|
55
|
-
|
|
56
|
-
|
|
64
|
+
return content;
|
|
65
|
+
}
|
|
66
|
+
if (artifact.type === 'mindmap') {
|
|
67
|
+
return `<!DOCTYPE html>
|
|
57
68
|
<html lang="en">
|
|
58
69
|
<head>
|
|
59
70
|
<meta charset="UTF-8">
|
|
60
71
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
61
72
|
<title>${artifact.title}</title>
|
|
62
|
-
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
|
|
63
|
-
<script src="https://cdn.jsdelivr.net/npm/markmap-view@0.17.2"></script>
|
|
64
|
-
<script src="https://cdn.jsdelivr.net/npm/markmap-lib@0.17.2"></script>
|
|
73
|
+
<script src="https://cdn.jsdelivr.net/npm/d3@7.8.5/dist/d3.min.js"></script>
|
|
74
|
+
<script src="https://cdn.jsdelivr.net/npm/markmap-view@0.17.2/dist/browser/index.js"></script>
|
|
75
|
+
<script src="https://cdn.jsdelivr.net/npm/markmap-lib@0.17.2/dist/browser/index.js"></script>
|
|
65
76
|
<style>
|
|
66
77
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
67
78
|
:root {
|
|
@@ -81,6 +92,8 @@ export class ArtifactManager {
|
|
|
81
92
|
--root-bg: #4f46e5;
|
|
82
93
|
--root-border: #4338ca;
|
|
83
94
|
--root-text: #ffffff;
|
|
95
|
+
--pillar-bg: #f1f5f9;
|
|
96
|
+
--pillar-border: #94a3b8;
|
|
84
97
|
--link-stroke: #818cf8;
|
|
85
98
|
--badge-bg: rgba(168, 85, 247, 0.12);
|
|
86
99
|
--badge-color: #7e22ce;
|
|
@@ -103,13 +116,15 @@ export class ArtifactManager {
|
|
|
103
116
|
--root-bg: #6366f1;
|
|
104
117
|
--root-border: #818cf8;
|
|
105
118
|
--root-text: #ffffff;
|
|
119
|
+
--pillar-bg: #0f172a;
|
|
120
|
+
--pillar-border: #475569;
|
|
106
121
|
--link-stroke: #6366f1;
|
|
107
122
|
--badge-bg: rgba(168, 85, 247, 0.2);
|
|
108
123
|
--badge-color: #c084fc;
|
|
109
124
|
--badge-border: rgba(168, 85, 247, 0.35);
|
|
110
125
|
}
|
|
111
126
|
body {
|
|
112
|
-
margin: 0; padding:
|
|
127
|
+
margin: 0; padding: 16px;
|
|
113
128
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
114
129
|
background: var(--bg-page);
|
|
115
130
|
color: var(--text-main);
|
|
@@ -117,31 +132,31 @@ export class ArtifactManager {
|
|
|
117
132
|
overflow-x: hidden;
|
|
118
133
|
transition: background 0.3s ease;
|
|
119
134
|
}
|
|
120
|
-
.header { text-align: center; margin-bottom:
|
|
121
|
-
h1 { font-size:
|
|
135
|
+
.header { text-align: center; margin-bottom: 12px; }
|
|
136
|
+
h1 { font-size: 18px; color: var(--text-main); margin: 0 0 6px 0; font-weight: 800; letter-spacing: -0.3px; }
|
|
122
137
|
.badge {
|
|
123
138
|
font-size: 11px;
|
|
124
139
|
background: var(--badge-bg);
|
|
125
140
|
color: var(--badge-color);
|
|
126
|
-
padding:
|
|
141
|
+
padding: 3px 12px; border-radius: 9999px;
|
|
127
142
|
border: 1px solid var(--badge-border);
|
|
128
143
|
text-transform: uppercase; font-weight: 700; letter-spacing: 0.5px;
|
|
129
144
|
display: inline-block; margin-bottom: 6px;
|
|
130
145
|
}
|
|
131
146
|
.controls {
|
|
132
|
-
display: flex; gap: 8px; margin-bottom:
|
|
147
|
+
display: flex; gap: 8px; margin-bottom: 12px; align-items: center; flex-wrap: wrap; justify-content: center;
|
|
133
148
|
}
|
|
134
149
|
.btn {
|
|
135
150
|
background: var(--btn-bg); border: 1px solid var(--btn-border);
|
|
136
|
-
color: var(--btn-text); padding:
|
|
151
|
+
color: var(--btn-text); padding: 6px 14px; border-radius: 8px; font-size: 12px;
|
|
137
152
|
font-weight: 700; cursor: pointer; transition: all 0.15s; display: flex; align-items: center; gap: 6px;
|
|
138
153
|
box-shadow: 0 2px 4px rgba(0,0,0,0.03);
|
|
139
154
|
}
|
|
140
155
|
.btn:hover { background: var(--btn-hover); transform: translateY(-1px); }
|
|
141
156
|
.btn:active { transform: translateY(0); }
|
|
142
157
|
.viewer-card {
|
|
143
|
-
width: 100%; max-width:
|
|
144
|
-
position: relative; overflow: hidden; border-radius:
|
|
158
|
+
width: 100%; max-width: 1300px; height: 76vh; min-height: 520px;
|
|
159
|
+
position: relative; overflow: hidden; border-radius: 16px;
|
|
145
160
|
background: var(--bg-viewport); backdrop-filter: blur(20px);
|
|
146
161
|
border: 1px solid var(--border-viewport);
|
|
147
162
|
box-shadow: var(--shadow-viewport);
|
|
@@ -151,51 +166,104 @@ export class ArtifactManager {
|
|
|
151
166
|
width: 100%; height: 100%;
|
|
152
167
|
display: block;
|
|
153
168
|
cursor: grab;
|
|
169
|
+
user-select: none;
|
|
154
170
|
}
|
|
155
171
|
#mindmapSvg:active { cursor: grabbing; }
|
|
172
|
+
|
|
173
|
+
/* Native SVG Mindmap Node Styles */
|
|
174
|
+
.mindmap-link {
|
|
175
|
+
fill: none;
|
|
176
|
+
stroke: var(--link-stroke);
|
|
177
|
+
stroke-width: 2.2px;
|
|
178
|
+
stroke-linecap: round;
|
|
179
|
+
transition: stroke 0.2s ease;
|
|
180
|
+
}
|
|
181
|
+
.node-rect {
|
|
182
|
+
fill: var(--node-bg);
|
|
183
|
+
stroke: var(--node-border);
|
|
184
|
+
stroke-width: 1.5px;
|
|
185
|
+
transition: all 0.2s ease;
|
|
186
|
+
cursor: pointer;
|
|
187
|
+
}
|
|
188
|
+
.node-rect:hover {
|
|
189
|
+
stroke: var(--root-bg);
|
|
190
|
+
stroke-width: 2px;
|
|
191
|
+
}
|
|
192
|
+
.node-rect.root {
|
|
193
|
+
fill: var(--root-bg);
|
|
194
|
+
stroke: var(--root-border);
|
|
195
|
+
stroke-width: 2px;
|
|
196
|
+
}
|
|
197
|
+
.node-rect.pillar {
|
|
198
|
+
fill: var(--pillar-bg);
|
|
199
|
+
stroke: var(--pillar-border);
|
|
200
|
+
stroke-width: 1.8px;
|
|
201
|
+
}
|
|
202
|
+
.node-text {
|
|
203
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
204
|
+
font-size: 13px;
|
|
205
|
+
font-weight: 600;
|
|
206
|
+
fill: var(--node-text);
|
|
207
|
+
pointer-events: none;
|
|
208
|
+
user-select: none;
|
|
209
|
+
}
|
|
210
|
+
.depth-0 .node-text {
|
|
211
|
+
font-size: 15px;
|
|
212
|
+
font-weight: 800;
|
|
213
|
+
fill: var(--root-text);
|
|
214
|
+
}
|
|
215
|
+
.depth-1 .node-text {
|
|
216
|
+
font-size: 13.5px;
|
|
217
|
+
font-weight: 700;
|
|
218
|
+
}
|
|
219
|
+
.badge-circle {
|
|
220
|
+
fill: var(--root-bg);
|
|
221
|
+
stroke: var(--bg-viewport);
|
|
222
|
+
stroke-width: 1.5px;
|
|
223
|
+
transition: transform 0.15s ease;
|
|
224
|
+
}
|
|
225
|
+
.badge-circle:hover {
|
|
226
|
+
transform: scale(1.15);
|
|
227
|
+
}
|
|
228
|
+
.badge-text {
|
|
229
|
+
font-family: monospace;
|
|
230
|
+
font-size: 12px;
|
|
231
|
+
font-weight: bold;
|
|
232
|
+
fill: #ffffff;
|
|
233
|
+
pointer-events: none;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* Markmap CSS Overrides */
|
|
237
|
+
foreignObject {
|
|
238
|
+
overflow: visible !important;
|
|
239
|
+
}
|
|
156
240
|
.markmap-foreign {
|
|
157
241
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
|
|
158
|
-
font-size:
|
|
242
|
+
font-size: 13px !important;
|
|
159
243
|
font-weight: 600 !important;
|
|
160
|
-
line-height: 1.
|
|
244
|
+
line-height: 1.35 !important;
|
|
161
245
|
color: var(--node-text) !important;
|
|
162
246
|
background: var(--node-bg) !important;
|
|
163
247
|
border: 1.5px solid var(--node-border) !important;
|
|
164
248
|
border-radius: 8px !important;
|
|
165
|
-
padding:
|
|
249
|
+
padding: 5px 12px !important;
|
|
166
250
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04) !important;
|
|
167
|
-
display: inline-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
251
|
+
display: inline-block !important;
|
|
252
|
+
white-space: normal !important;
|
|
253
|
+
max-width: 320px !important;
|
|
254
|
+
word-break: break-word !important;
|
|
171
255
|
}
|
|
172
256
|
.markmap-node[data-depth="0"] .markmap-foreign {
|
|
173
257
|
background: var(--root-bg) !important;
|
|
174
258
|
color: var(--root-text) !important;
|
|
175
259
|
border-color: var(--root-border) !important;
|
|
176
|
-
font-size:
|
|
260
|
+
font-size: 15px !important;
|
|
177
261
|
font-weight: 800 !important;
|
|
178
262
|
border-radius: 10px !important;
|
|
179
|
-
padding:
|
|
263
|
+
padding: 7px 16px !important;
|
|
180
264
|
box-shadow: 0 4px 14px rgba(79, 70, 229, 0.35) !important;
|
|
181
265
|
}
|
|
182
|
-
|
|
183
|
-
font-weight: 700 !important;
|
|
184
|
-
border-width: 1.8px !important;
|
|
185
|
-
}
|
|
186
|
-
.markmap-link {
|
|
187
|
-
fill: none !important;
|
|
188
|
-
stroke: var(--link-stroke) !important;
|
|
189
|
-
stroke-width: 2px !important;
|
|
190
|
-
stroke-linecap: round !important;
|
|
191
|
-
}
|
|
192
|
-
.markmap-node > circle {
|
|
193
|
-
fill: var(--root-bg) !important;
|
|
194
|
-
stroke: var(--root-border) !important;
|
|
195
|
-
stroke-width: 2px !important;
|
|
196
|
-
r: 6 !important;
|
|
197
|
-
cursor: pointer !important;
|
|
198
|
-
}
|
|
266
|
+
|
|
199
267
|
.help-hint {
|
|
200
268
|
position: absolute; bottom: 12px; right: 14px;
|
|
201
269
|
font-size: 11px; color: var(--text-muted); pointer-events: none;
|
|
@@ -222,178 +290,292 @@ export class ArtifactManager {
|
|
|
222
290
|
</div>
|
|
223
291
|
<div class="viewer-card" id="viewerCard">
|
|
224
292
|
<svg id="mindmapSvg"></svg>
|
|
225
|
-
<div class="help-hint">🖱️ Drag to pan · Scroll to zoom · Click
|
|
293
|
+
<div class="help-hint">🖱️ Drag to pan · Scroll to zoom · Click +/- handles to collapse branches</div>
|
|
226
294
|
</div>
|
|
227
295
|
<script>
|
|
228
296
|
const rawContent = ${JSON.stringify(artifact.content.trim())};
|
|
229
297
|
|
|
230
|
-
function
|
|
231
|
-
if (content.startsWith('#') || content.startsWith('-') || content.includes('\\n#') || content.includes('\\n-')) {
|
|
232
|
-
return content;
|
|
233
|
-
}
|
|
298
|
+
function parseTree(content) {
|
|
234
299
|
const lines = content.split('\\n');
|
|
235
|
-
const
|
|
300
|
+
const rootNode = { name: '${artifact.title.replace(/'/g, "\\'")}', children: [], collapsed: false };
|
|
301
|
+
const stack = [{ node: rootNode, depth: 0 }];
|
|
302
|
+
|
|
236
303
|
let baseIndent = -1;
|
|
237
|
-
for (let
|
|
304
|
+
for (let rawLine of lines) {
|
|
305
|
+
const line = rawLine.replace(/\\r$/, '');
|
|
238
306
|
const trimmed = line.trim();
|
|
239
307
|
if (!trimmed || trimmed === 'mindmap') continue;
|
|
308
|
+
|
|
240
309
|
const indent = line.search(/\\S/);
|
|
241
310
|
if (baseIndent === -1) baseIndent = indent;
|
|
242
311
|
const rel = Math.max(0, indent - baseIndent);
|
|
243
|
-
|
|
244
|
-
|
|
312
|
+
let depth = Math.floor(rel / 2);
|
|
313
|
+
|
|
245
314
|
let clean = trimmed
|
|
315
|
+
.replace(/^#+\\s*/, '')
|
|
316
|
+
.replace(/^[-*]\\s*/, '')
|
|
246
317
|
.replace(/^root\\(\\((.*?)\\)\\)$/, '$1')
|
|
247
318
|
.replace(/^\\(\\((.*?)\\)\\)$/, '$1')
|
|
248
319
|
.replace(/^\\[(.*?)\\]$/, '$1')
|
|
249
320
|
.replace(/^\\((.*?)\\)$/, '$1')
|
|
250
321
|
.replace(/^\\)\\)(.*?)\\(\\($/, '$1')
|
|
251
322
|
.replace(/^\\)(.*?)\\($/, '$1')
|
|
252
|
-
.replace(/^\\{\\{(.*?)\\}\\}/, '$1')
|
|
253
|
-
|
|
323
|
+
.replace(/^\\{\\{(.*?)\\}\\}/, '$1')
|
|
324
|
+
.trim();
|
|
325
|
+
|
|
254
326
|
if (depth === 0) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
mdLines.push('## ' + clean);
|
|
258
|
-
} else {
|
|
259
|
-
mdLines.push(' '.repeat(depth - 1) + '- ' + clean);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
return mdLines.join('\\n');
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
const markdownText = parseToMarkdown(rawContent);
|
|
266
|
-
let mmInstance = null;
|
|
267
|
-
|
|
268
|
-
function renderMarkmap() {
|
|
269
|
-
try {
|
|
270
|
-
if (window.markmap && window.markmap.Transformer) {
|
|
271
|
-
const { Transformer, Markmap } = window.markmap;
|
|
272
|
-
const transformer = new Transformer();
|
|
273
|
-
const { root } = transformer.transform(markdownText);
|
|
274
|
-
const svgEl = document.getElementById('mindmapSvg');
|
|
275
|
-
svgEl.innerHTML = '';
|
|
276
|
-
mmInstance = Markmap.create(svgEl, {
|
|
277
|
-
autoFit: true,
|
|
278
|
-
duration: 250,
|
|
279
|
-
nodeMinHeight: 28,
|
|
280
|
-
spacingVertical: 14,
|
|
281
|
-
spacingHorizontal: 85,
|
|
282
|
-
paddingX: 16
|
|
283
|
-
}, root);
|
|
284
|
-
return;
|
|
327
|
+
rootNode.name = clean || rootNode.name;
|
|
328
|
+
continue;
|
|
285
329
|
}
|
|
286
|
-
|
|
287
|
-
|
|
330
|
+
|
|
331
|
+
const newNode = { name: clean, children: [], collapsed: false };
|
|
332
|
+
while (stack.length > depth) stack.pop();
|
|
333
|
+
stack[stack.length - 1].node.children.push(newNode);
|
|
334
|
+
stack.push({ node: newNode, depth: depth });
|
|
288
335
|
}
|
|
289
|
-
|
|
336
|
+
|
|
337
|
+
return rootNode;
|
|
290
338
|
}
|
|
291
339
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const lines = markdownText.split('\\n').filter(l => l.trim().length > 0);
|
|
296
|
-
const rootNode = { name: '${artifact.title}', children: [] };
|
|
297
|
-
const stack = [{ node: rootNode, depth: 0 }];
|
|
340
|
+
const rootTree = parseTree(rawContent);
|
|
341
|
+
const svgEl = document.getElementById('mindmapSvg');
|
|
342
|
+
const viewerCard = document.getElementById('viewerCard');
|
|
298
343
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
344
|
+
let currentScale = 1;
|
|
345
|
+
let currentX = 0;
|
|
346
|
+
let currentY = 0;
|
|
347
|
+
let isPanning = false;
|
|
348
|
+
let startPointerX = 0;
|
|
349
|
+
let startPointerY = 0;
|
|
350
|
+
let startPosX = 0;
|
|
351
|
+
let startPosY = 0;
|
|
352
|
+
let bbox = { minX: 0, maxX: 800, minY: 0, maxY: 600 };
|
|
353
|
+
|
|
354
|
+
function renderTree() {
|
|
355
|
+
svgEl.innerHTML = '';
|
|
356
|
+
|
|
357
|
+
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
|
358
|
+
g.setAttribute('id', 'viewportGroup');
|
|
359
|
+
svgEl.appendChild(g);
|
|
360
|
+
|
|
361
|
+
// Measure node pill dimensions based on text length
|
|
362
|
+
function measure(node, depth = 0) {
|
|
363
|
+
node.depth = depth;
|
|
364
|
+
const textLen = (node.name || '').length;
|
|
365
|
+
const isRoot = depth === 0;
|
|
366
|
+
const isPillar = depth === 1;
|
|
367
|
+
const fontFactor = isRoot ? 9.5 : isPillar ? 8.2 : 7.6;
|
|
368
|
+
const pad = isRoot ? 40 : 28;
|
|
369
|
+
node.w = Math.max(isRoot ? 160 : 120, Math.min(360, textLen * fontFactor + pad));
|
|
370
|
+
node.h = isRoot ? 44 : isPillar ? 38 : 34;
|
|
371
|
+
if (node.children && !node.collapsed) {
|
|
372
|
+
node.children.forEach(c => measure(c, depth + 1));
|
|
312
373
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
stack[stack.length - 1].node.children.push(newNode);
|
|
316
|
-
stack.push({ node: newNode, depth: depth });
|
|
317
|
-
});
|
|
374
|
+
}
|
|
375
|
+
measure(rootTree, 0);
|
|
318
376
|
|
|
377
|
+
// Layout coordinates
|
|
319
378
|
let curY = 40;
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
379
|
+
const HORIZ_GAP = 75;
|
|
380
|
+
const VERT_GAP = 14;
|
|
381
|
+
|
|
382
|
+
function layout(node, startX = 40) {
|
|
383
|
+
node.x = startX;
|
|
384
|
+
if (!node.children || node.children.length === 0 || node.collapsed) {
|
|
385
|
+
node.y = curY + node.h / 2;
|
|
386
|
+
curY += node.h + VERT_GAP;
|
|
326
387
|
} else {
|
|
327
|
-
|
|
388
|
+
const nextX = startX + node.w + HORIZ_GAP;
|
|
389
|
+
node.children.forEach(c => layout(c, nextX));
|
|
328
390
|
const firstY = node.children[0].y;
|
|
329
391
|
const lastY = node.children[node.children.length - 1].y;
|
|
330
392
|
node.y = (firstY + lastY) / 2;
|
|
331
393
|
}
|
|
332
394
|
}
|
|
333
|
-
layout(
|
|
395
|
+
layout(rootTree, 40);
|
|
334
396
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
397
|
+
// Calculate Bounding Box
|
|
398
|
+
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
399
|
+
function findBounds(node) {
|
|
400
|
+
minX = Math.min(minX, node.x);
|
|
401
|
+
maxX = Math.max(maxX, node.x + node.w + 20);
|
|
402
|
+
minY = Math.min(minY, node.y - node.h / 2);
|
|
403
|
+
maxY = Math.max(maxY, node.y + node.h / 2);
|
|
404
|
+
if (node.children && !node.collapsed) {
|
|
405
|
+
node.children.forEach(findBounds);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
findBounds(rootTree);
|
|
409
|
+
bbox = { minX, maxX, minY, maxY };
|
|
338
410
|
|
|
411
|
+
// Draw links and nodes
|
|
339
412
|
function draw(node) {
|
|
340
|
-
if (node.children) {
|
|
341
|
-
node.children.forEach(
|
|
413
|
+
if (node.children && node.children.length > 0 && !node.collapsed) {
|
|
414
|
+
node.children.forEach(child => {
|
|
415
|
+
const x1 = node.x + node.w;
|
|
416
|
+
const y1 = node.y;
|
|
417
|
+
const x2 = child.x;
|
|
418
|
+
const y2 = child.y;
|
|
419
|
+
const dx = (x2 - x1) * 0.48;
|
|
342
420
|
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
343
|
-
const x1 = node.x + 130, y1 = node.y;
|
|
344
|
-
const x2 = c.x, y2 = c.y;
|
|
345
|
-
const dx = (x2 - x1) * 0.5;
|
|
346
421
|
path.setAttribute('d', 'M ' + x1 + ' ' + y1 + ' C ' + (x1 + dx) + ' ' + y1 + ', ' + (x2 - dx) + ' ' + y2 + ', ' + x2 + ' ' + y2);
|
|
347
|
-
path.setAttribute('class', '
|
|
422
|
+
path.setAttribute('class', 'mindmap-link');
|
|
348
423
|
g.appendChild(path);
|
|
349
|
-
draw(
|
|
424
|
+
draw(child);
|
|
350
425
|
});
|
|
351
426
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
427
|
+
|
|
428
|
+
const nodeG = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
|
429
|
+
nodeG.setAttribute('class', 'mindmap-node depth-' + node.depth);
|
|
430
|
+
|
|
431
|
+
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
|
432
|
+
rect.setAttribute('x', node.x);
|
|
433
|
+
rect.setAttribute('y', node.y - node.h / 2);
|
|
434
|
+
rect.setAttribute('width', node.w);
|
|
435
|
+
rect.setAttribute('height', node.h);
|
|
436
|
+
rect.setAttribute('rx', node.depth === 0 ? '12' : '8');
|
|
437
|
+
rect.setAttribute('ry', node.depth === 0 ? '12' : '8');
|
|
438
|
+
rect.setAttribute('class', 'node-rect ' + (node.depth === 0 ? 'root' : node.depth === 1 ? 'pillar' : 'leaf'));
|
|
439
|
+
nodeG.appendChild(rect);
|
|
440
|
+
|
|
441
|
+
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
|
442
|
+
text.setAttribute('x', node.x + node.w / 2);
|
|
443
|
+
text.setAttribute('y', node.y + (node.depth === 0 ? 5.5 : 4.5));
|
|
444
|
+
text.setAttribute('text-anchor', 'middle');
|
|
445
|
+
text.setAttribute('class', 'node-text');
|
|
446
|
+
text.textContent = node.name;
|
|
447
|
+
nodeG.appendChild(text);
|
|
448
|
+
|
|
449
|
+
// Collapsible Badge Button
|
|
450
|
+
if (node.children && node.children.length > 0) {
|
|
451
|
+
const badgeG = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
|
452
|
+
badgeG.setAttribute('transform', 'translate(' + (node.x + node.w) + ', ' + node.y + ')');
|
|
453
|
+
badgeG.style.cursor = 'pointer';
|
|
454
|
+
badgeG.onclick = (e) => {
|
|
455
|
+
e.stopPropagation();
|
|
456
|
+
node.collapsed = !node.collapsed;
|
|
457
|
+
renderTree();
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
|
|
461
|
+
circle.setAttribute('r', '7.5');
|
|
462
|
+
circle.setAttribute('class', 'badge-circle');
|
|
463
|
+
badgeG.appendChild(circle);
|
|
464
|
+
|
|
465
|
+
const sign = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
|
466
|
+
sign.setAttribute('y', '3.5');
|
|
467
|
+
sign.setAttribute('text-anchor', 'middle');
|
|
468
|
+
sign.setAttribute('class', 'badge-text');
|
|
469
|
+
sign.textContent = node.collapsed ? '+' : '−';
|
|
470
|
+
badgeG.appendChild(sign);
|
|
471
|
+
|
|
472
|
+
nodeG.appendChild(badgeG);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
g.appendChild(nodeG);
|
|
359
476
|
}
|
|
360
|
-
draw(
|
|
361
|
-
|
|
477
|
+
draw(rootTree);
|
|
478
|
+
|
|
479
|
+
applyTransform();
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function applyTransform() {
|
|
483
|
+
const g = document.getElementById('viewportGroup');
|
|
484
|
+
if (g) {
|
|
485
|
+
g.setAttribute('transform', 'translate(' + currentX + ', ' + currentY + ') scale(' + currentScale + ')');
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
function fitView() {
|
|
490
|
+
const cw = viewerCard.clientWidth || 1000;
|
|
491
|
+
const ch = viewerCard.clientHeight || 550;
|
|
492
|
+
const tw = (bbox.maxX - bbox.minX) + 80;
|
|
493
|
+
const th = (bbox.maxY - bbox.minY) + 80;
|
|
494
|
+
|
|
495
|
+
currentScale = Math.min(1.15, Math.max(0.35, Math.min((cw - 60) / tw, (ch - 60) / th)));
|
|
496
|
+
currentX = (cw - tw * currentScale) / 2 + 20 * currentScale;
|
|
497
|
+
currentY = (ch - th * currentScale) / 2 + 20 * currentScale;
|
|
498
|
+
applyTransform();
|
|
362
499
|
}
|
|
363
500
|
|
|
364
501
|
function zoomIn() {
|
|
365
|
-
|
|
502
|
+
currentScale = Math.min(currentScale * 1.25, 3.5);
|
|
503
|
+
applyTransform();
|
|
366
504
|
}
|
|
505
|
+
|
|
367
506
|
function zoomOut() {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
function fitView() {
|
|
371
|
-
if (mmInstance) mmInstance.fit();
|
|
507
|
+
currentScale = Math.max(currentScale * 0.8, 0.25);
|
|
508
|
+
applyTransform();
|
|
372
509
|
}
|
|
510
|
+
|
|
373
511
|
function toggleTheme() {
|
|
374
512
|
document.body.classList.toggle('theme-dark');
|
|
375
513
|
const isDark = document.body.classList.contains('theme-dark');
|
|
376
514
|
const btn = document.getElementById('themeToggleBtn');
|
|
377
515
|
if (btn) btn.textContent = isDark ? '☀️ Light Mode' : '🌙 Poster Dark';
|
|
378
516
|
}
|
|
517
|
+
|
|
379
518
|
function copySource() {
|
|
380
519
|
navigator.clipboard.writeText(rawContent).then(() => {
|
|
381
|
-
alert('Mind map source copied to clipboard!');
|
|
520
|
+
alert('Mind map source code copied to clipboard!');
|
|
382
521
|
});
|
|
383
522
|
}
|
|
384
523
|
|
|
524
|
+
// Pointer Interaction (Pan & Zoom)
|
|
525
|
+
viewerCard.addEventListener('pointerdown', (e) => {
|
|
526
|
+
isPanning = true;
|
|
527
|
+
startPointerX = e.clientX;
|
|
528
|
+
startPointerY = e.clientY;
|
|
529
|
+
startPosX = currentX;
|
|
530
|
+
startPosY = currentY;
|
|
531
|
+
viewerCard.setPointerCapture(e.pointerId);
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
viewerCard.addEventListener('pointermove', (e) => {
|
|
535
|
+
if (!isPanning) return;
|
|
536
|
+
currentX = startPosX + (e.clientX - startPointerX);
|
|
537
|
+
currentY = startPosY + (e.clientY - startPointerY);
|
|
538
|
+
applyTransform();
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
const endPan = (e) => {
|
|
542
|
+
isPanning = false;
|
|
543
|
+
try { viewerCard.releasePointerCapture(e.pointerId); } catch (_) {}
|
|
544
|
+
};
|
|
545
|
+
viewerCard.addEventListener('pointerup', endPan);
|
|
546
|
+
viewerCard.addEventListener('pointercancel', endPan);
|
|
547
|
+
|
|
548
|
+
viewerCard.addEventListener('wheel', (e) => {
|
|
549
|
+
e.preventDefault();
|
|
550
|
+
const delta = e.deltaY < 0 ? 1.12 : 0.89;
|
|
551
|
+
const newScale = Math.min(Math.max(currentScale * delta, 0.25), 3.5);
|
|
552
|
+
|
|
553
|
+
const rect = viewerCard.getBoundingClientRect();
|
|
554
|
+
const mouseX = e.clientX - rect.left;
|
|
555
|
+
const mouseY = e.clientY - rect.top;
|
|
556
|
+
|
|
557
|
+
currentX = mouseX - (mouseX - currentX) * (newScale / currentScale);
|
|
558
|
+
currentY = mouseY - (mouseY - currentY) * (newScale / currentScale);
|
|
559
|
+
currentScale = newScale;
|
|
560
|
+
applyTransform();
|
|
561
|
+
}, { passive: false });
|
|
562
|
+
|
|
563
|
+
window.addEventListener('resize', fitView);
|
|
385
564
|
window.addEventListener('load', () => {
|
|
386
|
-
|
|
565
|
+
renderTree();
|
|
566
|
+
setTimeout(fitView, 50);
|
|
387
567
|
});
|
|
388
|
-
if (document.readyState === 'complete')
|
|
568
|
+
if (document.readyState === 'complete') {
|
|
569
|
+
renderTree();
|
|
570
|
+
setTimeout(fitView, 50);
|
|
571
|
+
}
|
|
389
572
|
</script>
|
|
390
573
|
</body>
|
|
391
574
|
</html>`;
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const htmlGraph = `<!DOCTYPE html>
|
|
575
|
+
}
|
|
576
|
+
if (artifact.type === 'graph') {
|
|
577
|
+
const badgeLabel = '📊 Architecture Graph';
|
|
578
|
+
return `<!DOCTYPE html>
|
|
397
579
|
<html lang="en">
|
|
398
580
|
<head>
|
|
399
581
|
<meta charset="UTF-8">
|
|
@@ -442,7 +624,7 @@ export class ArtifactManager {
|
|
|
442
624
|
transition: background 0.3s ease;
|
|
443
625
|
}
|
|
444
626
|
.header { text-align: center; margin-bottom: 14px; }
|
|
445
|
-
h1 { font-size: 19px; color: var(--text-main); margin: 0 0 6px 0; font-weight: 800; }
|
|
627
|
+
h1 { font-size: 19px; color: var(--text-main); margin: 0 0 6px 0; font-weight: 800; letter-spacing: -0.3px; }
|
|
446
628
|
.badge {
|
|
447
629
|
font-size: 11px;
|
|
448
630
|
background: var(--badge-bg);
|
|
@@ -464,35 +646,22 @@ export class ArtifactManager {
|
|
|
464
646
|
.btn:hover { background: var(--btn-hover); transform: translateY(-1px); }
|
|
465
647
|
.btn:active { transform: translateY(0); }
|
|
466
648
|
.viewer-card {
|
|
467
|
-
width: 100%; max-width:
|
|
649
|
+
width: 100%; max-width: 1300px; height: 76vh; min-height: 520px;
|
|
468
650
|
position: relative; overflow: hidden; border-radius: 18px;
|
|
469
651
|
background: var(--bg-viewport); backdrop-filter: blur(20px);
|
|
470
652
|
border: 1px solid var(--border-viewport);
|
|
471
653
|
box-shadow: var(--shadow-viewport);
|
|
472
|
-
|
|
654
|
+
display: flex; align-items: center; justify-content: center;
|
|
655
|
+
touch-action: none; cursor: grab;
|
|
473
656
|
}
|
|
474
|
-
.viewer-card
|
|
475
|
-
.
|
|
657
|
+
.viewer-card:active { cursor: grabbing; }
|
|
658
|
+
.diagram-container {
|
|
476
659
|
width: 100%; height: 100%;
|
|
477
660
|
display: flex; align-items: center; justify-content: center;
|
|
478
661
|
transform-origin: center center;
|
|
479
|
-
|
|
480
|
-
}
|
|
481
|
-
.canvas-wrap.animating {
|
|
482
|
-
transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
483
|
-
}
|
|
484
|
-
.mermaid { width: 100%; text-align: center; }
|
|
485
|
-
.mermaid svg { max-width: 100%; height: auto; }
|
|
486
|
-
.help-hint {
|
|
487
|
-
position: absolute; bottom: 12px; right: 14px;
|
|
488
|
-
font-size: 11px; color: var(--text-muted); pointer-events: none;
|
|
489
|
-
background: rgba(255, 255, 255, 0.75); padding: 3px 8px; border-radius: 6px;
|
|
490
|
-
border: 1px solid rgba(0,0,0,0.05);
|
|
491
|
-
}
|
|
492
|
-
body.theme-dark .help-hint {
|
|
493
|
-
background: rgba(18, 24, 38, 0.7);
|
|
494
|
-
border-color: rgba(255, 255, 255, 0.08);
|
|
662
|
+
transition: transform 0.05s ease-out;
|
|
495
663
|
}
|
|
664
|
+
.mermaid { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
|
|
496
665
|
</style>
|
|
497
666
|
</head>
|
|
498
667
|
<body>
|
|
@@ -503,133 +672,64 @@ export class ArtifactManager {
|
|
|
503
672
|
<div class="controls">
|
|
504
673
|
<button class="btn" onclick="zoomIn()">🔍 Zoom +</button>
|
|
505
674
|
<button class="btn" onclick="zoomOut()">🔍 Zoom -</button>
|
|
506
|
-
<button class="btn" onclick="resetZoom()">⛶ Reset</button>
|
|
675
|
+
<button class="btn" onclick="resetZoom()">⛶ Fit / Reset</button>
|
|
507
676
|
<button class="btn" onclick="toggleTheme()" id="themeToggleBtn">🌙 Poster Dark</button>
|
|
508
677
|
</div>
|
|
509
678
|
<div class="viewer-card" id="viewerCard">
|
|
510
|
-
<div class="
|
|
511
|
-
<pre class="mermaid"
|
|
512
|
-
${artifact.content.trim()}
|
|
513
|
-
</pre>
|
|
679
|
+
<div class="diagram-container" id="diagramContainer">
|
|
680
|
+
<pre class="mermaid">${artifact.content.replace(/<antri_artifact[\s\S]*?>|<\/antri_artifact>/gi, '').trim()}</pre>
|
|
514
681
|
</div>
|
|
515
|
-
<div class="help-hint">🖱️ Drag to pan · Scroll to zoom</div>
|
|
516
682
|
</div>
|
|
517
683
|
<script>
|
|
518
684
|
let scale = 1.0;
|
|
519
685
|
let posX = 0;
|
|
520
686
|
let posY = 0;
|
|
521
687
|
let isDragging = false;
|
|
522
|
-
let
|
|
523
|
-
let
|
|
524
|
-
|
|
525
|
-
let startPosY = 0;
|
|
526
|
-
|
|
527
|
-
const activeTouches = new Map();
|
|
528
|
-
let initialPinchDist = 0;
|
|
529
|
-
let initialPinchScale = 1.0;
|
|
530
|
-
|
|
688
|
+
let startX = 0;
|
|
689
|
+
let startY = 0;
|
|
690
|
+
const container = document.getElementById('diagramContainer');
|
|
531
691
|
const viewerCard = document.getElementById('viewerCard');
|
|
532
|
-
const canvasWrap = document.getElementById('canvasWrap');
|
|
533
692
|
|
|
534
693
|
function updateTransform(animate = false) {
|
|
535
694
|
if (animate) {
|
|
536
|
-
|
|
537
|
-
setTimeout(() => canvasWrap.classList.remove('animating'), 320);
|
|
695
|
+
container.style.transition = 'transform 0.25s cubic-bezier(0.2, 0, 0, 1)';
|
|
538
696
|
} else {
|
|
539
|
-
|
|
697
|
+
container.style.transition = 'none';
|
|
540
698
|
}
|
|
541
|
-
|
|
699
|
+
container.style.transform = 'translate(' + posX + 'px, ' + posY + 'px) scale(' + scale + ')';
|
|
542
700
|
}
|
|
543
701
|
|
|
544
702
|
viewerCard.addEventListener('pointerdown', (e) => {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
isDragging = true;
|
|
550
|
-
viewerCard.classList.add('grabbing');
|
|
551
|
-
startPointerX = e.clientX;
|
|
552
|
-
startPointerY = e.clientY;
|
|
553
|
-
startPosX = posX;
|
|
554
|
-
startPosY = posY;
|
|
555
|
-
} else if (activeTouches.size === 2) {
|
|
556
|
-
isDragging = false;
|
|
557
|
-
viewerCard.classList.remove('grabbing');
|
|
558
|
-
const pts = Array.from(activeTouches.values());
|
|
559
|
-
initialPinchDist = Math.hypot(pts[0].x - pts[1].x, pts[0].y - pts[1].y);
|
|
560
|
-
initialPinchScale = scale;
|
|
561
|
-
}
|
|
703
|
+
isDragging = true;
|
|
704
|
+
startX = e.clientX - posX;
|
|
705
|
+
startY = e.clientY - posY;
|
|
706
|
+
viewerCard.setPointerCapture(e.pointerId);
|
|
562
707
|
});
|
|
563
708
|
|
|
564
709
|
viewerCard.addEventListener('pointermove', (e) => {
|
|
565
|
-
if (!
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
const dx = e.clientX - startPointerX;
|
|
570
|
-
const dy = e.clientY - startPointerY;
|
|
571
|
-
posX = startPosX + dx;
|
|
572
|
-
posY = startPosY + dy;
|
|
573
|
-
updateTransform(false);
|
|
574
|
-
} else if (activeTouches.size === 2) {
|
|
575
|
-
const pts = Array.from(activeTouches.values());
|
|
576
|
-
const currentDist = Math.hypot(pts[0].x - pts[1].x, pts[0].y - pts[1].y);
|
|
577
|
-
if (initialPinchDist > 0) {
|
|
578
|
-
scale = Math.min(Math.max(initialPinchScale * (currentDist / initialPinchDist), 0.2), 4.0);
|
|
579
|
-
updateTransform(false);
|
|
580
|
-
}
|
|
581
|
-
}
|
|
710
|
+
if (!isDragging) return;
|
|
711
|
+
posX = e.clientX - startX;
|
|
712
|
+
posY = e.clientY - startY;
|
|
713
|
+
updateTransform(false);
|
|
582
714
|
});
|
|
583
715
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
try { viewerCard.releasePointerCapture(e.pointerId); } catch {}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
} else if (activeTouches.size === 1) {
|
|
591
|
-
isDragging = true;
|
|
592
|
-
viewerCard.classList.add('grabbing');
|
|
593
|
-
const remaining = Array.from(activeTouches.values())[0];
|
|
594
|
-
startPointerX = remaining.x;
|
|
595
|
-
startPointerY = remaining.y;
|
|
596
|
-
startPosX = posX;
|
|
597
|
-
startPosY = posY;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
viewerCard.addEventListener('pointerup', endPointer);
|
|
602
|
-
viewerCard.addEventListener('pointercancel', endPointer);
|
|
716
|
+
const endDrag = (e) => {
|
|
717
|
+
isDragging = false;
|
|
718
|
+
try { viewerCard.releasePointerCapture(e.pointerId); } catch (_) {}
|
|
719
|
+
};
|
|
720
|
+
viewerCard.addEventListener('pointerup', endDrag);
|
|
721
|
+
viewerCard.addEventListener('pointercancel', endDrag);
|
|
603
722
|
|
|
604
723
|
viewerCard.addEventListener('wheel', (e) => {
|
|
605
724
|
e.preventDefault();
|
|
606
|
-
const delta = e.deltaY < 0 ? 1.
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
const rect = viewerCard.getBoundingClientRect();
|
|
610
|
-
const mouseX = e.clientX - rect.left - rect.width / 2;
|
|
611
|
-
const mouseY = e.clientY - rect.top - rect.height / 2;
|
|
612
|
-
|
|
613
|
-
posX = mouseX - (mouseX - posX) * (newScale / scale);
|
|
614
|
-
posY = mouseY - (mouseY - posY) * (newScale / scale);
|
|
615
|
-
scale = newScale;
|
|
725
|
+
const delta = e.deltaY < 0 ? 1.12 : 0.89;
|
|
726
|
+
scale = Math.min(Math.max(scale * delta, 0.25), 4.0);
|
|
616
727
|
updateTransform(false);
|
|
617
728
|
}, { passive: false });
|
|
618
729
|
|
|
619
|
-
function zoomIn() {
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
}
|
|
623
|
-
function zoomOut() {
|
|
624
|
-
scale = Math.max(scale * 0.8, 0.2);
|
|
625
|
-
updateTransform(true);
|
|
626
|
-
}
|
|
627
|
-
function resetZoom() {
|
|
628
|
-
scale = 1.0;
|
|
629
|
-
posX = 0;
|
|
630
|
-
posY = 0;
|
|
631
|
-
updateTransform(true);
|
|
632
|
-
}
|
|
730
|
+
function zoomIn() { scale = Math.min(scale * 1.25, 4.0); updateTransform(true); }
|
|
731
|
+
function zoomOut() { scale = Math.max(scale * 0.8, 0.25); updateTransform(true); }
|
|
732
|
+
function resetZoom() { scale = 1.0; posX = 0; posY = 0; updateTransform(true); }
|
|
633
733
|
function toggleTheme() {
|
|
634
734
|
document.body.classList.toggle('theme-dark');
|
|
635
735
|
const isDark = document.body.classList.contains('theme-dark');
|
|
@@ -637,32 +737,12 @@ ${artifact.content.trim()}
|
|
|
637
737
|
if (btn) btn.textContent = isDark ? '☀️ Light Mode' : '🌙 Poster Dark';
|
|
638
738
|
}
|
|
639
739
|
|
|
640
|
-
mermaid.initialize({
|
|
641
|
-
startOnLoad: true,
|
|
642
|
-
theme: 'base',
|
|
643
|
-
securityLevel: 'loose',
|
|
644
|
-
themeVariables: {
|
|
645
|
-
darkMode: false,
|
|
646
|
-
background: '#ffffff',
|
|
647
|
-
primaryColor: '#6366f1',
|
|
648
|
-
primaryTextColor: '#0f172a',
|
|
649
|
-
primaryBorderColor: '#4f46e5',
|
|
650
|
-
lineColor: '#6366f1',
|
|
651
|
-
secondaryColor: '#0ea5e9',
|
|
652
|
-
tertiaryColor: '#10b981',
|
|
653
|
-
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
|
|
654
|
-
fontSize: '14px'
|
|
655
|
-
}
|
|
656
|
-
});
|
|
740
|
+
mermaid.initialize({ startOnLoad: true, theme: 'base', securityLevel: 'loose' });
|
|
657
741
|
</script>
|
|
658
742
|
</body>
|
|
659
743
|
</html>`;
|
|
660
|
-
fs.writeFileSync(path.join(this.baseDir, `${artifact.id}.html`), htmlGraph, 'utf-8');
|
|
661
|
-
}
|
|
662
744
|
}
|
|
663
|
-
|
|
664
|
-
this.persistIndex();
|
|
665
|
-
return artifact;
|
|
745
|
+
return artifact.content;
|
|
666
746
|
}
|
|
667
747
|
getArtifact(id) {
|
|
668
748
|
return this.artifacts.get(id) || null;
|