From 0d7ffaff65c93b2a7e2723d68591dc6ca23a6cb5 Mon Sep 17 00:00:00 2001 From: Claudio Wunder Date: Sun, 23 Mar 2025 15:51:37 +0100 Subject: [PATCH 1/6] feat: use git only when requested --- README.md | 14 ++++++++++---- bin/cli.mjs | 10 ++++++++++ src/constants.mjs | 3 +++ src/generators.mjs | 10 ++++------ src/generators/addon-verify/index.mjs | 2 +- src/generators/api-links/index.mjs | 11 +++++++---- src/generators/ast-js/index.mjs | 2 +- src/generators/json-simple/index.mjs | 2 +- src/generators/legacy-html-all/index.mjs | 2 +- src/generators/legacy-html/index.mjs | 2 +- src/generators/legacy-json-all/index.mjs | 2 +- src/generators/legacy-json/index.mjs | 2 +- src/generators/man-page/index.mjs | 2 +- src/generators/orama-db/index.mjs | 2 +- src/generators/types.d.ts | 3 +++ 15 files changed, 46 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 9148a2a3..7fc1d3b2 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,16 @@ CLI tool to generate API documentation of a Node.js project. Options: -i, --input [patterns...] Specify input file patterns using glob syntax - --ignore [patterns...] Specify files to be ignored from the input using glob syntax + --ignore [patterns...] Specify which input files to ignore using glob syntax -o, --output Specify the relative or absolute output directory - -v, --version Specify the target version of Node.js, semver compliant (default: "v22.6.0") - -c, --changelog Specify the path (file: or https://) to the CHANGELOG.md file (default: "https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md") - -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") + -v, --version Specify the target version of Node.js, semver compliant (default: "v22.11.0") + -c, --changelog Specify the path (file: or https://) to the CHANGELOG.md file (default: + "https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md") + -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") + --disable-rule [rule...] Disable a specific linter rule (choices: "invalid-change-version", + "missing-change-version", "missing-introduced-in", default: []) + --lint-dry-run Run linter in dry-run mode (default: false) + -r, --reporter [reporter] Specify the linter reporter (choices: "console", "github", default: "console") -h, --help display help for command ``` diff --git a/bin/cli.mjs b/bin/cli.mjs index df1cbc4e..2c9b94ae 100755 --- a/bin/cli.mjs +++ b/bin/cli.mjs @@ -67,6 +67,9 @@ program .addOption( new Option('--lint-dry-run', 'Run linter in dry-run mode').default(false) ) + .addOption( + new Option('--use-git', 'Run git commands when needed').default(false) + ) .addOption( new Option('-r, --reporter [reporter]', 'Specify the linter reporter') .choices(Object.keys(reporters)) @@ -85,6 +88,7 @@ program * @property {string} changelog Specifies the path to the Node.js CHANGELOG.md file. * @property {string[]} disableRule Specifies the linter rules to disable. * @property {boolean} lintDryRun Specifies whether the linter should run in dry-run mode. + * @property {boolean} useGit Specifies whether the parser should execute optional git commands. (Should only be used within a git repo) * @property {keyof reporters} reporter Specifies the linter reporter. * * @name ProgramOptions @@ -100,6 +104,7 @@ const { changelog, disableRule, lintDryRun, + useGit, reporter, } = program.opts(); @@ -117,6 +122,7 @@ 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 && output) { @@ -131,9 +137,13 @@ if (target && output) { version: coerce(version), // A list of all Node.js major versions with LTS status releases: await getAllMajors(), + // If it should run git commands when needed + // (should only be used within a git repo) + useGit, }); } +// Reports Lint Content linter.report(reporter); exit(Number(linter.hasError())); diff --git a/src/constants.mjs b/src/constants.mjs index 473cf35b..0fb6a75e 100644 --- a/src/constants.mjs +++ b/src/constants.mjs @@ -7,6 +7,9 @@ export const DOC_NODE_VERSION = process.version; export const DOC_NODE_CHANGELOG_URL = 'https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md'; +// The base URL for the Node.js runtime GitHub repository +export const DOC_NODE_REPO_URL = 'https://github.com/nodejs/node'; + // This is the Node.js Base URL for viewing a file within GitHub UI export const DOC_NODE_BLOB_BASE_URL = 'https://github.com/nodejs/node/blob/HEAD/'; diff --git a/src/generators.mjs b/src/generators.mjs index b276d779..bb03c290 100644 --- a/src/generators.mjs +++ b/src/generators.mjs @@ -13,8 +13,8 @@ const availableGenerators = { }; /** - * @typedef {{ ast: import('./generators/types.d.ts').GeneratorMetadata}} AstGenerator The AST "generator" is a facade for the AST tree and it isn't really a generator - * @typedef {import('./generators/types.d.ts').AvailableGenerators & AstGenerator} AllGenerators A complete set of the available generators, including the AST one + * @typedef {{ ast: GeneratorMetadata}} AstGenerator The AST "generator" is a facade for the AST tree and it isn't really a generator + * @typedef {AvailableGenerators & AstGenerator} AllGenerators A complete set of the available generators, including the AST one * @param markdownInput * @param jsInput * @@ -41,14 +41,12 @@ const createGenerator = markdownInput => { * * @type {{ [K in keyof AllGenerators]: ReturnType }} */ - const cachedGenerators = { - ast: Promise.resolve(markdownInput), - }; + const cachedGenerators = { ast: Promise.resolve(markdownInput) }; /** * Runs the Generator engine with the provided top-level input and the given generator options * - * @param {import('./generators/types.d.ts').GeneratorOptions} options The options for the generator runtime + * @param {GeneratorOptions} options The options for the generator runtime */ const runGenerators = async ({ generators, ...extra }) => { // Note that this method is blocking, and will only execute one generator per-time diff --git a/src/generators/addon-verify/index.mjs b/src/generators/addon-verify/index.mjs index 76a91ee8..450bf962 100644 --- a/src/generators/addon-verify/index.mjs +++ b/src/generators/addon-verify/index.mjs @@ -20,7 +20,7 @@ import { * * @typedef {Array} Input * - * @type {import('../types.d.ts').GeneratorMetadata} + * @type {GeneratorMetadata} */ export default { name: 'addon-verify', diff --git a/src/generators/api-links/index.mjs b/src/generators/api-links/index.mjs index b0b00640..890bcc65 100644 --- a/src/generators/api-links/index.mjs +++ b/src/generators/api-links/index.mjs @@ -9,6 +9,7 @@ import { import { extractExports } from './utils/extractExports.mjs'; import { findDefinitions } from './utils/findDefinitions.mjs'; import { checkIndirectReferences } from './utils/checkIndirectReferences.mjs'; +import { DOC_NODE_REPO_URL } from '../../constants.mjs'; /** * This generator is responsible for mapping publicly accessible functions in @@ -20,7 +21,7 @@ import { checkIndirectReferences } from './utils/checkIndirectReferences.mjs'; * * @typedef {Array} Input * - * @type {import('../types.d.ts').GeneratorMetadata>} + * @type {GeneratorMetadata>} */ export default { name: 'api-links', @@ -40,7 +41,7 @@ export default { * @param {Input} input * @param {Partial} options */ - async generate(input, { output }) { + async generate(input, { output, useGit }) { /** * @type Record */ @@ -54,9 +55,11 @@ export default { if (input.length > 0) { const repositoryDirectory = dirname(input[0].path); - const repository = getBaseGitHubUrl(repositoryDirectory); + const repository = useGit + ? getBaseGitHubUrl(repositoryDirectory) + : DOC_NODE_REPO_URL; - const tag = getCurrentGitHash(repositoryDirectory); + const tag = useGit ? getCurrentGitHash(repositoryDirectory) : 'HEAD'; baseGithubLink = `${repository}/blob/${tag}`; } diff --git a/src/generators/ast-js/index.mjs b/src/generators/ast-js/index.mjs index 440365a5..b31cb047 100644 --- a/src/generators/ast-js/index.mjs +++ b/src/generators/ast-js/index.mjs @@ -11,7 +11,7 @@ import createJsParser from '../../parsers/javascript.mjs'; * * @typedef {unknown} Input * - * @type {import('../types.d.ts').GeneratorMetadata>} + * @type {GeneratorMetadata>} */ export default { name: 'ast-js', diff --git a/src/generators/json-simple/index.mjs b/src/generators/json-simple/index.mjs index a551593c..979e2121 100644 --- a/src/generators/json-simple/index.mjs +++ b/src/generators/json-simple/index.mjs @@ -17,7 +17,7 @@ import { getRemark } from '../../utils/remark.mjs'; * * @typedef {Array} Input * - * @type {import('../types.d.ts').GeneratorMetadata} + * @type {GeneratorMetadata} */ export default { name: 'json-simple', diff --git a/src/generators/legacy-html-all/index.mjs b/src/generators/legacy-html-all/index.mjs index a2abdb2e..7004aa4f 100644 --- a/src/generators/legacy-html-all/index.mjs +++ b/src/generators/legacy-html-all/index.mjs @@ -29,7 +29,7 @@ import { getRemarkRehype } from '../../utils/remark.mjs'; * * @typedef {Array} Input * - * @type {import('../types.d.ts').GeneratorMetadata} + * @type {GeneratorMetadata} */ export default { name: 'legacy-html-all', diff --git a/src/generators/legacy-html/index.mjs b/src/generators/legacy-html/index.mjs index 33358c33..c7f836d7 100644 --- a/src/generators/legacy-html/index.mjs +++ b/src/generators/legacy-html/index.mjs @@ -31,7 +31,7 @@ import { getRemarkRehype } from '../../utils/remark.mjs'; * * @typedef {Array} Input * - * @type {import('../types.d.ts').GeneratorMetadata>} + * @type {GeneratorMetadata>} */ export default { name: 'legacy-html', diff --git a/src/generators/legacy-json-all/index.mjs b/src/generators/legacy-json-all/index.mjs index 9bb36310..b2e9cdf8 100644 --- a/src/generators/legacy-json-all/index.mjs +++ b/src/generators/legacy-json-all/index.mjs @@ -9,7 +9,7 @@ import { join } from 'node:path'; * * @typedef {Array} Input * - * @type {import('../types.d.ts').GeneratorMetadata} + * @type {GeneratorMetadata} */ export default { name: 'legacy-json-all', diff --git a/src/generators/legacy-json/index.mjs b/src/generators/legacy-json/index.mjs index 8cf70e88..add7ff87 100644 --- a/src/generators/legacy-json/index.mjs +++ b/src/generators/legacy-json/index.mjs @@ -16,7 +16,7 @@ import { createSectionBuilder } from './utils/buildSection.mjs'; * * @typedef {Array} Input * - * @type {import('../types.d.ts').GeneratorMetadata} + * @type {GeneratorMetadata} */ export default { name: 'legacy-json', diff --git a/src/generators/man-page/index.mjs b/src/generators/man-page/index.mjs index 8ee045aa..f5ec60ab 100644 --- a/src/generators/man-page/index.mjs +++ b/src/generators/man-page/index.mjs @@ -16,7 +16,7 @@ import { DOC_SLUG_ENVIRONMENT, DOC_SLUG_OPTIONS } from '../../constants.mjs'; * * @typedef {Array} Input * - * @type {import('../types.d.ts').GeneratorMetadata} + * @type {GeneratorMetadata} */ export default { name: 'man-page', diff --git a/src/generators/orama-db/index.mjs b/src/generators/orama-db/index.mjs index d6624f90..c2210c6b 100644 --- a/src/generators/orama-db/index.mjs +++ b/src/generators/orama-db/index.mjs @@ -12,7 +12,7 @@ import { createSectionBuilder } from '../legacy-json/utils/buildSection.mjs'; * * @typedef {Array} Input * - * @type {import('../types.d.ts').GeneratorMetadata} + * @type {GeneratorMetadata} */ export default { name: 'orama-db', diff --git a/src/generators/types.d.ts b/src/generators/types.d.ts index 110b5dc0..e5066a89 100644 --- a/src/generators/types.d.ts +++ b/src/generators/types.d.ts @@ -30,6 +30,9 @@ declare global { // A list of all Node.js major versions and their respective release information releases: Array; + + // Wether to use `git` commands while running the generator + useGit: boolean; } export interface GeneratorMetadata { From 946322c92797989682b0deee164c6fa3c6d0c98c Mon Sep 17 00:00:00 2001 From: Claudio Wunder Date: Sun, 23 Mar 2025 15:52:42 +0100 Subject: [PATCH 2/6] chore: updated readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7fc1d3b2..c3899fe7 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ Options: --disable-rule [rule...] Disable a specific linter rule (choices: "invalid-change-version", "missing-change-version", "missing-introduced-in", default: []) --lint-dry-run Run linter in dry-run mode (default: false) + --use-git Run git commands when needed (default: false) -r, --reporter [reporter] Specify the linter reporter (choices: "console", "github", default: "console") -h, --help display help for command ``` From cbe2257e5ea72f2fb55df0fdcd70f596cc25ea29 Mon Sep 17 00:00:00 2001 From: Claudio Wunder Date: Mon, 24 Mar 2025 10:19:53 +0100 Subject: [PATCH 3/6] chore: code review changes and changed approach --- bin/cli.mjs | 25 +++++--- package-lock.json | 63 +++++++++++++++++++ package.json | 1 + src/constants.mjs | 3 - src/generators/api-links/index.mjs | 42 +++---------- .../api-links/utils/getBaseGitHubUrl.mjs | 35 ----------- src/generators/types.d.ts | 7 ++- 7 files changed, 92 insertions(+), 84 deletions(-) delete mode 100644 src/generators/api-links/utils/getBaseGitHubUrl.mjs diff --git a/bin/cli.mjs b/bin/cli.mjs index 2c9b94ae..d7d08023 100755 --- a/bin/cli.mjs +++ b/bin/cli.mjs @@ -4,17 +4,18 @@ import { resolve } from 'node:path'; import { argv, exit } from 'node:process'; import { Command, Option } from 'commander'; +import parseGitUrl from 'git-url-parse'; import { coerce } from 'semver'; import { DOC_NODE_CHANGELOG_URL, DOC_NODE_VERSION } from '../src/constants.mjs'; import createGenerator from '../src/generators.mjs'; import generators from '../src/generators/index.mjs'; -import createMarkdownLoader from '../src/loaders/markdown.mjs'; -import createMarkdownParser from '../src/parsers/markdown.mjs'; -import createNodeReleases from '../src/releases.mjs'; import createLinter from '../src/linter/index.mjs'; import reporters from '../src/linter/reporters/index.mjs'; import rules from '../src/linter/rules/index.mjs'; +import createMarkdownLoader from '../src/loaders/markdown.mjs'; +import createMarkdownParser from '../src/parsers/markdown.mjs'; +import createNodeReleases from '../src/releases.mjs'; const availableGenerators = Object.keys(generators); @@ -68,7 +69,9 @@ program new Option('--lint-dry-run', 'Run linter in dry-run mode').default(false) ) .addOption( - new Option('--use-git', 'Run git commands when needed').default(false) + new Option('--git-ref', 'The current Node.js git ref').default( + 'https://github.com/nodejs/node/tree/HEAD' + ) ) .addOption( new Option('-r, --reporter [reporter]', 'Specify the linter reporter') @@ -104,7 +107,7 @@ const { changelog, disableRule, lintDryRun, - useGit, + gitRef, reporter, } = program.opts(); @@ -113,6 +116,8 @@ const linter = createLinter(lintDryRun, disableRule); const { loadFiles } = createMarkdownLoader(); const { parseApiDocs } = createMarkdownParser(); +const parsedGitRef = parseGitUrl(gitRef); + const apiDocFiles = await loadFiles(input, ignore); const parsedApiDocs = await parseApiDocs(apiDocFiles); @@ -125,21 +130,21 @@ const { getAllMajors } = createNodeReleases(changelog); // Runs the Linter on the parsed API docs linter.lintAll(parsedApiDocs); -if (target && output) { +if (target) { await runGenerators({ // A list of target modes for the API docs parser generators: target, // Resolved `input` to be used input: input, // Resolved `output` path to be used - output: resolve(output), + output: output && resolve(output), // Resolved SemVer of current Node.js version version: coerce(version), // A list of all Node.js major versions with LTS status releases: await getAllMajors(), - // If it should run git commands when needed - // (should only be used within a git repo) - useGit, + // The current Node.js's git ref to be used within API + // doc generation. This is used only to stamp some files. + gitRef: parsedGitRef, }); } diff --git a/package-lock.json b/package-lock.json index dab87828..969b9750 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "commander": "^13.1.0", "dedent": "^1.5.3", "estree-util-visit": "^2.0.0", + "git-url-parse": "^16.0.1", "github-slugger": "^2.0.0", "hast-util-to-string": "^3.0.1", "hastscript": "^9.0.1", @@ -554,6 +555,12 @@ "undici-types": "~6.20.0" } }, + "node_modules/@types/parse-path": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/parse-path/-/parse-path-7.0.3.tgz", + "integrity": "sha512-LriObC2+KYZD3FzCrgWGv/qufdUy4eXrxcLgQMfYXgPbLIecKIsVBaQgUPmxSSLcjmYbDTQbMgr6qr6l/eb7Bg==", + "license": "MIT" + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -1460,6 +1467,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/git-up": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-8.0.1.tgz", + "integrity": "sha512-2XFu1uNZMSjkyetaF+8rqn6P0XqpMq/C+2ycjI6YwrIKcszZ5/WR4UubxjN0lILOKqLkLaHDaCr2B6fP1cke6g==", + "license": "MIT", + "dependencies": { + "is-ssh": "^1.4.0", + "parse-url": "^9.2.0" + } + }, + "node_modules/git-url-parse": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-16.0.1.tgz", + "integrity": "sha512-mcD36GrhAzX5JVOsIO52qNpgRyFzYWRbU1VSRFCvJt1IJvqfvH427wWw/CFqkWvjVPtdG5VTx4MKUeC5GeFPDQ==", + "license": "MIT", + "dependencies": { + "git-up": "^8.0.0" + } + }, "node_modules/github-slugger": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", @@ -1739,6 +1765,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-ssh": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.1.tgz", + "integrity": "sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==", + "license": "MIT", + "dependencies": { + "protocols": "^2.0.1" + } + }, "node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -3183,6 +3218,28 @@ "node": ">= 18" } }, + "node_modules/parse-path": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.1.tgz", + "integrity": "sha512-6ReLMptznuuOEzLoGEa+I1oWRSj2Zna5jLWC+l6zlfAI4dbbSaIES29ThzuPkbhNahT65dWzfoZEO6cfJw2Ksg==", + "license": "MIT", + "dependencies": { + "protocols": "^2.0.0" + } + }, + "node_modules/parse-url": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-9.2.0.tgz", + "integrity": "sha512-bCgsFI+GeGWPAvAiUv63ZorMeif3/U0zaXABGJbOWt5OH2KCaPHF6S+0ok4aqM9RuIPGyZdx9tR9l13PsW4AYQ==", + "license": "MIT", + "dependencies": { + "@types/parse-path": "^7.0.0", + "parse-path": "^7.0.0" + }, + "engines": { + "node": ">=14.13.0" + } + }, "node_modules/pascal-case": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", @@ -3275,6 +3332,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/protocols": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.2.tgz", + "integrity": "sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", diff --git a/package.json b/package.json index 5524d571..2437813e 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "commander": "^13.1.0", "dedent": "^1.5.3", "estree-util-visit": "^2.0.0", + "git-url-parse": "^16.0.1", "github-slugger": "^2.0.0", "hast-util-to-string": "^3.0.1", "hastscript": "^9.0.1", diff --git a/src/constants.mjs b/src/constants.mjs index 0fb6a75e..473cf35b 100644 --- a/src/constants.mjs +++ b/src/constants.mjs @@ -7,9 +7,6 @@ export const DOC_NODE_VERSION = process.version; export const DOC_NODE_CHANGELOG_URL = 'https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md'; -// The base URL for the Node.js runtime GitHub repository -export const DOC_NODE_REPO_URL = 'https://github.com/nodejs/node'; - // This is the Node.js Base URL for viewing a file within GitHub UI export const DOC_NODE_BLOB_BASE_URL = 'https://github.com/nodejs/node/blob/HEAD/'; diff --git a/src/generators/api-links/index.mjs b/src/generators/api-links/index.mjs index 890bcc65..fe9f902b 100644 --- a/src/generators/api-links/index.mjs +++ b/src/generators/api-links/index.mjs @@ -1,15 +1,10 @@ 'use strict'; -import { basename, dirname, join } from 'node:path'; +import { basename, join } from 'node:path'; import { writeFile } from 'node:fs/promises'; -import { - getBaseGitHubUrl, - getCurrentGitHash, -} from './utils/getBaseGitHubUrl.mjs'; import { extractExports } from './utils/extractExports.mjs'; import { findDefinitions } from './utils/findDefinitions.mjs'; import { checkIndirectReferences } from './utils/checkIndirectReferences.mjs'; -import { DOC_NODE_REPO_URL } from '../../constants.mjs'; /** * This generator is responsible for mapping publicly accessible functions in @@ -41,58 +36,39 @@ export default { * @param {Input} input * @param {Partial} options */ - async generate(input, { output, useGit }) { + async generate(input, { output, gitRef }) { /** * @type Record */ const definitions = {}; - /** - * @type {string} - */ - let baseGithubLink; - - if (input.length > 0) { - const repositoryDirectory = dirname(input[0].path); - - const repository = useGit - ? getBaseGitHubUrl(repositoryDirectory) - : DOC_NODE_REPO_URL; - - const tag = useGit ? getCurrentGitHash(repositoryDirectory) : 'HEAD'; - - baseGithubLink = `${repository}/blob/${tag}`; - } + const gitBaseUrl = `https://${gitRef.host}/${gitRef.full_name}/blob/${gitRef.commit ?? 'HEAD'}`; input.forEach(program => { /** * Mapping of definitions to their line number + * * @type {Record} * @example { 'someclass.foo': 10 } */ const nameToLineNumberMap = {}; // `http.js` -> `http` - const programBasename = basename(program.path, '.js'); + const baseName = basename(program.path, '.js'); - const exports = extractExports( - program, - programBasename, - nameToLineNumberMap - ); + const exports = extractExports(program, baseName, nameToLineNumberMap); - findDefinitions(program, programBasename, nameToLineNumberMap, exports); + findDefinitions(program, baseName, nameToLineNumberMap, exports); checkIndirectReferences(program, exports, nameToLineNumberMap); - const githubLink = - `${baseGithubLink}/lib/${programBasename}.js`.replaceAll('\\', '/'); + const fullGitUrl = `${gitBaseUrl}/lib/${baseName}.js`; // Add the exports we found in this program to our output Object.keys(nameToLineNumberMap).forEach(key => { const lineNumber = nameToLineNumberMap[key]; - definitions[key] = `${githubLink}#L${lineNumber}`; + definitions[key] = `${fullGitUrl}#L${lineNumber}`; }); }); diff --git a/src/generators/api-links/utils/getBaseGitHubUrl.mjs b/src/generators/api-links/utils/getBaseGitHubUrl.mjs deleted file mode 100644 index 5bbe313b..00000000 --- a/src/generators/api-links/utils/getBaseGitHubUrl.mjs +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; - -import { execSync } from 'node:child_process'; - -/** - * @param {string} cwd - */ -export function getBaseGitHubUrl(cwd) { - let url = execSync('git remote get-url origin', { cwd }).toString().trim(); - - if (url.startsWith('git@')) { - // It's an ssh url, we need to transform it to be https - // Ex/ git@github.com:nodejs/node.git -> https://github.com/nodejs/node.git - let [, repository] = url.split(':'); - - url = `https://github.com/${repository}`; - } - - // https://github.com/nodejs/node.git -> https://github.com/nodejs/node - if (url.endsWith('.git')) { - url = url.substring(0, url.length - 4); - } - - return url; -} - -/** - * Grabs the current Git commit hash within a directory - * @param cwd - */ -export function getCurrentGitHash(cwd) { - const hash = execSync('git rev-parse HEAD', { cwd }).toString().trim(); - - return hash; -} diff --git a/src/generators/types.d.ts b/src/generators/types.d.ts index e5066a89..83c17b1f 100644 --- a/src/generators/types.d.ts +++ b/src/generators/types.d.ts @@ -1,6 +1,7 @@ +import type { GitUrl } from 'git-url-parse'; import type { SemVer } from 'semver'; -import type availableGenerators from './index.mjs'; import type { ApiDocReleaseEntry } from '../types'; +import type availableGenerators from './index.mjs'; declare global { // All available generators as an inferable type, to allow Generator interfaces @@ -31,8 +32,8 @@ declare global { // A list of all Node.js major versions and their respective release information releases: Array; - // Wether to use `git` commands while running the generator - useGit: boolean; + // The current Node.js's git ref to be used within the API doc generation + gitRef: GitUrl; } export interface GeneratorMetadata { From e5b049c4937371a572db9c863c29cfff6d740f7b Mon Sep 17 00:00:00 2001 From: Claudio Wunder Date: Mon, 24 Mar 2025 10:20:43 +0100 Subject: [PATCH 4/6] chore: updated readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c3899fe7..297dbd22 100644 --- a/README.md +++ b/README.md @@ -43,10 +43,10 @@ Options: "https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md") -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") - --disable-rule [rule...] Disable a specific linter rule (choices: "invalid-change-version", - "missing-change-version", "missing-introduced-in", default: []) + --disable-rule [rule...] Disable a specific linter rule (choices: "invalid-change-version", "missing-change-version", + "missing-introduced-in", default: []) --lint-dry-run Run linter in dry-run mode (default: false) - --use-git Run git commands when needed (default: false) + --git-ref The current Node.js git ref -r, --reporter [reporter] Specify the linter reporter (choices: "console", "github", default: "console") -h, --help display help for command ``` From e8ab82e2459f9919ccc302440e7480ac19940584 Mon Sep 17 00:00:00 2001 From: Claudio Wunder Date: Mon, 24 Mar 2025 10:37:46 +0100 Subject: [PATCH 5/6] chore: use snapshots --- .../api-links/test/fixtures.test.mjs | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/generators/api-links/test/fixtures.test.mjs b/src/generators/api-links/test/fixtures.test.mjs index 9f8ee53e..226a1bb3 100644 --- a/src/generators/api-links/test/fixtures.test.mjs +++ b/src/generators/api-links/test/fixtures.test.mjs @@ -19,7 +19,34 @@ describe('api links', () => { input: [sourceFile], }); - const actualOutput = await apiLinks.generate(astJsResult, {}); + const actualOutput = await apiLinks.generate(astJsResult, { + gitRef: { + protocols: ['https'], + protocol: 'https', + port: '', + resource: 'github.com', + host: 'github.com', + user: '', + password: '', + pathname: '/nodejs/node/tree/HEAD', + hash: '', + search: '', + href: 'https://github.com/nodejs/node/tree/HEAD', + query: {}, + parse_failed: false, + token: '', + source: 'github.com', + git_suffix: false, + name: 'node', + owner: 'nodejs', + commit: 'HEAD', + ref: 'HEAD', + filepathtype: 'tree', + filepath: '', + organization: 'nodejs', + full_name: 'nodejs/node', + }, + }); for (const [k, v] of Object.entries(actualOutput)) { actualOutput[k] = v.replace(/.*(?=lib\/)/, ''); From 2d61ea1fed0d684109bc2b96edf15d504d606c3a Mon Sep 17 00:00:00 2001 From: Claudio Wunder Date: Mon, 24 Mar 2025 13:12:50 +0100 Subject: [PATCH 6/6] chore: code review --- README.md | 6 +- bin/cli.mjs | 11 ++-- package-lock.json | 63 ------------------- package.json | 1 - src/generators/api-links/index.mjs | 4 +- .../api-links/test/fixtures.test.mjs | 27 +------- src/generators/types.d.ts | 8 ++- 7 files changed, 14 insertions(+), 106 deletions(-) diff --git a/README.md b/README.md index 297dbd22..68b822f1 100644 --- a/README.md +++ b/README.md @@ -43,10 +43,10 @@ Options: "https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md") -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") - --disable-rule [rule...] Disable a specific linter rule (choices: "invalid-change-version", "missing-change-version", - "missing-introduced-in", default: []) + --disable-rule [rule...] Disable a specific linter rule (choices: "invalid-change-version", + "missing-change-version", "missing-introduced-in", default: []) --lint-dry-run Run linter in dry-run mode (default: false) - --git-ref The current Node.js git ref + --git-ref A git ref/commit URL pointing to Node.js -r, --reporter [reporter] Specify the linter reporter (choices: "console", "github", default: "console") -h, --help display help for command ``` diff --git a/bin/cli.mjs b/bin/cli.mjs index d7d08023..f911bf97 100755 --- a/bin/cli.mjs +++ b/bin/cli.mjs @@ -4,7 +4,6 @@ import { resolve } from 'node:path'; import { argv, exit } from 'node:process'; import { Command, Option } from 'commander'; -import parseGitUrl from 'git-url-parse'; import { coerce } from 'semver'; import { DOC_NODE_CHANGELOG_URL, DOC_NODE_VERSION } from '../src/constants.mjs'; @@ -69,7 +68,7 @@ program new Option('--lint-dry-run', 'Run linter in dry-run mode').default(false) ) .addOption( - new Option('--git-ref', 'The current Node.js git ref').default( + new Option('--git-ref', 'A git ref/commit URL pointing to Node.js').default( 'https://github.com/nodejs/node/tree/HEAD' ) ) @@ -116,8 +115,6 @@ const linter = createLinter(lintDryRun, disableRule); const { loadFiles } = createMarkdownLoader(); const { parseApiDocs } = createMarkdownParser(); -const parsedGitRef = parseGitUrl(gitRef); - const apiDocFiles = await loadFiles(input, ignore); const parsedApiDocs = await parseApiDocs(apiDocFiles); @@ -142,9 +139,9 @@ if (target) { version: coerce(version), // A list of all Node.js major versions with LTS status releases: await getAllMajors(), - // The current Node.js's git ref to be used within API - // doc generation. This is used only to stamp some files. - gitRef: parsedGitRef, + // An URL containing a git ref URL pointing to the commit or ref that was used + // to generate the API docs. This is used to link to the source code of the + gitRef, }); } diff --git a/package-lock.json b/package-lock.json index 969b9750..dab87828 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ "commander": "^13.1.0", "dedent": "^1.5.3", "estree-util-visit": "^2.0.0", - "git-url-parse": "^16.0.1", "github-slugger": "^2.0.0", "hast-util-to-string": "^3.0.1", "hastscript": "^9.0.1", @@ -555,12 +554,6 @@ "undici-types": "~6.20.0" } }, - "node_modules/@types/parse-path": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/parse-path/-/parse-path-7.0.3.tgz", - "integrity": "sha512-LriObC2+KYZD3FzCrgWGv/qufdUy4eXrxcLgQMfYXgPbLIecKIsVBaQgUPmxSSLcjmYbDTQbMgr6qr6l/eb7Bg==", - "license": "MIT" - }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -1467,25 +1460,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/git-up": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-8.0.1.tgz", - "integrity": "sha512-2XFu1uNZMSjkyetaF+8rqn6P0XqpMq/C+2ycjI6YwrIKcszZ5/WR4UubxjN0lILOKqLkLaHDaCr2B6fP1cke6g==", - "license": "MIT", - "dependencies": { - "is-ssh": "^1.4.0", - "parse-url": "^9.2.0" - } - }, - "node_modules/git-url-parse": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-16.0.1.tgz", - "integrity": "sha512-mcD36GrhAzX5JVOsIO52qNpgRyFzYWRbU1VSRFCvJt1IJvqfvH427wWw/CFqkWvjVPtdG5VTx4MKUeC5GeFPDQ==", - "license": "MIT", - "dependencies": { - "git-up": "^8.0.0" - } - }, "node_modules/github-slugger": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", @@ -1765,15 +1739,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-ssh": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.1.tgz", - "integrity": "sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==", - "license": "MIT", - "dependencies": { - "protocols": "^2.0.1" - } - }, "node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -3218,28 +3183,6 @@ "node": ">= 18" } }, - "node_modules/parse-path": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.1.tgz", - "integrity": "sha512-6ReLMptznuuOEzLoGEa+I1oWRSj2Zna5jLWC+l6zlfAI4dbbSaIES29ThzuPkbhNahT65dWzfoZEO6cfJw2Ksg==", - "license": "MIT", - "dependencies": { - "protocols": "^2.0.0" - } - }, - "node_modules/parse-url": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-9.2.0.tgz", - "integrity": "sha512-bCgsFI+GeGWPAvAiUv63ZorMeif3/U0zaXABGJbOWt5OH2KCaPHF6S+0ok4aqM9RuIPGyZdx9tR9l13PsW4AYQ==", - "license": "MIT", - "dependencies": { - "@types/parse-path": "^7.0.0", - "parse-path": "^7.0.0" - }, - "engines": { - "node": ">=14.13.0" - } - }, "node_modules/pascal-case": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", @@ -3332,12 +3275,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/protocols": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.2.tgz", - "integrity": "sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==", - "license": "MIT" - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", diff --git a/package.json b/package.json index 2437813e..5524d571 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,6 @@ "commander": "^13.1.0", "dedent": "^1.5.3", "estree-util-visit": "^2.0.0", - "git-url-parse": "^16.0.1", "github-slugger": "^2.0.0", "hast-util-to-string": "^3.0.1", "hastscript": "^9.0.1", diff --git a/src/generators/api-links/index.mjs b/src/generators/api-links/index.mjs index fe9f902b..93441450 100644 --- a/src/generators/api-links/index.mjs +++ b/src/generators/api-links/index.mjs @@ -42,8 +42,6 @@ export default { */ const definitions = {}; - const gitBaseUrl = `https://${gitRef.host}/${gitRef.full_name}/blob/${gitRef.commit ?? 'HEAD'}`; - input.forEach(program => { /** * Mapping of definitions to their line number @@ -62,7 +60,7 @@ export default { checkIndirectReferences(program, exports, nameToLineNumberMap); - const fullGitUrl = `${gitBaseUrl}/lib/${baseName}.js`; + const fullGitUrl = `${gitRef}/lib/${baseName}.js`; // Add the exports we found in this program to our output Object.keys(nameToLineNumberMap).forEach(key => { diff --git a/src/generators/api-links/test/fixtures.test.mjs b/src/generators/api-links/test/fixtures.test.mjs index 226a1bb3..028ea5a9 100644 --- a/src/generators/api-links/test/fixtures.test.mjs +++ b/src/generators/api-links/test/fixtures.test.mjs @@ -20,32 +20,7 @@ describe('api links', () => { }); const actualOutput = await apiLinks.generate(astJsResult, { - gitRef: { - protocols: ['https'], - protocol: 'https', - port: '', - resource: 'github.com', - host: 'github.com', - user: '', - password: '', - pathname: '/nodejs/node/tree/HEAD', - hash: '', - search: '', - href: 'https://github.com/nodejs/node/tree/HEAD', - query: {}, - parse_failed: false, - token: '', - source: 'github.com', - git_suffix: false, - name: 'node', - owner: 'nodejs', - commit: 'HEAD', - ref: 'HEAD', - filepathtype: 'tree', - filepath: '', - organization: 'nodejs', - full_name: 'nodejs/node', - }, + gitRef: 'https://github.com/nodejs/node/tree/HEAD', }); for (const [k, v] of Object.entries(actualOutput)) { diff --git a/src/generators/types.d.ts b/src/generators/types.d.ts index 83c17b1f..a3eb07b6 100644 --- a/src/generators/types.d.ts +++ b/src/generators/types.d.ts @@ -1,4 +1,3 @@ -import type { GitUrl } from 'git-url-parse'; import type { SemVer } from 'semver'; import type { ApiDocReleaseEntry } from '../types'; import type availableGenerators from './index.mjs'; @@ -32,8 +31,11 @@ declare global { // A list of all Node.js major versions and their respective release information releases: Array; - // The current Node.js's git ref to be used within the API doc generation - gitRef: GitUrl; + // An URL containing a git ref URL pointing to the commit or ref that was used + // to generate the API docs. This is used to link to the source code of the + // i.e. https://github.com/nodejs/node/tree/2cb1d07e0f6d9456438016bab7db4688ab354fd2 + // i.e. https://gitlab.com/someone/node/tree/HEAD + gitRef: string; } export interface GeneratorMetadata {