@hawkeyexl/manni 4.3.1 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/batch-DFRCLY77.js +36 -0
- package/dist/build-Q5C6SX5J.js +31 -0
- package/dist/calibrate-XQILKXS3.js +31 -0
- package/dist/capture-JQMOC3BW.js +32 -0
- package/dist/check-HYNGXYJV.js +18 -0
- package/dist/check-HYNGXYJV.js.map +1 -0
- package/dist/check-NFZQLJKN.js +27 -0
- package/dist/check-NFZQLJKN.js.map +1 -0
- package/dist/check-U54XV6BP.js +40 -0
- package/dist/check-U54XV6BP.js.map +1 -0
- package/dist/chunk-252LNOEG.js +622 -0
- package/dist/chunk-252LNOEG.js.map +1 -0
- package/dist/chunk-2H7UOFLK.js +11 -0
- package/dist/chunk-2H7UOFLK.js.map +1 -0
- package/dist/chunk-2U3ORT6D.js +230 -0
- package/dist/chunk-2U3ORT6D.js.map +1 -0
- package/dist/chunk-3AFUD75K.js +23 -0
- package/dist/chunk-3AFUD75K.js.map +1 -0
- package/dist/{chunk-3R23C5DT.js → chunk-4TSWU2SU.js} +2 -14
- package/dist/chunk-4TSWU2SU.js.map +1 -0
- package/dist/chunk-5KHIFVD2.js +1192 -0
- package/dist/chunk-5KHIFVD2.js.map +1 -0
- package/dist/chunk-5YXBLLAC.js +2165 -0
- package/dist/chunk-5YXBLLAC.js.map +1 -0
- package/dist/chunk-644JVKJ4.js +3872 -0
- package/dist/chunk-644JVKJ4.js.map +1 -0
- package/dist/chunk-6OYEI2VV.js +88 -0
- package/dist/chunk-6OYEI2VV.js.map +1 -0
- package/dist/chunk-77AINBYM.js +19 -0
- package/dist/chunk-77AINBYM.js.map +1 -0
- package/dist/chunk-77HX34KD.js +1287 -0
- package/dist/chunk-77HX34KD.js.map +1 -0
- package/dist/{chunk-CFDUZRM2.js → chunk-7QMCHA4N.js} +32 -240
- package/dist/chunk-7QMCHA4N.js.map +1 -0
- package/dist/chunk-BUXDLRDT.js +455 -0
- package/dist/chunk-BUXDLRDT.js.map +1 -0
- package/dist/chunk-C6OH6CNF.js +388 -0
- package/dist/chunk-C6OH6CNF.js.map +1 -0
- package/dist/chunk-CK7SKVHR.js +1042 -0
- package/dist/chunk-CK7SKVHR.js.map +1 -0
- package/dist/chunk-CYWHFSRT.js +6737 -0
- package/dist/chunk-CYWHFSRT.js.map +1 -0
- package/dist/chunk-ERMSO34F.js +17 -0
- package/dist/chunk-ERMSO34F.js.map +1 -0
- package/dist/{chunk-IOYXPBCL.js → chunk-G3T47CFV.js} +1 -7
- package/dist/{chunk-IOYXPBCL.js.map → chunk-G3T47CFV.js.map} +1 -1
- package/dist/chunk-G7NJSREW.js +979 -0
- package/dist/chunk-G7NJSREW.js.map +1 -0
- package/dist/chunk-GLP5PSXB.js +72 -0
- package/dist/chunk-GLP5PSXB.js.map +1 -0
- package/dist/chunk-H2DLH2JI.js +198 -0
- package/dist/chunk-H2DLH2JI.js.map +1 -0
- package/dist/chunk-H6FZ66XR.js +634 -0
- package/dist/chunk-H6FZ66XR.js.map +1 -0
- package/dist/{chunk-KJR7OVDX.js → chunk-IEQHSCZG.js} +56 -137
- package/dist/chunk-IEQHSCZG.js.map +1 -0
- package/dist/chunk-IKEWBMCN.js +98 -0
- package/dist/chunk-IKEWBMCN.js.map +1 -0
- package/dist/chunk-JOHKIAVH.js +5440 -0
- package/dist/chunk-JOHKIAVH.js.map +1 -0
- package/dist/chunk-JVTNMVYU.js +10921 -0
- package/dist/chunk-JVTNMVYU.js.map +1 -0
- package/dist/chunk-K3D6FPV6.js +164 -0
- package/dist/chunk-K3D6FPV6.js.map +1 -0
- package/dist/{chunk-UBMMXS2Y.js → chunk-KCGV52AM.js} +69 -48
- package/dist/{chunk-UBMMXS2Y.js.map → chunk-KCGV52AM.js.map} +1 -1
- package/dist/chunk-LAKAWRV5.js +1651 -0
- package/dist/chunk-LAKAWRV5.js.map +1 -0
- package/dist/chunk-LJ2RDH3F.js +49 -0
- package/dist/chunk-LJ2RDH3F.js.map +1 -0
- package/dist/chunk-M2JCK5F6.js +805 -0
- package/dist/chunk-M2JCK5F6.js.map +1 -0
- package/dist/chunk-MNH7QO4Z.js +15 -0
- package/dist/chunk-MNH7QO4Z.js.map +1 -0
- package/dist/{chunk-HAPTXWU2.js → chunk-MYC3O5EJ.js} +4 -4
- package/dist/chunk-MYMBCTDE.js +387 -0
- package/dist/chunk-MYMBCTDE.js.map +1 -0
- package/dist/chunk-NCPWXHDO.js +683 -0
- package/dist/chunk-NCPWXHDO.js.map +1 -0
- package/dist/chunk-NWZ2SLYL.js +2957 -0
- package/dist/chunk-NWZ2SLYL.js.map +1 -0
- package/dist/chunk-OBFENF3U.js +934 -0
- package/dist/chunk-OBFENF3U.js.map +1 -0
- package/dist/chunk-OWBRDNRZ.js +16 -0
- package/dist/chunk-OWBRDNRZ.js.map +1 -0
- package/dist/{chunk-KTSJ2ZHA.js → chunk-PAU352SV.js} +5 -3
- package/dist/{chunk-KTSJ2ZHA.js.map → chunk-PAU352SV.js.map} +1 -1
- package/dist/chunk-PCE7QHXJ.js +68 -0
- package/dist/chunk-PCE7QHXJ.js.map +1 -0
- package/dist/chunk-PCHZY2I7.js +299 -0
- package/dist/chunk-PCHZY2I7.js.map +1 -0
- package/dist/chunk-PHF3D7ER.js +1042 -0
- package/dist/chunk-PHF3D7ER.js.map +1 -0
- package/dist/chunk-Q35YIDBV.js +1202 -0
- package/dist/chunk-Q35YIDBV.js.map +1 -0
- package/dist/chunk-RLR4TKUZ.js +4398 -0
- package/dist/chunk-RLR4TKUZ.js.map +1 -0
- package/dist/chunk-RNVYGWIC.js +30 -0
- package/dist/chunk-RNVYGWIC.js.map +1 -0
- package/dist/chunk-SE4JN5XN.js +19 -0
- package/dist/chunk-SE4JN5XN.js.map +1 -0
- package/dist/chunk-TIUTIOFB.js +25 -0
- package/dist/chunk-TIUTIOFB.js.map +1 -0
- package/dist/chunk-TU2WUBVZ.js +2 -0
- package/dist/chunk-TU2WUBVZ.js.map +1 -0
- package/dist/chunk-TZOYZK2E.js +98 -0
- package/dist/chunk-TZOYZK2E.js.map +1 -0
- package/dist/chunk-UKZNLVJW.js +17 -0
- package/dist/chunk-UKZNLVJW.js.map +1 -0
- package/dist/chunk-UZC7LDAQ.js +178 -0
- package/dist/chunk-UZC7LDAQ.js.map +1 -0
- package/dist/chunk-V46OILVC.js +3090 -0
- package/dist/chunk-V46OILVC.js.map +1 -0
- package/dist/chunk-WQE54PNH.js +1975 -0
- package/dist/chunk-WQE54PNH.js.map +1 -0
- package/dist/chunk-X3BPBDGQ.js +52 -0
- package/dist/chunk-X3BPBDGQ.js.map +1 -0
- package/dist/chunk-XSLV76YK.js +54 -0
- package/dist/chunk-XSLV76YK.js.map +1 -0
- package/dist/{chunk-5HNHEUD5.js → chunk-XYLUCIKQ.js} +3 -3
- package/dist/chunk-YEUYKR62.js +72 -0
- package/dist/chunk-YEUYKR62.js.map +1 -0
- package/dist/{chunk-G5CM2VGQ.js → chunk-YFQBFNQS.js} +8 -94
- package/dist/chunk-YFQBFNQS.js.map +1 -0
- package/dist/chunk-YIL4XLLJ.js +1661 -0
- package/dist/chunk-YIL4XLLJ.js.map +1 -0
- package/dist/chunk-YNHZHSSM.js +41 -0
- package/dist/chunk-YNHZHSSM.js.map +1 -0
- package/dist/chunk-YTCZRLTU.js +96 -0
- package/dist/chunk-YTCZRLTU.js.map +1 -0
- package/dist/chunk-YYBFZLAJ.js +374 -0
- package/dist/chunk-YYBFZLAJ.js.map +1 -0
- package/dist/chunk-ZXRAE55H.js +31 -0
- package/dist/chunk-ZXRAE55H.js.map +1 -0
- package/dist/cli-2QPR2OZG.js +232 -0
- package/dist/cli-2QPR2OZG.js.map +1 -0
- package/dist/cli-4IOPGZHR.js +1203 -0
- package/dist/cli-4IOPGZHR.js.map +1 -0
- package/dist/cli-5FL73WHA.js +346 -0
- package/dist/cli-5FL73WHA.js.map +1 -0
- package/dist/cli-C262QOWM.js +739 -0
- package/dist/cli-C262QOWM.js.map +1 -0
- package/dist/cli-LJLLIQB2.js +423 -0
- package/dist/cli-LJLLIQB2.js.map +1 -0
- package/dist/cli-OFPZ5MAS.js +626 -0
- package/dist/cli-OFPZ5MAS.js.map +1 -0
- package/dist/cli-SHSMSRQY.js +28 -0
- package/dist/cli-SHSMSRQY.js.map +1 -0
- package/dist/cli-SRHFUZHA.js +473 -0
- package/dist/cli-SRHFUZHA.js.map +1 -0
- package/dist/cli-URZQXL4K.js +552 -0
- package/dist/cli-URZQXL4K.js.map +1 -0
- package/dist/cli.d.ts +12 -2
- package/dist/cli.js +109 -7661
- package/dist/cli.js.map +1 -1
- package/dist/docmeta.js +15 -3
- package/dist/docmeta.js.map +1 -1
- package/dist/github-FE6KCNYJ.js +27 -0
- package/dist/github-FE6KCNYJ.js.map +1 -0
- package/dist/github-QXL3VMK2.js +32 -0
- package/dist/github-QXL3VMK2.js.map +1 -0
- package/dist/index.d.ts +65 -3
- package/dist/index.js +407 -337
- package/dist/index.js.map +1 -1
- package/dist/json-7WV7KL6H.js +17 -0
- package/dist/json-7WV7KL6H.js.map +1 -0
- package/dist/json-SGZ6ZRFD.js +35 -0
- package/dist/json-SGZ6ZRFD.js.map +1 -0
- package/dist/lint-DL4LJRAY.js +28 -0
- package/dist/lint-DL4LJRAY.js.map +1 -0
- package/dist/list-6BAXTZUM.js +29 -0
- package/dist/list-6BAXTZUM.js.map +1 -0
- package/dist/list-7BKNYPSB.js +31 -0
- package/dist/list-7BKNYPSB.js.map +1 -0
- package/dist/page-3U2GCFNE.js +41 -0
- package/dist/page-3U2GCFNE.js.map +1 -0
- package/dist/picker-3XF36MJF.js +14 -0
- package/dist/picker-3XF36MJF.js.map +1 -0
- package/dist/pretty-2H57QVTY.js +43 -0
- package/dist/pretty-2H57QVTY.js.map +1 -0
- package/dist/pretty-N6DO4OOL.js +37 -0
- package/dist/pretty-N6DO4OOL.js.map +1 -0
- package/dist/reporters-M6LJ2IYU.js +21 -0
- package/dist/reporters-M6LJ2IYU.js.map +1 -0
- package/dist/reporters-N6GHXSS7.js +42 -0
- package/dist/reporters-N6GHXSS7.js.map +1 -0
- package/dist/reporters-UCNEV7PH.js +71 -0
- package/dist/reporters-UCNEV7PH.js.map +1 -0
- package/dist/run-XZDAREJE.js +33 -0
- package/dist/run-XZDAREJE.js.map +1 -0
- package/dist/term-5ICGKPC3.js +1592 -0
- package/dist/term-5ICGKPC3.js.map +1 -0
- package/dist/types-Y6TXHM7M.js +10 -0
- package/dist/types-Y6TXHM7M.js.map +1 -0
- package/dist/validate-GQRM77YN.js +16 -0
- package/dist/validate-GQRM77YN.js.map +1 -0
- package/package.json +1 -1
- package/plugin/manni/.claude-plugin/plugin.json +9 -0
- package/plugin/manni/hooks/hooks.json +52 -0
- package/plugin/manni/skills/check/SKILL.md +20 -0
- package/plugin/manni/skills/evals/SKILL.md +27 -0
- package/plugin/manni/skills/fix/SKILL.md +56 -0
- package/plugin/manni/skills/setup/SKILL.md +41 -0
- package/dist/batch-A5HZKYIW.js +0 -18
- package/dist/calibrate-S5K6QHUY.js +0 -13
- package/dist/capture-OZEZDABQ.js +0 -15
- package/dist/chunk-3R23C5DT.js.map +0 -1
- package/dist/chunk-CFDUZRM2.js.map +0 -1
- package/dist/chunk-G5CM2VGQ.js.map +0 -1
- package/dist/chunk-KJR7OVDX.js.map +0 -1
- package/dist/chunk-V4KUVE47.js +0 -27170
- package/dist/chunk-V4KUVE47.js.map +0 -1
- package/dist/chunk-ZQBTK3DO.js +0 -26518
- package/dist/chunk-ZQBTK3DO.js.map +0 -1
- package/dist/picker-6HRMETE7.js +0 -12
- package/plugin/tracevals/.claude-plugin/plugin.json +0 -9
- package/plugin/tracevals/hooks/hooks.json +0 -17
- /package/dist/{batch-A5HZKYIW.js.map → batch-DFRCLY77.js.map} +0 -0
- /package/dist/{calibrate-S5K6QHUY.js.map → build-Q5C6SX5J.js.map} +0 -0
- /package/dist/{capture-OZEZDABQ.js.map → calibrate-XQILKXS3.js.map} +0 -0
- /package/dist/{picker-6HRMETE7.js.map → capture-JQMOC3BW.js.map} +0 -0
- /package/dist/{chunk-HAPTXWU2.js.map → chunk-MYC3O5EJ.js.map} +0 -0
- /package/dist/{chunk-5HNHEUD5.js.map → chunk-XYLUCIKQ.js.map} +0 -0
|
@@ -0,0 +1,634 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
URI_BASE_ID,
|
|
4
|
+
artifactLocation,
|
|
5
|
+
fileUri,
|
|
6
|
+
normalizeRoot
|
|
7
|
+
} from "./chunk-GLP5PSXB.js";
|
|
8
|
+
import {
|
|
9
|
+
LintError,
|
|
10
|
+
matchSections,
|
|
11
|
+
occurrenceRange
|
|
12
|
+
} from "./chunk-CK7SKVHR.js";
|
|
13
|
+
import {
|
|
14
|
+
REPORT_FORMAT_LIST,
|
|
15
|
+
renderJunit
|
|
16
|
+
} from "./chunk-C6OH6CNF.js";
|
|
17
|
+
import {
|
|
18
|
+
isErrorSeverity
|
|
19
|
+
} from "./chunk-JVTNMVYU.js";
|
|
20
|
+
import {
|
|
21
|
+
palette
|
|
22
|
+
} from "./chunk-RNVYGWIC.js";
|
|
23
|
+
import {
|
|
24
|
+
escapeWorkflowCommandMessage,
|
|
25
|
+
escapeWorkflowCommandProperty
|
|
26
|
+
} from "./chunk-MNH7QO4Z.js";
|
|
27
|
+
import {
|
|
28
|
+
package_default
|
|
29
|
+
} from "./chunk-UZC7LDAQ.js";
|
|
30
|
+
|
|
31
|
+
// src/lint/core/rule-id.ts
|
|
32
|
+
var RULE_ID_PREFIX = "manni:lint";
|
|
33
|
+
var TOOL_NAME = "manni";
|
|
34
|
+
var STRUCTURE_JOB = "structure";
|
|
35
|
+
function ruleName(type) {
|
|
36
|
+
return type.replace(/_error$/, "").replace(/_/g, "-");
|
|
37
|
+
}
|
|
38
|
+
function ruleId(type, job = STRUCTURE_JOB) {
|
|
39
|
+
return `${RULE_ID_PREFIX}/${job}/${ruleName(type)}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// src/lint/reporters/junit.ts
|
|
43
|
+
var JUNIT_CLASSNAME = "manni.lint";
|
|
44
|
+
function toFieldError(finding) {
|
|
45
|
+
return {
|
|
46
|
+
schema: RULE_ID_PREFIX,
|
|
47
|
+
instancePath: "",
|
|
48
|
+
message: finding.heading != null ? `${finding.heading}: ${finding.message}` : finding.message,
|
|
49
|
+
keyword: `${STRUCTURE_JOB}/${ruleName(finding.type)}`,
|
|
50
|
+
severity: finding.severity,
|
|
51
|
+
line: finding.position.start.line,
|
|
52
|
+
col: finding.position.start.column
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function toValidationResults(run) {
|
|
56
|
+
return run.results.filter((result) => result.skipped == null).map((result) => ({
|
|
57
|
+
file: result.file,
|
|
58
|
+
// meta's `format` is the extractor that read the file. A lint result does
|
|
59
|
+
// not carry the parser that produced its tree, and no reporter reached
|
|
60
|
+
// through here reads the field, so it names the domain rather than
|
|
61
|
+
// inventing a format the run never recorded.
|
|
62
|
+
format: "lint",
|
|
63
|
+
// meta's invariant, not a count: `ok` is "no error-severity finding".
|
|
64
|
+
// Read as "no findings at all", a file whose only finding is a warning
|
|
65
|
+
// renders as a `✗` through meta's own pretty reporter - which is a
|
|
66
|
+
// legitimate consumer, since this function is exported - while lint's
|
|
67
|
+
// exit code says the run passed.
|
|
68
|
+
ok: !result.findings.some(isErrorSeverity),
|
|
69
|
+
schemas: [RULE_ID_PREFIX],
|
|
70
|
+
errors: result.findings.map(toFieldError)
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
function renderJunit2(run) {
|
|
74
|
+
return renderJunit(toValidationResults(run), {
|
|
75
|
+
classname: JUNIT_CLASSNAME
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/lint/reporters/sarif.ts
|
|
80
|
+
var SARIF_VERSION = "2.1.0";
|
|
81
|
+
var SARIF_SCHEMA = "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json";
|
|
82
|
+
var INFORMATION_URI = "https://github.com/hawkeyexl/manni";
|
|
83
|
+
var LEVELS = {
|
|
84
|
+
notice: "note",
|
|
85
|
+
warning: "warning",
|
|
86
|
+
error: "error"
|
|
87
|
+
};
|
|
88
|
+
var SKIP_DESCRIPTIONS = {
|
|
89
|
+
"no-template": "File was not linted: no template resolved for it.",
|
|
90
|
+
"unsupported-format": "File was not linted: no parser handles its format.",
|
|
91
|
+
unreadable: "File was not linted: it could not be read."
|
|
92
|
+
};
|
|
93
|
+
function region(position) {
|
|
94
|
+
return {
|
|
95
|
+
startLine: position.start.line,
|
|
96
|
+
startColumn: position.start.column,
|
|
97
|
+
endLine: position.end.line,
|
|
98
|
+
endColumn: position.end.column
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function location(file, root, position) {
|
|
102
|
+
return {
|
|
103
|
+
physicalLocation: {
|
|
104
|
+
artifactLocation: artifactLocation(file, root),
|
|
105
|
+
region: position ? region(position) : void 0
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function messageText(finding) {
|
|
110
|
+
return finding.heading != null ? `${finding.heading}: ${finding.message}` : finding.message;
|
|
111
|
+
}
|
|
112
|
+
function words(id) {
|
|
113
|
+
return id.split(/[^A-Za-z0-9]+/).filter(Boolean);
|
|
114
|
+
}
|
|
115
|
+
function pascalCase(id) {
|
|
116
|
+
return words(id).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
|
|
117
|
+
}
|
|
118
|
+
function humanize(id) {
|
|
119
|
+
const text = words(id).join(" ");
|
|
120
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
121
|
+
}
|
|
122
|
+
function buildRules(run) {
|
|
123
|
+
const indexOf = /* @__PURE__ */ new Map();
|
|
124
|
+
const order = [];
|
|
125
|
+
const severities = /* @__PURE__ */ new Map();
|
|
126
|
+
for (const result of run.results) {
|
|
127
|
+
for (const finding of result.findings) {
|
|
128
|
+
let seen = severities.get(finding.type);
|
|
129
|
+
if (!seen) {
|
|
130
|
+
seen = /* @__PURE__ */ new Set();
|
|
131
|
+
severities.set(finding.type, seen);
|
|
132
|
+
indexOf.set(finding.type, order.length);
|
|
133
|
+
order.push(finding.type);
|
|
134
|
+
}
|
|
135
|
+
seen.add(finding.severity);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const descriptors = order.map((type) => {
|
|
139
|
+
const rule = ruleName(type);
|
|
140
|
+
const descriptor = {
|
|
141
|
+
id: ruleId(type),
|
|
142
|
+
name: pascalCase(rule),
|
|
143
|
+
shortDescription: { text: humanize(rule) }
|
|
144
|
+
};
|
|
145
|
+
const [only, ...rest] = [...severities.get(type) ?? []];
|
|
146
|
+
if (only !== void 0 && rest.length === 0) {
|
|
147
|
+
descriptor.defaultConfiguration = { level: LEVELS[only] };
|
|
148
|
+
}
|
|
149
|
+
return descriptor;
|
|
150
|
+
});
|
|
151
|
+
return { descriptors, indexOf };
|
|
152
|
+
}
|
|
153
|
+
function toResult(finding, file, rules, root) {
|
|
154
|
+
return {
|
|
155
|
+
ruleId: ruleId(finding.type),
|
|
156
|
+
// Always populated in practice, since the index is built from these same
|
|
157
|
+
// findings. Omitted rather than faked if it ever is not: a wrong index
|
|
158
|
+
// points the alert at somebody else's rule, which is worse than none.
|
|
159
|
+
ruleIndex: rules.indexOf.get(finding.type),
|
|
160
|
+
level: LEVELS[finding.severity],
|
|
161
|
+
message: { text: messageText(finding) },
|
|
162
|
+
locations: [location(file, root, finding.position)],
|
|
163
|
+
properties: finding.heading != null ? { heading: finding.heading } : void 0
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function buildSkips(run, root) {
|
|
167
|
+
const indexOf = /* @__PURE__ */ new Map();
|
|
168
|
+
const descriptors = [];
|
|
169
|
+
const notifications = [];
|
|
170
|
+
for (const result of run.results) {
|
|
171
|
+
const reason = result.skipped;
|
|
172
|
+
if (reason == null) continue;
|
|
173
|
+
let index = indexOf.get(reason);
|
|
174
|
+
if (index === void 0) {
|
|
175
|
+
index = descriptors.length;
|
|
176
|
+
indexOf.set(reason, index);
|
|
177
|
+
descriptors.push({
|
|
178
|
+
id: reason,
|
|
179
|
+
name: pascalCase(reason),
|
|
180
|
+
shortDescription: { text: SKIP_DESCRIPTIONS[reason] }
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
notifications.push({
|
|
184
|
+
// Declared in `tool.driver.notifications` and referenced by id *and*
|
|
185
|
+
// index, for the same reason results reference their rules both ways.
|
|
186
|
+
descriptor: { id: reason, index },
|
|
187
|
+
level: "note",
|
|
188
|
+
message: { text: skipMessage(result, reason) },
|
|
189
|
+
locations: [location(result.file, root)]
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return { descriptors, notifications };
|
|
193
|
+
}
|
|
194
|
+
function skipMessage(result, reason) {
|
|
195
|
+
return result.reason ?? SKIP_DESCRIPTIONS[reason];
|
|
196
|
+
}
|
|
197
|
+
function renderSarif(run, opts = {}) {
|
|
198
|
+
const root = normalizeRoot(opts.root ?? process.cwd());
|
|
199
|
+
const rules = buildRules(run);
|
|
200
|
+
const skips = buildSkips(run, root);
|
|
201
|
+
const results = run.results.flatMap(
|
|
202
|
+
(result) => result.findings.map(
|
|
203
|
+
(finding) => toResult(finding, result.file, rules, root)
|
|
204
|
+
)
|
|
205
|
+
);
|
|
206
|
+
const driver = {
|
|
207
|
+
name: "manni-lint",
|
|
208
|
+
informationUri: INFORMATION_URI,
|
|
209
|
+
version: package_default.version,
|
|
210
|
+
// Emitted even when empty: results point into this array, so a consumer
|
|
211
|
+
// always looks here, and a stable shape is cheaper than a special case.
|
|
212
|
+
rules: rules.descriptors,
|
|
213
|
+
notifications: skips.descriptors.length > 0 ? skips.descriptors : void 0
|
|
214
|
+
};
|
|
215
|
+
const invocation = {
|
|
216
|
+
// Findings are the tool doing its job, not failing at it. This would only
|
|
217
|
+
// be false if manni lint itself could not run, and that path exits 2
|
|
218
|
+
// before any report is rendered.
|
|
219
|
+
executionSuccessful: true,
|
|
220
|
+
toolExecutionNotifications: skips.notifications.length > 0 ? skips.notifications : void 0
|
|
221
|
+
};
|
|
222
|
+
const log = {
|
|
223
|
+
$schema: SARIF_SCHEMA,
|
|
224
|
+
version: SARIF_VERSION,
|
|
225
|
+
runs: [
|
|
226
|
+
{
|
|
227
|
+
tool: { driver },
|
|
228
|
+
// Declared unconditionally: it is what makes every relative `uri` in
|
|
229
|
+
// this report mean anything, and a reader should not have to infer the
|
|
230
|
+
// base from whether some result happened to use it.
|
|
231
|
+
originalUriBaseIds: { [URI_BASE_ID]: { uri: fileUri(root) } },
|
|
232
|
+
invocations: [invocation],
|
|
233
|
+
results
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
};
|
|
237
|
+
return JSON.stringify(log, null, 2);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// src/lint/reporters/alignment.ts
|
|
241
|
+
var LABEL_WIDTH = 22;
|
|
242
|
+
var ARROW = "\u2190";
|
|
243
|
+
var ELLIPSIS = "\u2026";
|
|
244
|
+
var TIMES = "\xD7";
|
|
245
|
+
function pad(label) {
|
|
246
|
+
return label.length >= LABEL_WIDTH ? `${label} ` : label.padEnd(LABEL_WIDTH + 1);
|
|
247
|
+
}
|
|
248
|
+
function titleText(title) {
|
|
249
|
+
return title === null ? "(no heading)" : `"${title}"`;
|
|
250
|
+
}
|
|
251
|
+
function ruleLabel(rule) {
|
|
252
|
+
if (rule.id !== void 0) return rule.id;
|
|
253
|
+
if (typeof rule.heading === "string") return rule.heading;
|
|
254
|
+
return "(any)";
|
|
255
|
+
}
|
|
256
|
+
function pageHeading(tree) {
|
|
257
|
+
const [only] = tree.sections;
|
|
258
|
+
if (tree.sections.length === 1 && only && only.level <= 1) {
|
|
259
|
+
const text2 = only.title || null;
|
|
260
|
+
if (text2 === null) return { text: null, note: "no heading" };
|
|
261
|
+
const synthesized = only.titlePosition !== null && tree.frontmatterPosition !== null && only.titlePosition.start.offset === tree.frontmatterPosition.start.offset && only.titlePosition.end.offset === tree.frontmatterPosition.end.offset;
|
|
262
|
+
return { text: text2, note: synthesized ? "synthesized from frontmatter" : null };
|
|
263
|
+
}
|
|
264
|
+
const raw = tree.frontmatter?.["title"];
|
|
265
|
+
const text = typeof raw === "string" && raw !== "" ? raw : null;
|
|
266
|
+
return { text, note: text === null ? "no heading" : "synthesized from frontmatter" };
|
|
267
|
+
}
|
|
268
|
+
function pageSections(tree) {
|
|
269
|
+
const [only] = tree.sections;
|
|
270
|
+
if (tree.sections.length === 1 && only && only.level <= 1) return only.sections;
|
|
271
|
+
return tree.sections;
|
|
272
|
+
}
|
|
273
|
+
function matchedRow(depth, run) {
|
|
274
|
+
const head = run[0];
|
|
275
|
+
if (!head) return { depth, text: `${pad("(empty run)")}${ARROW} (missing)` };
|
|
276
|
+
const rule = head.rule;
|
|
277
|
+
const first = head.section;
|
|
278
|
+
const last = (run[run.length - 1] ?? head).section;
|
|
279
|
+
const label = run.length === 1 ? ruleLabel(rule) : `${ruleLabel(rule)} ${TIMES}${run.length}`;
|
|
280
|
+
const coerced = run.length === 1 && head.coerced ? " (coerced)" : "";
|
|
281
|
+
const arrow = run.length === 1 ? `${titleText(first.title || null)}${coerced}` : `${titleText(first.title || null)} ${ELLIPSIS} ${titleText(last.title || null)}`;
|
|
282
|
+
return { depth, text: `${pad(label)}${ARROW} ${arrow}` };
|
|
283
|
+
}
|
|
284
|
+
function absentLabel(rule) {
|
|
285
|
+
return occurrenceRange(rule).min > 0 ? "(missing)" : "(none)";
|
|
286
|
+
}
|
|
287
|
+
function missingRows(depth, rule) {
|
|
288
|
+
if (!rule.repeat) {
|
|
289
|
+
return [{ depth, text: `${pad(ruleLabel(rule))}${ARROW} ${absentLabel(rule)}` }];
|
|
290
|
+
}
|
|
291
|
+
const label = absentLabel(rule);
|
|
292
|
+
const rows = [{ depth, text: pad(rule.id ?? "(repeat)").trimEnd() }];
|
|
293
|
+
for (const member of rule.repeat) {
|
|
294
|
+
rows.push({ depth: depth + 1, text: `${pad(ruleLabel(member))}${ARROW} ${label}` });
|
|
295
|
+
}
|
|
296
|
+
return rows;
|
|
297
|
+
}
|
|
298
|
+
function insertMissing(matched, missing) {
|
|
299
|
+
const out = [];
|
|
300
|
+
let mi = 0;
|
|
301
|
+
for (const entry of matched) {
|
|
302
|
+
while (mi < missing.length) {
|
|
303
|
+
const next = missing[mi];
|
|
304
|
+
if (!next || entry.index !== null && next.index >= entry.index) break;
|
|
305
|
+
out.push(...next.rows);
|
|
306
|
+
mi++;
|
|
307
|
+
}
|
|
308
|
+
out.push(...entry.rows);
|
|
309
|
+
}
|
|
310
|
+
while (mi < missing.length) {
|
|
311
|
+
const next = missing[mi];
|
|
312
|
+
if (!next) break;
|
|
313
|
+
out.push(...next.rows);
|
|
314
|
+
mi++;
|
|
315
|
+
}
|
|
316
|
+
return out;
|
|
317
|
+
}
|
|
318
|
+
function alignLevel(rules, sections, parent, depth) {
|
|
319
|
+
if (rules === void 0) return [];
|
|
320
|
+
const { matches } = matchSections(sections, rules, { parent });
|
|
321
|
+
const ruleIndex = new Map(rules.map((r, i2) => [r, i2]));
|
|
322
|
+
const rootOf = /* @__PURE__ */ new Map();
|
|
323
|
+
for (const rule of rules) {
|
|
324
|
+
if (rule.repeat) for (const member of rule.repeat) rootOf.set(member, rule);
|
|
325
|
+
else rootOf.set(rule, rule);
|
|
326
|
+
}
|
|
327
|
+
const rootOfRule = (rule) => rootOf.get(rule) ?? rule;
|
|
328
|
+
const matchedRoots = new Set(matches.map((m) => rootOfRule(m.rule)));
|
|
329
|
+
const bySection = new Map(matches.map((m) => [m.section, m]));
|
|
330
|
+
const matched = [];
|
|
331
|
+
let i = 0;
|
|
332
|
+
while (i < sections.length) {
|
|
333
|
+
const section = sections[i];
|
|
334
|
+
if (!section) break;
|
|
335
|
+
const match = bySection.get(section);
|
|
336
|
+
if (!match) {
|
|
337
|
+
matched.push({
|
|
338
|
+
index: null,
|
|
339
|
+
rows: [{ depth, text: `(unexpected) ${titleText(section.title || null)}` }]
|
|
340
|
+
});
|
|
341
|
+
i++;
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
const root = rootOfRule(match.rule);
|
|
345
|
+
if (root.repeat) {
|
|
346
|
+
const taken = [];
|
|
347
|
+
while (i < sections.length) {
|
|
348
|
+
const here = sections[i];
|
|
349
|
+
if (!here) break;
|
|
350
|
+
const next = bySection.get(here);
|
|
351
|
+
if (!next || rootOfRule(next.rule) !== root) break;
|
|
352
|
+
taken.push(next);
|
|
353
|
+
i++;
|
|
354
|
+
}
|
|
355
|
+
const rows2 = [{ depth, text: pad(root.id ?? "(repeat)").trimEnd() }];
|
|
356
|
+
let run2 = [];
|
|
357
|
+
const flushMember = () => {
|
|
358
|
+
if (run2.length === 0) return;
|
|
359
|
+
rows2.push(matchedRow(depth + 1, run2));
|
|
360
|
+
for (const m of run2) {
|
|
361
|
+
rows2.push(...alignLevel(m.rule.sections, m.section.sections, m.section, depth + 2));
|
|
362
|
+
}
|
|
363
|
+
run2 = [];
|
|
364
|
+
};
|
|
365
|
+
for (const m of taken) {
|
|
366
|
+
const first = run2[0];
|
|
367
|
+
if (first && first.rule !== m.rule) flushMember();
|
|
368
|
+
run2.push(m);
|
|
369
|
+
}
|
|
370
|
+
flushMember();
|
|
371
|
+
const takenMembers = new Set(taken.map((m) => m.rule));
|
|
372
|
+
for (const member of root.repeat) {
|
|
373
|
+
if (takenMembers.has(member)) continue;
|
|
374
|
+
rows2.push({ depth: depth + 1, text: `${pad(ruleLabel(member))}${ARROW} (missing)` });
|
|
375
|
+
}
|
|
376
|
+
matched.push({ index: ruleIndex.get(root) ?? null, rows: rows2 });
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
const run = [match];
|
|
380
|
+
i++;
|
|
381
|
+
while (i < sections.length) {
|
|
382
|
+
const here = sections[i];
|
|
383
|
+
if (!here) break;
|
|
384
|
+
const next = bySection.get(here);
|
|
385
|
+
if (!next || next.rule !== match.rule) break;
|
|
386
|
+
run.push(next);
|
|
387
|
+
i++;
|
|
388
|
+
}
|
|
389
|
+
const rows = [matchedRow(depth, run)];
|
|
390
|
+
for (const m of run) {
|
|
391
|
+
rows.push(...alignLevel(m.rule.sections, m.section.sections, m.section, depth + 1));
|
|
392
|
+
}
|
|
393
|
+
matched.push({ index: ruleIndex.get(match.rule) ?? null, rows });
|
|
394
|
+
}
|
|
395
|
+
const missing = rules.filter((rule) => !matchedRoots.has(rule)).map((rule) => {
|
|
396
|
+
const index = ruleIndex.get(rule);
|
|
397
|
+
if (index === void 0) {
|
|
398
|
+
throw new LintError("alignLevel: rule missing from its own index");
|
|
399
|
+
}
|
|
400
|
+
return { index, rows: missingRows(depth, rule) };
|
|
401
|
+
});
|
|
402
|
+
return insertMissing(matched, missing);
|
|
403
|
+
}
|
|
404
|
+
function explainAlignment(tree, template) {
|
|
405
|
+
const heading = pageHeading(tree);
|
|
406
|
+
const arrow = heading.text !== null ? `${titleText(heading.text)}${heading.note ? ` (${heading.note})` : ""}` : `(${heading.note ?? "no heading"})`;
|
|
407
|
+
const rows = [{ depth: 0, text: `${pad("(page)")}${ARROW} ${arrow}` }];
|
|
408
|
+
rows.push(...alignLevel(template.sections, pageSections(tree), null, 1));
|
|
409
|
+
return rows;
|
|
410
|
+
}
|
|
411
|
+
function formatAlignment(rows) {
|
|
412
|
+
return rows.map((row) => `${" ".repeat(row.depth)}${row.text}`);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// src/lint/reporters/index.ts
|
|
416
|
+
function plural(n, word) {
|
|
417
|
+
return `${n} ${word}${n === 1 ? "" : "s"}`;
|
|
418
|
+
}
|
|
419
|
+
function locate(finding) {
|
|
420
|
+
return `${finding.position.start.line}:${finding.position.start.column}`;
|
|
421
|
+
}
|
|
422
|
+
function describeFinding(finding) {
|
|
423
|
+
return finding.heading != null ? `${finding.heading}: ${finding.message}` : finding.message;
|
|
424
|
+
}
|
|
425
|
+
function levelPrefix(c, severity) {
|
|
426
|
+
if (severity === "error") return "";
|
|
427
|
+
return `${severity === "notice" ? c.dim("notice") : c.yellow("warning")} `;
|
|
428
|
+
}
|
|
429
|
+
function renderPretty(run, opts = {}) {
|
|
430
|
+
const c = palette(opts.color ?? false);
|
|
431
|
+
const lines = [];
|
|
432
|
+
let warnings = 0;
|
|
433
|
+
let notices = 0;
|
|
434
|
+
for (const result of run.results) {
|
|
435
|
+
if (result.skipped != null) {
|
|
436
|
+
const why = result.reason ?? result.skipped;
|
|
437
|
+
lines.push(`${c.yellow("-")} ${result.file} ${c.dim(`skipped: ${why}`)}`);
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
if (result.success && result.findings.length === 0) {
|
|
441
|
+
lines.push(`${c.green("\u2713")} ${result.file}`);
|
|
442
|
+
continue;
|
|
443
|
+
}
|
|
444
|
+
const mark = result.success ? c.yellow("\u26A0") : c.red("\u2717");
|
|
445
|
+
lines.push(`${mark} ${result.file}`);
|
|
446
|
+
for (const finding of result.findings) {
|
|
447
|
+
if (finding.severity === "warning") warnings++;
|
|
448
|
+
else if (finding.severity === "notice") notices++;
|
|
449
|
+
lines.push(
|
|
450
|
+
` ${c.dim(locate(finding))} ${c.cyan(ruleId(finding.type))} ${levelPrefix(c, finding.severity)}${describeFinding(finding)}`
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
const { checked, passed, failed, skipped } = run.summary;
|
|
455
|
+
const warningsText = warnings > 0 ? `, ${plural(warnings, "warning")}` : "";
|
|
456
|
+
const noticesText = notices > 0 ? `, ${plural(notices, "notice")}` : "";
|
|
457
|
+
const summary = `${plural(checked, "file")} checked, ${passed} passed, ${failed} failed, ${skipped} skipped${warningsText}${noticesText}`;
|
|
458
|
+
if (lines.length > 0) lines.push("");
|
|
459
|
+
lines.push(failed > 0 ? c.red(summary) : c.green(summary));
|
|
460
|
+
return lines.join("\n");
|
|
461
|
+
}
|
|
462
|
+
function renderJson(run) {
|
|
463
|
+
const results = run.results.map((result) => ({
|
|
464
|
+
file: result.file,
|
|
465
|
+
success: result.success,
|
|
466
|
+
errors: result.findings.map((finding) => ({
|
|
467
|
+
type: finding.type,
|
|
468
|
+
// Additive, and deliberately beside `type` rather than instead of it.
|
|
469
|
+
// `ruleId` is the family id every other reporter files this finding
|
|
470
|
+
// under; `tool` names which tool produced it, the question a second
|
|
471
|
+
// lint job makes worth asking.
|
|
472
|
+
ruleId: ruleId(finding.type),
|
|
473
|
+
tool: TOOL_NAME,
|
|
474
|
+
heading: finding.heading,
|
|
475
|
+
message: finding.message,
|
|
476
|
+
position: finding.position,
|
|
477
|
+
// Additive too, and the reason it has to be: `success: true` beside a
|
|
478
|
+
// non-empty `errors` array is exactly what a warning-only file looks
|
|
479
|
+
// like now that `success` means "no error-severity finding" rather than
|
|
480
|
+
// "no findings". Without this key a consumer has no way to tell that
|
|
481
|
+
// apart from an error the JSON shape simply forgot to fail on.
|
|
482
|
+
severity: finding.severity
|
|
483
|
+
})),
|
|
484
|
+
// Additive, and the one thing this shape could not say. A skipped file is
|
|
485
|
+
// `{success: false, errors: []}`, which is also what a failure whose
|
|
486
|
+
// finding vanished looks like - so a consumer counting failures counted a
|
|
487
|
+
// file nothing read as a file that was read and found wanting. Null rather
|
|
488
|
+
// than absent, because a key that comes and goes makes "not skipped" and
|
|
489
|
+
// "an older manni" the same observation. The prose `reason` stays off the
|
|
490
|
+
// wire; it is a diagnostic for the pretty and SARIF reports.
|
|
491
|
+
skipped: result.skipped ?? null
|
|
492
|
+
}));
|
|
493
|
+
return JSON.stringify(results, null, 2);
|
|
494
|
+
}
|
|
495
|
+
function renderGithub(run) {
|
|
496
|
+
const lines = [];
|
|
497
|
+
for (const result of run.results) {
|
|
498
|
+
for (const finding of result.findings) {
|
|
499
|
+
const params = [
|
|
500
|
+
`file=${escapeWorkflowCommandProperty(result.file)}`,
|
|
501
|
+
`line=${finding.position.start.line}`,
|
|
502
|
+
`col=${finding.position.start.column}`,
|
|
503
|
+
`title=${escapeWorkflowCommandProperty(ruleId(finding.type))}`
|
|
504
|
+
];
|
|
505
|
+
const message = escapeWorkflowCommandMessage(describeFinding(finding));
|
|
506
|
+
lines.push(`::${finding.severity} ${params.join(",")}::${message}`);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return lines.join("\n");
|
|
510
|
+
}
|
|
511
|
+
function alignmentFor(result) {
|
|
512
|
+
const source = result.alignment;
|
|
513
|
+
if (!source) return null;
|
|
514
|
+
return formatAlignment(explainAlignment(source.tree, source.template));
|
|
515
|
+
}
|
|
516
|
+
function renderExplain(run, opts = {}) {
|
|
517
|
+
const c = palette(opts.color ?? false);
|
|
518
|
+
const lines = [];
|
|
519
|
+
for (const result of run.results) {
|
|
520
|
+
const chosen = result.template;
|
|
521
|
+
lines.push(`${chosen ? c.cyan("\u25B8") : c.dim("-")} ${c.bold(result.file)}`);
|
|
522
|
+
const steps = result.resolution?.steps ?? [];
|
|
523
|
+
if (steps.length === 0) {
|
|
524
|
+
lines.push(` ${c.dim("(no resolution recorded)")}`);
|
|
525
|
+
}
|
|
526
|
+
for (const step of steps) {
|
|
527
|
+
const mark = step.ref ? c.green("\u2192") : c.dim("\xB7");
|
|
528
|
+
const label = step.ref ? c.bold(step.ref) : c.dim(step.detail);
|
|
529
|
+
const suffix = step.ref ? ` ${c.dim(step.detail)}` : "";
|
|
530
|
+
lines.push(` ${mark} ${step.stage.padEnd(20)} ${label}${suffix}`);
|
|
531
|
+
}
|
|
532
|
+
const alignment = chosen ? alignmentFor(result) : null;
|
|
533
|
+
if (alignment && alignment.length > 0) {
|
|
534
|
+
lines.push(` ${c.dim("alignment")}`);
|
|
535
|
+
for (const row of alignment) lines.push(` ${row}`);
|
|
536
|
+
}
|
|
537
|
+
const cause = result.resolution?.cause;
|
|
538
|
+
if (cause === "unknown-type") {
|
|
539
|
+
const type = result.resolution?.unknownType ?? "(none recorded)";
|
|
540
|
+
const near = result.resolution?.suggestions ?? [];
|
|
541
|
+
const known = result.resolution?.knownTypes ?? [];
|
|
542
|
+
const hint = near.length ? `; did you mean ${near.join(", ")}?` : known.length ? `; known doctypes: ${known.join(", ")}` : "";
|
|
543
|
+
lines.push(` ${c.red("\u2717")} no template serves type "${type}"${hint}`);
|
|
544
|
+
} else if (cause === "no-type") {
|
|
545
|
+
lines.push(` ${c.dim("skipped: the page declares no type")}`);
|
|
546
|
+
}
|
|
547
|
+
lines.push("");
|
|
548
|
+
}
|
|
549
|
+
const routed = run.results.filter((r) => r.template != null).length;
|
|
550
|
+
lines.push(
|
|
551
|
+
`${run.results.length} file${run.results.length === 1 ? "" : "s"}, ${routed} routed, ${run.results.length - routed} unrouted`
|
|
552
|
+
);
|
|
553
|
+
return lines.join("\n");
|
|
554
|
+
}
|
|
555
|
+
function render(run, format, opts = {}) {
|
|
556
|
+
switch (format) {
|
|
557
|
+
case "json":
|
|
558
|
+
return renderJson(run);
|
|
559
|
+
case "github":
|
|
560
|
+
return renderGithub(run);
|
|
561
|
+
case "sarif":
|
|
562
|
+
return renderSarif(run, opts.root === void 0 ? {} : { root: opts.root });
|
|
563
|
+
case "junit":
|
|
564
|
+
return renderJunit2(run);
|
|
565
|
+
case "explain":
|
|
566
|
+
return renderExplain(run, opts);
|
|
567
|
+
case "pretty":
|
|
568
|
+
return renderPretty(run, opts);
|
|
569
|
+
default: {
|
|
570
|
+
const unreachable = format;
|
|
571
|
+
throw new LintError(
|
|
572
|
+
`Unknown report format ${JSON.stringify(unreachable)}. Use ${REPORT_FORMAT_LIST}.`
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
function templateLine(c, entry) {
|
|
578
|
+
const title = entry.title !== "" ? ` ${c.dim("\u2014")} ${entry.title}` : "";
|
|
579
|
+
const types = entry.types.length > 0 ? entry.types.join(", ") : "(no types declared)";
|
|
580
|
+
return ` ${c.cyan(entry.id)}${title} ${c.dim(`types: ${types}`)} ${c.dim(`[${entry.source}]`)}`;
|
|
581
|
+
}
|
|
582
|
+
function renderTemplates(info, format, opts = {}) {
|
|
583
|
+
if (format === "json") return JSON.stringify(info, null, 2);
|
|
584
|
+
const c = palette(opts.color ?? false);
|
|
585
|
+
const lines = [c.bold("Templates:")];
|
|
586
|
+
if (info.templates.length === 0) {
|
|
587
|
+
lines.push(c.dim(" (none)"));
|
|
588
|
+
} else {
|
|
589
|
+
for (const entry of info.templates) lines.push(templateLine(c, entry));
|
|
590
|
+
}
|
|
591
|
+
return lines.join("\n");
|
|
592
|
+
}
|
|
593
|
+
function formatLine(c, entry) {
|
|
594
|
+
const head = ` ${c.cyan(entry.name)} ${entry.label} (${entry.extensions.join(", ")})`;
|
|
595
|
+
if (entry.kinds.length === 0) return head;
|
|
596
|
+
return `${head} ${c.dim(`kinds: ${entry.kinds.join(", ")}`)}`;
|
|
597
|
+
}
|
|
598
|
+
function renderTools(tools, format, opts = {}) {
|
|
599
|
+
if (format === "json") return JSON.stringify(tools, null, 2);
|
|
600
|
+
const c = palette(opts.color ?? false);
|
|
601
|
+
const lines = [c.bold("Jobs:")];
|
|
602
|
+
for (const entry of tools) {
|
|
603
|
+
const state = [
|
|
604
|
+
entry.configured ? "configured" : "not configured",
|
|
605
|
+
entry.available ? "available" : "unavailable"
|
|
606
|
+
].join(", ");
|
|
607
|
+
const version = entry.version ?? "\u2014";
|
|
608
|
+
lines.push(
|
|
609
|
+
` ${c.cyan(entry.job)} tool: ${c.bold(entry.tool)} ${version} [${state}]`
|
|
610
|
+
);
|
|
611
|
+
lines.push(` config: ${c.dim(entry.config)}`);
|
|
612
|
+
lines.push(` ${c.dim("formats:")}`);
|
|
613
|
+
for (const info of entry.formats) lines.push(formatLine(c, info));
|
|
614
|
+
}
|
|
615
|
+
return lines.join("\n");
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
export {
|
|
619
|
+
RULE_ID_PREFIX,
|
|
620
|
+
TOOL_NAME,
|
|
621
|
+
ruleName,
|
|
622
|
+
ruleId,
|
|
623
|
+
toValidationResults,
|
|
624
|
+
renderJunit2 as renderJunit,
|
|
625
|
+
renderSarif,
|
|
626
|
+
renderPretty,
|
|
627
|
+
renderJson,
|
|
628
|
+
renderGithub,
|
|
629
|
+
renderExplain,
|
|
630
|
+
render,
|
|
631
|
+
renderTemplates,
|
|
632
|
+
renderTools
|
|
633
|
+
};
|
|
634
|
+
//# sourceMappingURL=chunk-H6FZ66XR.js.map
|