Skip to content

Commit 63e0d97

Browse files
flakey5araujogui
authored andcommitted
feat: linter
Signed-off-by: flakey5 <[email protected]>
1 parent 11a7953 commit 63e0d97

File tree

8 files changed

+177
-4
lines changed

8 files changed

+177
-4
lines changed

bin/cli.mjs

+29-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env node
22

33
import { resolve } from 'node:path';
4-
import { argv } from 'node:process';
4+
import { argv, exit } from 'node:process';
55

66
import { Command, Option } from 'commander';
77

@@ -12,6 +12,8 @@ import generators from '../src/generators/index.mjs';
1212
import createMarkdownLoader from '../src/loaders/markdown.mjs';
1313
import createMarkdownParser from '../src/parsers/markdown.mjs';
1414
import createNodeReleases from '../src/releases.mjs';
15+
import { Linter } from '../src/linter/index.mjs';
16+
import reporters from '../src/linter/reporters/index.mjs';
1517

1618
const availableGenerators = Object.keys(generators);
1719

@@ -50,6 +52,12 @@ program
5052
'Set the processing target modes'
5153
).choices(availableGenerators)
5254
)
55+
.addOption(new Option('--skip-validation', 'TODO').default(false))
56+
.addOption(
57+
new Option('--reporter', 'TODO')
58+
.choices(Object.keys(reporters))
59+
.default('console')
60+
)
5361
.parse(argv);
5462

5563
/**
@@ -66,7 +74,17 @@ program
6674
* @type {Options}
6775
* @description The return type for values sent to the program from the CLI.
6876
*/
69-
const { input, output, target = [], version, changelog } = program.opts();
77+
const {
78+
input,
79+
output,
80+
target = [],
81+
version,
82+
changelog,
83+
skipValidation,
84+
reporter,
85+
} = program.opts();
86+
87+
const linter = skipValidation ? undefined : new Linter();
7088

7189
const { loadFiles } = createMarkdownLoader();
7290
const { parseApiDocs } = createMarkdownParser();
@@ -91,4 +109,13 @@ await runGenerators({
91109
version: coerce(version),
92110
// A list of all Node.js major versions with LTS status
93111
releases: await getAllMajors(),
112+
linter,
94113
});
114+
115+
if (linter) {
116+
linter.report(reporter);
117+
118+
if (linter.hasError) {
119+
exit(1);
120+
}
121+
}

src/generators/types.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { SemVer } from 'semver';
22
import type availableGenerators from './index.mjs';
33
import type { ApiDocReleaseEntry } from '../types';
4+
import type { Linter } from '../linter/index.mjs';
45

56
declare global {
67
// All available generators as an inferable type, to allow Generator interfaces
@@ -30,6 +31,8 @@ declare global {
3031

3132
// A list of all Node.js major versions and their respective release information
3233
releases: Array<ApiDocReleaseEntry>;
34+
35+
linter: Linter | undefined;
3336
}
3437

3538
export interface GeneratorMetadata<I extends any, O extends any> {

src/linter/index.mjs

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// @ts-check
2+
'use strict';
3+
4+
import reporters from './reporters/index.mjs';
5+
6+
/**
7+
*
8+
*/
9+
export class Linter {
10+
#_hasError = false;
11+
12+
/**
13+
* @type {Array<import('./types.d.ts').LintMessage>}
14+
*/
15+
#messages = [];
16+
17+
/**
18+
*
19+
*/
20+
get hasError() {
21+
return this.#_hasError;
22+
}
23+
24+
/**
25+
* @param {import('./types.d.ts').LintMessage} msg
26+
*/
27+
log(msg) {
28+
if (msg.level === 'error') {
29+
this.#_hasError = true;
30+
}
31+
32+
this.#messages.push(msg);
33+
}
34+
35+
/**
36+
* @param {keyof reporters} reporterName
37+
*/
38+
report(reporterName) {
39+
const reporter = reporters[reporterName];
40+
41+
for (const message of this.#messages) {
42+
reporter(message);
43+
}
44+
}
45+
46+
/**
47+
* @param {string} msg
48+
* @param {import('./types.d.ts').LintMessageLocation | undefined} location
49+
*/
50+
info(msg, location) {
51+
this.log({
52+
level: 'info',
53+
msg,
54+
location,
55+
});
56+
}
57+
58+
/**
59+
* @param {string} msg
60+
* @param {import('./types.d.ts').LintMessageLocation | undefined} location
61+
*/
62+
warn(msg, location) {
63+
this.log({
64+
level: 'warn',
65+
msg,
66+
location,
67+
});
68+
}
69+
70+
/**
71+
* @param {string} msg
72+
* @param {import('./types.d.ts').LintMessageLocation | undefined} location
73+
*/
74+
error(msg, location) {
75+
this.log({
76+
level: 'error',
77+
msg,
78+
location,
79+
});
80+
}
81+
}

src/linter/reporters/console.mjs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// @ts-check
2+
3+
'use strict';
4+
5+
import { styleText } from 'node:util';
6+
7+
/**
8+
* TODO is there a way to grab the parameter type for styleText since the types aren't exported
9+
* @type {Record<import('../types.d.ts').LintLevel, string>}
10+
*/
11+
const levelToColorMap = {
12+
info: 'gray',
13+
warn: 'yellow',
14+
error: 'red',
15+
};
16+
17+
/**
18+
* @type {import('../types.d.ts').Reporter}
19+
*/
20+
export default msg => {
21+
console.log(styleText(levelToColorMap[msg.level], msg.msg));
22+
};

src/linter/reporters/github.mjs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// @ts-check
2+
3+
'use strict';
4+
5+
/**
6+
* GitHub action reporter for
7+
*
8+
* @type {import('../types.d.ts').Reporter}
9+
*/
10+
export default msg => {
11+
// TODO
12+
console.log(msg);
13+
};

src/linter/reporters/index.mjs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
3+
import console from './console.mjs';
4+
import github from './github.mjs';
5+
6+
export default /** @type {const} */ ({
7+
console,
8+
github,
9+
});

src/linter/types.d.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export type LintLevel = 'info' | 'warn' | 'error';
2+
3+
export interface LintMessageLocation {
4+
// The absolute path to the file
5+
path: string;
6+
line: number;
7+
column: number;
8+
}
9+
10+
export interface LintMessage {
11+
level: LintLevel;
12+
msg: string;
13+
location?: LintMessageLocation;
14+
}
15+
16+
export type Reporter = (msg: LintMessage) => void;

src/parsers/markdown.mjs

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ import { createNodeSlugger } from '../utils/slugger.mjs';
1414

1515
/**
1616
* Creates an API doc parser for a given Markdown API doc file
17+
*
18+
* @param {import('./linter/index.mjs').Linter | undefined} linter
1719
*/
18-
const createParser = () => {
20+
const createParser = linter => {
1921
// Creates an instance of the Remark processor with GFM support
2022
// which is used for stringifying the AST tree back to Markdown
2123
const remarkProcessor = getRemark();
22-
24+
linter?.info('asd123');
2325
const {
2426
setHeadingMetadata,
2527
addYAMLMetadata,

0 commit comments

Comments
 (0)