Skip to content

Commit 3f61385

Browse files
authored
chore: provide ref from string (#231)
* feat: use git only when requested * chore: updated readme * chore: code review changes and changed approach * chore: updated readme * chore: use snapshots * chore: code review
1 parent 7e52dc0 commit 3f61385

File tree

16 files changed

+60
-93
lines changed

16 files changed

+60
-93
lines changed

README.md

+11-4
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,17 @@ CLI tool to generate API documentation of a Node.js project.
3636

3737
Options:
3838
-i, --input [patterns...] Specify input file patterns using glob syntax
39-
--ignore [patterns...] Specify files to be ignored from the input using glob syntax
39+
--ignore [patterns...] Specify which input files to ignore using glob syntax
4040
-o, --output <path> Specify the relative or absolute output directory
41-
-v, --version <semver> Specify the target version of Node.js, semver compliant (default: "v22.6.0")
42-
-c, --changelog <url> Specify the path (file: or https://) to the CHANGELOG.md file (default: "https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md")
43-
-t, --target [mode...] Set the processing target modes (choices: "json-simple", "legacy-html", "legacy-html-all", "man-page", "legacy-json", "legacy-json-all", "addon-verify", "api-links", "orama-db")
41+
-v, --version <semver> Specify the target version of Node.js, semver compliant (default: "v22.11.0")
42+
-c, --changelog <url> Specify the path (file: or https://) to the CHANGELOG.md file (default:
43+
"https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md")
44+
-t, --target [mode...] Set the processing target modes (choices: "json-simple", "legacy-html", "legacy-html-all",
45+
"man-page", "legacy-json", "legacy-json-all", "addon-verify", "api-links", "orama-db")
46+
--disable-rule [rule...] Disable a specific linter rule (choices: "invalid-change-version",
47+
"missing-change-version", "missing-introduced-in", default: [])
48+
--lint-dry-run Run linter in dry-run mode (default: false)
49+
--git-ref A git ref/commit URL pointing to Node.js
50+
-r, --reporter [reporter] Specify the linter reporter (choices: "console", "github", default: "console")
4451
-h, --help display help for command
4552
```

bin/cli.mjs

+17-5
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ import { coerce } from 'semver';
99
import { DOC_NODE_CHANGELOG_URL, DOC_NODE_VERSION } from '../src/constants.mjs';
1010
import createGenerator from '../src/generators.mjs';
1111
import generators from '../src/generators/index.mjs';
12-
import createMarkdownLoader from '../src/loaders/markdown.mjs';
13-
import createMarkdownParser from '../src/parsers/markdown.mjs';
14-
import createNodeReleases from '../src/releases.mjs';
1512
import createLinter from '../src/linter/index.mjs';
1613
import reporters from '../src/linter/reporters/index.mjs';
1714
import rules from '../src/linter/rules/index.mjs';
15+
import createMarkdownLoader from '../src/loaders/markdown.mjs';
16+
import createMarkdownParser from '../src/parsers/markdown.mjs';
17+
import createNodeReleases from '../src/releases.mjs';
1818

1919
const availableGenerators = Object.keys(generators);
2020

@@ -67,6 +67,11 @@ program
6767
.addOption(
6868
new Option('--lint-dry-run', 'Run linter in dry-run mode').default(false)
6969
)
70+
.addOption(
71+
new Option('--git-ref', 'A git ref/commit URL pointing to Node.js').default(
72+
'https://github.com/nodejs/node/tree/HEAD'
73+
)
74+
)
7075
.addOption(
7176
new Option('-r, --reporter [reporter]', 'Specify the linter reporter')
7277
.choices(Object.keys(reporters))
@@ -85,6 +90,7 @@ program
8590
* @property {string} changelog Specifies the path to the Node.js CHANGELOG.md file.
8691
* @property {string[]} disableRule Specifies the linter rules to disable.
8792
* @property {boolean} lintDryRun Specifies whether the linter should run in dry-run mode.
93+
* @property {boolean} useGit Specifies whether the parser should execute optional git commands. (Should only be used within a git repo)
8894
* @property {keyof reporters} reporter Specifies the linter reporter.
8995
*
9096
* @name ProgramOptions
@@ -100,6 +106,7 @@ const {
100106
changelog,
101107
disableRule,
102108
lintDryRun,
109+
gitRef,
103110
reporter,
104111
} = program.opts();
105112

@@ -117,23 +124,28 @@ const { runGenerators } = createGenerator(parsedApiDocs);
117124
// Retrieves Node.js release metadata from a given Node.js version and CHANGELOG.md file
118125
const { getAllMajors } = createNodeReleases(changelog);
119126

127+
// Runs the Linter on the parsed API docs
120128
linter.lintAll(parsedApiDocs);
121129

122-
if (target && output) {
130+
if (target) {
123131
await runGenerators({
124132
// A list of target modes for the API docs parser
125133
generators: target,
126134
// Resolved `input` to be used
127135
input: input,
128136
// Resolved `output` path to be used
129-
output: resolve(output),
137+
output: output && resolve(output),
130138
// Resolved SemVer of current Node.js version
131139
version: coerce(version),
132140
// A list of all Node.js major versions with LTS status
133141
releases: await getAllMajors(),
142+
// An URL containing a git ref URL pointing to the commit or ref that was used
143+
// to generate the API docs. This is used to link to the source code of the
144+
gitRef,
134145
});
135146
}
136147

148+
// Reports Lint Content
137149
linter.report(reporter);
138150

139151
exit(Number(linter.hasError()));

src/generators.mjs

+4-6
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ const availableGenerators = {
1313
};
1414

1515
/**
16-
* @typedef {{ ast: import('./generators/types.d.ts').GeneratorMetadata<ApiDocMetadataEntry, ApiDocMetadataEntry>}} AstGenerator The AST "generator" is a facade for the AST tree and it isn't really a generator
17-
* @typedef {import('./generators/types.d.ts').AvailableGenerators & AstGenerator} AllGenerators A complete set of the available generators, including the AST one
16+
* @typedef {{ ast: GeneratorMetadata<ApiDocMetadataEntry, ApiDocMetadataEntry>}} AstGenerator The AST "generator" is a facade for the AST tree and it isn't really a generator
17+
* @typedef {AvailableGenerators & AstGenerator} AllGenerators A complete set of the available generators, including the AST one
1818
* @param markdownInput
1919
* @param jsInput
2020
*
@@ -41,14 +41,12 @@ const createGenerator = markdownInput => {
4141
*
4242
* @type {{ [K in keyof AllGenerators]: ReturnType<AllGenerators[K]['generate']> }}
4343
*/
44-
const cachedGenerators = {
45-
ast: Promise.resolve(markdownInput),
46-
};
44+
const cachedGenerators = { ast: Promise.resolve(markdownInput) };
4745

4846
/**
4947
* Runs the Generator engine with the provided top-level input and the given generator options
5048
*
51-
* @param {import('./generators/types.d.ts').GeneratorOptions} options The options for the generator runtime
49+
* @param {GeneratorOptions} options The options for the generator runtime
5250
*/
5351
const runGenerators = async ({ generators, ...extra }) => {
5452
// Note that this method is blocking, and will only execute one generator per-time

src/generators/addon-verify/index.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
*
2121
* @typedef {Array<ApiDocMetadataEntry>} Input
2222
*
23-
* @type {import('../types.d.ts').GeneratorMetadata<Input, string>}
23+
* @type {GeneratorMetadata<Input, string>}
2424
*/
2525
export default {
2626
name: 'addon-verify',

src/generators/api-links/index.mjs

+9-32
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
'use strict';
22

3-
import { basename, dirname, join } from 'node:path';
3+
import { basename, join } from 'node:path';
44
import { writeFile } from 'node:fs/promises';
5-
import {
6-
getBaseGitHubUrl,
7-
getCurrentGitHash,
8-
} from './utils/getBaseGitHubUrl.mjs';
95
import { extractExports } from './utils/extractExports.mjs';
106
import { findDefinitions } from './utils/findDefinitions.mjs';
117
import { checkIndirectReferences } from './utils/checkIndirectReferences.mjs';
@@ -20,7 +16,7 @@ import { checkIndirectReferences } from './utils/checkIndirectReferences.mjs';
2016
*
2117
* @typedef {Array<JsProgram>} Input
2218
*
23-
* @type {import('../types.d.ts').GeneratorMetadata<Input, Record<string, string>>}
19+
* @type {GeneratorMetadata<Input, Record<string, string>>}
2420
*/
2521
export default {
2622
name: 'api-links',
@@ -40,56 +36,37 @@ export default {
4036
* @param {Input} input
4137
* @param {Partial<GeneratorOptions>} options
4238
*/
43-
async generate(input, { output }) {
39+
async generate(input, { output, gitRef }) {
4440
/**
4541
* @type Record<string, string>
4642
*/
4743
const definitions = {};
4844

49-
/**
50-
* @type {string}
51-
*/
52-
let baseGithubLink;
53-
54-
if (input.length > 0) {
55-
const repositoryDirectory = dirname(input[0].path);
56-
57-
const repository = getBaseGitHubUrl(repositoryDirectory);
58-
59-
const tag = getCurrentGitHash(repositoryDirectory);
60-
61-
baseGithubLink = `${repository}/blob/${tag}`;
62-
}
63-
6445
input.forEach(program => {
6546
/**
6647
* Mapping of definitions to their line number
48+
*
6749
* @type {Record<string, number>}
6850
* @example { 'someclass.foo': 10 }
6951
*/
7052
const nameToLineNumberMap = {};
7153

7254
// `http.js` -> `http`
73-
const programBasename = basename(program.path, '.js');
55+
const baseName = basename(program.path, '.js');
7456

75-
const exports = extractExports(
76-
program,
77-
programBasename,
78-
nameToLineNumberMap
79-
);
57+
const exports = extractExports(program, baseName, nameToLineNumberMap);
8058

81-
findDefinitions(program, programBasename, nameToLineNumberMap, exports);
59+
findDefinitions(program, baseName, nameToLineNumberMap, exports);
8260

8361
checkIndirectReferences(program, exports, nameToLineNumberMap);
8462

85-
const githubLink =
86-
`${baseGithubLink}/lib/${programBasename}.js`.replaceAll('\\', '/');
63+
const fullGitUrl = `${gitRef}/lib/${baseName}.js`;
8764

8865
// Add the exports we found in this program to our output
8966
Object.keys(nameToLineNumberMap).forEach(key => {
9067
const lineNumber = nameToLineNumberMap[key];
9168

92-
definitions[key] = `${githubLink}#L${lineNumber}`;
69+
definitions[key] = `${fullGitUrl}#L${lineNumber}`;
9370
});
9471
});
9572

