@helping-ai-workflow/md2doc 2.7.0 → 2.8.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.
- package/lib/md2doc.js +244 -24
- package/package.json +2 -2
package/lib/md2doc.js
CHANGED
|
@@ -1368,6 +1368,34 @@ const html = `<!DOCTYPE html>
|
|
|
1368
1368
|
background: rgba(147, 197, 253, 0.35);
|
|
1369
1369
|
box-shadow: inset 0 0 0 1px #93c5fd;
|
|
1370
1370
|
}
|
|
1371
|
+
.lightbox-swatch {
|
|
1372
|
+
width: 16px;
|
|
1373
|
+
height: 16px;
|
|
1374
|
+
min-width: 16px;
|
|
1375
|
+
padding: 0;
|
|
1376
|
+
border-radius: 50%;
|
|
1377
|
+
border: 2px solid rgba(255, 255, 255, 0.4);
|
|
1378
|
+
cursor: pointer;
|
|
1379
|
+
align-self: center;
|
|
1380
|
+
}
|
|
1381
|
+
.lightbox-swatch.is-active {
|
|
1382
|
+
border-color: #ffffff;
|
|
1383
|
+
box-shadow: 0 0 0 2px #93c5fd;
|
|
1384
|
+
}
|
|
1385
|
+
/* Inline annotation overlay left behind after closing the lightbox:
|
|
1386
|
+
same-viewBox svg over the source figure, in-memory only. */
|
|
1387
|
+
.anno-inline-wrap {
|
|
1388
|
+
position: relative;
|
|
1389
|
+
display: inline-block;
|
|
1390
|
+
max-width: 100%;
|
|
1391
|
+
}
|
|
1392
|
+
.anno-inline {
|
|
1393
|
+
position: absolute;
|
|
1394
|
+
inset: 0;
|
|
1395
|
+
width: 100%;
|
|
1396
|
+
height: 100%;
|
|
1397
|
+
pointer-events: none;
|
|
1398
|
+
}
|
|
1371
1399
|
.lightbox-sep {
|
|
1372
1400
|
width: 1px;
|
|
1373
1401
|
align-self: stretch;
|
|
@@ -2187,16 +2215,25 @@ ${mermaidInitTag}` : ''}
|
|
|
2187
2215
|
// close/reopen keeps them, reload starts clean (they are reading-session
|
|
2188
2216
|
// scratch, and localStorage keys would go stale when the doc regenerates).
|
|
2189
2217
|
var ANNO_NS = 'http://www.w3.org/2000/svg';
|
|
2218
|
+
var ANNO_COLORS = ['#ef4444', '#3b82f6', '#22c55e', '#f59e0b', '#111827'];
|
|
2219
|
+
// Office-like absolute stroke widths: rendered px at fit zoom (S/M/L).
|
|
2220
|
+
var ANNO_WIDTHS = [1, 2, 4];
|
|
2190
2221
|
var annoStore = (typeof WeakMap === 'function') ? new WeakMap() : null;
|
|
2191
2222
|
var annoShapes = [];
|
|
2192
2223
|
var annoSvg = null;
|
|
2193
|
-
var annoMode = null; // null | 'f' | 'e' | 'r' | 'm'
|
|
2224
|
+
var annoMode = null; // null | 'f' | 'e' | 'r' | 'l' | 'a' | 'm'
|
|
2194
2225
|
var annoSelected = null;
|
|
2195
2226
|
var annoDraft = null;
|
|
2196
2227
|
var annoUndoStack = [];
|
|
2197
2228
|
var annoRedoStack = [];
|
|
2198
2229
|
var annoStrokeW = 3;
|
|
2230
|
+
var annoColor = ANNO_COLORS[0];
|
|
2231
|
+
var annoWidth = ANNO_WIDTHS[1];
|
|
2199
2232
|
var annoToolButtons = {};
|
|
2233
|
+
var annoStyleButtons = [];
|
|
2234
|
+
var annoSourceNode = null;
|
|
2235
|
+
var annoCloneEl = null;
|
|
2236
|
+
var annoBaseSrc = null;
|
|
2200
2237
|
|
|
2201
2238
|
function lightboxIsOpen() {
|
|
2202
2239
|
return !!lightboxEl && !lightboxEl.hidden;
|
|
@@ -2308,11 +2345,12 @@ ${mermaidInitTag}` : ''}
|
|
|
2308
2345
|
function annoShapeEl(shape) {
|
|
2309
2346
|
var tag = (shape.type === 'line' || shape.type === 'arrow') ? 'line' : shape.type;
|
|
2310
2347
|
var el = document.createElementNS(ANNO_NS, tag);
|
|
2348
|
+
var color = shape.color || ANNO_COLORS[0];
|
|
2311
2349
|
if (shape.type === 'line' || shape.type === 'arrow') {
|
|
2312
2350
|
el.setAttribute('x1', shape.x1.toFixed(1)); el.setAttribute('y1', shape.y1.toFixed(1));
|
|
2313
2351
|
el.setAttribute('x2', shape.x2.toFixed(1)); el.setAttribute('y2', shape.y2.toFixed(1));
|
|
2314
2352
|
el.setAttribute('stroke-linecap', 'round');
|
|
2315
|
-
if (shape.type === 'arrow') el.setAttribute('marker-end', 'url(#anno-arrow-
|
|
2353
|
+
if (shape.type === 'arrow') el.setAttribute('marker-end', 'url(#anno-arrow-' + color.slice(1) + ')');
|
|
2316
2354
|
} else if (shape.type === 'rect') {
|
|
2317
2355
|
el.setAttribute('x', shape.x.toFixed(1)); el.setAttribute('y', shape.y.toFixed(1));
|
|
2318
2356
|
el.setAttribute('width', Math.max(0.1, shape.w).toFixed(1));
|
|
@@ -2329,32 +2367,36 @@ ${mermaidInitTag}` : ''}
|
|
|
2329
2367
|
el.setAttribute('stroke-linejoin', 'round');
|
|
2330
2368
|
el.setAttribute('stroke-linecap', 'round');
|
|
2331
2369
|
}
|
|
2332
|
-
el.setAttribute('stroke',
|
|
2333
|
-
el.setAttribute('stroke-width',
|
|
2370
|
+
el.setAttribute('stroke', color);
|
|
2371
|
+
el.setAttribute('stroke-width', (shape.sw || annoStrokeW).toFixed(2));
|
|
2334
2372
|
return el;
|
|
2335
2373
|
}
|
|
2336
2374
|
|
|
2337
|
-
function annoEnsureDefs() {
|
|
2375
|
+
function annoEnsureDefs(svg) {
|
|
2338
2376
|
var defs = document.createElementNS(ANNO_NS, 'defs');
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2377
|
+
ANNO_COLORS.forEach(function (color) {
|
|
2378
|
+
var marker = document.createElementNS(ANNO_NS, 'marker');
|
|
2379
|
+
// Same id + content in every overlay svg, so document-wide url(#) lookups
|
|
2380
|
+
// always resolve to an identical marker.
|
|
2381
|
+
marker.setAttribute('id', 'anno-arrow-' + color.slice(1));
|
|
2382
|
+
marker.setAttribute('markerWidth', '8');
|
|
2383
|
+
marker.setAttribute('markerHeight', '8');
|
|
2384
|
+
marker.setAttribute('refX', '6.4');
|
|
2385
|
+
marker.setAttribute('refY', '3');
|
|
2386
|
+
marker.setAttribute('orient', 'auto');
|
|
2387
|
+
var tip = document.createElementNS(ANNO_NS, 'path');
|
|
2388
|
+
tip.setAttribute('d', 'M0 0 L7 3 L0 6 Z');
|
|
2389
|
+
tip.setAttribute('fill', color);
|
|
2390
|
+
marker.appendChild(tip);
|
|
2391
|
+
defs.appendChild(marker);
|
|
2392
|
+
});
|
|
2393
|
+
svg.appendChild(defs);
|
|
2352
2394
|
}
|
|
2353
2395
|
|
|
2354
2396
|
function annoRedraw() {
|
|
2355
2397
|
if (!annoSvg) return;
|
|
2356
2398
|
while (annoSvg.firstChild) annoSvg.removeChild(annoSvg.firstChild);
|
|
2357
|
-
annoEnsureDefs();
|
|
2399
|
+
annoEnsureDefs(annoSvg);
|
|
2358
2400
|
annoShapes.forEach(function (shape, index) {
|
|
2359
2401
|
var g = document.createElementNS(ANNO_NS, 'g');
|
|
2360
2402
|
g.setAttribute('data-anno-id', String(index));
|
|
@@ -2370,13 +2412,14 @@ ${mermaidInitTag}` : ''}
|
|
|
2370
2412
|
}
|
|
2371
2413
|
hit.setAttribute('fill', 'none');
|
|
2372
2414
|
hit.setAttribute('stroke', 'transparent');
|
|
2373
|
-
hit.setAttribute('stroke-width', String(annoStrokeW * 5));
|
|
2415
|
+
hit.setAttribute('stroke-width', String(Math.max((shape.sw || annoStrokeW) * 5, 10 / (lightboxFitZoom || 1))));
|
|
2374
2416
|
hit.setAttribute('data-anno-hit', '');
|
|
2375
2417
|
g.appendChild(hit);
|
|
2376
2418
|
}
|
|
2377
2419
|
annoSvg.appendChild(g);
|
|
2378
2420
|
});
|
|
2379
2421
|
if (annoSelected && annoShapes.indexOf(annoSelected) !== -1) {
|
|
2422
|
+
var u = 1.5 / (lightboxFitZoom || 1); // ~1.5px at fit zoom
|
|
2380
2423
|
var box = annoBBox(annoSelected);
|
|
2381
2424
|
var ui = document.createElementNS(ANNO_NS, 'rect');
|
|
2382
2425
|
ui.setAttribute('data-anno-ui', '');
|
|
@@ -2384,10 +2427,10 @@ ${mermaidInitTag}` : ''}
|
|
|
2384
2427
|
ui.setAttribute('width', Math.max(0.1, box.w)); ui.setAttribute('height', Math.max(0.1, box.h));
|
|
2385
2428
|
ui.setAttribute('fill', 'none');
|
|
2386
2429
|
ui.setAttribute('stroke', '#3b82f6');
|
|
2387
|
-
ui.setAttribute('stroke-width', String(
|
|
2388
|
-
ui.setAttribute('stroke-dasharray', (
|
|
2430
|
+
ui.setAttribute('stroke-width', String(u));
|
|
2431
|
+
ui.setAttribute('stroke-dasharray', (u * 4) + ' ' + (u * 2));
|
|
2389
2432
|
annoSvg.appendChild(ui);
|
|
2390
|
-
var hs =
|
|
2433
|
+
var hs = u * 6;
|
|
2391
2434
|
[[box.x, box.y], [box.x + box.w, box.y], [box.x, box.y + box.h], [box.x + box.w, box.y + box.h]]
|
|
2392
2435
|
.forEach(function (corner, i) {
|
|
2393
2436
|
var h = document.createElementNS(ANNO_NS, 'rect');
|
|
@@ -2404,6 +2447,7 @@ ${mermaidInitTag}` : ''}
|
|
|
2404
2447
|
function annoPushOp(op) {
|
|
2405
2448
|
annoUndoStack.push(op);
|
|
2406
2449
|
annoRedoStack.length = 0;
|
|
2450
|
+
annoBake();
|
|
2407
2451
|
}
|
|
2408
2452
|
|
|
2409
2453
|
function annoApplyOp(op, reverse) {
|
|
@@ -2415,6 +2459,10 @@ ${mermaidInitTag}` : ''}
|
|
|
2415
2459
|
else annoShapes.splice(annoShapes.indexOf(op.shape), 1);
|
|
2416
2460
|
} else if (op.kind === 'geom') {
|
|
2417
2461
|
annoSetGeom(op.shape, reverse ? op.before : op.after);
|
|
2462
|
+
} else if (op.kind === 'style') {
|
|
2463
|
+
var style = reverse ? op.before : op.after;
|
|
2464
|
+
op.shape.color = style.color;
|
|
2465
|
+
op.shape.sw = style.sw;
|
|
2418
2466
|
} else if (op.kind === 'clear') {
|
|
2419
2467
|
if (reverse) op.shapes.forEach(function (s) { annoShapes.push(s); });
|
|
2420
2468
|
else annoShapes.length = 0;
|
|
@@ -2428,6 +2476,7 @@ ${mermaidInitTag}` : ''}
|
|
|
2428
2476
|
annoRedoStack.push(op);
|
|
2429
2477
|
annoSelected = null;
|
|
2430
2478
|
annoRedraw();
|
|
2479
|
+
annoBake();
|
|
2431
2480
|
}
|
|
2432
2481
|
|
|
2433
2482
|
function annoRedo() {
|
|
@@ -2437,6 +2486,7 @@ ${mermaidInitTag}` : ''}
|
|
|
2437
2486
|
annoUndoStack.push(op);
|
|
2438
2487
|
annoSelected = null;
|
|
2439
2488
|
annoRedraw();
|
|
2489
|
+
annoBake();
|
|
2440
2490
|
}
|
|
2441
2491
|
|
|
2442
2492
|
function annoClearAll() {
|
|
@@ -2457,6 +2507,129 @@ ${mermaidInitTag}` : ''}
|
|
|
2457
2507
|
annoRedraw();
|
|
2458
2508
|
}
|
|
2459
2509
|
|
|
2510
|
+
function setAnnoStyle(patch) {
|
|
2511
|
+
if (patch.color) annoColor = patch.color;
|
|
2512
|
+
if (patch.w) annoWidth = patch.w;
|
|
2513
|
+
annoStyleButtons.forEach(function (entry) {
|
|
2514
|
+
entry.button.classList.toggle('is-active',
|
|
2515
|
+
entry.kind === 'color' ? entry.value === annoColor : entry.value === annoWidth);
|
|
2516
|
+
});
|
|
2517
|
+
// With a selection, the pickers restyle it (undoably); otherwise they only
|
|
2518
|
+
// set the style for the next shape.
|
|
2519
|
+
if (annoSelected) {
|
|
2520
|
+
var beforeStyle = { color: annoSelected.color, sw: annoSelected.sw };
|
|
2521
|
+
annoSelected.color = patch.color || annoSelected.color;
|
|
2522
|
+
if (patch.w) annoSelected.sw = patch.w / (lightboxFitZoom || 1);
|
|
2523
|
+
annoPushOp({
|
|
2524
|
+
kind: 'style', shape: annoSelected,
|
|
2525
|
+
before: beforeStyle,
|
|
2526
|
+
after: { color: annoSelected.color, sw: annoSelected.sw },
|
|
2527
|
+
});
|
|
2528
|
+
annoRedraw();
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
// Re-bake the shown raster clone (image + shapes composited to a PNG data
|
|
2533
|
+
// URI) so a native right-click "Copy image" carries the annotations.
|
|
2534
|
+
function annoShapesSvgMarkup() {
|
|
2535
|
+
var svg = document.createElementNS(ANNO_NS, 'svg');
|
|
2536
|
+
svg.setAttribute('xmlns', ANNO_NS);
|
|
2537
|
+
svg.setAttribute('viewBox', '0 0 ' + lightboxNaturalW + ' ' + lightboxNaturalH);
|
|
2538
|
+
svg.setAttribute('width', lightboxNaturalW);
|
|
2539
|
+
svg.setAttribute('height', lightboxNaturalH);
|
|
2540
|
+
annoEnsureDefs(svg);
|
|
2541
|
+
annoShapes.forEach(function (shape) { svg.appendChild(annoShapeEl(shape)); });
|
|
2542
|
+
return new XMLSerializer().serializeToString(svg);
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
function annoComposite(drawBase, scale, done) {
|
|
2546
|
+
var canvas = document.createElement('canvas');
|
|
2547
|
+
canvas.width = lightboxNaturalW * scale;
|
|
2548
|
+
canvas.height = lightboxNaturalH * scale;
|
|
2549
|
+
var ctx = canvas.getContext('2d');
|
|
2550
|
+
drawBase(ctx, canvas, function () {
|
|
2551
|
+
if (!annoShapes.length) { done(canvas); return; }
|
|
2552
|
+
var overlay = new Image();
|
|
2553
|
+
overlay.onload = function () {
|
|
2554
|
+
ctx.drawImage(overlay, 0, 0, canvas.width, canvas.height);
|
|
2555
|
+
done(canvas);
|
|
2556
|
+
};
|
|
2557
|
+
overlay.onerror = function () { done(canvas); };
|
|
2558
|
+
overlay.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(annoShapesSvgMarkup());
|
|
2559
|
+
});
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2562
|
+
function annoBake() {
|
|
2563
|
+
if (!annoCloneEl || annoCloneEl.tagName !== 'IMG' || !annoBaseSrc) return;
|
|
2564
|
+
var expected = annoCloneEl;
|
|
2565
|
+
annoComposite(function (ctx, canvas, next) {
|
|
2566
|
+
var base = new Image();
|
|
2567
|
+
base.onload = function () { ctx.drawImage(base, 0, 0, canvas.width, canvas.height); next(); };
|
|
2568
|
+
base.onerror = function () { next(); };
|
|
2569
|
+
base.src = annoBaseSrc;
|
|
2570
|
+
}, 1, function (canvas) {
|
|
2571
|
+
if (annoCloneEl !== expected) return; // lightbox moved on to another image
|
|
2572
|
+
try { annoCloneEl.src = canvas.toDataURL('image/png'); }
|
|
2573
|
+
catch (e) { /* tainted canvas — keep the plain image */ }
|
|
2574
|
+
});
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
function annoCopyImage() {
|
|
2578
|
+
var clone = annoCloneEl;
|
|
2579
|
+
if (!clone) return;
|
|
2580
|
+
var isImg = clone.tagName === 'IMG';
|
|
2581
|
+
annoComposite(function (ctx, canvas, next) {
|
|
2582
|
+
ctx.fillStyle = '#ffffff';
|
|
2583
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
2584
|
+
var base = new Image();
|
|
2585
|
+
base.onload = function () { ctx.drawImage(base, 0, 0, canvas.width, canvas.height); next(); };
|
|
2586
|
+
base.onerror = function () { next(); };
|
|
2587
|
+
base.src = isImg ? (annoBaseSrc || clone.src)
|
|
2588
|
+
: 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(new XMLSerializer().serializeToString(clone));
|
|
2589
|
+
}, isImg ? 1 : 2, function (canvas) {
|
|
2590
|
+
try {
|
|
2591
|
+
canvas.toBlob(function (blob) {
|
|
2592
|
+
if (!blob || typeof ClipboardItem === 'undefined' || !navigator.clipboard || !navigator.clipboard.write) return;
|
|
2593
|
+
navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })]).catch(function () {});
|
|
2594
|
+
}, 'image/png');
|
|
2595
|
+
} catch (e) { /* clipboard unavailable */ }
|
|
2596
|
+
});
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
// After Esc the drawings stay visible on the inline figure: a same-viewBox
|
|
2600
|
+
// overlay svg over the source element. In-memory only — gone on reload.
|
|
2601
|
+
function annoSyncInline() {
|
|
2602
|
+
var node = annoSourceNode;
|
|
2603
|
+
if (!node) return;
|
|
2604
|
+
var visual = lightboxSourceOf(node);
|
|
2605
|
+
if (!visual || !visual.parentNode) return;
|
|
2606
|
+
var wrap = visual.closest ? visual.closest('.anno-inline-wrap') : null;
|
|
2607
|
+
var shapes = annoShapes;
|
|
2608
|
+
if (!shapes.length) {
|
|
2609
|
+
if (wrap) {
|
|
2610
|
+
var old = wrap.querySelector('svg.anno-inline');
|
|
2611
|
+
if (old) wrap.removeChild(old);
|
|
2612
|
+
}
|
|
2613
|
+
return;
|
|
2614
|
+
}
|
|
2615
|
+
if (!wrap) {
|
|
2616
|
+
wrap = document.createElement('span');
|
|
2617
|
+
wrap.className = 'anno-inline-wrap';
|
|
2618
|
+
visual.parentNode.insertBefore(wrap, visual);
|
|
2619
|
+
wrap.appendChild(visual);
|
|
2620
|
+
}
|
|
2621
|
+
var overlay = wrap.querySelector('svg.anno-inline');
|
|
2622
|
+
if (!overlay) {
|
|
2623
|
+
overlay = document.createElementNS(ANNO_NS, 'svg');
|
|
2624
|
+
overlay.setAttribute('class', 'anno-inline');
|
|
2625
|
+
wrap.appendChild(overlay);
|
|
2626
|
+
}
|
|
2627
|
+
overlay.setAttribute('viewBox', '0 0 ' + lightboxNaturalW + ' ' + lightboxNaturalH);
|
|
2628
|
+
while (overlay.firstChild) overlay.removeChild(overlay.firstChild);
|
|
2629
|
+
annoEnsureDefs(overlay);
|
|
2630
|
+
shapes.forEach(function (shape) { overlay.appendChild(annoShapeEl(shape)); });
|
|
2631
|
+
}
|
|
2632
|
+
|
|
2460
2633
|
function setAnnoMode(mode) {
|
|
2461
2634
|
annoMode = (annoMode === mode) ? null : mode;
|
|
2462
2635
|
if (annoMode !== 'm') annoSelected = null;
|
|
@@ -2519,6 +2692,11 @@ ${mermaidInitTag}` : ''}
|
|
|
2519
2692
|
annoSelected = null;
|
|
2520
2693
|
annoRedraw();
|
|
2521
2694
|
}
|
|
2695
|
+
// The baked clone still shows the shape at its old spot — revert to the
|
|
2696
|
+
// base image for the gesture; the overlay alone renders the live shapes.
|
|
2697
|
+
if (annoDraft && annoCloneEl && annoCloneEl.tagName === 'IMG' && annoBaseSrc) {
|
|
2698
|
+
annoCloneEl.src = annoBaseSrc;
|
|
2699
|
+
}
|
|
2522
2700
|
return;
|
|
2523
2701
|
}
|
|
2524
2702
|
var shape;
|
|
@@ -2527,6 +2705,8 @@ ${mermaidInitTag}` : ''}
|
|
|
2527
2705
|
else if (annoMode === 'l') shape = { type: 'line', x1: pt.x, y1: pt.y, x2: pt.x, y2: pt.y };
|
|
2528
2706
|
else if (annoMode === 'a') shape = { type: 'arrow', x1: pt.x, y1: pt.y, x2: pt.x, y2: pt.y };
|
|
2529
2707
|
else shape = { type: 'rect', x: pt.x, y: pt.y, w: 0, h: 0 };
|
|
2708
|
+
shape.color = annoColor;
|
|
2709
|
+
shape.sw = annoWidth / (lightboxFitZoom || 1);
|
|
2530
2710
|
annoDraft = { kind: 'draw', shape: shape, start: pt, el: annoShapeEl(shape), clientDist: 0, lastClient: [event.clientX, event.clientY] };
|
|
2531
2711
|
annoSvg.appendChild(annoDraft.el);
|
|
2532
2712
|
}
|
|
@@ -2593,11 +2773,16 @@ ${mermaidInitTag}` : ''}
|
|
|
2593
2773
|
}
|
|
2594
2774
|
if (d.moved) {
|
|
2595
2775
|
annoPushOp({ kind: 'geom', shape: d.shape, before: d.before, after: annoGeomOf(d.shape) });
|
|
2776
|
+
} else {
|
|
2777
|
+
annoBake(); // gesture reverted the clone to the base image — restore it
|
|
2596
2778
|
}
|
|
2597
2779
|
annoRedraw();
|
|
2598
2780
|
}
|
|
2599
2781
|
|
|
2600
2782
|
function annoSetup(sourceNode) {
|
|
2783
|
+
annoSourceNode = sourceNode;
|
|
2784
|
+
annoCloneEl = lightboxCanvas.firstElementChild;
|
|
2785
|
+
annoBaseSrc = (annoCloneEl && annoCloneEl.tagName === 'IMG') ? annoCloneEl.src : null;
|
|
2601
2786
|
annoShapes = [];
|
|
2602
2787
|
if (annoStore) {
|
|
2603
2788
|
annoShapes = annoStore.get(sourceNode);
|
|
@@ -2618,6 +2803,7 @@ ${mermaidInitTag}` : ''}
|
|
|
2618
2803
|
lightboxCanvas.appendChild(annoSvg);
|
|
2619
2804
|
annoMode = null;
|
|
2620
2805
|
setAnnoMode(null);
|
|
2806
|
+
if (annoShapes.length) annoBake();
|
|
2621
2807
|
}
|
|
2622
2808
|
|
|
2623
2809
|
function buildLightbox() {
|
|
@@ -2658,6 +2844,25 @@ ${mermaidInitTag}` : ''}
|
|
|
2658
2844
|
annoToolButtons[tool[0]] = button;
|
|
2659
2845
|
bar.appendChild(button);
|
|
2660
2846
|
});
|
|
2847
|
+
ANNO_COLORS.forEach(function (color) {
|
|
2848
|
+
var swatch = lightboxButton('', 'Stroke color ' + color, function () { setAnnoStyle({ color: color }); });
|
|
2849
|
+
swatch.className = 'lightbox-swatch';
|
|
2850
|
+
swatch.style.background = color;
|
|
2851
|
+
swatch.setAttribute('data-anno-color', color);
|
|
2852
|
+
if (color === annoColor) swatch.classList.add('is-active');
|
|
2853
|
+
annoStyleButtons.push({ kind: 'color', value: color, button: swatch });
|
|
2854
|
+
bar.appendChild(swatch);
|
|
2855
|
+
});
|
|
2856
|
+
[['S', ANNO_WIDTHS[0]], ['M', ANNO_WIDTHS[1]], ['L', ANNO_WIDTHS[2]]].forEach(function (width) {
|
|
2857
|
+
var button = lightboxButton(width[0], 'Stroke width ' + width[1] + 'px', function () { setAnnoStyle({ w: width[1] }); });
|
|
2858
|
+
button.setAttribute('data-anno-width', String(width[1]));
|
|
2859
|
+
if (width[1] === annoWidth) button.classList.add('is-active');
|
|
2860
|
+
annoStyleButtons.push({ kind: 'width', value: width[1], button: button });
|
|
2861
|
+
bar.appendChild(button);
|
|
2862
|
+
});
|
|
2863
|
+
var copyButton = lightboxButton('⧉', 'Copy image with annotations', annoCopyImage);
|
|
2864
|
+
copyButton.setAttribute('data-anno-copy', '');
|
|
2865
|
+
bar.appendChild(copyButton);
|
|
2661
2866
|
var clearButton = lightboxButton('Clear', 'Clear all annotations', annoClearAll);
|
|
2662
2867
|
clearButton.setAttribute('data-anno-clear', '');
|
|
2663
2868
|
bar.appendChild(clearButton);
|
|
@@ -2752,7 +2957,18 @@ ${mermaidInitTag}` : ''}
|
|
|
2752
2957
|
|
|
2753
2958
|
var isVector = !!(source.tagName && source.tagName.toLowerCase() === 'svg');
|
|
2754
2959
|
var clone = source.cloneNode(true);
|
|
2755
|
-
|
|
2960
|
+
// Mermaid scopes its embedded <style> to the svg's #id — dropping the id
|
|
2961
|
+
// kills the theme. Rename it instead (avoids a duplicate id) and rewrite
|
|
2962
|
+
// the scoped selectors to the new name.
|
|
2963
|
+
if (isVector && source.id) {
|
|
2964
|
+
var lightboxCloneId = 'lightbox-' + source.id;
|
|
2965
|
+
clone.setAttribute('id', lightboxCloneId);
|
|
2966
|
+
Array.prototype.forEach.call(clone.querySelectorAll('style'), function (styleEl) {
|
|
2967
|
+
styleEl.textContent = styleEl.textContent.split('#' + source.id).join('#' + lightboxCloneId);
|
|
2968
|
+
});
|
|
2969
|
+
} else {
|
|
2970
|
+
clone.removeAttribute('id');
|
|
2971
|
+
}
|
|
2756
2972
|
clone.removeAttribute('class');
|
|
2757
2973
|
clone.removeAttribute('style');
|
|
2758
2974
|
clone.removeAttribute('width');
|
|
@@ -2782,6 +2998,10 @@ ${mermaidInitTag}` : ''}
|
|
|
2782
2998
|
lightboxEl.hidden = true;
|
|
2783
2999
|
document.body.removeAttribute('data-lightbox-open');
|
|
2784
3000
|
annoCancelDraft();
|
|
3001
|
+
annoSyncInline();
|
|
3002
|
+
annoSourceNode = null;
|
|
3003
|
+
annoCloneEl = null;
|
|
3004
|
+
annoBaseSrc = null;
|
|
2785
3005
|
annoSvg = null;
|
|
2786
3006
|
annoMode = null;
|
|
2787
3007
|
setAnnoMode(null);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helping-ai-workflow/md2doc",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.1",
|
|
4
4
|
"description": "Markdown → HTML / PDF renderer with WaveDrom, Mermaid, and Graphviz support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"preinstall": "node scripts/preinstall.js",
|
|
39
|
-
"test": "node test/md2doc.test.js && node test/images.test.js && node test/scroll-anchor.test.js && node test/lightbox.test.js && node test/lightbox-anno.test.js && node test/reader-panels.test.js && node test/cli.test.js && node test/code-operator.test.js"
|
|
39
|
+
"test": "node test/md2doc.test.js && node test/images.test.js && node test/scroll-anchor.test.js && node test/lightbox.test.js && node test/lightbox-anno.test.js && node test/lightbox-anno-style.test.js && node test/reader-panels.test.js && node test/cli.test.js && node test/code-operator.test.js"
|
|
40
40
|
},
|
|
41
41
|
"repository": {
|
|
42
42
|
"type": "git",
|