@trailmark/core 0.1.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.
Files changed (94) hide show
  1. package/dist/baseline.d.ts +21 -0
  2. package/dist/baseline.d.ts.map +1 -0
  3. package/dist/baseline.js +187 -0
  4. package/dist/baseline.js.map +1 -0
  5. package/dist/diff.d.ts +3 -0
  6. package/dist/diff.d.ts.map +1 -0
  7. package/dist/diff.js +120 -0
  8. package/dist/diff.js.map +1 -0
  9. package/dist/fingerprint.d.ts +8 -0
  10. package/dist/fingerprint.d.ts.map +1 -0
  11. package/dist/fingerprint.js +85 -0
  12. package/dist/fingerprint.js.map +1 -0
  13. package/dist/hash.d.ts +4 -0
  14. package/dist/hash.d.ts.map +1 -0
  15. package/dist/hash.js +29 -0
  16. package/dist/hash.js.map +1 -0
  17. package/dist/impact.d.ts +5 -0
  18. package/dist/impact.d.ts.map +1 -0
  19. package/dist/impact.js +27 -0
  20. package/dist/impact.js.map +1 -0
  21. package/dist/index.d.ts +12 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +28 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/issue.d.ts +10 -0
  26. package/dist/issue.d.ts.map +1 -0
  27. package/dist/issue.js +40 -0
  28. package/dist/issue.js.map +1 -0
  29. package/dist/normalize.d.ts +3 -0
  30. package/dist/normalize.d.ts.map +1 -0
  31. package/dist/normalize.js +59 -0
  32. package/dist/normalize.js.map +1 -0
  33. package/dist/report/buildReport.d.ts +3 -0
  34. package/dist/report/buildReport.d.ts.map +1 -0
  35. package/dist/report/buildReport.js +223 -0
  36. package/dist/report/buildReport.js.map +1 -0
  37. package/dist/report/formatConsole.d.ts +3 -0
  38. package/dist/report/formatConsole.d.ts.map +1 -0
  39. package/dist/report/formatConsole.js +112 -0
  40. package/dist/report/formatConsole.js.map +1 -0
  41. package/dist/report/index.d.ts +4 -0
  42. package/dist/report/index.d.ts.map +1 -0
  43. package/dist/report/index.js +20 -0
  44. package/dist/report/index.js.map +1 -0
  45. package/dist/report/sort.d.ts +9 -0
  46. package/dist/report/sort.d.ts.map +1 -0
  47. package/dist/report/sort.js +20 -0
  48. package/dist/report/sort.js.map +1 -0
  49. package/dist/report/types.d.ts +85 -0
  50. package/dist/report/types.d.ts.map +1 -0
  51. package/dist/report/types.js +3 -0
  52. package/dist/report/types.js.map +1 -0
  53. package/dist/run.d.ts +8 -0
  54. package/dist/run.d.ts.map +1 -0
  55. package/dist/run.js +20 -0
  56. package/dist/run.js.map +1 -0
  57. package/dist/scope.d.ts +5 -0
  58. package/dist/scope.d.ts.map +1 -0
  59. package/dist/scope.js +23 -0
  60. package/dist/scope.js.map +1 -0
  61. package/dist/types.d.ts +150 -0
  62. package/dist/types.d.ts.map +1 -0
  63. package/dist/types.js +3 -0
  64. package/dist/types.js.map +1 -0
  65. package/dist/url.d.ts +3 -0
  66. package/dist/url.d.ts.map +1 -0
  67. package/dist/url.js +82 -0
  68. package/dist/url.js.map +1 -0
  69. package/package.json +23 -0
  70. package/src/baseline.ts +217 -0
  71. package/src/diff.ts +150 -0
  72. package/src/fingerprint.ts +107 -0
  73. package/src/hash.ts +29 -0
  74. package/src/impact.ts +27 -0
  75. package/src/index.ts +11 -0
  76. package/src/issue.ts +49 -0
  77. package/src/normalize.ts +66 -0
  78. package/src/report/buildReport.ts +276 -0
  79. package/src/report/formatConsole.ts +137 -0
  80. package/src/report/index.ts +3 -0
  81. package/src/report/sort.ts +28 -0
  82. package/src/report/types.ts +101 -0
  83. package/src/run.ts +22 -0
  84. package/src/scope.ts +25 -0
  85. package/src/types.ts +167 -0
  86. package/src/url.ts +102 -0
  87. package/test/baseline.test.ts +151 -0
  88. package/test/diff.test.ts +113 -0
  89. package/test/fingerprint.test.ts +41 -0
  90. package/test/issue.test.ts +79 -0
  91. package/test/report.build.test.ts +191 -0
  92. package/test/report.console.test.ts +102 -0
  93. package/test/url.test.ts +25 -0
  94. package/tsconfig.json +8 -0
