@beehexa/hexasync-template-report-render 2608.15.1 → 2608.20.18
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/package.json +6 -6
- package/dist/diffCollapse.d.ts +0 -12
- package/dist/diffCollapse.d.ts.map +0 -1
- package/dist/diffCollapse.js +0 -31
- package/dist/diffCollapse.js.map +0 -1
- package/dist/flowChart.d.ts +0 -82
- package/dist/flowChart.d.ts.map +0 -1
- package/dist/flowChart.js +0 -250
- package/dist/flowChart.js.map +0 -1
- package/dist/index.d.ts +0 -17
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -17
- package/dist/index.js.map +0 -1
- package/dist/renderHtml.d.ts +0 -5
- package/dist/renderHtml.d.ts.map +0 -1
- package/dist/renderHtml.js +0 -449
- package/dist/renderHtml.js.map +0 -1
- package/dist/renderMarkdown.d.ts +0 -11
- package/dist/renderMarkdown.d.ts.map +0 -1
- package/dist/renderMarkdown.js +0 -412
- package/dist/renderMarkdown.js.map +0 -1
- package/dist/renderValidation.d.ts +0 -7
- package/dist/renderValidation.d.ts.map +0 -1
- package/dist/renderValidation.js +0 -191
- package/dist/renderValidation.js.map +0 -1
- package/dist/renderValidationHtml.d.ts +0 -7
- package/dist/renderValidationHtml.d.ts.map +0 -1
- package/dist/renderValidationHtml.js +0 -189
- package/dist/renderValidationHtml.js.map +0 -1
package/dist/renderMarkdown.js
DELETED
|
@@ -1,412 +0,0 @@
|
|
|
1
|
-
import { collapseDiff } from './diffCollapse.js';
|
|
2
|
-
import { buildMermaid } from './flowChart.js';
|
|
3
|
-
/** Per-status label + color. Colors render in the VSCode markdown preview (and
|
|
4
|
-
* most HTML-capable renderers); where inline styles are stripped, the <strong>
|
|
5
|
-
* and emoji still convey the highlight. */
|
|
6
|
-
const STATUS_STYLE = {
|
|
7
|
-
added: { color: '#22863a', label: '+ added' }, // green
|
|
8
|
-
inherited: { color: '#6a737d', label: '= inherited' }, // gray
|
|
9
|
-
customized: { color: '#0366d6', label: '✏ customized' }, // blue
|
|
10
|
-
excluded: { color: '#b31d28', label: '✂ excluded' }, // red
|
|
11
|
-
lost: { color: '#d73a49', label: '⚠ LOST' }, // bright red
|
|
12
|
-
};
|
|
13
|
-
/** Colored, bold status badge for a table cell. */
|
|
14
|
-
function statusBadge(s) {
|
|
15
|
-
const { color, label } = STATUS_STYLE[s];
|
|
16
|
-
return `<span style="color:${color}"><strong>${label}</strong></span>`;
|
|
17
|
-
}
|
|
18
|
-
/** Display priority: changes first (LOST, customized, removed, added), inherited last. */
|
|
19
|
-
const STATUS_RANK = {
|
|
20
|
-
lost: 0,
|
|
21
|
-
customized: 1,
|
|
22
|
-
excluded: 2,
|
|
23
|
-
added: 3,
|
|
24
|
-
inherited: 4,
|
|
25
|
-
};
|
|
26
|
-
function byStatusThenName(a, b) {
|
|
27
|
-
return (STATUS_RANK[a.status] - STATUS_RANK[b.status] ||
|
|
28
|
-
a.parentKey.localeCompare(b.parentKey) ||
|
|
29
|
-
a.idOrKey.localeCompare(b.idOrKey));
|
|
30
|
-
}
|
|
31
|
-
/** Group components by type (parentKey) so each type collapses independently.
|
|
32
|
-
* Groups with changes sort first (lowest status rank) and open by default;
|
|
33
|
-
* all-inherited groups sort last and stay collapsed for focused review. */
|
|
34
|
-
function groupByType(components) {
|
|
35
|
-
const groups = new Map();
|
|
36
|
-
for (const c of components) {
|
|
37
|
-
if (!groups.has(c.parentKey))
|
|
38
|
-
groups.set(c.parentKey, []);
|
|
39
|
-
groups.get(c.parentKey).push(c);
|
|
40
|
-
}
|
|
41
|
-
return [...groups.entries()]
|
|
42
|
-
.map(([type, comps]) => {
|
|
43
|
-
const sorted = comps.slice().sort(byStatusThenName);
|
|
44
|
-
const minRank = Math.min(...sorted.map((c) => STATUS_RANK[c.status]));
|
|
45
|
-
return {
|
|
46
|
-
type,
|
|
47
|
-
comps: sorted,
|
|
48
|
-
minRank,
|
|
49
|
-
hasChanges: sorted.some((c) => c.status !== 'inherited'),
|
|
50
|
-
};
|
|
51
|
-
})
|
|
52
|
-
.sort((a, b) => a.minRank - b.minRank || a.type.localeCompare(b.type));
|
|
53
|
-
}
|
|
54
|
-
/** Per-type status breakdown for a group's `<summary>` (priority order, colored). */
|
|
55
|
-
function groupSummary(type, comps) {
|
|
56
|
-
const counts = {
|
|
57
|
-
lost: 0,
|
|
58
|
-
customized: 0,
|
|
59
|
-
excluded: 0,
|
|
60
|
-
added: 0,
|
|
61
|
-
inherited: 0,
|
|
62
|
-
};
|
|
63
|
-
for (const c of comps)
|
|
64
|
-
counts[c.status]++;
|
|
65
|
-
const parts = Object.keys(counts)
|
|
66
|
-
.filter((s) => counts[s] > 0)
|
|
67
|
-
.map((s) => `${counts[s]} ${statusBadge(s)}`);
|
|
68
|
-
return `<strong>${escHtml(type)}</strong> — ${comps.length} component${comps.length === 1 ? '' : 's'} · ${parts.join(' · ')}`;
|
|
69
|
-
}
|
|
70
|
-
/** Escape text for inline HTML inside a Markdown table cell. Also neutralizes
|
|
71
|
-
* `|` (breaks cells) and `$` (a math-extension delimiter — JSONata like `$.x`
|
|
72
|
-
* would otherwise be parsed as LaTeX and throw a KaTeX error in the viewer). */
|
|
73
|
-
export function escHtml(text) {
|
|
74
|
-
return String(text ?? '')
|
|
75
|
-
.replace(/&/g, '&')
|
|
76
|
-
.replace(/</g, '<')
|
|
77
|
-
.replace(/>/g, '>')
|
|
78
|
-
.replace(/"/g, '"') // interpolated into href="…"; must not break the attribute
|
|
79
|
-
.replace(/\|/g, '|')
|
|
80
|
-
.replace(/\$/g, '$');
|
|
81
|
-
}
|
|
82
|
-
/** One colored diff line (red removed / green added / gray context), inline-styled. */
|
|
83
|
-
function diffLineMd(l) {
|
|
84
|
-
const style = l.startsWith('+ ')
|
|
85
|
-
? 'background:#e6ffec;color:#116329'
|
|
86
|
-
: l.startsWith('- ')
|
|
87
|
-
? 'background:#ffebe9;color:#b31d28'
|
|
88
|
-
: 'color:#57606a';
|
|
89
|
-
return `<div style="${style};padding:0 .5rem">${escHtml(l)}</div>`;
|
|
90
|
-
}
|
|
91
|
-
/** Color-coded git-diff block; long unchanged runs collapse behind an expandable ellipsis. */
|
|
92
|
-
function styledDiff(diffText) {
|
|
93
|
-
const rows = collapseDiff(diffText)
|
|
94
|
-
.map((seg) => {
|
|
95
|
-
const body = seg.lines.map(diffLineMd).join('');
|
|
96
|
-
return seg.collapsed
|
|
97
|
-
? `<details><summary style="color:#57606a;cursor:pointer;padding:0 .5rem">⋯ ${seg.lines.length} unchanged lines ⋯</summary>${body}</details>`
|
|
98
|
-
: body;
|
|
99
|
-
})
|
|
100
|
-
.join('');
|
|
101
|
-
return `<div style="font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.82rem;white-space:pre-wrap;border:1px solid #d0d7de;border-radius:6px;margin:.3rem 0">${rows}</div>`;
|
|
102
|
-
}
|
|
103
|
-
/** Full-width Mermaid flow row for a puller/pusher, directly under its component row.
|
|
104
|
-
* Emitted as a fenced ```mermaid block (renders in Mermaid-aware markdown viewers;
|
|
105
|
-
* the HTML report renders it live). */
|
|
106
|
-
function flowRowMd(flow, colspan) {
|
|
107
|
-
const phaseCount = flow.phases.length;
|
|
108
|
-
const stepCount = flow.phases.reduce((n, p) => n + p.steps.length, 0);
|
|
109
|
-
const summary = flow.kind === 'creation'
|
|
110
|
-
? `creation workflow — ${stepCount} step(s)`
|
|
111
|
-
: `${flow.kind} flow — ${phaseCount} phase(s), ${stepCount} step(s)`;
|
|
112
|
-
return (`<tr><td colspan="${colspan}" style="background:#f6f8fa">` +
|
|
113
|
-
`<details open><summary>${summary}</summary>\n\n` +
|
|
114
|
-
'```mermaid\n' +
|
|
115
|
-
buildMermaid(flow) +
|
|
116
|
-
'\n```\n\n</details></td></tr>');
|
|
117
|
-
}
|
|
118
|
-
/** Full-width diff row for a customized component (open by default, under its row). */
|
|
119
|
-
function diffRowHtml(diffText) {
|
|
120
|
-
const changes = diffText
|
|
121
|
-
.split('\n')
|
|
122
|
-
.filter((l) => l.startsWith('+ ') || l.startsWith('- ')).length;
|
|
123
|
-
return `<details open><summary>customization diff — ${changes} change${changes === 1 ? '' : 's'} (inherited → final)</summary>${styledDiff(diffText)}</details>`;
|
|
124
|
-
}
|
|
125
|
-
/** Diff cell for a customized component: a per-generation "overwrite history" accordion
|
|
126
|
-
* (D→C, C→B, B→A — last open, it is THIS's real override) when the component crossed
|
|
127
|
-
* more than one generation hop; otherwise the single inherited→final diff. */
|
|
128
|
-
function diffCellMd(c) {
|
|
129
|
-
const phases = c.diffPhases;
|
|
130
|
-
if (phases && phases.length > 0) {
|
|
131
|
-
const last = phases.length - 1;
|
|
132
|
-
const parts = phases
|
|
133
|
-
.map((ph, i) => {
|
|
134
|
-
const open = i === last ? ' open' : '';
|
|
135
|
-
return `<details${open}><summary>${i + 1}. ${escHtml(ph.fromLabel)} → ${escHtml(ph.toLabel)} — ${ph.changeCount} change${ph.changeCount === 1 ? '' : 's'}</summary>${styledDiff(ph.diffText)}</details>`;
|
|
136
|
-
})
|
|
137
|
-
.join('');
|
|
138
|
-
const caption = phases.length === 1
|
|
139
|
-
? `<em>Overwritten: ${escHtml(phases[0].fromLabel)} → ${escHtml(phases[0].toLabel)}</em>`
|
|
140
|
-
: `<em>Overwrite history — ${phases.length} project hops (lowest → highest precedence; last is the winner):</em>`;
|
|
141
|
-
return `${caption}${parts}`;
|
|
142
|
-
}
|
|
143
|
-
return diffRowHtml(c.diffText ?? '');
|
|
144
|
-
}
|
|
145
|
-
/** Nested sub-table (metrics / webhook targets / map entries) under a component row.
|
|
146
|
-
* Collapsible; open when any sub-item changed. Customized items show a diff; items
|
|
147
|
-
* with a step-flow (e.g. a webhook target's pullSteps) show a Mermaid chart. */
|
|
148
|
-
function subTableRowMd(subTable, colspan) {
|
|
149
|
-
const items = subTable.items
|
|
150
|
-
.slice()
|
|
151
|
-
.sort((a, b) => STATUS_RANK[a.status] - STATUS_RANK[b.status] ||
|
|
152
|
-
a.idOrKey.localeCompare(b.idOrKey));
|
|
153
|
-
const counts = {
|
|
154
|
-
lost: 0,
|
|
155
|
-
customized: 0,
|
|
156
|
-
excluded: 0,
|
|
157
|
-
added: 0,
|
|
158
|
-
inherited: 0,
|
|
159
|
-
};
|
|
160
|
-
for (const it of subTable.items)
|
|
161
|
-
counts[it.status]++;
|
|
162
|
-
const parts = Object.keys(counts)
|
|
163
|
-
.filter((s) => counts[s] > 0)
|
|
164
|
-
.map((s) => `${counts[s]} ${statusBadge(s)}`);
|
|
165
|
-
const hasChanges = subTable.items.some((it) => it.status !== 'inherited');
|
|
166
|
-
const rows = items
|
|
167
|
-
.map((it) => {
|
|
168
|
-
let r = `<tr><td><code>${escHtml(it.label)}</code></td><td>${statusBadge(it.status)}</td></tr>`;
|
|
169
|
-
if (it.status === 'customized' && it.diffText) {
|
|
170
|
-
r += `<tr><td colspan="2" style="background:#f6f8fa">${diffRowHtml(it.diffText)}</td></tr>`;
|
|
171
|
-
}
|
|
172
|
-
if (it.flow)
|
|
173
|
-
r += flowRowMd(it.flow, 2);
|
|
174
|
-
return r;
|
|
175
|
-
})
|
|
176
|
-
.join('');
|
|
177
|
-
return (`<tr><td colspan="${colspan}" style="background:#fbfcfd">` +
|
|
178
|
-
`<details${hasChanges ? ' open' : ''}><summary>${escHtml(subTable.title)} — ${subTable.items.length} · ${parts.join(' · ')}</summary>` +
|
|
179
|
-
`<table><thead><tr><th>${escHtml(subTable.title)}</th><th>Status</th></tr></thead><tbody>${rows}</tbody></table>` +
|
|
180
|
-
`</details></td></tr>`);
|
|
181
|
-
}
|
|
182
|
-
/** Compact counts rollup for high-cardinality sub-collections (e.g. metrics). */
|
|
183
|
-
function subComponentsRowMd(subs, colspan) {
|
|
184
|
-
const lines = subs
|
|
185
|
-
.filter((s) => s.added || s.removed || s.customized)
|
|
186
|
-
.map((s) => {
|
|
187
|
-
const parts = [];
|
|
188
|
-
if (s.added)
|
|
189
|
-
parts.push(`+${s.added} added`);
|
|
190
|
-
if (s.removed)
|
|
191
|
-
parts.push(`−${s.removed} removed`);
|
|
192
|
-
if (s.customized)
|
|
193
|
-
parts.push(`~${s.customized} customized`);
|
|
194
|
-
return `<div><strong>${escHtml(s.title)}:</strong> ${parts.join(' · ')}</div>`;
|
|
195
|
-
})
|
|
196
|
-
.join('');
|
|
197
|
-
if (!lines)
|
|
198
|
-
return '';
|
|
199
|
-
return `<tr><td colspan="${colspan}" style="background:#fbfcfd">${lines}</td></tr>`;
|
|
200
|
-
}
|
|
201
|
-
/** Render the project chain as clickable HTML links (for the HTML provenance table). */
|
|
202
|
-
function htmlHierarchy(hierarchy) {
|
|
203
|
-
if (!hierarchy.length)
|
|
204
|
-
return '';
|
|
205
|
-
return hierarchy
|
|
206
|
-
.map((h) => h.link
|
|
207
|
-
? `<a href="${escHtml(h.link)}">${escHtml(h.label)}</a>`
|
|
208
|
-
: `<strong>${escHtml(h.label)}</strong>`)
|
|
209
|
-
.join(' → ');
|
|
210
|
-
}
|
|
211
|
-
const GEN_LABEL = (g) => g === 0 ? '0 (current)' : g === 1 ? '1 (parent)' : `${g} (ancestor)`;
|
|
212
|
-
/**
|
|
213
|
-
* Render the Merge Integrity Report (AD-6). Warnings/errors are surfaced at the
|
|
214
|
-
* TOP so a LOST row can never be buried. Pure string formatting — no I/O.
|
|
215
|
-
*/
|
|
216
|
-
export function renderReport(model) {
|
|
217
|
-
const lines = [];
|
|
218
|
-
const warnCount = model.warnings.length;
|
|
219
|
-
lines.push(`# Merge Integrity Report — ${model.projectTitle}`);
|
|
220
|
-
lines.push('');
|
|
221
|
-
// --- Summary (top) ---
|
|
222
|
-
lines.push(warnCount > 0
|
|
223
|
-
? `## ⚠ Summary — ${warnCount} ${warnCount === 1 ? 'WARNING' : 'WARNINGS'}`
|
|
224
|
-
: `## Summary — OK`);
|
|
225
|
-
lines.push('');
|
|
226
|
-
// HTML table so inline-styled status badges render (markdown pipe-table cells
|
|
227
|
-
// strip inline `style` attributes in many renderers).
|
|
228
|
-
lines.push('<table><thead><tr><th>Status</th><th>Count</th></tr></thead><tbody>');
|
|
229
|
-
Object.keys(model.counts)
|
|
230
|
-
.sort((a, b) => STATUS_RANK[a] - STATUS_RANK[b])
|
|
231
|
-
.forEach((s) => {
|
|
232
|
-
const cell = s === 'lost' && model.counts[s] > 0
|
|
233
|
-
? `<strong>${model.counts[s]}</strong>`
|
|
234
|
-
: `${model.counts[s]}`;
|
|
235
|
-
lines.push(`<tr><td>${statusBadge(s)}</td><td>${cell}</td></tr>`);
|
|
236
|
-
});
|
|
237
|
-
lines.push('</tbody></table>');
|
|
238
|
-
lines.push('');
|
|
239
|
-
if (warnCount > 0) {
|
|
240
|
-
for (const w of model.warnings)
|
|
241
|
-
lines.push(`> ${w}`);
|
|
242
|
-
lines.push('');
|
|
243
|
-
}
|
|
244
|
-
lines.push('---');
|
|
245
|
-
lines.push('');
|
|
246
|
-
// --- Composed projects (resolved merge order) ---
|
|
247
|
-
lines.push('## Composed projects (resolved merge order)');
|
|
248
|
-
lines.push('');
|
|
249
|
-
lines.push('<table><thead><tr><th>#</th><th>Project</th><th>Generation</th><th>Weight</th><th>Merged</th></tr></thead><tbody>');
|
|
250
|
-
// Resolved merge order (CAP-7): deepest generation first, then ascending weight
|
|
251
|
-
// (higher weight merges later/wins), then declaration/BFS order — matching linearize.
|
|
252
|
-
const mergeOrderWeight = (x) => Number.isFinite(x.weight) ? x.weight : 0;
|
|
253
|
-
model.composedProjects
|
|
254
|
-
.slice()
|
|
255
|
-
.sort((a, b) => b.generation - a.generation ||
|
|
256
|
-
mergeOrderWeight(a) - mergeOrderWeight(b) ||
|
|
257
|
-
a.order - b.order)
|
|
258
|
-
.forEach((p, i, arr) => {
|
|
259
|
-
const weight = Number.isFinite(p.weight) ? String(p.weight) : '—';
|
|
260
|
-
const isLastWins = i === arr.length - 1;
|
|
261
|
-
const when = i === 0 && !isLastWins
|
|
262
|
-
? 'first'
|
|
263
|
-
: isLastWins
|
|
264
|
-
? '<span style="color:#22863a"><strong>last (wins)</strong></span>'
|
|
265
|
-
: '';
|
|
266
|
-
const rowStyle = isLastWins ? ' style="background:#e6ffec"' : '';
|
|
267
|
-
const projectCell = isLastWins
|
|
268
|
-
? `<strong>${escHtml(p.project)}</strong>`
|
|
269
|
-
: escHtml(p.project);
|
|
270
|
-
lines.push(`<tr${rowStyle}><td>${i + 1}</td><td>${projectCell}</td><td>${GEN_LABEL(p.generation)}</td><td>${weight}</td><td>${when}</td></tr>`);
|
|
271
|
-
});
|
|
272
|
-
lines.push('</tbody></table>');
|
|
273
|
-
lines.push('');
|
|
274
|
-
lines.push('---');
|
|
275
|
-
lines.push('');
|
|
276
|
-
// --- Global component provenance (grouped by type, collapsible) ---
|
|
277
|
-
// One collapsible <details> per type so a reviewer can expand just the type of
|
|
278
|
-
// interest (e.g. pullers) and collapse the rest. Rendered as HTML tables so each
|
|
279
|
-
// customized/flow row can be a full-width row beneath its component.
|
|
280
|
-
lines.push('## Global component provenance');
|
|
281
|
-
lines.push('');
|
|
282
|
-
lines.push('_Grouped by type — click a type to expand/collapse. Types with changes are expanded; unchanged types are collapsed._');
|
|
283
|
-
lines.push('');
|
|
284
|
-
for (const g of groupByType(model.components)) {
|
|
285
|
-
lines.push(`<details${g.hasChanges ? ' open' : ''}><summary>${groupSummary(g.type, g.comps)}</summary>`);
|
|
286
|
-
lines.push('<table>');
|
|
287
|
-
lines.push('<thead><tr><th>Component</th><th>Status</th><th>Winner</th><th>Weight</th><th>Hierarchy path</th></tr></thead>');
|
|
288
|
-
lines.push('<tbody>');
|
|
289
|
-
for (const c of g.comps) {
|
|
290
|
-
const weight = c.weight !== undefined ? String(c.weight) : '—';
|
|
291
|
-
lines.push(`<tr><td><code>${escHtml(c.idOrKey)}</code></td><td>${statusBadge(c.status)}</td><td>${escHtml(c.winner) || '—'}</td><td>${weight}</td><td>${htmlHierarchy(c.hierarchy)}</td></tr>`);
|
|
292
|
-
// Customized → an explanatory diff row directly beneath (inherited → final,
|
|
293
|
-
// or a per-generation overwrite-history accordion when multi-hop).
|
|
294
|
-
if (c.status === 'customized' && (c.diffText || c.diffPhases)) {
|
|
295
|
-
lines.push(`<tr><td colspan="5" style="background:#f6f8fa">${diffCellMd(c)}</td></tr>`);
|
|
296
|
-
}
|
|
297
|
-
// Puller/pusher → a Mermaid flow chart row directly beneath (any status).
|
|
298
|
-
if (c.flow)
|
|
299
|
-
lines.push(flowRowMd(c.flow, 5));
|
|
300
|
-
// Object/task → a nested metrics sub-table row.
|
|
301
|
-
if (c.subTable)
|
|
302
|
-
lines.push(subTableRowMd(c.subTable, 5));
|
|
303
|
-
if (c.subComponents) {
|
|
304
|
-
const r = subComponentsRowMd(c.subComponents, 5);
|
|
305
|
-
if (r)
|
|
306
|
-
lines.push(r);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
lines.push('</tbody></table>');
|
|
310
|
-
lines.push('</details>');
|
|
311
|
-
lines.push('');
|
|
312
|
-
}
|
|
313
|
-
// --- Wholesale overwrites that dropped components (accidental-loss signal) ---
|
|
314
|
-
if (model.wholesaleLosses.length > 0) {
|
|
315
|
-
lines.push('---');
|
|
316
|
-
lines.push('');
|
|
317
|
-
lines.push('## ⚠ Wholesale overwrites (dropped components)');
|
|
318
|
-
lines.push('');
|
|
319
|
-
lines.push('A later source replaced these arrays **wholesale** with items that have no `id`/`key`, ' +
|
|
320
|
-
'dropping the id/key components listed below. This was **not** an explicit `!` removal — ' +
|
|
321
|
-
'verify each drop is intended (it may be an accidental loss).');
|
|
322
|
-
lines.push('');
|
|
323
|
-
for (const wl of model.wholesaleLosses) {
|
|
324
|
-
const fileName = wl.sourceFile.split(/[\\/]/).filter(Boolean).pop() ?? '';
|
|
325
|
-
const fileLink = wl.sourceLink
|
|
326
|
-
? `<a href="${escHtml(wl.sourceLink)}"><code>${escHtml(fileName)}</code></a>`
|
|
327
|
-
: `<code>${escHtml(fileName)}</code>`;
|
|
328
|
-
lines.push(`<details open><summary>⚠ <code>${escHtml(wl.parentKey)}</code> — dropped ${wl.droppedIds.length} component(s): ${wl.droppedIds.map((d) => `<code>${escHtml(d)}</code>`).join(', ')} (replaced by ${fileLink})</summary>`);
|
|
329
|
-
lines.push('');
|
|
330
|
-
lines.push(styledDiff(wl.diffText));
|
|
331
|
-
lines.push('');
|
|
332
|
-
lines.push('</details>');
|
|
333
|
-
lines.push('');
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
// --- Variables (added / changed vs inherited) ---
|
|
337
|
-
if (model.variableChanges.length > 0) {
|
|
338
|
-
lines.push('---');
|
|
339
|
-
lines.push('');
|
|
340
|
-
lines.push('## Variables (added / changed)');
|
|
341
|
-
lines.push('');
|
|
342
|
-
lines.push('Variables this project **adds** or **changes** vs. what it inherits ' +
|
|
343
|
-
'(unchanged inherited variables are omitted). Values shown git-diff style.');
|
|
344
|
-
lines.push('');
|
|
345
|
-
const added = model.variableChanges.filter((v) => v.status === 'added').length;
|
|
346
|
-
const customized = model.variableChanges.length - added;
|
|
347
|
-
const parts = [];
|
|
348
|
-
if (added > 0)
|
|
349
|
-
parts.push(`${added} ${statusBadge('added')}`);
|
|
350
|
-
if (customized > 0)
|
|
351
|
-
parts.push(`${customized} ${statusBadge('customized')}`);
|
|
352
|
-
// Wrap the whole list in one collapsible group so it can be folded away.
|
|
353
|
-
lines.push(`<details open><summary><strong>variables</strong> — ${model.variableChanges.length} changed · ${parts.join(' · ')}</summary>`);
|
|
354
|
-
lines.push('');
|
|
355
|
-
for (const v of model.variableChanges) {
|
|
356
|
-
lines.push(`<details open><summary>${statusBadge(v.status)} <code>${escHtml(v.key)}</code></summary>`);
|
|
357
|
-
lines.push('');
|
|
358
|
-
lines.push(styledDiff(v.diffText));
|
|
359
|
-
lines.push('');
|
|
360
|
-
lines.push('</details>');
|
|
361
|
-
lines.push('');
|
|
362
|
-
}
|
|
363
|
-
lines.push('</details>');
|
|
364
|
-
lines.push('');
|
|
365
|
-
}
|
|
366
|
-
// --- Per-project contribution ---
|
|
367
|
-
const byProject = new Map();
|
|
368
|
-
for (const c of model.components) {
|
|
369
|
-
const key = c.winner || '—';
|
|
370
|
-
if (!byProject.has(key))
|
|
371
|
-
byProject.set(key, []);
|
|
372
|
-
byProject.get(key).push(c);
|
|
373
|
-
}
|
|
374
|
-
if (byProject.size > 0) {
|
|
375
|
-
lines.push('---');
|
|
376
|
-
lines.push('');
|
|
377
|
-
lines.push('## Per-project contribution');
|
|
378
|
-
lines.push('');
|
|
379
|
-
for (const [proj, comps] of byProject) {
|
|
380
|
-
lines.push(`### ${escHtml(proj)}`);
|
|
381
|
-
lines.push('');
|
|
382
|
-
// Group this project's components by type, collapsible (same as global).
|
|
383
|
-
for (const g of groupByType(comps)) {
|
|
384
|
-
lines.push(`<details${g.hasChanges ? ' open' : ''}><summary>${groupSummary(g.type, g.comps)}</summary>`);
|
|
385
|
-
lines.push('<table><thead><tr><th>Component</th><th>Fate</th></tr></thead><tbody>');
|
|
386
|
-
for (const c of g.comps) {
|
|
387
|
-
lines.push(`<tr><td><code>${escHtml(c.idOrKey)}</code></td><td>${statusBadge(c.status)}</td></tr>`);
|
|
388
|
-
// Customized → diff row directly beneath, here too.
|
|
389
|
-
if (c.status === 'customized' && (c.diffText || c.diffPhases)) {
|
|
390
|
-
lines.push(`<tr><td colspan="2" style="background:#f6f8fa">${diffCellMd(c)}</td></tr>`);
|
|
391
|
-
}
|
|
392
|
-
// Puller/pusher/creation → Mermaid flow chart row, here too.
|
|
393
|
-
if (c.flow)
|
|
394
|
-
lines.push(flowRowMd(c.flow, 2));
|
|
395
|
-
// Object/task → nested metrics sub-table, here too.
|
|
396
|
-
if (c.subTable)
|
|
397
|
-
lines.push(subTableRowMd(c.subTable, 2));
|
|
398
|
-
if (c.subComponents) {
|
|
399
|
-
const r = subComponentsRowMd(c.subComponents, 2);
|
|
400
|
-
if (r)
|
|
401
|
-
lines.push(r);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
lines.push('</tbody></table>');
|
|
405
|
-
lines.push('</details>');
|
|
406
|
-
lines.push('');
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
return lines.join('\n');
|
|
411
|
-
}
|
|
412
|
-
//# sourceMappingURL=renderMarkdown.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"renderMarkdown.js","sourceRoot":"","sources":["../src/renderMarkdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { ValidationReportModel } from '@beehexa/hexasync-template-report-model';
|
|
2
|
-
/**
|
|
3
|
-
* Render the validation report as Markdown (advisory; committed alongside output.yaml).
|
|
4
|
-
* Pure string formatting — deterministic, no timestamps. Mirrors renderReport's shape.
|
|
5
|
-
*/
|
|
6
|
-
export declare function renderValidationReport(model: ValidationReportModel): string;
|
|
7
|
-
//# sourceMappingURL=renderValidation.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"renderValidation.d.ts","sourceRoot":"","sources":["../src/renderValidation.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,qBAAqB,EAEtB,MAAM,yCAAyC,CAAC;AAmDjD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAyC3E"}
|
package/dist/renderValidation.js
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { escHtml } from './renderMarkdown.js';
|
|
2
|
-
import { SEVERITY_ORDER } from '@beehexa/hexasync-template-validate';
|
|
3
|
-
import { ruleDocsFor } from '@beehexa/hexasync-template-validate';
|
|
4
|
-
const SEV_LABEL = {
|
|
5
|
-
critical: 'CRITICAL',
|
|
6
|
-
high: 'HIGH',
|
|
7
|
-
major: 'MAJOR',
|
|
8
|
-
medium: 'MEDIUM',
|
|
9
|
-
low: 'LOW',
|
|
10
|
-
'very-low': 'VERY LOW',
|
|
11
|
-
};
|
|
12
|
-
/** Prose-safe text for Markdown: HTML-escape (escHtml handles & < > " | $), collapse
|
|
13
|
-
* newlines to spaces, and escape Markdown structural chars so an interpolated message,
|
|
14
|
-
* id, or path can't break the surrounding bullet / bold / link / code span. */
|
|
15
|
-
function mdText(s) {
|
|
16
|
-
return escHtml(s)
|
|
17
|
-
.replace(/\s*\n\s*/g, ' ')
|
|
18
|
-
.replace(/([\\`*_[\]])/g, '\\$1');
|
|
19
|
-
}
|
|
20
|
-
/** Render a message that may contain `` `...` `` inline-code spans: prose segments are
|
|
21
|
-
* prose-escaped (mdText); code segments become real Markdown code spans (so a literal
|
|
22
|
-
* pattern like `**Name**` renders highlighted/monospace instead of as bold or plain text).
|
|
23
|
-
* Content inside a span is kept literal — only stray backticks/newlines are neutralized. */
|
|
24
|
-
function mdInline(s) {
|
|
25
|
-
return s
|
|
26
|
-
.split(/(`[^`]*`)/g)
|
|
27
|
-
.map((part) => {
|
|
28
|
-
if (part.length >= 2 && part.startsWith('`') && part.endsWith('`')) {
|
|
29
|
-
const code = part
|
|
30
|
-
.slice(1, -1)
|
|
31
|
-
.replace(/\s*\n\s*/g, ' ')
|
|
32
|
-
.replace(/`/g, '');
|
|
33
|
-
return '`' + code + '`';
|
|
34
|
-
}
|
|
35
|
-
return mdText(part);
|
|
36
|
-
})
|
|
37
|
-
.join('');
|
|
38
|
-
}
|
|
39
|
-
/** Encode a link target so spaces, parens, or newlines can't terminate the Markdown link. */
|
|
40
|
-
function mdUrl(u) {
|
|
41
|
-
return encodeURI(u).replace(/[()]/g, (c) => '%' + c.charCodeAt(0).toString(16).toUpperCase());
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Render the validation report as Markdown (advisory; committed alongside output.yaml).
|
|
45
|
-
* Pure string formatting — deterministic, no timestamps. Mirrors renderReport's shape.
|
|
46
|
-
*/
|
|
47
|
-
export function renderValidationReport(model) {
|
|
48
|
-
const lines = [];
|
|
49
|
-
lines.push(`# Validation Report — ${mdText(model.projectTitle)}`);
|
|
50
|
-
lines.push('');
|
|
51
|
-
if (model.total === 0) {
|
|
52
|
-
lines.push('## ✓ No validation issues');
|
|
53
|
-
lines.push('');
|
|
54
|
-
lines.push('The composed profile passed all enabled validation rules.');
|
|
55
|
-
lines.push('');
|
|
56
|
-
return lines.join('\n');
|
|
57
|
-
}
|
|
58
|
-
const summary = SEVERITY_ORDER.filter((s) => model.counts[s] > 0)
|
|
59
|
-
.map((s) => `${model.counts[s]} ${SEV_LABEL[s]}`)
|
|
60
|
-
.join(' · ');
|
|
61
|
-
lines.push(`## Summary — ${summary}`);
|
|
62
|
-
lines.push('');
|
|
63
|
-
for (const g of model.issuesByComponent) {
|
|
64
|
-
const real = g.issues.filter(isRealIssue);
|
|
65
|
-
if (real.length === 0)
|
|
66
|
-
continue;
|
|
67
|
-
const label = g.sourceLink
|
|
68
|
-
? `[${mdText(g.idOrKey)}](${mdUrl(g.sourceLink)})`
|
|
69
|
-
: `\`${mdText(g.idOrKey)}\``;
|
|
70
|
-
lines.push(`### ${mdText(g.parentKey)} — ${label}`);
|
|
71
|
-
lines.push('');
|
|
72
|
-
for (const i of real)
|
|
73
|
-
lines.push(...renderIssueMd(i));
|
|
74
|
-
}
|
|
75
|
-
const crossCutting = model.crossCutting.filter(isRealIssue);
|
|
76
|
-
if (crossCutting.length > 0) {
|
|
77
|
-
lines.push('## Project-wide');
|
|
78
|
-
lines.push('');
|
|
79
|
-
for (const i of crossCutting)
|
|
80
|
-
lines.push(...renderIssueMd(i));
|
|
81
|
-
}
|
|
82
|
-
lines.push(...renderNoticesMd(model));
|
|
83
|
-
lines.push(...renderAppendixMd(model));
|
|
84
|
-
return lines.join('\n');
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* A finding about the profile's CONFIGURATION, as opposed to a migration notice.
|
|
88
|
-
*
|
|
89
|
-
* The split is `very-low` (reported by Jazz, 2026-08-11): a deprecation, a retired component type, a legacy-but-working
|
|
90
|
-
* shape. *"It doesn't break the profile runtime. Just focus on real configuration issues."* Interleaved, a project with
|
|
91
|
-
* many legacy pullers pushed the findings that DO break something off the top of the report.
|
|
92
|
-
*/
|
|
93
|
-
const isRealIssue = (issue) => issue.severity !== 'very-low';
|
|
94
|
-
/**
|
|
95
|
-
* The trailing notices section — everything `very-low`, after the real findings and before the appendix.
|
|
96
|
-
*
|
|
97
|
-
* Gathered rather than merely sorted last. Severity ordering alone would still have put a legacy puller's notice
|
|
98
|
-
* INSIDE that puller's own `###` block, so a reader scanning component by component kept meeting them; and a component
|
|
99
|
-
* whose only finding is a notice got a heading that promised a problem. Here the body above contains configuration
|
|
100
|
-
* issues only, and the notices are one list a reader can act on when migrating rather than while debugging.
|
|
101
|
-
*
|
|
102
|
-
* Component identity travels in the line, since these are no longer under a component heading — a notice that cannot
|
|
103
|
-
* say WHICH puller is legacy is not actionable.
|
|
104
|
-
*/
|
|
105
|
-
function renderNoticesMd(model) {
|
|
106
|
-
const notices = [];
|
|
107
|
-
for (const g of model.issuesByComponent)
|
|
108
|
-
for (const i of g.issues)
|
|
109
|
-
if (!isRealIssue(i))
|
|
110
|
-
notices.push({ issue: i, where: `${g.parentKey} — ${g.idOrKey}` });
|
|
111
|
-
for (const i of model.crossCutting)
|
|
112
|
-
if (!isRealIssue(i))
|
|
113
|
-
notices.push({ issue: i });
|
|
114
|
-
if (notices.length === 0)
|
|
115
|
-
return [];
|
|
116
|
-
const out = [];
|
|
117
|
-
out.push('## Deprecations & legacy notices');
|
|
118
|
-
out.push('');
|
|
119
|
-
out.push('_None of these breaks the profile at runtime._ They are here so a template can be migrated before the ' +
|
|
120
|
-
'platform stops carrying the shape — act on them when you next touch the component, not while debugging a run.');
|
|
121
|
-
out.push('');
|
|
122
|
-
for (const { issue, where } of notices) {
|
|
123
|
-
const rendered = renderIssueMd(issue);
|
|
124
|
-
// The component, appended to the finding's own first line — these sit under no `###` heading of their own.
|
|
125
|
-
if (where !== undefined && rendered.length > 0)
|
|
126
|
-
rendered[0] = `${rendered[0]} — in \`${mdText(where)}\``;
|
|
127
|
-
out.push(...rendered);
|
|
128
|
-
}
|
|
129
|
-
return out;
|
|
130
|
-
}
|
|
131
|
-
/** Appendix: explain every rule that appears in this report — what it checks and what
|
|
132
|
-
* breaks if ignored — so a reader can act on a rule id without leaving the document. */
|
|
133
|
-
function renderAppendixMd(model) {
|
|
134
|
-
const ids = [];
|
|
135
|
-
for (const g of model.issuesByComponent)
|
|
136
|
-
for (const i of g.issues)
|
|
137
|
-
ids.push(i.ruleId);
|
|
138
|
-
for (const i of model.crossCutting)
|
|
139
|
-
ids.push(i.ruleId);
|
|
140
|
-
const docs = ruleDocsFor(ids);
|
|
141
|
-
if (docs.length === 0)
|
|
142
|
-
return [];
|
|
143
|
-
const out = [];
|
|
144
|
-
out.push('## Appendix — rule reference');
|
|
145
|
-
out.push('');
|
|
146
|
-
out.push('Every rule flagged above, with what it checks and what breaks if it is left unfixed.');
|
|
147
|
-
out.push('');
|
|
148
|
-
for (const { ruleId, doc } of docs) {
|
|
149
|
-
// Heading is just the (code-wrapped) rule id so GitHub's heading slug is a stable
|
|
150
|
-
// `#<ruleid>` (lowercased) that the inline rule links above point at; title on its own line.
|
|
151
|
-
out.push(`### \`${mdText(ruleId)}\``);
|
|
152
|
-
out.push('');
|
|
153
|
-
out.push(`**${mdInline(doc.title)}**`);
|
|
154
|
-
out.push('');
|
|
155
|
-
out.push(`- **What:** ${mdInline(doc.what)}`);
|
|
156
|
-
out.push(`- **Why it matters:** ${mdInline(doc.consequence)}`);
|
|
157
|
-
out.push('');
|
|
158
|
-
}
|
|
159
|
-
return out;
|
|
160
|
-
}
|
|
161
|
-
/** Anchor/slug for a rule's appendix entry — matches GitHub's slug of a `` `RULE` `` heading
|
|
162
|
-
* (backticks stripped, lowercased) and the HTML report's explicit `id`. */
|
|
163
|
-
function ruleAnchor(ruleId) {
|
|
164
|
-
return ruleId.toLowerCase();
|
|
165
|
-
}
|
|
166
|
-
/** A rule id rendered as a Markdown link to its appendix entry. */
|
|
167
|
-
function ruleLinkMd(ruleId) {
|
|
168
|
-
return `[\`${mdText(ruleId)}\`](#${ruleAnchor(ruleId)})`;
|
|
169
|
-
}
|
|
170
|
-
function renderIssueMd(i) {
|
|
171
|
-
const out = [];
|
|
172
|
-
const link = ruleLinkMd(i.ruleId);
|
|
173
|
-
// A message may place the rule-id link inline via a `{{rule}}` marker; otherwise the
|
|
174
|
-
// linked rule id trails the headline. Either way the id links to the appendix.
|
|
175
|
-
const head = i.message.includes('{{rule}}')
|
|
176
|
-
? `- **[${SEV_LABEL[i.severity]}] ${i.message.split('{{rule}}').map(mdInline).join(link)}**`
|
|
177
|
-
: `- **[${SEV_LABEL[i.severity]}] ${mdInline(i.message)}** ${link}`;
|
|
178
|
-
out.push(head);
|
|
179
|
-
if (i.why)
|
|
180
|
-
out.push(` - ${mdInline(i.why)}`);
|
|
181
|
-
if (i.snippetDiff) {
|
|
182
|
-
out.push('');
|
|
183
|
-
out.push(' ```');
|
|
184
|
-
for (const l of i.snippetDiff.split('\n'))
|
|
185
|
-
out.push(` ${l}`);
|
|
186
|
-
out.push(' ```');
|
|
187
|
-
}
|
|
188
|
-
out.push('');
|
|
189
|
-
return out;
|
|
190
|
-
}
|
|
191
|
-
//# sourceMappingURL=renderValidation.js.map
|