Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions bin/cli.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const {
const linter = createLinter(lintDryRun, disableRule);

const { loadFiles } = createMarkdownLoader();
const { parseApiDocs } = createMarkdownParser();
const { parseApiDocs } = createMarkdownParser(linter);

const apiDocFiles = await loadFiles(input, ignore);

Expand All @@ -124,9 +124,6 @@ const { runGenerators } = createGenerator(parsedApiDocs);
// Retrieves Node.js release metadata from a given Node.js version and CHANGELOG.md file
const { getAllMajors } = createNodeReleases(changelog);

// Runs the Linter on the parsed API docs
linter.lintAll(parsedApiDocs);

if (target) {
await runGenerators({
// A list of target modes for the API docs parser
Expand Down
12 changes: 6 additions & 6 deletions src/linter/engine.mjs
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
'use strict';

/**
* Creates a linter engine instance to validate ApiDocMetadataEntry entries
* Creates a linter engine instance to validate mdast trees.
*
* @param {import('./types').LintRule[]} rules Lint rules to validate the entries against
*/
const createLinterEngine = rules => {
/**
* Validates an array of ApiDocMetadataEntry entries against all defined rules
* Validates an array of mdast trees against all defined rules
*
* @param {ApiDocMetadataEntry[]} entries
* @param {import('mdast').Root[]} ast
* @returns {import('./types').LintIssue[]}
*/
const lintAll = entries => {
const lint = ast => {
const issues = [];

for (const rule of rules) {
issues.push(...rule(entries));
issues.push(...rule(ast));
}

return issues;
};

return {
lintAll,
lint,
};
};

Expand Down
12 changes: 7 additions & 5 deletions src/linter/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import reporters from './reporters/index.mjs';
import rules from './rules/index.mjs';

/**
* Creates a linter instance to validate ApiDocMetadataEntry entries
* Creates a linter instance to validate mdast trees
*
* @param {boolean} dryRun Whether to run the engine in dry-run mode
* @param {string[]} disabledRules List of disabled rules names
* @returns {import('./types').Linter}
*/
const createLinter = (dryRun, disabledRules) => {
/**
Expand All @@ -34,10 +35,11 @@ const createLinter = (dryRun, disabledRules) => {
/**
* Lints all entries using the linter engine
*
* @param entries
* @param {import('mdast').Root} ast
* @returns {void}
*/
const lintAll = entries => {
issues.push(...engine.lintAll(entries));
const lint = ast => {
issues.push(...engine.lint(ast));
};

/**
Expand Down Expand Up @@ -68,7 +70,7 @@ const createLinter = (dryRun, disabledRules) => {
};

return {
lintAll,
lint,
report,
hasError,
};
Expand Down
12 changes: 6 additions & 6 deletions src/linter/rules/index.mjs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
'use strict';

import { duplicateStabilityNodes } from './duplicate-stability-nodes.mjs';
import { invalidChangeVersion } from './invalid-change-version.mjs';
import { missingChangeVersion } from './missing-change-version.mjs';
// import { duplicateStabilityNodes } from './duplicate-stability-nodes.mjs';
// import { invalidChangeVersion } from './invalid-change-version.mjs';
// import { missingChangeVersion } from './missing-change-version.mjs';
import { missingIntroducedIn } from './missing-introduced-in.mjs';

/**
* @type {Record<string, import('../types').LintRule>}
*/
export default {
'duplicate-stability-nodes': duplicateStabilityNodes,
'invalid-change-version': invalidChangeVersion,
'missing-change-version': missingChangeVersion,
// 'duplicate-stability-nodes': duplicateStabilityNodes,
// 'invalid-change-version': invalidChangeVersion,
// 'missing-change-version': missingChangeVersion,
'missing-introduced-in': missingIntroducedIn,
};
35 changes: 21 additions & 14 deletions src/linter/rules/missing-introduced-in.mjs
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
import { LINT_MESSAGES } from '../constants.mjs';

/**
* Checks if `introduced_in` field is missing
* Checks if `introduced_in` node is missing
*
* @param {ApiDocMetadataEntry[]} entries
* @param {import('mdast').Root} tree
* @returns {Array<import('../types.d.ts').LintIssue>}
*/
export const missingIntroducedIn = entries => {
const issues = [];
export const missingIntroducedIn = tree => {
const regex = /<!--introduced_in=.*-->/;

for (const entry of entries) {
// Early continue if not a top-level heading or if introduced_in exists
if (entry.heading.depth !== 1 || entry.introduced_in) continue;
const introduced_in = tree.children.find(
node => node.type === 'html' && regex.test(node.value)
);

issues.push({
level: 'info',
message: LINT_MESSAGES.missingIntroducedIn,
location: {
path: entry.api_doc_source,
if (!introduced_in) {
return [
{
level: 'info',
message: LINT_MESSAGES.missingIntroducedIn,
location: {
path: '?',
position: {
start: { line: 1, column: 1 },
end: { line: 1, column: 1 },
},
},
},
});
];
}

return issues;
return [];
};
9 changes: 8 additions & 1 deletion src/linter/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { Root } from 'mdast';
import { Position } from 'unist';

export interface Linter {
lint: (ast: Root) => void;
report: (reporterName: keyof typeof reporters) => void;
hasError: () => boolean;
}

export type IssueLevel = 'info' | 'warn' | 'error';

export interface LintIssueLocation {
Expand All @@ -13,6 +20,6 @@ export interface LintIssue {
location: LintIssueLocation;
}

type LintRule = (input: ApiDocMetadataEntry[]) => LintIssue[];
type LintRule = (input: Root[]) => LintIssue[];

export type Reporter = (msg: LintIssue) => void;
6 changes: 4 additions & 2 deletions src/parsers/markdown.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import { createNodeSlugger } from '../utils/slugger/index.mjs';
/**
* Creates an API doc parser for a given Markdown API doc file
*
* @param {import('./linter/index.mjs').Linter | undefined} linter
* @param {import('../linter/types').Linter} linter
*/
const createParser = () => {
const createParser = linter => {
// Creates an instance of the Remark processor with GFM support
// which is used for stringifying the AST tree back to Markdown
const remarkProcessor = getRemark();
Expand Down Expand Up @@ -63,6 +63,8 @@ const createParser = () => {
// Parses the API doc into an AST tree using `unified` and `remark`
const apiDocTree = remarkProcessor.parse(resolvedApiDoc);

linter.lint(apiDocTree);

// Get all Markdown Footnote definitions from the tree
const markdownDefinitions = selectAll('definition', apiDocTree);

Expand Down
Loading