@dsgraph/report 0.0.0-stage → 0.3.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/LICENSE +21 -0
- package/README.md +7 -2
- package/dist/changeset.d.ts +18 -0
- package/dist/changeset.d.ts.map +1 -0
- package/dist/changeset.js +163 -0
- package/dist/changeset.js.map +1 -0
- package/dist/findings.d.ts +29 -0
- package/dist/findings.d.ts.map +1 -0
- package/dist/findings.js +105 -0
- package/dist/findings.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/values.d.ts +12 -0
- package/dist/values.d.ts.map +1 -0
- package/dist/values.js +112 -0
- package/dist/values.js.map +1 -0
- package/package.json +30 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Adam Reznik
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @dsgraph/report
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Formatters for changesets and findings: `text`, `markdown`, `json`. Propagated value changes are listed under the direct change that caused them; values are shown as hex, px, ΔE.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { formatChangeset, formatFindings } from '@dsgraph/report'
|
|
7
|
+
console.log(formatChangeset(changeset, { format: 'markdown' }))
|
|
8
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Changeset, Impact } from '@dsgraph/core';
|
|
2
|
+
import { formatValue } from './values.js';
|
|
3
|
+
export type Format = 'text' | 'markdown' | 'json';
|
|
4
|
+
export interface ChangesetFormatOptions {
|
|
5
|
+
format?: Format;
|
|
6
|
+
/** Token types by id (from the head graph) for value formatting. */
|
|
7
|
+
types?: Map<string, string | null>;
|
|
8
|
+
/** Max propagated targets listed under a cause. */
|
|
9
|
+
maxPropagated?: number;
|
|
10
|
+
/** Where the changes reach into a project's code (`impactOf`); adds the places under each change. */
|
|
11
|
+
impact?: Impact;
|
|
12
|
+
/** Max places listed under a change. */
|
|
13
|
+
maxSites?: number;
|
|
14
|
+
}
|
|
15
|
+
/** Formats a changeset. Propagated value changes are listed under the direct change that caused them. */
|
|
16
|
+
export declare function formatChangeset(cs: Changeset, opts?: ChangesetFormatOptions): string;
|
|
17
|
+
export { formatValue };
|
|
18
|
+
//# sourceMappingURL=changeset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changeset.d.ts","sourceRoot":"","sources":["../src/changeset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwB,SAAS,EAAE,MAAM,EAAS,MAAM,eAAe,CAAA;AACnF,OAAO,EAAyC,WAAW,EAAc,MAAM,aAAa,CAAA;AAE5F,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAA;AAmEjD,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAA;IAClC,mDAAmD;IACnD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,qGAAqG;IACrG,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAYD,yGAAyG;AACzG,wBAAgB,eAAe,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,GAAE,sBAA2B,GAAG,MAAM,CA8ExF;AAcD,OAAO,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { formatDelta, formatSide, formatSource, formatValue, formatWhen } from './values.js';
|
|
2
|
+
const LEVEL_TITLE = {
|
|
3
|
+
major: 'Breaking (major)',
|
|
4
|
+
minor: 'Minor',
|
|
5
|
+
patch: 'Patch',
|
|
6
|
+
none: 'No impact',
|
|
7
|
+
};
|
|
8
|
+
const typeOf = (c) => {
|
|
9
|
+
const side = (c.after ?? c.before);
|
|
10
|
+
if (side && typeof side === 'object' && 'type' in side)
|
|
11
|
+
return side.type ?? null;
|
|
12
|
+
return null;
|
|
13
|
+
};
|
|
14
|
+
/** One line describing a change; `type` comes from the head token when known. */
|
|
15
|
+
function describe(c, types, code) {
|
|
16
|
+
const t = types.get(c.target) ?? typeOf(c);
|
|
17
|
+
const where = formatWhen(c.when);
|
|
18
|
+
switch (c.kind) {
|
|
19
|
+
case 'token.added':
|
|
20
|
+
return `added ${code(c.target)}`;
|
|
21
|
+
case 'token.removed': {
|
|
22
|
+
const maybe = c.possibleRenames?.length
|
|
23
|
+
? ` — possibly renamed to ${c.possibleRenames.map(code).join(' or ')}`
|
|
24
|
+
: '';
|
|
25
|
+
return `removed ${code(c.target)}${maybe}`;
|
|
26
|
+
}
|
|
27
|
+
case 'token.renamed':
|
|
28
|
+
return `renamed ${code(c.from ?? '?')} → ${code(c.target)}${c.confidence < 0.8 ? ` (likely, ${Math.round(c.confidence * 100)}%)` : ''}`;
|
|
29
|
+
case 'token.value-changed': {
|
|
30
|
+
const delta = formatDelta(c.delta);
|
|
31
|
+
return `${code(c.target)}${where}: ${formatSide(t, c.before)} → ${formatSide(t, c.after)}${delta ? ` (${delta})` : ''}`;
|
|
32
|
+
}
|
|
33
|
+
case 'token.notation-changed':
|
|
34
|
+
return `${code(c.target)}${where}: same value, written differently`;
|
|
35
|
+
case 'token.alias-retargeted':
|
|
36
|
+
return `${code(c.target)}${where}: now ${formatSide(t, c.after)}, same value`;
|
|
37
|
+
case 'token.type-changed':
|
|
38
|
+
return `${code(c.target)}: type ${String(c.before)} → ${String(c.after)}`;
|
|
39
|
+
case 'token.missing-in-context':
|
|
40
|
+
return `${code(c.target)} is no longer defined${where}`;
|
|
41
|
+
case 'token.contexts-changed':
|
|
42
|
+
return `${code(c.target)}: depends on ${JSON.stringify(c.before)} → ${JSON.stringify(c.after)}`;
|
|
43
|
+
case 'token.deprecated': {
|
|
44
|
+
const d = c.after;
|
|
45
|
+
return `deprecated ${code(c.target)}${d?.replacement ? ` — use ${code(d.replacement)}` : d?.reason ? ` — ${d.reason}` : ''}`;
|
|
46
|
+
}
|
|
47
|
+
case 'token.undeprecated':
|
|
48
|
+
return `no longer deprecated ${code(c.target)}`;
|
|
49
|
+
case 'token.description-changed':
|
|
50
|
+
return `${code(c.target)}: description changed`;
|
|
51
|
+
case 'token.extensions-changed':
|
|
52
|
+
return `${code(c.target)}: $extensions changed`;
|
|
53
|
+
case 'group.extends-changed':
|
|
54
|
+
return `group ${code(c.target)}: $extends ${String(c.before ?? '—')} → ${String(c.after ?? '—')}`;
|
|
55
|
+
case 'context.added':
|
|
56
|
+
case 'context.removed':
|
|
57
|
+
return `${c.kind === 'context.added' ? 'added' : 'removed'} context ${code(c.target)}`;
|
|
58
|
+
case 'modifier.added':
|
|
59
|
+
case 'modifier.removed':
|
|
60
|
+
return `${c.kind === 'modifier.added' ? 'added' : 'removed'} modifier ${code(c.target)}`;
|
|
61
|
+
default:
|
|
62
|
+
return `${c.kind} ${code(c.target)}`;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const plural = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
|
|
66
|
+
/** `src/button.css:12, src/card.scss:4 and 3 more` */
|
|
67
|
+
function sitesLine(ci, max, code) {
|
|
68
|
+
const listed = ci.sites.slice(0, max).map((s) => code(`${s.file}:${s.line}`));
|
|
69
|
+
const more = ci.sites.length > max ? ` and ${ci.sites.length - max} more` : '';
|
|
70
|
+
const verb = ci.effect === 'breaks' ? 'breaks' : 'changes';
|
|
71
|
+
return `${verb} ${plural(ci.sites.length, 'place')} in the code: ${listed.join(', ')}${more}`;
|
|
72
|
+
}
|
|
73
|
+
/** Formats a changeset. Propagated value changes are listed under the direct change that caused them. */
|
|
74
|
+
export function formatChangeset(cs, opts = {}) {
|
|
75
|
+
const format = opts.format ?? 'text';
|
|
76
|
+
if (format === 'json')
|
|
77
|
+
return `${JSON.stringify(opts.impact ? { ...cs, impact: opts.impact } : cs, null, 2)}\n`;
|
|
78
|
+
const md = format === 'markdown';
|
|
79
|
+
const code = (s) => (md ? `\`${s}\`` : s);
|
|
80
|
+
const types = opts.types ?? new Map();
|
|
81
|
+
const max = opts.maxPropagated ?? 5;
|
|
82
|
+
const maxSites = opts.maxSites ?? 5;
|
|
83
|
+
const impactBy = new Map((opts.impact?.changes ?? []).map((ci) => [ci.change, ci]));
|
|
84
|
+
const propagatedBy = new Map();
|
|
85
|
+
for (const c of cs.changes)
|
|
86
|
+
for (const cause of c.cause)
|
|
87
|
+
propagatedBy.set(cause, [...(propagatedBy.get(cause) ?? []), c]);
|
|
88
|
+
const shown = cs.changes.filter((c) => !(c.origin === 'propagated' && c.cause.length > 0));
|
|
89
|
+
const counts = cs.summary.counts;
|
|
90
|
+
const summary = [
|
|
91
|
+
counts.removed ? `${counts.removed} removed` : '',
|
|
92
|
+
counts.renamed ? `${counts.renamed} renamed` : '',
|
|
93
|
+
counts.changed
|
|
94
|
+
? `${counts.changed} changed${counts.propagated ? ` (+${counts.propagated} through references)` : ''}`
|
|
95
|
+
: '',
|
|
96
|
+
counts.added ? `${counts.added} added` : '',
|
|
97
|
+
counts.deprecated ? `${counts.deprecated} deprecated` : '',
|
|
98
|
+
].filter(Boolean);
|
|
99
|
+
const lines = [];
|
|
100
|
+
const title = cs.changes.length === 0 ? 'no changes' : `suggested bump: ${cs.summary.level}`;
|
|
101
|
+
if (md) {
|
|
102
|
+
lines.push(`## dsgraph diff — ${title}`, '');
|
|
103
|
+
lines.push(`${formatSource(cs.base.source)} → ${formatSource(cs.head.source)}`, '');
|
|
104
|
+
if (summary.length)
|
|
105
|
+
lines.push(`**${summary.join(' · ')}**`, '');
|
|
106
|
+
if (opts.impact)
|
|
107
|
+
lines.push(impactSummary(opts.impact), '');
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
lines.push(`dsgraph diff — ${title}`, `${formatSource(cs.base.source)} → ${formatSource(cs.head.source)}`);
|
|
111
|
+
if (summary.length)
|
|
112
|
+
lines.push(summary.join(' · '));
|
|
113
|
+
if (opts.impact)
|
|
114
|
+
lines.push(impactSummary(opts.impact));
|
|
115
|
+
lines.push('');
|
|
116
|
+
}
|
|
117
|
+
for (const level of ['major', 'minor', 'patch', 'none']) {
|
|
118
|
+
const group = shown.filter((c) => c.level === level);
|
|
119
|
+
if (group.length === 0)
|
|
120
|
+
continue;
|
|
121
|
+
const collapsible = md && (level === 'patch' || level === 'none');
|
|
122
|
+
if (collapsible)
|
|
123
|
+
lines.push(`<details><summary>${LEVEL_TITLE[level]} (${group.length})</summary>`, '');
|
|
124
|
+
else
|
|
125
|
+
lines.push(md ? `### ${LEVEL_TITLE[level]} (${group.length})` : `${LEVEL_TITLE[level]} (${group.length})`, '');
|
|
126
|
+
for (const c of group) {
|
|
127
|
+
lines.push(`${md ? '- ' : ' '}${describe(c, types, code)}`);
|
|
128
|
+
const via = propagatedBy.get(c.id);
|
|
129
|
+
if (via?.length) {
|
|
130
|
+
const names = [...new Set(via.map((p) => p.target))];
|
|
131
|
+
const listed = names.slice(0, max).map(code).join(', ');
|
|
132
|
+
lines.push(`${md ? ' - ' : ' '}affects ${listed}${names.length > max ? ` and ${names.length - max} more` : ''}`);
|
|
133
|
+
}
|
|
134
|
+
const ci = impactBy.get(c.id);
|
|
135
|
+
if (ci)
|
|
136
|
+
lines.push(`${md ? ' - ' : ' '}${sitesLine(ci, maxSites, code)}`);
|
|
137
|
+
}
|
|
138
|
+
lines.push('');
|
|
139
|
+
if (collapsible)
|
|
140
|
+
lines.push('</details>', '');
|
|
141
|
+
}
|
|
142
|
+
if (cs.contexts.partial)
|
|
143
|
+
lines.push(md
|
|
144
|
+
? '> Some contexts were not fully compared (too many permutations).'
|
|
145
|
+
: 'Note: some contexts were not fully compared.', '');
|
|
146
|
+
return `${lines
|
|
147
|
+
.join('\n')
|
|
148
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
149
|
+
.trimEnd()}\n`;
|
|
150
|
+
}
|
|
151
|
+
function impactSummary(impact) {
|
|
152
|
+
if (impact.breaks === 0 && impact.looksDifferent === 0)
|
|
153
|
+
return 'In the code: nothing uses the changed tokens.';
|
|
154
|
+
const parts = [
|
|
155
|
+
impact.breaks ? `${plural(impact.breaks, 'place')} ${impact.breaks === 1 ? 'breaks' : 'break'}` : '',
|
|
156
|
+
impact.looksDifferent
|
|
157
|
+
? `${plural(impact.looksDifferent, 'place')} ${impact.looksDifferent === 1 ? 'looks' : 'look'} different`
|
|
158
|
+
: '',
|
|
159
|
+
].filter(Boolean);
|
|
160
|
+
return `In the code: ${parts.join(', ')} (${plural(impact.files.length, 'file')}).`;
|
|
161
|
+
}
|
|
162
|
+
export { formatValue };
|
|
163
|
+
//# sourceMappingURL=changeset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changeset.js","sourceRoot":"","sources":["../src/changeset.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Finding, Severity } from '@dsgraph/core';
|
|
2
|
+
import type { Format } from './changeset.js';
|
|
3
|
+
export interface FindingGroup {
|
|
4
|
+
rule: string;
|
|
5
|
+
severity: Severity;
|
|
6
|
+
/** The message with quoted values replaced by `"…"`; the message itself for a group of one. */
|
|
7
|
+
pattern: string;
|
|
8
|
+
findings: Finding[];
|
|
9
|
+
/** The file shared by every finding, if any. */
|
|
10
|
+
file?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Groups repeated findings: same rule, same severity, same message up to quoted values and numbers. Order is kept. */
|
|
13
|
+
export declare function groupFindings(findings: readonly Finding[]): FindingGroup[];
|
|
14
|
+
/** What tells one finding of a group from another: its token, else the quoted values of its message. */
|
|
15
|
+
export declare function findingLabel(f: Finding): string;
|
|
16
|
+
export interface FindingsFormatOptions {
|
|
17
|
+
format?: Format;
|
|
18
|
+
/**
|
|
19
|
+
* Collapse repeated findings (default true). Text lists `examples` labels per group;
|
|
20
|
+
* Markdown puts every finding of a group into a `<details>` block, up to `maxListed`.
|
|
21
|
+
*/
|
|
22
|
+
group?: boolean;
|
|
23
|
+
examples?: number;
|
|
24
|
+
maxListed?: number;
|
|
25
|
+
/** Markdown: start with the `## dsgraph check — …` heading (default true). */
|
|
26
|
+
heading?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare function formatFindings(findings: readonly Finding[], opts?: FindingsFormatOptions): string;
|
|
29
|
+
//# sourceMappingURL=findings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findings.d.ts","sourceRoot":"","sources":["../src/findings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAS5C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,QAAQ,CAAA;IAClB,+FAA+F;IAC/F,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAOD,uHAAuH;AACvH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,YAAY,EAAE,CAgB1E;AAYD,wGAAwG;AACxG,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAG/C;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAUD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAAE,IAAI,GAAE,qBAA0B,GAAG,MAAM,CAyErG"}
|
package/dist/findings.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { formatWhen } from './values.js';
|
|
2
|
+
const ICON = { error: '✖', warning: '▲', info: '•' };
|
|
3
|
+
/** Findings of one rule whose messages differ only in quoted values (`Color "…" is a string`). */
|
|
4
|
+
/** `file:line` when a finding points into code, the file alone otherwise. */
|
|
5
|
+
const where = (loc) => `${loc.file}${loc.line ? `:${loc.line}` : ''}`;
|
|
6
|
+
const QUOTED = /"[^"]*"/g;
|
|
7
|
+
/** What differs between repeated messages: quoted values and numbers (`steps 0 and 1`). */
|
|
8
|
+
const VARIABLE = /"[^"]*"|\b\d+(?:\.\d+)?\b/g;
|
|
9
|
+
const mask = (part) => (part.startsWith('"') ? '"…"' : '…');
|
|
10
|
+
/** Groups repeated findings: same rule, same severity, same message up to quoted values and numbers. Order is kept. */
|
|
11
|
+
export function groupFindings(findings) {
|
|
12
|
+
const groups = new Map();
|
|
13
|
+
for (const f of findings) {
|
|
14
|
+
const pattern = f.message.replace(VARIABLE, mask);
|
|
15
|
+
const key = `${f.severity}\u0000${f.rule}\u0000${pattern}`;
|
|
16
|
+
const g = groups.get(key);
|
|
17
|
+
if (g)
|
|
18
|
+
g.findings.push(f);
|
|
19
|
+
else
|
|
20
|
+
groups.set(key, { rule: f.rule, severity: f.severity, pattern, findings: [f] });
|
|
21
|
+
}
|
|
22
|
+
for (const g of groups.values()) {
|
|
23
|
+
g.pattern = restoreShared(g.findings.map((f) => f.message));
|
|
24
|
+
const files = new Set(g.findings.map((f) => f.loc?.file));
|
|
25
|
+
const [file] = files;
|
|
26
|
+
if (files.size === 1 && file)
|
|
27
|
+
g.file = file;
|
|
28
|
+
}
|
|
29
|
+
return [...groups.values()];
|
|
30
|
+
}
|
|
31
|
+
/** Masks only the values that differ between messages; a shared one stays (`use "px"`, `2025.10`). */
|
|
32
|
+
function restoreShared(messages) {
|
|
33
|
+
const parts = messages.map((m) => m.match(VARIABLE) ?? []);
|
|
34
|
+
let i = 0;
|
|
35
|
+
return messages[0].replace(VARIABLE, (q) => {
|
|
36
|
+
const k = i++;
|
|
37
|
+
return parts.every((ps) => ps[k] === q) ? q : mask(q);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/** What tells one finding of a group from another: its token, else the quoted values of its message. */
|
|
41
|
+
export function findingLabel(f) {
|
|
42
|
+
const subject = f.nodes[0] ?? f.message.match(QUOTED)?.join(' ') ?? f.message;
|
|
43
|
+
return `${subject}${formatWhen(f.when)}`;
|
|
44
|
+
}
|
|
45
|
+
const summaryOf = (findings) => {
|
|
46
|
+
const counts = { error: 0, warning: 0, info: 0 };
|
|
47
|
+
for (const f of findings)
|
|
48
|
+
counts[f.severity]++;
|
|
49
|
+
return `${counts.error} errors · ${counts.warning} warnings · ${counts.info} info`;
|
|
50
|
+
};
|
|
51
|
+
const cell = (s) => s.replace(/\|/g, '\\|');
|
|
52
|
+
export function formatFindings(findings, opts = {}) {
|
|
53
|
+
const format = opts.format ?? 'text';
|
|
54
|
+
if (format === 'json')
|
|
55
|
+
return `${JSON.stringify(findings, null, 2)}\n`;
|
|
56
|
+
const grouped = opts.group ?? true;
|
|
57
|
+
const md = format === 'markdown';
|
|
58
|
+
if (findings.length === 0)
|
|
59
|
+
return md ? '## dsgraph check — no findings\n' : 'dsgraph check — no findings\n';
|
|
60
|
+
const summary = summaryOf(findings);
|
|
61
|
+
const head = opts.heading === false ? '' : `## dsgraph check — ${summary}\n\n`;
|
|
62
|
+
if (md) {
|
|
63
|
+
if (!grouped) {
|
|
64
|
+
const rows = findings.map((f) => `| ${ICON[f.severity]} ${f.severity} | \`${f.rule}\` | ${cell(f.message)}${formatWhen(f.when)} | ${f.loc?.file ? `\`${where(f.loc)}\`` : ''} |`);
|
|
65
|
+
return `${head}| | Rule | Finding | File |\n|---|---|---|---|\n${rows.join('\n')}\n`;
|
|
66
|
+
}
|
|
67
|
+
const groups = groupFindings(findings);
|
|
68
|
+
const max = opts.maxListed ?? 50;
|
|
69
|
+
const rows = groups.map((g) => `| ${ICON[g.severity]} ${g.severity} | \`${g.rule}\` | ${g.findings.length} | ${cell(g.pattern)}${g.findings.length === 1 ? formatWhen(g.findings[0].when) : ''} | ${g.findings.length === 1 && g.findings[0].loc?.file ? `\`${where(g.findings[0].loc)}\`` : g.file ? `\`${g.file}\`` : ''} |`);
|
|
70
|
+
const details = groups
|
|
71
|
+
.filter((g) => g.findings.length > 1)
|
|
72
|
+
.map((g) => {
|
|
73
|
+
const items = g.findings
|
|
74
|
+
.slice(0, max)
|
|
75
|
+
.map((f) => `- ${cell(f.message)}${formatWhen(f.when)}${f.loc?.line ? ` — \`${where(f.loc)}\`` : f.nodes[0] ? ` — \`${f.nodes[0]}\`` : ''}`);
|
|
76
|
+
if (g.findings.length > max)
|
|
77
|
+
items.push(`- … and ${g.findings.length - max} more`);
|
|
78
|
+
return `<details><summary>${ICON[g.severity]} <code>${g.rule}</code> — ${g.findings.length} × ${escapeHtml(g.pattern)}</summary>\n\n${items.join('\n')}\n\n</details>`;
|
|
79
|
+
});
|
|
80
|
+
return `${head}| | Rule | Count | Finding | File |\n|---|---|---|---|---|\n${rows.join('\n')}\n${details.length ? `\n${details.join('\n\n')}\n` : ''}`;
|
|
81
|
+
}
|
|
82
|
+
const line = (severity, rule, text) => `${ICON[severity]} ${severity.padEnd(7)} ${rule.padEnd(30)} ${text}`;
|
|
83
|
+
if (!grouped)
|
|
84
|
+
return `dsgraph check — ${summary}\n\n${findings
|
|
85
|
+
.map((f) => line(f.severity, f.rule, `${f.message}${formatWhen(f.when)}${f.loc?.file ? ` (${where(f.loc)})` : ''}`))
|
|
86
|
+
.join('\n')}\n`;
|
|
87
|
+
const examples = opts.examples ?? 3;
|
|
88
|
+
const indent = ' '.repeat(41);
|
|
89
|
+
const lines = [];
|
|
90
|
+
for (const g of groupFindings(findings)) {
|
|
91
|
+
const n = g.findings.length;
|
|
92
|
+
const file = g.file ? ` (${g.file})` : '';
|
|
93
|
+
if (n === 1) {
|
|
94
|
+
const f = g.findings[0];
|
|
95
|
+
lines.push(line(f.severity, f.rule, `${f.message}${formatWhen(f.when)}${f.loc?.file ? ` (${where(f.loc)})` : ''}`));
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
lines.push(line(g.severity, g.rule, `${n}× ${g.pattern}${file}`));
|
|
99
|
+
const labels = g.findings.slice(0, examples).map(findingLabel);
|
|
100
|
+
lines.push(`${indent}${labels.join(', ')}${n > examples ? `, … and ${n - examples} more` : ''}`);
|
|
101
|
+
}
|
|
102
|
+
return `dsgraph check — ${summary}\n\n${lines.join('\n')}\n`;
|
|
103
|
+
}
|
|
104
|
+
const escapeHtml = (s) => s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
105
|
+
//# sourceMappingURL=findings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findings.js","sourceRoot":"","sources":["../src/findings.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { type ChangesetFormatOptions, type Format, formatChangeset } from './changeset.js';
|
|
2
|
+
export { type FindingGroup, type FindingsFormatOptions, findingLabel, formatFindings, groupFindings, } from './findings.js';
|
|
3
|
+
export { formatDelta, formatSide, formatSource, formatValue, formatWhen } from './values.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,sBAAsB,EAAE,KAAK,MAAM,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC1F,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC1B,YAAY,EACZ,cAAc,EACd,aAAa,GACd,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4C,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC1F,OAAO,EAGL,YAAY,EACZ,cAAc,EACd,aAAa,GACd,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA"}
|
package/dist/values.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type SourceMeta } from '@dsgraph/core';
|
|
2
|
+
/**
|
|
3
|
+
* Short human-readable form of a canonical value. Never throws: a value that does not have the
|
|
4
|
+
* shape of its type (a source error) is shown as it is.
|
|
5
|
+
*/
|
|
6
|
+
export declare function formatValue(type: string | null, value: unknown): string;
|
|
7
|
+
/** Value of a changeset side (`{ raw, value }`) with the alias it came from, if any. */
|
|
8
|
+
export declare function formatSide(type: string | null, side: unknown): string;
|
|
9
|
+
export declare function formatDelta(delta: Record<string, unknown> | undefined): string;
|
|
10
|
+
export declare function formatSource(s: SourceMeta): string;
|
|
11
|
+
export declare const formatWhen: (when: Record<string, string> | null | undefined) => string;
|
|
12
|
+
//# sourceMappingURL=values.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../src/values.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,UAAU,EAAE,MAAM,eAAe,CAAA;AAQ5E;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAMvE;AA8CD,wFAAwF;AACxF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAKrE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,CAqB9E;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAMlD;AAED,eAAO,MAAM,UAAU,SAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS,KAAG,MAKrE,CAAA"}
|
package/dist/values.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { colorToHex } from '@dsgraph/core';
|
|
2
|
+
const isObj = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
3
|
+
const plain = (value) => typeof value === 'string' || typeof value === 'number' ? String(value) : JSON.stringify(value);
|
|
4
|
+
/**
|
|
5
|
+
* Short human-readable form of a canonical value. Never throws: a value that does not have the
|
|
6
|
+
* shape of its type (a source error) is shown as it is.
|
|
7
|
+
*/
|
|
8
|
+
export function formatValue(type, value) {
|
|
9
|
+
try {
|
|
10
|
+
return formatTyped(type, value);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return plain(value);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function formatTyped(type, value) {
|
|
17
|
+
if (value === null || value === undefined)
|
|
18
|
+
return '—';
|
|
19
|
+
switch (type) {
|
|
20
|
+
case 'color': {
|
|
21
|
+
if (!isObj(value) || !Array.isArray(value.components))
|
|
22
|
+
return plain(value);
|
|
23
|
+
const c = value;
|
|
24
|
+
const hex = colorToHex(c);
|
|
25
|
+
const alpha = c.alpha < 1 ? ` ${Math.round(c.alpha * 100)}%` : '';
|
|
26
|
+
return c.space === 'srgb' ? `${hex}${alpha}` : `${hex}${alpha} (${c.space})`;
|
|
27
|
+
}
|
|
28
|
+
case 'dimension':
|
|
29
|
+
case 'duration': {
|
|
30
|
+
const d = value;
|
|
31
|
+
return `${d.value}${d.unit}`;
|
|
32
|
+
}
|
|
33
|
+
case 'fontFamily':
|
|
34
|
+
return value.join(', ');
|
|
35
|
+
case 'cubicBezier':
|
|
36
|
+
return `cubic-bezier(${value.join(', ')})`;
|
|
37
|
+
case 'shadow':
|
|
38
|
+
return value
|
|
39
|
+
.map((l) => [
|
|
40
|
+
l.inset ? 'inset' : '',
|
|
41
|
+
...['offsetX', 'offsetY', 'blur', 'spread'].map((k) => formatValue('dimension', l[k])),
|
|
42
|
+
formatValue('color', l.color),
|
|
43
|
+
]
|
|
44
|
+
.filter(Boolean)
|
|
45
|
+
.join(' '))
|
|
46
|
+
.join(', ');
|
|
47
|
+
case 'border': {
|
|
48
|
+
const b = value;
|
|
49
|
+
return `${formatValue('dimension', b.width)} ${typeof b.style === 'string' ? b.style : 'dashed'} ${formatValue('color', b.color)}`;
|
|
50
|
+
}
|
|
51
|
+
case 'typography': {
|
|
52
|
+
const t = value;
|
|
53
|
+
return `${formatValue('fontWeight', t.fontWeight)} ${formatValue('dimension', t.fontSize)}/${t.lineHeight ?? '—'} ${formatValue('fontFamily', t.fontFamily)}`;
|
|
54
|
+
}
|
|
55
|
+
default:
|
|
56
|
+
return plain(value);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Value of a changeset side (`{ raw, value }`) with the alias it came from, if any. */
|
|
60
|
+
export function formatSide(type, side) {
|
|
61
|
+
if (!isObj(side))
|
|
62
|
+
return formatValue(type, side);
|
|
63
|
+
const v = formatValue(type, side.value);
|
|
64
|
+
const raw = typeof side.raw === 'string' && /^\{[^{}]+\}$/.test(side.raw) ? ` ← ${side.raw}` : '';
|
|
65
|
+
return `${v}${raw}`;
|
|
66
|
+
}
|
|
67
|
+
export function formatDelta(delta) {
|
|
68
|
+
if (!delta)
|
|
69
|
+
return '';
|
|
70
|
+
const parts = [];
|
|
71
|
+
if (typeof delta.deltaEOK === 'number')
|
|
72
|
+
parts.push(`ΔE ${delta.deltaEOK}`);
|
|
73
|
+
if (typeof delta.deltaAlpha === 'number')
|
|
74
|
+
parts.push(`α ${delta.deltaAlpha > 0 ? '+' : ''}${delta.deltaAlpha}`);
|
|
75
|
+
if (typeof delta.px === 'number')
|
|
76
|
+
parts.push(`${delta.px > 0 ? '+' : ''}${delta.px}px`);
|
|
77
|
+
if (typeof delta.ms === 'number')
|
|
78
|
+
parts.push(`${delta.ms > 0 ? '+' : ''}${delta.ms}ms`);
|
|
79
|
+
if (typeof delta.by === 'number')
|
|
80
|
+
parts.push(`${delta.by > 0 ? '+' : ''}${delta.by}`);
|
|
81
|
+
if (Array.isArray(delta.fields))
|
|
82
|
+
parts.push(`changed: ${delta.fields.join(', ')}`);
|
|
83
|
+
for (const [k, one] of [
|
|
84
|
+
['layers', 'layer'],
|
|
85
|
+
['stops', 'stop'],
|
|
86
|
+
]) {
|
|
87
|
+
const d = delta[k];
|
|
88
|
+
// A list holds the indices that changed; a string is a count change ("1 → 2").
|
|
89
|
+
if (Array.isArray(d))
|
|
90
|
+
parts.push(`${d.length === 1 ? one : k} ${d.map((i) => Number(i) + 1).join(', ')}`);
|
|
91
|
+
else if (d !== undefined)
|
|
92
|
+
parts.push(`${k}: ${String(d)}`);
|
|
93
|
+
}
|
|
94
|
+
if (delta.unit !== undefined)
|
|
95
|
+
parts.push(`unit: ${String(delta.unit)}`);
|
|
96
|
+
return parts.join(', ');
|
|
97
|
+
}
|
|
98
|
+
export function formatSource(s) {
|
|
99
|
+
if (s.kind === 'npm')
|
|
100
|
+
return `npm:${s.package}@${s.version}`;
|
|
101
|
+
if (s.kind === 'github')
|
|
102
|
+
return `github:${s.repo}@${s.ref}${s.commit ? ` (${s.commit.slice(0, 7)})` : ''}${s.path ? `/${s.path}` : ''}`;
|
|
103
|
+
if (s.path)
|
|
104
|
+
return s.path;
|
|
105
|
+
return s.kind;
|
|
106
|
+
}
|
|
107
|
+
export const formatWhen = (when) => when && Object.keys(when).length > 0
|
|
108
|
+
? ` (${Object.entries(when)
|
|
109
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
110
|
+
.join(', ')})`
|
|
111
|
+
: '';
|
|
112
|
+
//# sourceMappingURL=values.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"values.js","sourceRoot":"","sources":["../src/values.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsgraph/report",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Formatters for dsgraph changesets and findings: text, Markdown, JSON.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/specsure/specsure.git",
|
|
20
|
+
"directory": "packages/dsgraph-report"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/specsure/specsure/tree/main/packages/dsgraph-report#readme",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/specsure/specsure/issues"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20.19"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@dsgraph/core": "0.3.0"
|
|
31
|
+
}
|
|
32
|
+
}
|