package/dist/issue.js ADDED
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeFailureHint = normalizeFailureHint;
4
+ exports.buildRelaxedIssueId = buildRelaxedIssueId;
5
+ exports.buildIssueId = buildIssueId;
6
+ const hash_1 = require("./hash");
7
+ function normalizeFailureHint(summary) {
8
+ if (!summary) {
9
+ return undefined;
10
+ }
11
+ const normalized = summary
12
+ .toLowerCase()
13
+ .replace(/["']/g, "")
14
+ .replace(/\d+/g, "#")
15
+ .replace(/\s+/g, " ")
16
+ .trim();
17
+ if (!normalized) {
18
+ return undefined;
19
+ }
20
+ return normalized;
21
+ }
22
+ function buildRelaxedIssueId(input) {
23
+ return (0, hash_1.hashObject)({
24
+ ruleId: input.ruleId,
25
+ pageKey: input.pageKey,
26
+ targetHash: input.targetHash,
27
+ });
28
+ }
29
+ function buildIssueId(input) {
30
+ const payload = {
31
+ ruleId: input.ruleId,
32
+ pageKey: input.pageKey,
33
+ targetHash: input.targetHash,
34
+ };
35
+ if (input.failureHint) {
36
+ payload.failureHint = input.failureHint;
37
+ }
38
+ return (0, hash_1.hashObject)(payload);
39
+ }
40
+ //# sourceMappingURL=issue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue.js","sourceRoot":"","sources":["../src/issue.ts"],"names":[],"mappings":";;AASA,oDAiBC;AAED,kDAMC;AAED,oCAYC;AAhDD,iCAAmC;AASnC,SAAgB,oBAAoB,CAAC,OAA2B;IAC9D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,UAAU,GAAG,OAAO;SACvB,WAAW,EAAE;SACb,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;SACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAA;IAET,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,SAAgB,mBAAmB,CAAC,KAAwC;IAC1E,OAAO,IAAA,iBAAU,EAAC;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU,EAAE,KAAK,CAAC,UAAU;KAC7B,CAAC,CAAA;AACJ,CAAC;AAED,SAAgB,YAAY,CAAC,KAAmB;IAC9C,MAAM,OAAO,GAA2B;QACtC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU,EAAE,KAAK,CAAC,UAAU;KAC7B,CAAA;IAED,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAA;IACzC,CAAC;IAED,OAAO,IAAA,iBAAU,EAAC,OAAO,CAAC,CAAA;AAC5B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { NormalizeInput, TrailmarkFinding } from "./types";
2
+ export declare function normalizeAxeResults(input: NormalizeInput): TrailmarkFinding[];
3
+ //# sourceMappingURL=normalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAc1D,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,gBAAgB,EAAE,CAgD7E"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeAxeResults = normalizeAxeResults;
4
+ const fingerprint_1 = require("./fingerprint");
5
+ const issue_1 = require("./issue");
6
+ const url_1 = require("./url");
7
+ function truncate(value, maxLength) {
8
+ if (!value) {
9
+ return undefined;
10
+ }
11
+ if (value.length <= maxLength) {
12
+ return value;
13
+ }
14
+ return value.slice(0, maxLength);
15
+ }
16
+ function normalizeAxeResults(input) {
17
+ const pageKey = (0, url_1.normalizeUrlToPageKey)(input.pageUrl, input.urlOptions);
18
+ const htmlMaxLength = input.htmlMaxLength ?? 400;
19
+ const failureSummaryMaxLength = input.failureSummaryMaxLength ?? 400;
20
+ const findings = [];
21
+ for (const violation of input.results.violations ?? []) {
22
+ for (const node of violation.nodes ?? []) {
23
+ const fingerprint = (0, fingerprint_1.buildTargetFingerprint)(node);
24
+ const failureSummary = truncate(node.failureSummary, failureSummaryMaxLength);
25
+ const failureHint = (0, issue_1.normalizeFailureHint)(failureSummary);
26
+ const relaxedIssueId = (0, issue_1.buildRelaxedIssueId)({
27
+ ruleId: violation.id,
28
+ pageKey,
29
+ targetHash: fingerprint.targetHash,
30
+ });
31
+ const issueId = (0, issue_1.buildIssueId)({
32
+ ruleId: violation.id,
33
+ pageKey,
34
+ targetHash: fingerprint.targetHash,
35
+ failureHint,
36
+ });
37
+ findings.push({
38
+ issueId,
39
+ relaxedIssueId,
40
+ ruleId: violation.id,
41
+ impact: violation.impact,
42
+ tags: [...(violation.tags ?? [])],
43
+ help: violation.help,
44
+ helpUrl: violation.helpUrl,
45
+ pageUrl: input.pageUrl,
46
+ pageKey,
47
+ target: Array.isArray(node.target) ? [...node.target] : [],
48
+ selectorHint: fingerprint.selectorHint ?? undefined,
49
+ targetHash: fingerprint.targetHash,
50
+ nodeHtml: truncate(node.html, htmlMaxLength),
51
+ failureSummary,
52
+ failureHint,
53
+ meta: input.meta,
54
+ });
55
+ }
56
+ }
57
+ return findings;
58
+ }
59
+ //# sourceMappingURL=normalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":";;AAiBA,kDAgDC;AAjED,+CAAsD;AACtD,mCAAiF;AACjF,+BAA6C;AAG7C,SAAS,QAAQ,CAAC,KAAyB,EAAE,SAAiB;IAC5D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;AAClC,CAAC;AAED,SAAgB,mBAAmB,CAAC,KAAqB;IACvD,MAAM,OAAO,GAAG,IAAA,2BAAqB,EAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;IACtE,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,IAAI,GAAG,CAAA;IAChD,MAAM,uBAAuB,GAAG,KAAK,CAAC,uBAAuB,IAAI,GAAG,CAAA;IAEpE,MAAM,QAAQ,GAAuB,EAAE,CAAA;IAEvC,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC;QACvD,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YACzC,MAAM,WAAW,GAAG,IAAA,oCAAsB,EAAC,IAAI,CAAC,CAAA;YAChD,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,uBAAuB,CAAC,CAAA;YAC7E,MAAM,WAAW,GAAG,IAAA,4BAAoB,EAAC,cAAc,CAAC,CAAA;YAExD,MAAM,cAAc,GAAG,IAAA,2BAAmB,EAAC;gBACzC,MAAM,EAAE,SAAS,CAAC,EAAE;gBACpB,OAAO;gBACP,UAAU,EAAE,WAAW,CAAC,UAAU;aACnC,CAAC,CAAA;YAEF,MAAM,OAAO,GAAG,IAAA,oBAAY,EAAC;gBAC3B,MAAM,EAAE,SAAS,CAAC,EAAE;gBACpB,OAAO;gBACP,UAAU,EAAE,WAAW,CAAC,UAAU;gBAClC,WAAW;aACZ,CAAC,CAAA;YAEF,QAAQ,CAAC,IAAI,CAAC;gBACZ,OAAO;gBACP,cAAc;gBACd,MAAM,EAAE,SAAS,CAAC,EAAE;gBACpB,MAAM,EAAE,SAAS,CAAC,MAAM;gBACxB,IAAI,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;gBACjC,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,OAAO;gBACP,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;gBAC1D,YAAY,EAAE,WAAW,CAAC,YAAY,IAAI,SAAS;gBACnD,UAAU,EAAE,WAAW,CAAC,UAAU;gBAClC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC;gBAC5C,cAAc;gBACd,WAAW;gBACX,IAAI,EAAE,KAAK,CAAC,IAAI;aACjB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { BuildReportInput, TrailmarkReport } from "./types";
2
+ export declare function buildReport(input: BuildReportInput): TrailmarkReport;
3
+ //# sourceMappingURL=buildReport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildReport.d.ts","sourceRoot":"","sources":["../../src/report/buildReport.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,eAAe,EAGhB,MAAM,SAAS,CAAA;AAmHhB,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,eAAe,CA0JpE"}
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildReport = buildReport;
4
+ const hash_1 = require("../hash");
5
+ const impact_1 = require("../impact");
6
+ const sort_1 = require("./sort");
7
+ function dedupeAndSortTags(tags) {
8
+ return Array.from(new Set(tags)).sort((left, right) => left.localeCompare(right));
9
+ }
10
+ function compareOccurrence(left, right) {
11
+ const projectDiff = (left.projectName ?? "").localeCompare(right.projectName ?? "");
12
+ if (projectDiff !== 0) {
13
+ return projectDiff;
14
+ }
15
+ const testDiff = (left.testId ?? "").localeCompare(right.testId ?? "");
16
+ if (testDiff !== 0) {
17
+ return testDiff;
18
+ }
19
+ const urlDiff = left.url.localeCompare(right.url);
20
+ if (urlDiff !== 0) {
21
+ return urlDiff;
22
+ }
23
+ const timestampDiff = left.timestamp.localeCompare(right.timestamp);
24
+ if (timestampDiff !== 0) {
25
+ return timestampDiff;
26
+ }
27
+ return (left.occurrenceId ?? "").localeCompare(right.occurrenceId ?? "");
28
+ }
29
+ function toSortedRecord(map) {
30
+ const sorted = Array.from(map.entries()).sort((left, right) => left[0].localeCompare(right[0]));
31
+ const record = {};
32
+ for (const [key, value] of sorted) {
33
+ record[key] = value;
34
+ }
35
+ return record;
36
+ }
37
+ function toSortedAttachment(attachment) {
38
+ return {
39
+ kind: attachment.kind,
40
+ path: attachment.path,
41
+ error: attachment.error,
42
+ };
43
+ }
44
+ function compareAttachment(left, right) {
45
+ const kindDiff = left.kind.localeCompare(right.kind);
46
+ if (kindDiff !== 0) {
47
+ return kindDiff;
48
+ }
49
+ const pathDiff = (left.path ?? "").localeCompare(right.path ?? "");
50
+ if (pathDiff !== 0) {
51
+ return pathDiff;
52
+ }
53
+ return (left.error ?? "").localeCompare(right.error ?? "");
54
+ }
55
+ function resolveAttachments(finding, artifacts) {
56
+ const fromOccurrenceId = finding.occurrenceId
57
+ ? artifacts?.byOccurrenceId?.[finding.occurrenceId]
58
+ : undefined;
59
+ const fromIssueId = artifacts?.byIssueId?.[finding.issueId];
60
+ const source = fromOccurrenceId ?? finding.attachments ?? fromIssueId ?? [];
61
+ return [...source].map(toSortedAttachment).sort(compareAttachment);
62
+ }
63
+ function occurrenceKey(finding, occurrence) {
64
+ if (finding.occurrenceId) {
65
+ return finding.occurrenceId;
66
+ }
67
+ return (0, hash_1.hashObject)({
68
+ issueId: finding.issueId,
69
+ testId: occurrence.testId,
70
+ projectName: occurrence.projectName,
71
+ url: occurrence.url,
72
+ selector: finding.target[0] ?? finding.selectorHint ?? "",
73
+ });
74
+ }
75
+ function findingSortKey(finding) {
76
+ return [
77
+ (0, impact_1.impactRank)(finding.impact),
78
+ finding.ruleId,
79
+ finding.pageKey,
80
+ finding.issueId,
81
+ finding.meta?.projectName ?? "",
82
+ finding.meta?.testId ?? "",
83
+ finding.target[0] ?? finding.selectorHint ?? "",
84
+ ].join("|");
85
+ }
86
+ function uniqueSorted(values) {
87
+ return Array.from(new Set(values)).sort((left, right) => left.localeCompare(right));
88
+ }
89
+ function buildReport(input) {
90
+ const createdAt = input.createdAt ?? new Date().toISOString();
91
+ const issuesById = new Map();
92
+ const scannedPages = new Set();
93
+ const sortedFindings = [...input.run.findings].sort((left, right) => findingSortKey(left).localeCompare(findingSortKey(right)));
94
+ for (const finding of sortedFindings) {
95
+ scannedPages.add(finding.pageKey);
96
+ const existing = issuesById.get(finding.issueId);
97
+ const issue = existing ?? {
98
+ issueId: finding.issueId,
99
+ ruleId: finding.ruleId,
100
+ impact: finding.impact,
101
+ tags: dedupeAndSortTags(finding.tags),
102
+ pageKey: finding.pageKey,
103
+ url: finding.pageUrl,
104
+ target: [...finding.target],
105
+ selectorHint: finding.selectorHint,
106
+ failureSummary: finding.failureSummary,
107
+ occurrences: [],
108
+ occurrenceKeys: new Set(),
109
+ };
110
+ if (!existing) {
111
+ issuesById.set(finding.issueId, issue);
112
+ }
113
+ const occurrence = {
114
+ occurrenceId: finding.occurrenceId,
115
+ testId: finding.meta?.testId,
116
+ projectName: finding.meta?.projectName,
117
+ url: finding.pageUrl,
118
+ timestamp: finding.occurredAt ?? input.run.finishedAt ?? input.run.startedAt,
119
+ attachments: resolveAttachments(finding, input.artifacts),
120
+ };
121
+ const key = occurrenceKey(finding, occurrence);
122
+ if (issue.occurrenceKeys.has(key)) {
123
+ continue;
124
+ }
125
+ issue.occurrenceKeys.add(key);
126
+ issue.occurrences.push(occurrence);
127
+ }
128
+ const issues = Array.from(issuesById.values())
129
+ .map((issue) => ({
130
+ issueId: issue.issueId,
131
+ ruleId: issue.ruleId,
132
+ impact: issue.impact,
133
+ tags: issue.tags,
134
+ pageKey: issue.pageKey,
135
+ url: issue.url,
136
+ target: issue.target,
137
+ selectorHint: issue.selectorHint,
138
+ failureSummary: issue.failureSummary,
139
+ occurrences: [...issue.occurrences].sort(compareOccurrence),
140
+ }))
141
+ .sort(sort_1.compareIssueLike);
142
+ const byImpact = new Map();
143
+ const byRuleId = new Map();
144
+ const byPageKey = new Map();
145
+ for (const issue of issues) {
146
+ const impact = (0, impact_1.impactKey)(issue.impact);
147
+ byImpact.set(impact, (byImpact.get(impact) ?? 0) + 1);
148
+ byRuleId.set(issue.ruleId, (byRuleId.get(issue.ruleId) ?? 0) + 1);
149
+ byPageKey.set(issue.pageKey, (byPageKey.get(issue.pageKey) ?? 0) + 1);
150
+ }
151
+ const newIssueIds = uniqueSorted(input.diff?.newFindings.map((finding) => finding.issueId) ?? []);
152
+ const existingIssueIds = uniqueSorted(input.diff?.existing.map((entry) => entry.finding.issueId) ?? []);
153
+ const resolvedIssueIds = uniqueSorted(input.diff?.resolved.map((entry) => entry.issueId) ?? []);
154
+ const summary = {
155
+ scannedPages: scannedPages.size,
156
+ totalIssues: issues.length,
157
+ totalOccurrences: sortedFindings.length,
158
+ scanErrors: input.run.scanErrors.length,
159
+ newIssues: newIssueIds.length,
160
+ existingIssues: existingIssueIds.length,
161
+ resolvedIssues: resolvedIssueIds.length,
162
+ byImpact: toSortedRecord(byImpact),
163
+ byRuleId: toSortedRecord(byRuleId),
164
+ byPageKey: toSortedRecord(byPageKey),
165
+ };
166
+ const report = {
167
+ run: {
168
+ reportVersion: 2,
169
+ mode: input.mode,
170
+ createdAt,
171
+ startedAt: input.run.startedAt,
172
+ finishedAt: input.run.finishedAt,
173
+ configHash: input.configHash,
174
+ tool: input.run.tool,
175
+ engine: {
176
+ scanner: input.run.tool.scanner,
177
+ runtime: "playwright",
178
+ },
179
+ metadata: input.run.metadata,
180
+ },
181
+ summary,
182
+ issues,
183
+ };
184
+ if (input.diff) {
185
+ const issuesByIssueId = new Map(issues.map((issue) => [issue.issueId, issue]));
186
+ const newIssues = newIssueIds
187
+ .map((issueId) => {
188
+ const issue = issuesByIssueId.get(issueId);
189
+ if (!issue) {
190
+ const fallback = input.diff?.newFindings.find((finding) => finding.issueId === issueId);
191
+ if (!fallback) {
192
+ return undefined;
193
+ }
194
+ return {
195
+ issueId,
196
+ ruleId: fallback.ruleId,
197
+ impact: fallback.impact,
198
+ pageKey: fallback.pageKey,
199
+ selectorHint: fallback.target[0] ?? fallback.selectorHint,
200
+ occurrenceCount: 1,
201
+ };
202
+ }
203
+ return {
204
+ issueId,
205
+ ruleId: issue.ruleId,
206
+ impact: issue.impact,
207
+ pageKey: issue.pageKey,
208
+ selectorHint: issue.target[0] ?? issue.selectorHint,
209
+ occurrenceCount: issue.occurrences.length,
210
+ };
211
+ })
212
+ .filter((entry) => Boolean(entry))
213
+ .sort(sort_1.compareIssueLike);
214
+ report.diff = {
215
+ newIssueIds,
216
+ existingIssueIds,
217
+ resolvedIssueIds,
218
+ newIssues,
219
+ };
220
+ }
221
+ return report;
222
+ }
223
+ //# sourceMappingURL=buildReport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildReport.js","sourceRoot":"","sources":["../../src/report/buildReport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { FormatConsoleOptions, TrailmarkReport } from "./types";
2
+ export declare function formatConsoleReport(report: TrailmarkReport, options?: FormatConsoleOptions): string;
3
+ //# sourceMappingURL=formatConsole.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatConsole.d.ts","sourceRoot":"","sources":["../../src/report/formatConsole.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAwB,MAAM,SAAS,CAAA;AAkDrF,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,oBAAyB,GACjC,MAAM,CAmFR"}
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatConsoleReport = formatConsoleReport;
4
+ const impact_1 = require("../impact");
5
+ const sort_1 = require("./sort");
6
+ function topPages(issues, limit) {
7
+ const counts = new Map();
8
+ for (const issue of issues) {
9
+ counts.set(issue.pageKey, (counts.get(issue.pageKey) ?? 0) + 1);
10
+ }
11
+ return Array.from(counts.entries())
12
+ .sort((left, right) => {
13
+ const countDiff = right[1] - left[1];
14
+ if (countDiff !== 0) {
15
+ return countDiff;
16
+ }
17
+ return left[0].localeCompare(right[0]);
18
+ })
19
+ .slice(0, limit)
20
+ .map(([page]) => page)
21
+ .join(", ");
22
+ }
23
+ function firstArtifactPath(issue) {
24
+ for (const occurrence of issue.occurrences) {
25
+ for (const attachment of occurrence.attachments) {
26
+ if (attachment.path) {
27
+ return attachment.path;
28
+ }
29
+ }
30
+ }
31
+ return undefined;
32
+ }
33
+ function firstReproHint(issue) {
34
+ const occurrence = issue.occurrences[0];
35
+ if (!occurrence) {
36
+ return `url=${issue.url}`;
37
+ }
38
+ const segments = [];
39
+ if (occurrence.testId) {
40
+ segments.push(`testId=${occurrence.testId}`);
41
+ }
42
+ segments.push(`url=${occurrence.url}`);
43
+ return segments.join(" ");
44
+ }
45
+ function formatConsoleReport(report, options = {}) {
46
+ const failOnImpact = options.failOnImpact ?? ["serious", "critical"];
47
+ const topPagesPerRule = options.topPagesPerRule ?? 3;
48
+ const lines = [];
49
+ lines.push(`trailmark: scanned pages=${report.summary.scannedPages} | total issues=${report.summary.totalIssues} | NEW=${report.summary.newIssues} | fail on=${failOnImpact.join(", ")}`);
50
+ if (!report.diff) {
51
+ if (report.summary.scanErrors > 0) {
52
+ lines.push(`trailmark: scan errors=${report.summary.scanErrors}`);
53
+ }
54
+ return lines.join("\n");
55
+ }
56
+ if (report.diff.newIssueIds.length === 0) {
57
+ lines.push("trailmark: no new accessibility violations compared to baseline.");
58
+ if (report.summary.scanErrors > 0) {
59
+ lines.push(`trailmark: scan errors=${report.summary.scanErrors}`);
60
+ }
61
+ return lines.join("\n");
62
+ }
63
+ const newIssueIds = new Set(report.diff.newIssueIds);
64
+ const newIssues = report.issues
65
+ .filter((issue) => newIssueIds.has(issue.issueId))
66
+ .sort(sort_1.compareIssueLike);
67
+ const byImpact = new Map();
68
+ for (const issue of newIssues) {
69
+ const impact = (0, impact_1.impactKey)(issue.impact);
70
+ const list = byImpact.get(impact) ?? [];
71
+ list.push(issue);
72
+ byImpact.set(impact, list);
73
+ }
74
+ const sortedImpactKeys = Array.from(byImpact.keys()).sort((left, right) => {
75
+ const leftRank = (0, impact_1.impactRank)(left);
76
+ const rightRank = (0, impact_1.impactRank)(right);
77
+ if (leftRank !== rightRank) {
78
+ return leftRank - rightRank;
79
+ }
80
+ return left.localeCompare(right);
81
+ });
82
+ for (const impact of sortedImpactKeys) {
83
+ const issues = byImpact.get(impact) ?? [];
84
+ lines.push(`trailmark: [${impact}] ${issues.length} NEW issue(s)`);
85
+ const byRule = new Map();
86
+ for (const issue of issues) {
87
+ const list = byRule.get(issue.ruleId) ?? [];
88
+ list.push(issue);
89
+ byRule.set(issue.ruleId, list);
90
+ }
91
+ const sortedRuleIds = Array.from(byRule.keys()).sort((left, right) => left.localeCompare(right));
92
+ for (const ruleId of sortedRuleIds) {
93
+ const ruleIssues = (byRule.get(ruleId) ?? []).sort(sort_1.compareIssueLike);
94
+ const pages = topPages(ruleIssues, topPagesPerRule);
95
+ lines.push(` rule ${ruleId} (${ruleIssues.length}) top pages: ${pages || "n/a"}`);
96
+ for (const issue of ruleIssues) {
97
+ const locator = issue.target[0] ?? issue.selectorHint ?? "<unknown-target>";
98
+ lines.push(` - ${impact} | ${issue.ruleId} | ${issue.pageKey} | ${locator}`);
99
+ const artifactPath = firstArtifactPath(issue);
100
+ if (artifactPath) {
101
+ lines.push(` artifact: ${artifactPath}`);
102
+ }
103
+ lines.push(` reproduce: ${firstReproHint(issue)}`);
104
+ }
105
+ }
106
+ }
107
+ if (report.summary.scanErrors > 0) {
108
+ lines.push(`trailmark: scan errors=${report.summary.scanErrors}`);
109
+ }
110
+ return lines.join("\n");
111
+ }
112
+ //# sourceMappingURL=formatConsole.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatConsole.js","sourceRoot":"","sources":["../../src/report/formatConsole.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from "./types";
2
+ export * from "./buildReport";
3
+ export * from "./formatConsole";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/report/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./buildReport"), exports);
19
+ __exportStar(require("./formatConsole"), exports);
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/report/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAuB;AACvB,gDAA6B;AAC7B,kDAA+B"}
@@ -0,0 +1,9 @@
1
+ import { TrailmarkImpact } from "../types";
2
+ export interface IssueSortInput {
3
+ issueId: string;
4
+ ruleId: string;
5
+ pageKey: string;
6
+ impact?: TrailmarkImpact;
7
+ }
8
+ export declare function compareIssueLike(left: IssueSortInput, right: IssueSortInput): number;
9
+ //# sourceMappingURL=sort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sort.d.ts","sourceRoot":"","sources":["../../src/report/sort.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE1C,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,eAAe,CAAA;CACzB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAiBpF"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compareIssueLike = compareIssueLike;
4
+ const impact_1 = require("../impact");
5
+ function compareIssueLike(left, right) {
6
+ const impactDiff = (0, impact_1.impactRank)(left.impact) - (0, impact_1.impactRank)(right.impact);
7
+ if (impactDiff !== 0) {
8
+ return impactDiff;
9
+ }
10
+ const ruleDiff = left.ruleId.localeCompare(right.ruleId);
11
+ if (ruleDiff !== 0) {
12
+ return ruleDiff;
13
+ }
14
+ const pageDiff = left.pageKey.localeCompare(right.pageKey);
15
+ if (pageDiff !== 0) {
16
+ return pageDiff;
17
+ }
18
+ return left.issueId.localeCompare(right.issueId);
19
+ }
20
+ //# sourceMappingURL=sort.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sort.js","sourceRoot":"","sources":["../../src/report/sort.ts"],"names":[],"mappings":";;AAUA,4CAiBC;AA3BD,sCAAsC;AAUtC,SAAgB,gBAAgB,CAAC,IAAoB,EAAE,KAAqB;IAC1E,MAAM,UAAU,GAAG,IAAA,mBAAU,EAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAA,mBAAU,EAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACrE,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACxD,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC1D,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AAClD,CAAC"}
@@ -0,0 +1,85 @@
1
+ import { DiffResult, TrailmarkAttachment, TrailmarkImpact, TrailmarkRun, TrailmarkToolInfo } from "../types";
2
+ export type TrailmarkReportMode = "baseline" | "check";
3
+ export interface TrailmarkArtifactIndex {
4
+ byOccurrenceId?: Record<string, TrailmarkAttachment[]>;
5
+ byIssueId?: Record<string, TrailmarkAttachment[]>;
6
+ }
7
+ export interface TrailmarkReportOccurrence {
8
+ occurrenceId?: string;
9
+ testId?: string;
10
+ projectName?: string;
11
+ url: string;
12
+ timestamp: string;
13
+ attachments: TrailmarkAttachment[];
14
+ }
15
+ export interface TrailmarkReportIssue {
16
+ issueId: string;
17
+ ruleId: string;
18
+ impact?: TrailmarkImpact;
19
+ tags: string[];
20
+ pageKey: string;
21
+ url: string;
22
+ target: string[];
23
+ selectorHint?: string;
24
+ failureSummary?: string;
25
+ occurrences: TrailmarkReportOccurrence[];
26
+ }
27
+ export interface TrailmarkReportDiffIssueSummary {
28
+ issueId: string;
29
+ ruleId: string;
30
+ impact?: TrailmarkImpact;
31
+ pageKey: string;
32
+ selectorHint?: string;
33
+ occurrenceCount: number;
34
+ }
35
+ export interface TrailmarkReportDiff {
36
+ newIssueIds: string[];
37
+ existingIssueIds: string[];
38
+ resolvedIssueIds: string[];
39
+ newIssues: TrailmarkReportDiffIssueSummary[];
40
+ }
41
+ export interface TrailmarkReportSummary {
42
+ scannedPages: number;
43
+ totalIssues: number;
44
+ totalOccurrences: number;
45
+ scanErrors: number;
46
+ newIssues: number;
47
+ existingIssues: number;
48
+ resolvedIssues: number;
49
+ byImpact: Record<string, number>;
50
+ byRuleId: Record<string, number>;
51
+ byPageKey: Record<string, number>;
52
+ }
53
+ export interface TrailmarkReportRunMetadata {
54
+ reportVersion: 2;
55
+ mode: TrailmarkReportMode;
56
+ createdAt: string;
57
+ startedAt: string;
58
+ finishedAt?: string;
59
+ configHash: string;
60
+ tool: TrailmarkToolInfo;
61
+ engine: {
62
+ scanner: string;
63
+ runtime: "playwright";
64
+ };
65
+ metadata?: Record<string, unknown>;
66
+ }
67
+ export interface TrailmarkReport {
68
+ run: TrailmarkReportRunMetadata;
69
+ summary: TrailmarkReportSummary;
70
+ issues: TrailmarkReportIssue[];
71
+ diff?: TrailmarkReportDiff;
72
+ }
73
+ export interface BuildReportInput {
74
+ run: TrailmarkRun;
75
+ mode: TrailmarkReportMode;
76
+ configHash: string;
77
+ diff?: DiffResult;
78
+ createdAt?: string;
79
+ artifacts?: TrailmarkArtifactIndex;
80
+ }
81
+ export interface FormatConsoleOptions {
82
+ failOnImpact?: string[];
83
+ topPagesPerRule?: number;
84
+ }
85
+ //# sourceMappingURL=types.d.ts.map