src/generators/api-links/test/fixtures.test.mjs

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ describe('api links', () => {
1919
input: [sourceFile],
2020
});
2121

22-
const actualOutput = await apiLinks.generate(astJsResult, {});
22+
const actualOutput = await apiLinks.generate(astJsResult, {
23+
gitRef: 'https://github.com/nodejs/node/tree/HEAD',
24+
});
2325

2426
for (const [k, v] of Object.entries(actualOutput)) {
2527
actualOutput[k] = v.replace(/.*(?=lib\/)/, '');

src/generators/api-links/utils/getBaseGitHubUrl.mjs

-35
This file was deleted.

src/generators/ast-js/index.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import createJsParser from '../../parsers/javascript.mjs';
1111
*
1212
* @typedef {unknown} Input
1313
*
14-
* @type {import('../types.d.ts').GeneratorMetadata<Input, Array<JsProgram>>}
14+
* @type {GeneratorMetadata<Input, Array<JsProgram>>}
1515
*/
1616
export default {
1717
name: 'ast-js',

src/generators/json-simple/index.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { getRemark } from '../../utils/remark.mjs';
1717
*
1818
* @typedef {Array<ApiDocMetadataEntry>} Input
1919
*
20-
* @type {import('../types.d.ts').GeneratorMetadata<Input, string>}
20+
* @type {GeneratorMetadata<Input, string>}
2121
*/
2222
export default {
2323
name: 'json-simple',

src/generators/legacy-html-all/index.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import { getRemarkRehype } from '../../utils/remark.mjs';
2929
*
3030
* @typedef {Array<TemplateValues>} Input
3131
*
32-
* @type {import('../types.d.ts').GeneratorMetadata<Input, string>}
32+
* @type {GeneratorMetadata<Input, string>}
3333
*/
3434
export default {
3535
name: 'legacy-html-all',

src/generators/legacy-html/index.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { getRemarkRehype } from '../../utils/remark.mjs';
3131
*
3232
* @typedef {Array<ApiDocMetadataEntry>} Input
3333
*
34-
* @type {import('../types.d.ts').GeneratorMetadata<Input, Array<TemplateValues>>}
34+
* @type {GeneratorMetadata<Input, Array<TemplateValues>>}
3535
*/
3636
export default {
3737
name: 'legacy-html',

src/generators/legacy-json-all/index.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { join } from 'node:path';
99
*
1010
* @typedef {Array<import('../legacy-json/types.d.ts').Section>} Input
1111
*
12-
* @type {import('../types.d.ts').GeneratorMetadata<Input, import('./types.d.ts').Output>}
12+
* @type {GeneratorMetadata<Input, import('./types.d.ts').Output>}
1313
*/
1414
export default {
1515
name: 'legacy-json-all',

src/generators/legacy-json/index.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { createSectionBuilder } from './utils/buildSection.mjs';
1616
*
1717
* @typedef {Array<ApiDocMetadataEntry>} Input
1818
*
19-
* @type {import('../types.d.ts').GeneratorMetadata<Input, import('./types.d.ts').Section[]>}
19+
* @type {GeneratorMetadata<Input, import('./types.d.ts').Section[]>}
2020
*/
2121
export default {
2222
name: 'legacy-json',

src/generators/man-page/index.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { DOC_SLUG_ENVIRONMENT, DOC_SLUG_OPTIONS } from './constants.mjs';
1616
*
1717
* @typedef {Array<ApiDocMetadataEntry>} Input
1818
*
19-
* @type {import('../types.d.ts').GeneratorMetadata<Input, string>}
19+
* @type {GeneratorMetadata<Input, string>}
2020
*/
2121
export default {
2222
name: 'man-page',

src/generators/orama-db/index.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { createSectionBuilder } from '../legacy-json/utils/buildSection.mjs';
1212
*
1313
* @typedef {Array<ApiDocMetadataEntry>} Input
1414
*
15-
* @type {import('../types.d.ts').GeneratorMetadata<Input, import('./types.d.ts').OramaDb>}
15+
* @type {GeneratorMetadata<Input, import('./types.d.ts').OramaDb>}
1616
*/
1717
export default {
1818
name: 'orama-db',

src/generators/types.d.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { SemVer } from 'semver';
2-
import type availableGenerators from './index.mjs';
32
import type { ApiDocReleaseEntry } from '../types';
3+
import type availableGenerators from './index.mjs';
44

55
declare global {
66
// All available generators as an inferable type, to allow Generator interfaces
@@ -30,6 +30,12 @@ declare global {
3030

3131
// A list of all Node.js major versions and their respective release information
3232
releases: Array<ApiDocReleaseEntry>;
33+
34+
// An URL containing a git ref URL pointing to the commit or ref that was used
35+
// to generate the API docs. This is used to link to the source code of the
36+
// i.e. https://github.com/nodejs/node/tree/2cb1d07e0f6d9456438016bab7db4688ab354fd2
37+
// i.e. https://gitlab.com/someone/node/tree/HEAD
38+
gitRef: string;
3339
}
3440

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

0 commit comments

Comments
 (0)