adr-kit 0.10.0 → 0.11.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/README.md +9 -6
- package/README.zh.md +7 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/completion.d.ts.map +1 -1
- package/dist/commands/completion.js +3 -2
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/graph.d.ts +2 -0
- package/dist/commands/graph.d.ts.map +1 -1
- package/dist/commands/graph.js +37 -7
- package/dist/commands/graph.js.map +1 -1
- package/dist/commands/supersede.js +1 -1
- package/dist/commands/supersede.js.map +1 -1
- package/dist/core/adr.d.ts +1 -0
- package/dist/core/adr.d.ts.map +1 -1
- package/dist/core/adr.js.map +1 -1
- package/dist/core/canvas-view.d.ts +19 -3
- package/dist/core/canvas-view.d.ts.map +1 -1
- package/dist/core/canvas-view.js +210 -15
- package/dist/core/canvas-view.js.map +1 -1
- package/dist/core/deliberation-html.d.ts.map +1 -1
- package/dist/core/deliberation-html.js +88 -16
- package/dist/core/deliberation-html.js.map +1 -1
- package/dist/core/deliberation-view.d.ts.map +1 -1
- package/dist/core/deliberation-view.js +28 -195
- package/dist/core/deliberation-view.js.map +1 -1
- package/dist/core/deliberation.d.ts +13 -0
- package/dist/core/deliberation.d.ts.map +1 -1
- package/dist/core/deliberation.js +11 -1
- package/dist/core/deliberation.js.map +1 -1
- package/dist/core/graph-html.d.ts +1 -1
- package/dist/core/graph-html.d.ts.map +1 -1
- package/dist/core/graph-html.js +163 -44
- package/dist/core/graph-html.js.map +1 -1
- package/dist/core/graph-view.d.ts +1 -1
- package/dist/core/graph-view.d.ts.map +1 -1
- package/dist/core/graph-view.js +9 -187
- package/dist/core/graph-view.js.map +1 -1
- package/dist/core/relation-focus.d.ts +4 -0
- package/dist/core/relation-focus.d.ts.map +1 -0
- package/dist/core/relation-focus.js +89 -0
- package/dist/core/relation-focus.js.map +1 -0
- package/dist/core/share.d.ts +30 -0
- package/dist/core/share.d.ts.map +1 -0
- package/dist/core/share.js +420 -0
- package/dist/core/share.js.map +1 -0
- package/dist/core/templates.d.ts +2 -0
- package/dist/core/templates.d.ts.map +1 -1
- package/dist/core/templates.js +2 -0
- package/dist/core/templates.js.map +1 -1
- package/dist/core/tool-integrations.d.ts.map +1 -1
- package/dist/core/tool-integrations.js +47 -29
- package/dist/core/tool-integrations.js.map +1 -1
- package/dist/core/validate.d.ts +1 -1
- package/dist/core/validate.d.ts.map +1 -1
- package/dist/core/validate.js +25 -14
- package/dist/core/validate.js.map +1 -1
- package/dist/core/view-text.d.ts +7 -0
- package/dist/core/view-text.d.ts.map +1 -1
- package/dist/core/view-text.js +15 -0
- package/dist/core/view-text.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/** Shared hover/keyboard emphasis for both offline views (ADR 11). */
|
|
2
|
+
export const RELATION_STYLE = String.raw `
|
|
3
|
+
.node, .card, .edge, #edges path { transition: opacity .16s ease; }
|
|
4
|
+
.node.relation-dim, .card.relation-dim { opacity: .25; }
|
|
5
|
+
.edge.relation-dim, #edges path.relation-dim { opacity: .12; }
|
|
6
|
+
.card:focus-visible { outline: 2px solid #7750a5; outline-offset: 3px; }
|
|
7
|
+
@media (prefers-reduced-motion: reduce) {
|
|
8
|
+
.node, .card, .edge, #edges path { transition: none; }
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
export const RELATION_SCRIPT = String.raw `
|
|
12
|
+
(() => {
|
|
13
|
+
const world = document.getElementById('world');
|
|
14
|
+
const viewport = document.getElementById('viewport');
|
|
15
|
+
if (!world || !viewport) return;
|
|
16
|
+
const isTree = !!document.getElementById('edges');
|
|
17
|
+
const nodes = Array.from(world.querySelectorAll(isTree ? '.card' : '.node'));
|
|
18
|
+
const key = node => isTree ? node.id : node.dataset.adr;
|
|
19
|
+
let active = null;
|
|
20
|
+
|
|
21
|
+
// For a map, only incident edges count. For a tree, walk upstream and
|
|
22
|
+
// downstream separately: walking both ways in one pass would pull in siblings.
|
|
23
|
+
function relatedNodes(id, links, tree) {
|
|
24
|
+
const lit = new Set([id]);
|
|
25
|
+
if (!tree) {
|
|
26
|
+
for (const link of links) {
|
|
27
|
+
if (link.from === id) lit.add(link.to);
|
|
28
|
+
if (link.to === id) lit.add(link.from);
|
|
29
|
+
}
|
|
30
|
+
return lit;
|
|
31
|
+
}
|
|
32
|
+
for (const direction of ['from', 'to']) {
|
|
33
|
+
const seen = new Set([id]), queue = [id];
|
|
34
|
+
for (let i = 0; i < queue.length; i++) {
|
|
35
|
+
for (const link of links) {
|
|
36
|
+
const next = direction === 'from' ? link.to : link.from;
|
|
37
|
+
if (link[direction] !== queue[i] || seen.has(next)) continue;
|
|
38
|
+
seen.add(next);
|
|
39
|
+
lit.add(next);
|
|
40
|
+
queue.push(next);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return lit;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function nodeFor(target) {
|
|
48
|
+
if (!target || !world.contains(target)) return null;
|
|
49
|
+
return target.closest('.card, .node') || target.closest('a')?.querySelector('.node') || null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function paint() {
|
|
53
|
+
if (active && active.hidden) active = null;
|
|
54
|
+
const paths = Array.from(world.querySelectorAll(isTree ? '#edges path' : '.edge'));
|
|
55
|
+
const links = paths.map(path => ({
|
|
56
|
+
path,
|
|
57
|
+
// Tree edges may start at an answer within a card, not the card itself.
|
|
58
|
+
from: isTree ? document.getElementById(path.dataset.from).closest('.card').id : path.dataset.from,
|
|
59
|
+
to: path.dataset.to,
|
|
60
|
+
}));
|
|
61
|
+
const id = active && key(active);
|
|
62
|
+
const lit = id ? relatedNodes(id, links, isTree) : null;
|
|
63
|
+
nodes.forEach(node => node.classList.toggle('relation-dim', !!lit && !lit.has(key(node))));
|
|
64
|
+
links.forEach(link => {
|
|
65
|
+
const related = !lit || (isTree ? lit.has(link.from) && lit.has(link.to) : link.from === id || link.to === id);
|
|
66
|
+
link.path.classList.toggle('relation-dim', !related);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function select(node) {
|
|
71
|
+
if (active === node) return;
|
|
72
|
+
active = node;
|
|
73
|
+
paint();
|
|
74
|
+
}
|
|
75
|
+
viewport.addEventListener('pointermove', event => {
|
|
76
|
+
if (event.buttons || event.pointerType === 'touch') return;
|
|
77
|
+
select(nodeFor(event.target));
|
|
78
|
+
});
|
|
79
|
+
viewport.addEventListener('pointerleave', () => select(null));
|
|
80
|
+
viewport.addEventListener('pointerdown', () => select(null));
|
|
81
|
+
world.addEventListener('focusin', event => select(nodeFor(event.target)));
|
|
82
|
+
world.addEventListener('focusout', event => select(nodeFor(event.relatedTarget)));
|
|
83
|
+
viewport.addEventListener('keydown', event => { if (event.key === 'Escape') select(null); });
|
|
84
|
+
window.addEventListener('blur', () => select(null));
|
|
85
|
+
// Folding recreates the tree's edges; apply emphasis to the new paths too.
|
|
86
|
+
world.addEventListener('adr-layout', paint);
|
|
87
|
+
})();
|
|
88
|
+
`;
|
|
89
|
+
//# sourceMappingURL=relation-focus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relation-focus.js","sourceRoot":"","sources":["../../src/core/relation-focus.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;CAQvC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6ExC,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Save-as-image action: renders the current view into a branded,
|
|
3
|
+
* self-contained PNG entirely on the client — serializes the diagram,
|
|
4
|
+
* rasterizes it, and composes the frame around it. No network, no third-party
|
|
5
|
+
* renderer, no runtime dependency (ADR 8/9): the only inputs are the live DOM
|
|
6
|
+
* and the page's own stylesheet text. Nothing is uploaded, and the browser
|
|
7
|
+
* decides where the download lands: a page cannot write to a chosen folder.
|
|
8
|
+
*/
|
|
9
|
+
/** The credit line every shared image carries. */
|
|
10
|
+
export declare const SHARE_WATERMARK = "luochang212/adr-kit";
|
|
11
|
+
/**
|
|
12
|
+
* The button is a camera, because that is what it does: it makes a picture of
|
|
13
|
+
* the view. A share glyph would promise sending it somewhere, a download glyph
|
|
14
|
+
* would promise only a file, and neither is what happens.
|
|
15
|
+
*
|
|
16
|
+
* The glyph is Lucide's `camera` (ISC), the same icon skill-zoo uses, at 24
|
|
17
|
+
* units in a 24 box and stroke 2 — 1.33px on screen at 16px, matching the
|
|
18
|
+
* Info glyph's 1.4.
|
|
19
|
+
*/
|
|
20
|
+
export declare const CAMERA_ICON: string;
|
|
21
|
+
export declare const SHARE_BUTTON_HTML: string;
|
|
22
|
+
/**
|
|
23
|
+
* The button carries no text, so its feedback is a status line: what was saved,
|
|
24
|
+
* whether the copy worked, and nothing it cannot know (a page cannot tell which
|
|
25
|
+
* folder the download reached).
|
|
26
|
+
*/
|
|
27
|
+
export declare const SHARE_STYLE: string;
|
|
28
|
+
export declare const GITHUB_MARK_PATH: string;
|
|
29
|
+
export declare const SHARE_SCRIPT: string;
|
|
30
|
+
//# sourceMappingURL=share.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share.d.ts","sourceRoot":"","sources":["../../src/core/share.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,kDAAkD;AAClD,eAAO,MAAM,eAAe,wBAAwB,CAAC;AAErD;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,QAGZ,CAAC;AAEb,eAAO,MAAM,iBAAiB,QACD,CAAC;AAE9B;;;;GAIG;AACH,eAAO,MAAM,WAAW,QAGvB,CAAC;AAIF,eAAO,MAAM,gBAAgB,QAK2D,CAAC;AAIzF,eAAO,MAAM,YAAY,QAuXxB,CAAC"}
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Save-as-image action: renders the current view into a branded,
|
|
3
|
+
* self-contained PNG entirely on the client — serializes the diagram,
|
|
4
|
+
* rasterizes it, and composes the frame around it. No network, no third-party
|
|
5
|
+
* renderer, no runtime dependency (ADR 8/9): the only inputs are the live DOM
|
|
6
|
+
* and the page's own stylesheet text. Nothing is uploaded, and the browser
|
|
7
|
+
* decides where the download lands: a page cannot write to a chosen folder.
|
|
8
|
+
*/
|
|
9
|
+
/** The credit line every shared image carries. */
|
|
10
|
+
export const SHARE_WATERMARK = 'luochang212/adr-kit';
|
|
11
|
+
/**
|
|
12
|
+
* The button is a camera, because that is what it does: it makes a picture of
|
|
13
|
+
* the view. A share glyph would promise sending it somewhere, a download glyph
|
|
14
|
+
* would promise only a file, and neither is what happens.
|
|
15
|
+
*
|
|
16
|
+
* The glyph is Lucide's `camera` (ISC), the same icon skill-zoo uses, at 24
|
|
17
|
+
* units in a 24 box and stroke 2 — 1.33px on screen at 16px, matching the
|
|
18
|
+
* Info glyph's 1.4.
|
|
19
|
+
*/
|
|
20
|
+
export const CAMERA_ICON = '<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">'
|
|
21
|
+
+ '<path d="M13.997 4a2 2 0 0 1 1.76 1.05l.486.9A2 2 0 0 0 18.003 7H20a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h1.997a2 2 0 0 0 1.759-1.048l.489-.904A2 2 0 0 1 10.004 4z"/>'
|
|
22
|
+
+ '<circle cx="12" cy="13" r="3"/>'
|
|
23
|
+
+ '</svg>';
|
|
24
|
+
export const SHARE_BUTTON_HTML = '<button id="share" class="js-control" aria-label="Save as image" title="Save as image">'
|
|
25
|
+
+ CAMERA_ICON + '</button>';
|
|
26
|
+
/**
|
|
27
|
+
* The button carries no text, so its feedback is a status line: what was saved,
|
|
28
|
+
* whether the copy worked, and nothing it cannot know (a page cannot tell which
|
|
29
|
+
* folder the download reached).
|
|
30
|
+
*/
|
|
31
|
+
export const SHARE_STYLE = String.raw `
|
|
32
|
+
.canvas-toast { position: fixed; left: 50%; bottom: 96px; z-index: 6; max-width: min(520px, calc(100vw - 32px)); padding: 9px 14px; background: #233c36; color: #fff; border-radius: 9px; font-size: 12px; line-height: 1.45; text-align: center; box-shadow: 0 8px 24px #233c3626; opacity: 0; transform: translate(-50%,8px); pointer-events: none; transition: opacity .18s ease, transform .18s ease; }
|
|
33
|
+
.canvas-toast.visible { opacity: 1; transform: translate(-50%,0); }
|
|
34
|
+
`;
|
|
35
|
+
// GitHub's mark-github octicon, a 16x16 path, drawn with Path2D. The credit
|
|
36
|
+
// is a logo and a short handle: a full URL would outweigh the diagram.
|
|
37
|
+
export const GITHUB_MARK_PATH = 'M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49'
|
|
38
|
+
+ '-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66'
|
|
39
|
+
+ '.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27'
|
|
40
|
+
+ 's1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48'
|
|
41
|
+
+ ' 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8z';
|
|
42
|
+
// Kept as readable JavaScript: tsc ships this string unchanged in the CLI bundle.
|
|
43
|
+
// All record text is server-escaped HTML, never interpolated into this program.
|
|
44
|
+
export const SHARE_SCRIPT = String.raw `
|
|
45
|
+
(() => {
|
|
46
|
+
const shareButton = document.getElementById('share');
|
|
47
|
+
if (!shareButton) return;
|
|
48
|
+
const REPO = '${SHARE_WATERMARK}';
|
|
49
|
+
const INK = '#233c36', MUTED = '#64756c', GREEN = '#294d3e', PAPER = '#f6f8f5', DOT = '#cdd8cc', LINE = '#dce4dc';
|
|
50
|
+
const HAIRLINE = '#e4eae4', TINT = 'rgba(41,77,62,.07)';
|
|
51
|
+
const SANS = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
52
|
+
const GITHUB_MARK = '${GITHUB_MARK_PATH}';
|
|
53
|
+
// The composed canvas is drawn at 2x so shared images stay crisp. The frame
|
|
54
|
+
// follows the diagram: the heading, the diagram, then the one-line footer,
|
|
55
|
+
// which is the shape's own bottom edge.
|
|
56
|
+
const SCALE = 2, PAD = 40, GAP = 24, FOOTER_H = 56, RADIUS = 20, MIN_W = 460;
|
|
57
|
+
const MAX_W = 2200, MAX_H = 4000;
|
|
58
|
+
|
|
59
|
+
// The status line. role=status + aria-live announce it to screen readers as
|
|
60
|
+
// well, and the text is cleared on hide so a repeated message still speaks.
|
|
61
|
+
const toast = document.createElement('div');
|
|
62
|
+
toast.className = 'canvas-toast';
|
|
63
|
+
toast.setAttribute('role', 'status');
|
|
64
|
+
toast.setAttribute('aria-live', 'polite');
|
|
65
|
+
document.body.appendChild(toast);
|
|
66
|
+
let toastTimer = 0;
|
|
67
|
+
function showToast(message) {
|
|
68
|
+
const dock = document.querySelector('.canvas-dock');
|
|
69
|
+
toast.style.bottom = ((dock ? dock.offsetHeight : 0) + 22) + 'px';
|
|
70
|
+
toast.textContent = message;
|
|
71
|
+
toast.classList.add('visible');
|
|
72
|
+
clearTimeout(toastTimer);
|
|
73
|
+
toastTimer = setTimeout(() => {
|
|
74
|
+
toast.classList.remove('visible');
|
|
75
|
+
toast.textContent = '';
|
|
76
|
+
}, 2600);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function diagramSize() {
|
|
80
|
+
const world = document.getElementById('world');
|
|
81
|
+
return { w: world.offsetWidth || world.scrollWidth, h: world.offsetHeight || world.scrollHeight };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* What the image is: the view's kind, its title, and its own statistics, all
|
|
86
|
+
* read off the page the reader is looking at. Shared images travel without
|
|
87
|
+
* the page, so they have to say it themselves.
|
|
88
|
+
*/
|
|
89
|
+
function shareFacts() {
|
|
90
|
+
const heading = document.querySelector('.viewer-heading h1');
|
|
91
|
+
const title = ((heading && heading.textContent) || document.title || 'ADR Kit').trim();
|
|
92
|
+
const isTree = !!document.getElementById('edges');
|
|
93
|
+
const stats = Array.from(document.querySelectorAll('.viewer-stats span'))
|
|
94
|
+
.map(span => Array.from(span.childNodes).map(node => node.textContent || '').join(' ').replace(/\s+/g, ' ').trim())
|
|
95
|
+
.filter(Boolean)
|
|
96
|
+
.join(' · ');
|
|
97
|
+
const kind = isTree ? 'Deliberation tree' : 'Decision map';
|
|
98
|
+
const numbered = isTree && title.match(/^(\d+)\s+(.+)$/s);
|
|
99
|
+
return {
|
|
100
|
+
kind: numbered ? 'ADR ' + numbered[1] + ' · ' + kind : kind,
|
|
101
|
+
title: numbered ? numbered[2] : title,
|
|
102
|
+
stats,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function pageCss() {
|
|
107
|
+
return Array.from(document.querySelectorAll('style')).map(style => style.textContent).join('\n');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function imageFrom(src) {
|
|
111
|
+
return new Promise((resolve, reject) => {
|
|
112
|
+
const img = new Image();
|
|
113
|
+
img.onload = () => resolve(img);
|
|
114
|
+
img.onerror = () => reject(new Error('diagram raster failed'));
|
|
115
|
+
img.src = src;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function svgDataUrl(svg) {
|
|
120
|
+
return 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// The embedded page CSS paints an opaque :root background; the composed
|
|
124
|
+
// dot grid is the canvas, so the diagram must stay transparent over it.
|
|
125
|
+
const TRANSPARENT_ROOT = ' :root{background:transparent}';
|
|
126
|
+
|
|
127
|
+
// The map is already one SVG: serialize it with the page styles embedded so
|
|
128
|
+
// the detached copy keeps its look. Width and height scale the whole
|
|
129
|
+
// viewBox, which keeps the geometry and the aspect ratio intact.
|
|
130
|
+
function mapImage(w, h) {
|
|
131
|
+
const svg = document.querySelector('#world svg').cloneNode(true);
|
|
132
|
+
svg.querySelectorAll('.relation-dim').forEach(node => node.classList.remove('relation-dim'));
|
|
133
|
+
svg.setAttribute('width', w);
|
|
134
|
+
svg.setAttribute('height', h);
|
|
135
|
+
const style = document.createElementNS('http://www.w3.org/2000/svg', 'style');
|
|
136
|
+
style.textContent = pageCss() + TRANSPARENT_ROOT;
|
|
137
|
+
svg.insertBefore(style, svg.firstChild);
|
|
138
|
+
return imageFrom(svgDataUrl(svg));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// The tree is HTML cards, so the laid-out world goes into a foreignObject
|
|
142
|
+
// and the browser rasterizes it. The shell keeps the interactive class so
|
|
143
|
+
// the absolute card layout still matches, and the clone is scaled by the
|
|
144
|
+
// export factor; collapsed branches stay collapsed and the fold buttons
|
|
145
|
+
// come off the copy.
|
|
146
|
+
function treeImage(w, h, factor) {
|
|
147
|
+
const clone = document.getElementById('world').cloneNode(true);
|
|
148
|
+
clone.querySelectorAll('.relation-dim').forEach(node => node.classList.remove('relation-dim'));
|
|
149
|
+
clone.removeAttribute('id');
|
|
150
|
+
clone.style.position = 'absolute';
|
|
151
|
+
clone.style.left = '0px';
|
|
152
|
+
clone.style.top = '0px';
|
|
153
|
+
clone.style.transformOrigin = '0 0';
|
|
154
|
+
clone.style.transform = 'scale(' + factor + ')';
|
|
155
|
+
clone.querySelectorAll('.branch').forEach(button => button.remove());
|
|
156
|
+
const shell = document.createElement('div');
|
|
157
|
+
shell.className = 'interactive';
|
|
158
|
+
shell.style.cssText = 'width:' + w + 'px;height:' + h + 'px;position:relative;overflow:hidden;background:transparent;';
|
|
159
|
+
const style = document.createElement('style');
|
|
160
|
+
style.textContent = pageCss() + TRANSPARENT_ROOT + ' .branch{display:none} .alts summary::after,.alts summary::marker{content:none}';
|
|
161
|
+
shell.appendChild(style);
|
|
162
|
+
shell.appendChild(clone);
|
|
163
|
+
return htmlImage(shell, w, h);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function htmlImage(shell, w, h) {
|
|
167
|
+
const foreign = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
|
|
168
|
+
foreign.setAttribute('width', w);
|
|
169
|
+
foreign.setAttribute('height', h);
|
|
170
|
+
foreign.appendChild(shell);
|
|
171
|
+
const frame = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
172
|
+
frame.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
|
173
|
+
frame.setAttribute('width', w);
|
|
174
|
+
frame.setAttribute('height', h);
|
|
175
|
+
frame.appendChild(foreign);
|
|
176
|
+
return imageFrom(svgDataUrl(frame));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Reuse the page's symbols and wording. A folded tree may no longer show
|
|
180
|
+
// every mark in its original legend; selectors refer to the actual drawing.
|
|
181
|
+
function legendEntries() {
|
|
182
|
+
return Array.from(document.querySelectorAll('.canvas-legend .legend > span'))
|
|
183
|
+
.filter(entry => !entry.dataset.shareSelector || document.querySelector(entry.dataset.shareSelector));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function legendImage(W) {
|
|
187
|
+
const entries = legendEntries();
|
|
188
|
+
if (!entries.length) return null;
|
|
189
|
+
const shell = document.createElement('div');
|
|
190
|
+
shell.className = 'canvas-legend share-legend';
|
|
191
|
+
const width = W - PAD * 2;
|
|
192
|
+
const style = document.createElement('style');
|
|
193
|
+
style.textContent = pageCss() + TRANSPARENT_ROOT
|
|
194
|
+
+ ' .share-legend{display:block;box-sizing:border-box;width:' + width + 'px;max-width:none;'
|
|
195
|
+
+ 'padding:0;border:0;border-radius:0;box-shadow:none;background:transparent;font:14px/1.5 ' + SANS + ';}'
|
|
196
|
+
+ ' .share-legend .legend{gap:12px 24px;} .share-legend .legend>span{max-width:100%;}'
|
|
197
|
+
+ ' .share-legend .legend .state{font-size:12px;} .share-legend i{flex-shrink:0;}';
|
|
198
|
+
shell.appendChild(style);
|
|
199
|
+
const legend = document.createElement('div');
|
|
200
|
+
legend.className = 'legend';
|
|
201
|
+
entries.forEach(entry => legend.appendChild(entry.cloneNode(true)));
|
|
202
|
+
shell.appendChild(legend);
|
|
203
|
+
shell.style.cssText = 'position:fixed;left:-10000px;top:0;';
|
|
204
|
+
document.body.appendChild(shell);
|
|
205
|
+
let height;
|
|
206
|
+
try {
|
|
207
|
+
height = Math.ceil(shell.getBoundingClientRect().height);
|
|
208
|
+
} finally {
|
|
209
|
+
shell.remove();
|
|
210
|
+
}
|
|
211
|
+
shell.style.cssText = 'transform-origin:0 0;transform:scale(' + SCALE + ');';
|
|
212
|
+
return { image: await htmlImage(shell, width * SCALE, height * SCALE), height };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function roundRect(ctx, x, y, w, h, r) {
|
|
216
|
+
ctx.beginPath();
|
|
217
|
+
ctx.moveTo(x + r, y);
|
|
218
|
+
ctx.arcTo(x + w, y, x + w, y + h, r);
|
|
219
|
+
ctx.arcTo(x + w, y + h, x, y + h, r);
|
|
220
|
+
ctx.arcTo(x, y + h, x, y, r);
|
|
221
|
+
ctx.arcTo(x, y, x + w, y, r);
|
|
222
|
+
ctx.closePath();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** Cut text to the room it has, marking what was left out with an ellipsis. */
|
|
226
|
+
function fitText(ctx, text, max) {
|
|
227
|
+
if (ctx.measureText(text).width <= max) return text;
|
|
228
|
+
let cut = text;
|
|
229
|
+
while (cut.length > 1 && ctx.measureText(cut + '…').width > max) cut = cut.slice(0, -1);
|
|
230
|
+
return cut + '…';
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function fileName() {
|
|
234
|
+
const slug = shareFacts().title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 80);
|
|
235
|
+
return (slug || 'adr-kit') + '-' + new Date().toISOString().slice(0, 10) + '.png';
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** Wrap measured text, including titles without spaces, without losing it. */
|
|
239
|
+
function wrapLines(ctx, text, width) {
|
|
240
|
+
const lines = [];
|
|
241
|
+
let line = '';
|
|
242
|
+
for (const word of text.match(/\S+\s*/g) || []) {
|
|
243
|
+
if (line && ctx.measureText((line + word).trimEnd()).width > width) {
|
|
244
|
+
lines.push(line.trimEnd());
|
|
245
|
+
line = '';
|
|
246
|
+
}
|
|
247
|
+
for (const char of Array.from(word)) {
|
|
248
|
+
if (line && ctx.measureText((line + char).trimEnd()).width > width) {
|
|
249
|
+
lines.push(line.trimEnd());
|
|
250
|
+
line = '';
|
|
251
|
+
}
|
|
252
|
+
line += char;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (line.trim()) lines.push(line.trimEnd());
|
|
256
|
+
return lines;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Size the typography for the exported sheet, independent of browser zoom.
|
|
260
|
+
// Measuring first reserves real space for long titles and wrapped statistics.
|
|
261
|
+
function headingLayout(ctx, W, facts) {
|
|
262
|
+
const unit = Math.max(1, Math.min(2, W / 1000));
|
|
263
|
+
const width = W - PAD * 2;
|
|
264
|
+
const same = facts.title.toLowerCase() === facts.kind.toLowerCase();
|
|
265
|
+
const rows = [];
|
|
266
|
+
let y = 32 * unit;
|
|
267
|
+
function block(text, size, weight, color, leading) {
|
|
268
|
+
const font = weight + ' ' + size * unit + 'px ' + SANS;
|
|
269
|
+
ctx.font = font;
|
|
270
|
+
for (const textLine of wrapLines(ctx, text, width)) {
|
|
271
|
+
rows.push({ text: textLine, font, color, y });
|
|
272
|
+
y += leading * unit;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (!same) {
|
|
276
|
+
block(facts.kind.toUpperCase(), 13, 600, GREEN, 18);
|
|
277
|
+
y += 10 * unit;
|
|
278
|
+
}
|
|
279
|
+
block(facts.title, 32, 700, INK, 40);
|
|
280
|
+
if (facts.stats) {
|
|
281
|
+
y += 12 * unit;
|
|
282
|
+
block(facts.stats, 15, 500, MUTED, 23);
|
|
283
|
+
}
|
|
284
|
+
return { rows, height: Math.ceil(y + 28 * unit) };
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/** A clear reading order: category, full title, then supporting facts. */
|
|
288
|
+
function heading(ctx, layout) {
|
|
289
|
+
ctx.textBaseline = 'top';
|
|
290
|
+
ctx.textAlign = 'left';
|
|
291
|
+
for (const row of layout.rows) {
|
|
292
|
+
ctx.font = row.font;
|
|
293
|
+
ctx.fillStyle = row.color;
|
|
294
|
+
ctx.fillText(row.text, PAD, row.y);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* The footer is part of the canvas rather than a slab on top of it: a light
|
|
300
|
+
* tint, closed by a hairline, sitting flush on
|
|
301
|
+
* the bottom edge. One line: who made it, and when.
|
|
302
|
+
*/
|
|
303
|
+
function footer(ctx, W, H) {
|
|
304
|
+
const top = H - FOOTER_H;
|
|
305
|
+
ctx.save();
|
|
306
|
+
roundRect(ctx, 0, 0, W, H, RADIUS);
|
|
307
|
+
ctx.clip();
|
|
308
|
+
ctx.fillStyle = TINT;
|
|
309
|
+
ctx.fillRect(0, top, W, FOOTER_H);
|
|
310
|
+
ctx.restore();
|
|
311
|
+
ctx.strokeStyle = HAIRLINE;
|
|
312
|
+
ctx.lineWidth = 1;
|
|
313
|
+
ctx.beginPath();
|
|
314
|
+
ctx.moveTo(0, top + 0.5);
|
|
315
|
+
ctx.lineTo(W, top + 0.5);
|
|
316
|
+
ctx.stroke();
|
|
317
|
+
|
|
318
|
+
const line = top + FOOTER_H / 2;
|
|
319
|
+
ctx.textBaseline = 'middle';
|
|
320
|
+
// The credit: the GitHub mark in the accent, then the handle.
|
|
321
|
+
const mark = 18;
|
|
322
|
+
ctx.save();
|
|
323
|
+
ctx.translate(PAD, line - mark / 2);
|
|
324
|
+
ctx.scale(mark / 16, mark / 16);
|
|
325
|
+
ctx.fillStyle = GREEN;
|
|
326
|
+
ctx.fill(new Path2D(GITHUB_MARK));
|
|
327
|
+
ctx.restore();
|
|
328
|
+
ctx.font = '600 14px ' + SANS;
|
|
329
|
+
ctx.fillStyle = INK;
|
|
330
|
+
ctx.textAlign = 'left';
|
|
331
|
+
ctx.fillText(fitText(ctx, REPO, W - PAD * 2 - mark - 110), PAD + mark + 8, line);
|
|
332
|
+
ctx.font = '500 13px ' + SANS;
|
|
333
|
+
ctx.fillStyle = MUTED;
|
|
334
|
+
ctx.textAlign = 'right';
|
|
335
|
+
ctx.fillText(new Date().toISOString().slice(0, 10), W - PAD, line);
|
|
336
|
+
ctx.textAlign = 'left';
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
async function renderShare() {
|
|
340
|
+
const size = diagramSize();
|
|
341
|
+
const s = Math.min(1, MAX_W / size.w, MAX_H / size.h);
|
|
342
|
+
const w = Math.round(size.w * s), h = Math.round(size.h * s);
|
|
343
|
+
// The frame hugs the diagram; only a very narrow one widens to keep the
|
|
344
|
+
// footer text readable.
|
|
345
|
+
const W = Math.max(w + PAD * 2, MIN_W);
|
|
346
|
+
const canvas = document.createElement('canvas');
|
|
347
|
+
const ctx = canvas.getContext('2d');
|
|
348
|
+
const facts = shareFacts();
|
|
349
|
+
const layout = headingLayout(ctx, W, facts);
|
|
350
|
+
const dx = Math.round((W - w) / 2), dy = layout.height;
|
|
351
|
+
const legend = await legendImage(W);
|
|
352
|
+
const legendHeight = legend ? legend.height + GAP : 0;
|
|
353
|
+
const H = dy + h + GAP + legendHeight + FOOTER_H;
|
|
354
|
+
canvas.width = W * SCALE;
|
|
355
|
+
canvas.height = H * SCALE;
|
|
356
|
+
ctx.scale(SCALE, SCALE);
|
|
357
|
+
// The canvas itself: a rounded paper card, dotted like the live view. The
|
|
358
|
+
// heading stays clear of dots so small supporting text stays legible.
|
|
359
|
+
roundRect(ctx, 0, 0, W, H, RADIUS);
|
|
360
|
+
ctx.fillStyle = PAPER;
|
|
361
|
+
ctx.fill();
|
|
362
|
+
ctx.save();
|
|
363
|
+
ctx.clip();
|
|
364
|
+
ctx.fillStyle = DOT;
|
|
365
|
+
for (let gx = 10; gx <= W - 10; gx += 20) {
|
|
366
|
+
for (let gy = dy; gy < dy + h; gy += 20) {
|
|
367
|
+
ctx.beginPath();
|
|
368
|
+
ctx.arc(gx, gy, 0.9, 0, 7);
|
|
369
|
+
ctx.fill();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
ctx.restore();
|
|
373
|
+
const isTree = !!document.getElementById('edges');
|
|
374
|
+
const img = await (isTree
|
|
375
|
+
? treeImage(w * SCALE, h * SCALE, s * SCALE)
|
|
376
|
+
: mapImage(w * SCALE, h * SCALE));
|
|
377
|
+
ctx.drawImage(img, dx, dy, w, h);
|
|
378
|
+
if (legend) ctx.drawImage(legend.image, PAD, dy + h + GAP, W - PAD * 2, legend.height);
|
|
379
|
+
heading(ctx, layout);
|
|
380
|
+
footer(ctx, W, H);
|
|
381
|
+
// The card's hairline goes last, so it reads as one edge around both zones.
|
|
382
|
+
roundRect(ctx, 0.5, 0.5, W - 1, H - 1, RADIUS);
|
|
383
|
+
ctx.strokeStyle = LINE;
|
|
384
|
+
ctx.lineWidth = 1;
|
|
385
|
+
ctx.stroke();
|
|
386
|
+
return new Promise((resolve, reject) => canvas.toBlob(
|
|
387
|
+
blob => blob ? resolve(blob) : reject(new Error('png encode failed')), 'image/png'));
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
shareButton.addEventListener('click', async () => {
|
|
391
|
+
shareButton.disabled = true;
|
|
392
|
+
showToast('Rendering…');
|
|
393
|
+
try {
|
|
394
|
+
const blob = await renderShare();
|
|
395
|
+
const name = fileName();
|
|
396
|
+
const url = URL.createObjectURL(blob);
|
|
397
|
+
const link = document.createElement('a');
|
|
398
|
+
link.href = url;
|
|
399
|
+
link.download = name;
|
|
400
|
+
document.body.appendChild(link);
|
|
401
|
+
link.click();
|
|
402
|
+
link.remove();
|
|
403
|
+
setTimeout(() => URL.revokeObjectURL(url), 4000);
|
|
404
|
+
let copied = false;
|
|
405
|
+
try {
|
|
406
|
+
await navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })]);
|
|
407
|
+
copied = true;
|
|
408
|
+
} catch (e) {}
|
|
409
|
+
// Only what the page can know: the name it handed over, and whether the
|
|
410
|
+
// clipboard took a copy. Where the download landed is the browser's call.
|
|
411
|
+
showToast(copied ? 'Saved ' + name + ' · copied to clipboard' : 'Saved ' + name);
|
|
412
|
+
} catch (e) {
|
|
413
|
+
showToast('Could not render the image');
|
|
414
|
+
if (window.console) console.error('adr-kit: share render failed', e);
|
|
415
|
+
}
|
|
416
|
+
shareButton.disabled = false;
|
|
417
|
+
});
|
|
418
|
+
})();
|
|
419
|
+
`;
|
|
420
|
+
//# sourceMappingURL=share.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share.js","sourceRoot":"","sources":["../../src/core/share.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,kDAAkD;AAClD,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAErD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,yLAAyL;MAChN,gMAAgM;MAChM,iCAAiC;MACjC,QAAQ,CAAC;AAEb,MAAM,CAAC,MAAM,iBAAiB,GAAG,yFAAyF;MACtH,WAAW,GAAG,WAAW,CAAC;AAE9B;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAA;;;CAGpC,CAAC;AAEF,4EAA4E;AAC5E,uEAAuE;AACvE,MAAM,CAAC,MAAM,gBAAgB,GAC3B,6FAA6F;MAC3F,4HAA4H;MAC5H,0IAA0I;MAC1I,sIAAsI;MACtI,oFAAoF,CAAC;AAEzF,kFAAkF;AAClF,gFAAgF;AAChF,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAA;;;;kBAIpB,eAAe;;;;yBAIR,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+WxC,CAAC"}
|
package/dist/core/templates.d.ts
CHANGED
|
@@ -38,6 +38,8 @@ export declare function droppedSections(proposal: AdrRecord): string[];
|
|
|
38
38
|
/**
|
|
39
39
|
* Rewrite a record's front matter for a lifecycle move: parse the existing
|
|
40
40
|
* block, merge `patch` over it, and re-emit the fields in canonical order.
|
|
41
|
+
* Supersede stamps only the retiring record and its immediate successor link;
|
|
42
|
+
* earlier records keep their historical links when the chain grows.
|
|
41
43
|
* Every non-creating move (accept, reject, supersede) must stamp the date so
|
|
42
44
|
* the front matter always reflects the current status; the Markdown body is
|
|
43
45
|
* left untouched. Only canonical fields survive: a key outside
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/core/templates.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,QAAQ,EACd,MAAM,UAAU,CAAC;AAoClB,0DAA0D;AAC1D,KAAK,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,MAAM,CAO5E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAyBxE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,GACjB,MAAM,CA6BR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,GACjB,MAAM,CAgER;AAMD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,SAAS,GAAG,MAAM,EAAE,CAI7D;AAED
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/core/templates.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,QAAQ,EACd,MAAM,UAAU,CAAC;AAoClB,0DAA0D;AAC1D,KAAK,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,MAAM,CAO5E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAyBxE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,GACjB,MAAM,CA6BR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,GACjB,MAAM,CAgER;AAMD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,SAAS,GAAG,MAAM,EAAE,CAI7D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,MAAM,CAoBnG"}
|
package/dist/core/templates.js
CHANGED
|
@@ -197,6 +197,8 @@ export function droppedSections(proposal) {
|
|
|
197
197
|
/**
|
|
198
198
|
* Rewrite a record's front matter for a lifecycle move: parse the existing
|
|
199
199
|
* block, merge `patch` over it, and re-emit the fields in canonical order.
|
|
200
|
+
* Supersede stamps only the retiring record and its immediate successor link;
|
|
201
|
+
* earlier records keep their historical links when the chain grows.
|
|
200
202
|
* Every non-creating move (accept, reject, supersede) must stamp the date so
|
|
201
203
|
* the front matter always reflects the current status; the Markdown body is
|
|
202
204
|
* left untouched. Only canonical fields survive: a key outside
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/core/templates.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/core/templates.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-integrations.d.ts","sourceRoot":"","sources":["../../src/core/tool-integrations.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAapD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAID,eAAO,MAAM,SAAS,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"tool-integrations.d.ts","sourceRoot":"","sources":["../../src/core/tool-integrations.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAapD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAID,eAAO,MAAM,SAAS,EAAE,QAAQ,EAyd/B,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,cAAc,EAAE,MAAM,EAElC,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAkBlE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,EAAE,CAqBzE;AAaD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,iBAAiB,EAAE,EAC1B,SAAS,GAAE,MAAM,EAAmB,GACnC,eAAe,EAAE,CAgCnB;AAwBD,yEAAyE;AACzE,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAEjE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAyB7E;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,iBAAiB,EAAE,EAC1B,SAAS,EAAE,MAAM,EAAE,GAClB,IAAI,CAeN;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,CAErF"}
|