living-documentation 7.42.0 → 7.43.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/src/frontend/diagram/custom-shapes.js +96 -0
- package/dist/src/frontend/diagram/main.js +7 -0
- package/dist/src/frontend/diagram/network.js +57 -49
- package/dist/src/frontend/diagram/node-rendering.js +96 -0
- package/dist/src/frontend/diagram/persistence.js +1 -0
- package/dist/src/frontend/diagram/ports.js +46 -13
- package/dist/src/frontend/diagram/state.js +2 -0
- package/dist/src/frontend/diagram.html +65 -0
- package/dist/src/frontend/i18n/en.json +1 -0
- package/dist/src/frontend/i18n/fr.json +1 -0
- package/dist/src/frontend/shape-editor.html +465 -0
- package/dist/src/routes/shape-libraries.d.ts +3 -0
- package/dist/src/routes/shape-libraries.d.ts.map +1 -0
- package/dist/src/routes/shape-libraries.js +98 -0
- package/dist/src/routes/shape-libraries.js.map +1 -0
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +3 -0
- package/dist/src/server.js.map +1 -1
- package/package.json +1 -1
|
@@ -409,6 +409,7 @@
|
|
|
409
409
|
"diagram.toolbar.postit": "Post-it (P)",
|
|
410
410
|
"diagram.toolbar.text_free": "Texte libre (T)",
|
|
411
411
|
"diagram.toolbar.image": "Image — double-clic sur le canvas pour choisir un fichier, ou coller (⌘V) depuis le presse-papier",
|
|
412
|
+
"diagram.toolbar.shape_editor": "Éditeur de formes personnalisées",
|
|
412
413
|
"diagram.toolbar.arrow": "Flèche (F)",
|
|
413
414
|
"diagram.toolbar.delete": "Supprimer (Suppr)",
|
|
414
415
|
"diagram.toolbar.align_guides": "Guides d'alignement — indique l'alignement entre formes du même type",
|
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="fr">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Shape editor — Living Documentation</title>
|
|
7
|
+
<script src="https://cdn.tailwindcss.com?plugins=typography"></script>
|
|
8
|
+
<script>
|
|
9
|
+
tailwind.config = { darkMode: "class", theme: { extend: {} } };
|
|
10
|
+
</script>
|
|
11
|
+
<style>
|
|
12
|
+
.btn {
|
|
13
|
+
display: inline-flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
height: 2rem;
|
|
17
|
+
padding: 0 0.75rem;
|
|
18
|
+
border-radius: 0.375rem;
|
|
19
|
+
font-size: 0.8125rem;
|
|
20
|
+
font-weight: 600;
|
|
21
|
+
border: 1px solid #d1d5db;
|
|
22
|
+
background: #fff;
|
|
23
|
+
color: #374151;
|
|
24
|
+
}
|
|
25
|
+
.btn:hover { background: #f3f4f6; }
|
|
26
|
+
.btn-primary {
|
|
27
|
+
border-color: #2563eb;
|
|
28
|
+
background: #2563eb;
|
|
29
|
+
color: #fff;
|
|
30
|
+
}
|
|
31
|
+
.btn-primary:hover { background: #1d4ed8; }
|
|
32
|
+
.btn-danger {
|
|
33
|
+
border-color: #fecaca;
|
|
34
|
+
color: #b91c1c;
|
|
35
|
+
}
|
|
36
|
+
.btn-danger:hover { background: #fef2f2; }
|
|
37
|
+
.field {
|
|
38
|
+
height: 2rem;
|
|
39
|
+
border: 1px solid #d1d5db;
|
|
40
|
+
border-radius: 0.375rem;
|
|
41
|
+
padding: 0 0.5rem;
|
|
42
|
+
font-size: 0.875rem;
|
|
43
|
+
background: #fff;
|
|
44
|
+
}
|
|
45
|
+
.shape-item.active {
|
|
46
|
+
background: #eff6ff;
|
|
47
|
+
color: #1d4ed8;
|
|
48
|
+
}
|
|
49
|
+
#previewStage {
|
|
50
|
+
position: relative;
|
|
51
|
+
width: min(34rem, 100%);
|
|
52
|
+
aspect-ratio: 1 / 1;
|
|
53
|
+
border: 1px solid #d1d5db;
|
|
54
|
+
border-radius: 0.5rem;
|
|
55
|
+
background:
|
|
56
|
+
linear-gradient(45deg, #f9fafb 25%, transparent 25%),
|
|
57
|
+
linear-gradient(-45deg, #f9fafb 25%, transparent 25%),
|
|
58
|
+
linear-gradient(45deg, transparent 75%, #f9fafb 75%),
|
|
59
|
+
linear-gradient(-45deg, transparent 75%, #f9fafb 75%);
|
|
60
|
+
background-size: 1.25rem 1.25rem;
|
|
61
|
+
background-position: 0 0, 0 0.625rem, 0.625rem -0.625rem, -0.625rem 0;
|
|
62
|
+
overflow: hidden;
|
|
63
|
+
}
|
|
64
|
+
#previewImage {
|
|
65
|
+
position: absolute;
|
|
66
|
+
inset: 0;
|
|
67
|
+
width: 100%;
|
|
68
|
+
height: 100%;
|
|
69
|
+
object-fit: fill;
|
|
70
|
+
pointer-events: none;
|
|
71
|
+
}
|
|
72
|
+
.anchor-dot {
|
|
73
|
+
position: absolute;
|
|
74
|
+
width: 0.9rem;
|
|
75
|
+
height: 0.9rem;
|
|
76
|
+
transform: translate(-50%, -50%);
|
|
77
|
+
border-radius: 999px;
|
|
78
|
+
border: 2px solid #fff;
|
|
79
|
+
background: #f97316;
|
|
80
|
+
box-shadow: 0 1px 4px rgba(0,0,0,.35);
|
|
81
|
+
cursor: grab;
|
|
82
|
+
}
|
|
83
|
+
.anchor-dot:active { cursor: grabbing; }
|
|
84
|
+
.anchor-dot span {
|
|
85
|
+
position: absolute;
|
|
86
|
+
left: 50%;
|
|
87
|
+
top: calc(100% + 0.2rem);
|
|
88
|
+
transform: translateX(-50%);
|
|
89
|
+
font: 10px/1 system-ui, sans-serif;
|
|
90
|
+
color: #374151;
|
|
91
|
+
background: rgba(255,255,255,.9);
|
|
92
|
+
padding: 1px 3px;
|
|
93
|
+
border-radius: 3px;
|
|
94
|
+
white-space: nowrap;
|
|
95
|
+
}
|
|
96
|
+
</style>
|
|
97
|
+
</head>
|
|
98
|
+
<body class="h-screen overflow-hidden bg-gray-50 text-gray-900">
|
|
99
|
+
<header class="h-12 border-b border-gray-200 bg-white flex items-center gap-2 px-3">
|
|
100
|
+
<button class="btn" onclick="history.back()">← Back</button>
|
|
101
|
+
<h1 class="text-sm font-semibold">Shape editor</h1>
|
|
102
|
+
<span id="saveState" class="ml-auto text-xs text-gray-500"></span>
|
|
103
|
+
</header>
|
|
104
|
+
|
|
105
|
+
<main class="h-[calc(100vh-3rem)] grid grid-cols-[17rem_1fr] overflow-hidden">
|
|
106
|
+
<aside class="border-r border-gray-200 bg-white flex flex-col min-h-0">
|
|
107
|
+
<div class="p-3 border-b border-gray-200 space-y-2">
|
|
108
|
+
<label class="block text-xs font-semibold text-gray-500">Library</label>
|
|
109
|
+
<div class="flex gap-2">
|
|
110
|
+
<select id="librarySelect" class="field flex-1"></select>
|
|
111
|
+
<button id="btnAddLibrary" class="btn">+</button>
|
|
112
|
+
</div>
|
|
113
|
+
<input id="libraryName" class="field w-full" placeholder="Library name" />
|
|
114
|
+
</div>
|
|
115
|
+
<div class="p-3 border-b border-gray-200 flex gap-2">
|
|
116
|
+
<button id="btnNewShape" class="btn btn-primary flex-1">New shape</button>
|
|
117
|
+
<button id="btnDeleteShape" class="btn btn-danger">Delete</button>
|
|
118
|
+
</div>
|
|
119
|
+
<div id="shapeList" class="flex-1 overflow-y-auto p-2 space-y-1"></div>
|
|
120
|
+
</aside>
|
|
121
|
+
|
|
122
|
+
<section class="min-w-0 min-h-0 overflow-y-auto p-5">
|
|
123
|
+
<div class="grid grid-cols-[minmax(20rem,34rem)_minmax(20rem,1fr)] gap-5 items-start">
|
|
124
|
+
<div class="space-y-3">
|
|
125
|
+
<div id="previewStage">
|
|
126
|
+
<img id="previewImage" alt="" />
|
|
127
|
+
</div>
|
|
128
|
+
<p class="text-xs text-gray-500">
|
|
129
|
+
Click on the image to add an anchor. Drag anchors to refine their position.
|
|
130
|
+
</p>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<div class="space-y-4">
|
|
134
|
+
<div class="grid grid-cols-2 gap-3">
|
|
135
|
+
<label class="space-y-1">
|
|
136
|
+
<span class="block text-xs font-semibold text-gray-500">Shape name</span>
|
|
137
|
+
<input id="shapeName" class="field w-full" placeholder="Shape name" />
|
|
138
|
+
</label>
|
|
139
|
+
<label class="space-y-1">
|
|
140
|
+
<span class="block text-xs font-semibold text-gray-500">Image / SVG</span>
|
|
141
|
+
<input id="imageFile" type="file" accept="image/*,.svg" class="block w-full text-sm" />
|
|
142
|
+
</label>
|
|
143
|
+
<label class="space-y-1">
|
|
144
|
+
<span class="block text-xs font-semibold text-gray-500">Width</span>
|
|
145
|
+
<input id="shapeWidth" type="number" min="16" max="1200" class="field w-full" />
|
|
146
|
+
</label>
|
|
147
|
+
<label class="space-y-1">
|
|
148
|
+
<span class="block text-xs font-semibold text-gray-500">Height</span>
|
|
149
|
+
<input id="shapeHeight" type="number" min="16" max="1200" class="field w-full" />
|
|
150
|
+
</label>
|
|
151
|
+
<label class="space-y-1 col-span-2">
|
|
152
|
+
<span class="block text-xs font-semibold text-gray-500">Text placement</span>
|
|
153
|
+
<select id="labelPlacement" class="field w-full">
|
|
154
|
+
<option value="below">Below the shape</option>
|
|
155
|
+
<option value="center">Centered in the shape</option>
|
|
156
|
+
</select>
|
|
157
|
+
</label>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<div class="flex flex-wrap gap-2">
|
|
161
|
+
<button id="btnDefaultAnchors" class="btn">Use 8 default anchors</button>
|
|
162
|
+
<button id="btnClearAnchors" class="btn">Clear anchors</button>
|
|
163
|
+
<button id="btnSaveShape" class="btn btn-primary">Save shape</button>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<div>
|
|
167
|
+
<div class="flex items-center justify-between mb-2">
|
|
168
|
+
<h2 class="text-xs font-semibold uppercase tracking-wide text-gray-500">Anchors</h2>
|
|
169
|
+
<span id="anchorCount" class="text-xs text-gray-500"></span>
|
|
170
|
+
</div>
|
|
171
|
+
<div id="anchorList" class="space-y-1"></div>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
</section>
|
|
176
|
+
</main>
|
|
177
|
+
|
|
178
|
+
<script type="module">
|
|
179
|
+
import { DEFAULT_CUSTOM_ANCHORS } from '/diagram/custom-shapes.js';
|
|
180
|
+
|
|
181
|
+
const els = {
|
|
182
|
+
saveState: document.getElementById('saveState'),
|
|
183
|
+
librarySelect: document.getElementById('librarySelect'),
|
|
184
|
+
libraryName: document.getElementById('libraryName'),
|
|
185
|
+
shapeList: document.getElementById('shapeList'),
|
|
186
|
+
previewStage: document.getElementById('previewStage'),
|
|
187
|
+
previewImage: document.getElementById('previewImage'),
|
|
188
|
+
shapeName: document.getElementById('shapeName'),
|
|
189
|
+
imageFile: document.getElementById('imageFile'),
|
|
190
|
+
shapeWidth: document.getElementById('shapeWidth'),
|
|
191
|
+
shapeHeight: document.getElementById('shapeHeight'),
|
|
192
|
+
labelPlacement: document.getElementById('labelPlacement'),
|
|
193
|
+
anchorList: document.getElementById('anchorList'),
|
|
194
|
+
anchorCount: document.getElementById('anchorCount'),
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
let store = { libraries: [] };
|
|
198
|
+
let activeLibraryId = null;
|
|
199
|
+
let activeShapeId = null;
|
|
200
|
+
let draft = null;
|
|
201
|
+
let draggingAnchorId = null;
|
|
202
|
+
|
|
203
|
+
const uid = (prefix) => `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
|
|
204
|
+
const activeLibrary = () => store.libraries.find((lib) => lib.id === activeLibraryId) || null;
|
|
205
|
+
const activeShape = () => activeLibrary()?.shapes.find((shape) => shape.id === activeShapeId) || null;
|
|
206
|
+
const clamp01 = (n) => Math.max(0, Math.min(1, n));
|
|
207
|
+
const escapeAttr = (value) => String(value ?? '').replace(/[&<>"']/g, (char) => ({
|
|
208
|
+
'&': '&',
|
|
209
|
+
'<': '<',
|
|
210
|
+
'>': '>',
|
|
211
|
+
'"': '"',
|
|
212
|
+
"'": ''',
|
|
213
|
+
}[char]));
|
|
214
|
+
|
|
215
|
+
function setStatus(text) {
|
|
216
|
+
els.saveState.textContent = text;
|
|
217
|
+
if (text) setTimeout(() => { if (els.saveState.textContent === text) els.saveState.textContent = ''; }, 1800);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async function loadStore() {
|
|
221
|
+
const res = await fetch('/api/shape-libraries');
|
|
222
|
+
store = await res.json();
|
|
223
|
+
if (!Array.isArray(store.libraries)) store.libraries = [];
|
|
224
|
+
if (!store.libraries.length) {
|
|
225
|
+
store.libraries.push({ id: uid('lib'), name: 'My shapes', shapes: [] });
|
|
226
|
+
}
|
|
227
|
+
activeLibraryId = store.libraries[0].id;
|
|
228
|
+
activeShapeId = store.libraries[0].shapes[0]?.id || null;
|
|
229
|
+
draft = activeShape() ? structuredClone(activeShape()) : newShapeDraft();
|
|
230
|
+
renderAll();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async function saveStore() {
|
|
234
|
+
const res = await fetch('/api/shape-libraries', {
|
|
235
|
+
method: 'PUT',
|
|
236
|
+
headers: { 'Content-Type': 'application/json' },
|
|
237
|
+
body: JSON.stringify(store),
|
|
238
|
+
});
|
|
239
|
+
store = await res.json();
|
|
240
|
+
setStatus('Saved');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function newShapeDraft() {
|
|
244
|
+
return {
|
|
245
|
+
id: uid('shape'),
|
|
246
|
+
name: 'New shape',
|
|
247
|
+
imageSrc: '',
|
|
248
|
+
width: 96,
|
|
249
|
+
height: 96,
|
|
250
|
+
labelPlacement: 'below',
|
|
251
|
+
anchors: structuredClone(DEFAULT_CUSTOM_ANCHORS),
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function renderAll() {
|
|
256
|
+
renderLibraries();
|
|
257
|
+
renderShapeList();
|
|
258
|
+
renderEditor();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function renderLibraries() {
|
|
262
|
+
els.librarySelect.innerHTML = '';
|
|
263
|
+
store.libraries.forEach((lib) => {
|
|
264
|
+
const opt = document.createElement('option');
|
|
265
|
+
opt.value = lib.id;
|
|
266
|
+
opt.textContent = lib.name;
|
|
267
|
+
opt.selected = lib.id === activeLibraryId;
|
|
268
|
+
els.librarySelect.appendChild(opt);
|
|
269
|
+
});
|
|
270
|
+
els.libraryName.value = activeLibrary()?.name || '';
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function renderShapeList() {
|
|
274
|
+
const lib = activeLibrary();
|
|
275
|
+
els.shapeList.innerHTML = '';
|
|
276
|
+
(lib?.shapes || []).forEach((shape) => {
|
|
277
|
+
const btn = document.createElement('button');
|
|
278
|
+
btn.type = 'button';
|
|
279
|
+
btn.className = `shape-item w-full flex items-center gap-2 px-2 py-1.5 rounded text-sm text-left hover:bg-gray-100 ${shape.id === activeShapeId ? 'active' : ''}`;
|
|
280
|
+
const img = document.createElement('img');
|
|
281
|
+
img.src = shape.imageSrc;
|
|
282
|
+
img.alt = '';
|
|
283
|
+
img.className = 'w-6 h-6 object-contain shrink-0';
|
|
284
|
+
const label = document.createElement('span');
|
|
285
|
+
label.className = 'truncate';
|
|
286
|
+
label.textContent = shape.name;
|
|
287
|
+
btn.append(img, label);
|
|
288
|
+
btn.addEventListener('click', () => {
|
|
289
|
+
activeShapeId = shape.id;
|
|
290
|
+
draft = structuredClone(shape);
|
|
291
|
+
renderAll();
|
|
292
|
+
});
|
|
293
|
+
els.shapeList.appendChild(btn);
|
|
294
|
+
});
|
|
295
|
+
if (!lib?.shapes?.length) {
|
|
296
|
+
els.shapeList.innerHTML = '<p class="text-xs text-gray-400 px-2 py-2">No shape yet.</p>';
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function renderEditor() {
|
|
301
|
+
if (!draft) draft = newShapeDraft();
|
|
302
|
+
els.previewStage.style.aspectRatio = `${Math.max(16, Number(draft.width) || 96)} / ${Math.max(16, Number(draft.height) || 96)}`;
|
|
303
|
+
els.previewImage.src = draft.imageSrc || '';
|
|
304
|
+
els.previewImage.style.display = draft.imageSrc ? 'block' : 'none';
|
|
305
|
+
els.shapeName.value = draft.name || '';
|
|
306
|
+
els.shapeWidth.value = draft.width || 96;
|
|
307
|
+
els.shapeHeight.value = draft.height || 96;
|
|
308
|
+
els.labelPlacement.value = draft.labelPlacement === 'center' ? 'center' : 'below';
|
|
309
|
+
renderAnchors();
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function renderAnchors() {
|
|
313
|
+
els.previewStage.querySelectorAll('.anchor-dot').forEach((dot) => dot.remove());
|
|
314
|
+
els.anchorList.innerHTML = '';
|
|
315
|
+
const anchors = draft.anchors || [];
|
|
316
|
+
els.anchorCount.textContent = `${anchors.length} anchor${anchors.length > 1 ? 's' : ''}`;
|
|
317
|
+
anchors.forEach((anchor, index) => {
|
|
318
|
+
const dot = document.createElement('button');
|
|
319
|
+
dot.type = 'button';
|
|
320
|
+
dot.className = 'anchor-dot';
|
|
321
|
+
dot.style.left = `${anchor.x * 100}%`;
|
|
322
|
+
dot.style.top = `${anchor.y * 100}%`;
|
|
323
|
+
dot.dataset.anchorId = anchor.id;
|
|
324
|
+
dot.innerHTML = `<span>${anchor.id}</span>`;
|
|
325
|
+
dot.addEventListener('pointerdown', (event) => {
|
|
326
|
+
event.preventDefault();
|
|
327
|
+
draggingAnchorId = anchor.id;
|
|
328
|
+
dot.setPointerCapture(event.pointerId);
|
|
329
|
+
});
|
|
330
|
+
els.previewStage.appendChild(dot);
|
|
331
|
+
|
|
332
|
+
const row = document.createElement('div');
|
|
333
|
+
row.className = 'grid grid-cols-[4.5rem_1fr_1fr_2rem] gap-2 items-center';
|
|
334
|
+
row.innerHTML = `
|
|
335
|
+
<input class="field !h-7 text-xs" value="${escapeAttr(anchor.id)}">
|
|
336
|
+
<input class="field !h-7 text-xs" type="number" min="0" max="100" step="1" value="${Math.round(anchor.x * 100)}">
|
|
337
|
+
<input class="field !h-7 text-xs" type="number" min="0" max="100" step="1" value="${Math.round(anchor.y * 100)}">
|
|
338
|
+
<button class="btn btn-danger !h-7 !px-0">×</button>
|
|
339
|
+
`;
|
|
340
|
+
const [idInput, xInput, yInput] = row.querySelectorAll('input');
|
|
341
|
+
idInput.addEventListener('input', () => { anchor.id = idInput.value.trim() || `p${index + 1}`; renderAnchors(); });
|
|
342
|
+
xInput.addEventListener('input', () => { anchor.x = clamp01(Number(xInput.value) / 100); renderAnchors(); });
|
|
343
|
+
yInput.addEventListener('input', () => { anchor.y = clamp01(Number(yInput.value) / 100); renderAnchors(); });
|
|
344
|
+
row.querySelector('button').addEventListener('click', () => {
|
|
345
|
+
draft.anchors = draft.anchors.filter((item) => item !== anchor);
|
|
346
|
+
renderAnchors();
|
|
347
|
+
});
|
|
348
|
+
els.anchorList.appendChild(row);
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function setAnchorFromEvent(anchor, event) {
|
|
353
|
+
const rect = els.previewStage.getBoundingClientRect();
|
|
354
|
+
anchor.x = clamp01((event.clientX - rect.left) / rect.width);
|
|
355
|
+
anchor.y = clamp01((event.clientY - rect.top) / rect.height);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
els.previewStage.addEventListener('pointermove', (event) => {
|
|
359
|
+
if (!draggingAnchorId || !draft) return;
|
|
360
|
+
const anchor = draft.anchors.find((item) => item.id === draggingAnchorId);
|
|
361
|
+
if (!anchor) return;
|
|
362
|
+
setAnchorFromEvent(anchor, event);
|
|
363
|
+
renderAnchors();
|
|
364
|
+
});
|
|
365
|
+
window.addEventListener('pointerup', () => { draggingAnchorId = null; });
|
|
366
|
+
els.previewStage.addEventListener('click', (event) => {
|
|
367
|
+
if (event.target.closest('.anchor-dot') || draggingAnchorId || !draft) return;
|
|
368
|
+
const anchor = { id: `p${(draft.anchors || []).length + 1}`, x: 0.5, y: 0.5 };
|
|
369
|
+
setAnchorFromEvent(anchor, event);
|
|
370
|
+
draft.anchors = [...(draft.anchors || []), anchor];
|
|
371
|
+
renderAnchors();
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
document.getElementById('btnAddLibrary').addEventListener('click', async () => {
|
|
375
|
+
const lib = { id: uid('lib'), name: 'New library', shapes: [] };
|
|
376
|
+
store.libraries.push(lib);
|
|
377
|
+
activeLibraryId = lib.id;
|
|
378
|
+
activeShapeId = null;
|
|
379
|
+
draft = newShapeDraft();
|
|
380
|
+
renderAll();
|
|
381
|
+
await saveStore();
|
|
382
|
+
});
|
|
383
|
+
els.librarySelect.addEventListener('change', () => {
|
|
384
|
+
activeLibraryId = els.librarySelect.value;
|
|
385
|
+
activeShapeId = activeLibrary()?.shapes[0]?.id || null;
|
|
386
|
+
draft = activeShape() ? structuredClone(activeShape()) : newShapeDraft();
|
|
387
|
+
renderAll();
|
|
388
|
+
});
|
|
389
|
+
els.libraryName.addEventListener('change', async () => {
|
|
390
|
+
const lib = activeLibrary();
|
|
391
|
+
if (!lib) return;
|
|
392
|
+
lib.name = els.libraryName.value.trim() || lib.name;
|
|
393
|
+
renderLibraries();
|
|
394
|
+
await saveStore();
|
|
395
|
+
});
|
|
396
|
+
document.getElementById('btnNewShape').addEventListener('click', () => {
|
|
397
|
+
activeShapeId = null;
|
|
398
|
+
draft = newShapeDraft();
|
|
399
|
+
renderAll();
|
|
400
|
+
});
|
|
401
|
+
document.getElementById('btnDeleteShape').addEventListener('click', async () => {
|
|
402
|
+
const lib = activeLibrary();
|
|
403
|
+
if (!lib || !activeShapeId) return;
|
|
404
|
+
lib.shapes = lib.shapes.filter((shape) => shape.id !== activeShapeId);
|
|
405
|
+
activeShapeId = lib.shapes[0]?.id || null;
|
|
406
|
+
draft = activeShape() ? structuredClone(activeShape()) : newShapeDraft();
|
|
407
|
+
renderAll();
|
|
408
|
+
await saveStore();
|
|
409
|
+
});
|
|
410
|
+
document.getElementById('btnDefaultAnchors').addEventListener('click', () => {
|
|
411
|
+
draft.anchors = structuredClone(DEFAULT_CUSTOM_ANCHORS);
|
|
412
|
+
renderAnchors();
|
|
413
|
+
});
|
|
414
|
+
document.getElementById('btnClearAnchors').addEventListener('click', () => {
|
|
415
|
+
draft.anchors = [];
|
|
416
|
+
renderAnchors();
|
|
417
|
+
});
|
|
418
|
+
document.getElementById('btnSaveShape').addEventListener('click', async () => {
|
|
419
|
+
const lib = activeLibrary();
|
|
420
|
+
if (!lib || !draft || !draft.imageSrc) return;
|
|
421
|
+
draft.name = els.shapeName.value.trim() || 'Untitled shape';
|
|
422
|
+
draft.width = Math.max(16, Math.min(1200, Math.round(Number(els.shapeWidth.value) || 96)));
|
|
423
|
+
draft.height = Math.max(16, Math.min(1200, Math.round(Number(els.shapeHeight.value) || 96)));
|
|
424
|
+
draft.labelPlacement = els.labelPlacement.value === 'below' ? 'below' : 'center';
|
|
425
|
+
const idx = lib.shapes.findIndex((shape) => shape.id === draft.id);
|
|
426
|
+
if (idx >= 0) lib.shapes[idx] = structuredClone(draft);
|
|
427
|
+
else lib.shapes.push(structuredClone(draft));
|
|
428
|
+
activeShapeId = draft.id;
|
|
429
|
+
renderAll();
|
|
430
|
+
await saveStore();
|
|
431
|
+
});
|
|
432
|
+
['shapeName', 'shapeWidth', 'shapeHeight', 'labelPlacement'].forEach((id) => {
|
|
433
|
+
document.getElementById(id).addEventListener('input', () => {
|
|
434
|
+
draft.name = els.shapeName.value;
|
|
435
|
+
draft.width = Number(els.shapeWidth.value) || 96;
|
|
436
|
+
draft.height = Number(els.shapeHeight.value) || 96;
|
|
437
|
+
draft.labelPlacement = els.labelPlacement.value === 'below' ? 'below' : 'center';
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
els.imageFile.addEventListener('change', async () => {
|
|
441
|
+
const file = els.imageFile.files && els.imageFile.files[0];
|
|
442
|
+
if (!file || !draft) return;
|
|
443
|
+
const data = await new Promise((resolve, reject) => {
|
|
444
|
+
const reader = new FileReader();
|
|
445
|
+
reader.onload = () => resolve(reader.result);
|
|
446
|
+
reader.onerror = reject;
|
|
447
|
+
reader.readAsDataURL(file);
|
|
448
|
+
});
|
|
449
|
+
const ext = (file.name.split('.').pop() || 'png').toLowerCase().replace(/[^a-z0-9]/g, '') || 'png';
|
|
450
|
+
const name = file.name.replace(/\.[^.]+$/, '').slice(0, 60);
|
|
451
|
+
const res = await fetch('/api/images/upload', {
|
|
452
|
+
method: 'POST',
|
|
453
|
+
headers: { 'Content-Type': 'application/json' },
|
|
454
|
+
body: JSON.stringify({ data, ext, name }),
|
|
455
|
+
});
|
|
456
|
+
const uploaded = await res.json();
|
|
457
|
+
draft.imageSrc = `/images/${uploaded.filename}`;
|
|
458
|
+
if (!els.shapeName.value || els.shapeName.value === 'New shape') draft.name = name || draft.name;
|
|
459
|
+
renderEditor();
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
loadStore();
|
|
463
|
+
</script>
|
|
464
|
+
</body>
|
|
465
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shape-libraries.d.ts","sourceRoot":"","sources":["../../../src/routes/shape-libraries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AA+GjC,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAc7D"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.shapeLibrariesRouter = shapeLibrariesRouter;
|
|
7
|
+
const express_1 = require("express");
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const FILE_NAME = '.shape-libraries.json';
|
|
11
|
+
function filePath(docsPath) {
|
|
12
|
+
return path_1.default.join(docsPath, FILE_NAME);
|
|
13
|
+
}
|
|
14
|
+
function loadStore(docsPath) {
|
|
15
|
+
const fp = filePath(docsPath);
|
|
16
|
+
if (!fs_1.default.existsSync(fp))
|
|
17
|
+
return { libraries: [] };
|
|
18
|
+
try {
|
|
19
|
+
const raw = JSON.parse(fs_1.default.readFileSync(fp, 'utf-8'));
|
|
20
|
+
return sanitizeStore(raw);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return { libraries: [] };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function saveStore(docsPath, store) {
|
|
27
|
+
fs_1.default.writeFileSync(filePath(docsPath), JSON.stringify(sanitizeStore(store), null, 2), 'utf-8');
|
|
28
|
+
}
|
|
29
|
+
function clamp01(n) {
|
|
30
|
+
return Math.max(0, Math.min(1, typeof n === 'number' && Number.isFinite(n) ? n : 0));
|
|
31
|
+
}
|
|
32
|
+
function safeId(value, fallback) {
|
|
33
|
+
if (typeof value !== 'string')
|
|
34
|
+
return fallback;
|
|
35
|
+
const clean = value.trim().replace(/[^a-zA-Z0-9_-]/g, '-').slice(0, 80);
|
|
36
|
+
return clean || fallback;
|
|
37
|
+
}
|
|
38
|
+
function safeName(value, fallback) {
|
|
39
|
+
if (typeof value !== 'string')
|
|
40
|
+
return fallback;
|
|
41
|
+
const clean = value.trim().slice(0, 120);
|
|
42
|
+
return clean || fallback;
|
|
43
|
+
}
|
|
44
|
+
function safeLabelPlacement(value) {
|
|
45
|
+
return value === 'center' ? 'center' : 'below';
|
|
46
|
+
}
|
|
47
|
+
function sanitizeStore(raw) {
|
|
48
|
+
const obj = raw && typeof raw === 'object' ? raw : {};
|
|
49
|
+
const rawLibraries = Array.isArray(obj.libraries) ? obj.libraries : [];
|
|
50
|
+
const libraries = rawLibraries.map((lib, libIndex) => {
|
|
51
|
+
const libObj = lib && typeof lib === 'object' ? lib : {};
|
|
52
|
+
const shapesRaw = Array.isArray(libObj.shapes) ? libObj.shapes : [];
|
|
53
|
+
return {
|
|
54
|
+
id: safeId(libObj.id, `lib-${libIndex + 1}`),
|
|
55
|
+
name: safeName(libObj.name, `Library ${libIndex + 1}`),
|
|
56
|
+
shapes: shapesRaw.map((shape, shapeIndex) => {
|
|
57
|
+
const shapeObj = shape && typeof shape === 'object' ? shape : {};
|
|
58
|
+
const anchorsRaw = Array.isArray(shapeObj.anchors) ? shapeObj.anchors : [];
|
|
59
|
+
const width = typeof shapeObj.width === 'number' && Number.isFinite(shapeObj.width)
|
|
60
|
+
? Math.max(16, Math.min(1200, Math.round(shapeObj.width)))
|
|
61
|
+
: 96;
|
|
62
|
+
const height = typeof shapeObj.height === 'number' && Number.isFinite(shapeObj.height)
|
|
63
|
+
? Math.max(16, Math.min(1200, Math.round(shapeObj.height)))
|
|
64
|
+
: 96;
|
|
65
|
+
return {
|
|
66
|
+
id: safeId(shapeObj.id, `shape-${shapeIndex + 1}`),
|
|
67
|
+
name: safeName(shapeObj.name, `Shape ${shapeIndex + 1}`),
|
|
68
|
+
imageSrc: typeof shapeObj.imageSrc === 'string' ? shapeObj.imageSrc : '',
|
|
69
|
+
width,
|
|
70
|
+
height,
|
|
71
|
+
labelPlacement: safeLabelPlacement(shapeObj.labelPlacement),
|
|
72
|
+
anchors: anchorsRaw.map((anchor, anchorIndex) => {
|
|
73
|
+
const anchorObj = anchor && typeof anchor === 'object' ? anchor : {};
|
|
74
|
+
return {
|
|
75
|
+
id: safeId(anchorObj.id, `p${anchorIndex + 1}`),
|
|
76
|
+
x: clamp01(anchorObj.x),
|
|
77
|
+
y: clamp01(anchorObj.y),
|
|
78
|
+
};
|
|
79
|
+
}).filter((anchor) => anchor.id),
|
|
80
|
+
};
|
|
81
|
+
}).filter((shape) => shape.imageSrc),
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
return { libraries };
|
|
85
|
+
}
|
|
86
|
+
function shapeLibrariesRouter(docsPath) {
|
|
87
|
+
const router = (0, express_1.Router)();
|
|
88
|
+
router.get('/', (_req, res) => {
|
|
89
|
+
res.json(loadStore(docsPath));
|
|
90
|
+
});
|
|
91
|
+
router.put('/', (req, res) => {
|
|
92
|
+
const store = sanitizeStore(req.body);
|
|
93
|
+
saveStore(docsPath, store);
|
|
94
|
+
res.json(store);
|
|
95
|
+
});
|
|
96
|
+
return router;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=shape-libraries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shape-libraries.js","sourceRoot":"","sources":["../../../src/routes/shape-libraries.ts"],"names":[],"mappings":"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"}
|
package/dist/src/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,WAAW,CAAC,EAChC,QAAQ,EACR,IAAI,EACJ,WAAmB,GACpB,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkE/B"}
|
package/dist/src/server.js
CHANGED
|
@@ -13,6 +13,7 @@ const browse_1 = require("./routes/browse");
|
|
|
13
13
|
const images_1 = require("./routes/images");
|
|
14
14
|
const files_1 = require("./routes/files");
|
|
15
15
|
const diagrams_1 = require("./routes/diagrams");
|
|
16
|
+
const shape_libraries_1 = require("./routes/shape-libraries");
|
|
16
17
|
const wordcloud_1 = require("./routes/wordcloud");
|
|
17
18
|
const annotations_1 = require("./routes/annotations");
|
|
18
19
|
const metadata_1 = require("./routes/metadata");
|
|
@@ -32,6 +33,7 @@ async function startServer({ docsPath, port, openBrowser = false, }) {
|
|
|
32
33
|
app.use('/api/images', (0, images_1.imagesRouter)(docsPath));
|
|
33
34
|
app.use('/api/files', (0, files_1.filesRouter)(docsPath));
|
|
34
35
|
app.use('/api/diagrams', (0, diagrams_1.diagramsRouter)(docsPath));
|
|
36
|
+
app.use('/api/shape-libraries', (0, shape_libraries_1.shapeLibrariesRouter)(docsPath));
|
|
35
37
|
app.use('/api/wordcloud', (0, wordcloud_1.wordcloudRouter)());
|
|
36
38
|
app.use('/api/annotations', (0, annotations_1.annotationsRouter)(docsPath));
|
|
37
39
|
app.use('/api/metadata', (0, metadata_1.metadataRouter)(docsPath));
|
|
@@ -49,6 +51,7 @@ async function startServer({ docsPath, port, openBrowser = false, }) {
|
|
|
49
51
|
app.get('/', (_req, res) => res.sendFile(path_1.default.join(frontendPath, 'index.html'), { dotfiles: 'allow' }));
|
|
50
52
|
app.get('/admin', (_req, res) => res.sendFile(path_1.default.join(frontendPath, 'admin.html'), { dotfiles: 'allow' }));
|
|
51
53
|
app.get('/diagram', (_req, res) => res.sendFile(path_1.default.join(frontendPath, 'diagram.html'), { dotfiles: 'allow' }));
|
|
54
|
+
app.get('/shape-editor', (_req, res) => res.sendFile(path_1.default.join(frontendPath, 'shape-editor.html'), { dotfiles: 'allow' }));
|
|
52
55
|
return new Promise((resolve) => {
|
|
53
56
|
app.listen(port, () => {
|
|
54
57
|
const url = `http://localhost:${port}`;
|
package/dist/src/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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"}
|