Skip to content

Commit e787728

Browse files
dweber019mnaumanali94frankkilcommins
authored
feat(core): add documentUrl to JS api and cli formatters (#2443)
* feat(core): add documentUrl to JS api and cli formatters * fix(test-harness): strip spectral version from sarif tests * chore(test-harness): fix whitespace linting issue * chore(test-harness): fix whitespace lint issue --------- Co-authored-by: Nauman <[email protected]> Co-authored-by: Frank Kilcommins <[email protected]> Co-authored-by: Frank Kilcommins <[email protected]>
1 parent d9ef27f commit e787728

34 files changed

+1074
-13
lines changed

docs/guides/2-cli.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,13 @@ Other options include:
4141
--resolver path to custom json-ref-resolver instance [string]
4242
-r, --ruleset path/URL to a ruleset file [string]
4343
-F, --fail-severity results of this level or above will trigger a failure exit code
44-
[string] [choices: "error", "warn", "info", "hint"] [default: "error"]
45-
-D, --display-only-failures only output results equal to or greater than --fail-severity [boolean] [default: false]
46-
--ignore-unknown-format do not warn about unmatched formats [boolean] [default: false]
47-
--fail-on-unmatched-globs fail on unmatched glob patterns [boolean] [default: false]
48-
-v, --verbose increase verbosity [boolean]
49-
-q, --quiet no logging - output only [boolean]
44+
[string] [choices: "error", "warn", "info", "hint"] [default: "error"]
45+
-D, --display-only-failures only output results equal to or greater than --fail-severity [boolean] [default: false]
46+
--ignore-unknown-format do not warn about unmatched formats [boolean] [default: false]
47+
--fail-on-unmatched-globs fail on unmatched glob patterns [boolean] [default: false]
48+
--show-documentation-url show documentation url in output result [boolean] [default: false]
49+
-v, --verbose increase verbosity [boolean]
50+
-q, --quiet no logging - output only [boolean]
5051
```
5152

5253
The Spectral CLI supports loading documents as YAML or JSON, and validation of OpenAPI v2/v3 documents via the built-in ruleset.

packages/cli/src/commands/__tests__/lint.test.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ describe('lint', () => {
8181
output: { stylish: '<stdout>' },
8282
ignoreUnknownFormat: false,
8383
failOnUnmatchedGlobs: false,
84+
showDocumentationUrl: false,
8485
});
8586
});
8687
});
@@ -94,6 +95,7 @@ describe('lint', () => {
9495
output: { stylish: '<stdout>' },
9596
ignoreUnknownFormat: false,
9697
failOnUnmatchedGlobs: false,
98+
showDocumentationUrl: false,
9799
});
98100
});
99101

@@ -106,6 +108,7 @@ describe('lint', () => {
106108
output: { stylish: '<stdout>' },
107109
ignoreUnknownFormat: false,
108110
failOnUnmatchedGlobs: false,
111+
showDocumentationUrl: false,
109112
});
110113
});
111114

@@ -118,6 +121,7 @@ describe('lint', () => {
118121
output: { json: '<stdout>' },
119122
ignoreUnknownFormat: false,
120123
failOnUnmatchedGlobs: false,
124+
showDocumentationUrl: false,
121125
});
122126
});
123127

@@ -184,6 +188,7 @@ describe('lint', () => {
184188
output: { stylish: '<stdout>' },
185189
ignoreUnknownFormat: true,
186190
failOnUnmatchedGlobs: false,
191+
showDocumentationUrl: false,
187192
});
188193
});
189194

@@ -195,6 +200,7 @@ describe('lint', () => {
195200
output: { stylish: '<stdout>' },
196201
ignoreUnknownFormat: false,
197202
failOnUnmatchedGlobs: true,
203+
showDocumentationUrl: false,
198204
});
199205
});
200206

@@ -244,13 +250,13 @@ describe('lint', () => {
244250
expect(process.stderr.write).nthCalledWith(2, `Error #1: ${chalk.red('some unhandled exception')}\n`);
245251
expect(process.stderr.write).nthCalledWith(
246252
3,
247-
expect.stringContaining(`packages/cli/src/commands/__tests__/lint.test.ts:236`),
253+
expect.stringContaining(`packages/cli/src/commands/__tests__/lint.test.ts:242`),
248254
);
249255

250256
expect(process.stderr.write).nthCalledWith(4, `Error #2: ${chalk.red('another one')}\n`);
251257
expect(process.stderr.write).nthCalledWith(
252258
5,
253-
expect.stringContaining(`packages/cli/src/commands/__tests__/lint.test.ts:237`),
259+
expect.stringContaining(`packages/cli/src/commands/__tests__/lint.test.ts:243`),
254260
);
255261

256262
expect(process.stderr.write).nthCalledWith(6, `Error #3: ${chalk.red('original exception')}\n`);

packages/cli/src/commands/lint.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ const lintCommand: CommandModule = {
151151
type: 'boolean',
152152
default: false,
153153
},
154+
'show-documentation-url': {
155+
description: 'show documentation url in output result',
156+
type: 'boolean',
157+
default: false,
158+
},
154159
verbose: {
155160
alias: 'v',
156161
description: 'increase verbosity',
@@ -175,6 +180,7 @@ const lintCommand: CommandModule = {
175180
encoding,
176181
ignoreUnknownFormat,
177182
failOnUnmatchedGlobs,
183+
showDocumentationUrl,
178184
...config
179185
} = args as unknown as ILintConfig & {
180186
documents: Array<number | string>;
@@ -189,6 +195,7 @@ const lintCommand: CommandModule = {
189195
encoding,
190196
ignoreUnknownFormat,
191197
failOnUnmatchedGlobs,
198+
showDocumentationUrl,
192199
ruleset,
193200
stdinFilepath,
194201
...pick<Partial<ILintConfig>, keyof ILintConfig>(config, ['verbose', 'quiet', 'resolver']),
@@ -198,6 +205,10 @@ const lintCommand: CommandModule = {
198205
linterResult.results = filterResultsBySeverity(linterResult.results, failSeverity);
199206
}
200207

208+
if (!showDocumentationUrl) {
209+
linterResult.results = removeDocumentationUrlFromResults(linterResult.results);
210+
}
211+
201212
await Promise.all(
202213
format.map(f => {
203214
const formattedOutput = formatOutput(
@@ -279,6 +290,10 @@ const filterResultsBySeverity = (results: IRuleResult[], failSeverity: FailSever
279290
return results.filter(r => r.severity <= diagnosticSeverity);
280291
};
281292

293+
const removeDocumentationUrlFromResults = (results: IRuleResult[]): IRuleResult[] => {
294+
return results.map(r => ({ ...r, documentationUrl: undefined }));
295+
};
296+
282297
export const severeEnoughToFail = (results: IRuleResult[], failSeverity: FailSeverity): boolean => {
283298
const diagnosticSeverity = getDiagnosticSeverity(failSeverity);
284299
return results.some(r => r.severity <= diagnosticSeverity);

packages/cli/src/services/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface ILintConfig {
2727
stdinFilepath?: string;
2828
ignoreUnknownFormat: boolean;
2929
failOnUnmatchedGlobs: boolean;
30+
showDocumentationUrl: boolean;
3031
verbose?: boolean;
3132
quiet?: boolean;
3233
}

packages/core/src/runner/lintNode.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ function processTargetResults(
9999
severity,
100100
...(source !== null ? { source } : null),
101101
range,
102+
documentationUrl: rule.documentationUrl ?? undefined,
102103
});
103104
}
104105
}

packages/core/src/types/spectral.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface IRunOpts {
1313
export interface ISpectralDiagnostic extends IDiagnostic {
1414
path: JsonPath;
1515
code: string | number;
16+
documentationUrl?: string;
1617
}
1718

1819
export type IRuleResult = ISpectralDiagnostic;

packages/formatters/src/__tests__/html.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,36 +18,42 @@ describe('HTML formatter', () => {
1818
<td>3:10</td>
1919
<td class="severity clr-hint">hint</td>
2020
<td>Info object should contain \`contact\` object.</td>
21+
<td></td>
2122
</tr>
2223
2324
<tr style="display:none" class="f-0">
2425
<td>3:10</td>
2526
<td class="severity clr-warning">warning</td>
2627
<td>OpenAPI object info \`description\` must be present and non-empty string.</td>
28+
<td></td>
2729
</tr>
2830
2931
<tr style="display:none" class="f-0">
3032
<td>5:14</td>
3133
<td class="severity clr-error">error</td>
3234
<td>Info must contain Stoplight</td>
35+
<td></td>
3336
</tr>
3437
3538
<tr style="display:none" class="f-0">
3639
<td>17:13</td>
3740
<td class="severity clr-information">information</td>
3841
<td>Operation \`description\` must be present and non-empty string.</td>
42+
<td></td>
3943
</tr>
4044
4145
<tr style="display:none" class="f-0">
4246
<td>64:14</td>
4347
<td class="severity clr-information">information</td>
4448
<td>Operation \`description\` must be present and non-empty string.</td>
49+
<td></td>
4550
</tr>
4651
4752
<tr style="display:none" class="f-0">
4853
<td>86:13</td>
4954
<td class="severity clr-information">information</td>
5055
<td>Operation \`description\` must be present and non-empty string.</td>
56+
<td></td>
5157
</tr>`);
5258
});
5359
});

packages/formatters/src/github-actions.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ export const githubActions: Formatter = results => {
4141
// FIXME: Use replaceAll instead after removing Node.js 14 support.
4242
const message = result.message.replace(/\n/g, '%0A');
4343

44-
return `::${OUTPUT_TYPES[result.severity]} ${paramsString}::${message}`;
44+
return `::${OUTPUT_TYPES[result.severity]} ${paramsString}::${message}${
45+
result.documentationUrl ? `::${result.documentationUrl}` : ''
46+
}`;
4547
})
4648
.join('\n');
4749
};

packages/formatters/src/html/html-template-message.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
<td><%= line %>:<%= character %></td>
33
<td class="severity clr-<%= severity %>"><%= severity %></td>
44
<td><%- message %></td>
5+
<td><% if(documentationUrl) { %><a href="<%- documentationUrl %>" target="_blank">documentation</a><% } %></td>
56
</tr>

packages/formatters/src/html/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ function renderMessages(messages: IRuleResult[], parentIndex: number): string {
5050
severity: getSeverityName(message.severity),
5151
message: message.message,
5252
code: message.code,
53+
documentationUrl: message.documentationUrl,
5354
});
5455
})
5556
.join('\n');

0 commit comments

Comments
 (0)