From 4fcaf793f6ab036ef91d2ce3824c4cb8994768e8 Mon Sep 17 00:00:00 2001 From: Jeff Williams Date: Fri, 12 Jan 2024 19:26:16 -0800 Subject: [PATCH] feat(jsdoc-core): move `parseSourceFiles()` to public API --- package-lock.json | 9 +++-- packages/jsdoc-ast/lib/ast-node.js | 3 +- packages/jsdoc-core/lib/api.js | 63 ++++++++++++++++++++++++++++- packages/jsdoc-core/package.json | 3 ++ packages/jsdoc/cli.js | 65 +----------------------------- 5 files changed, 75 insertions(+), 68 deletions(-) diff --git a/package-lock.json b/package-lock.json index f9c8690c..583c2f21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4532,9 +4532,9 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", + "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", "dev": true, "funding": [ { @@ -12522,8 +12522,11 @@ "version": "0.5.7", "license": "Apache-2.0", "dependencies": { + "@jsdoc/doclet": "^0.2.10", + "@jsdoc/parse": "^0.3.10", "cosmiconfig": "^9.0.0", "escape-string-regexp": "^5.0.0", + "fast-glob": "^3.3.2", "lodash": "^4.17.21", "strip-bom": "^5.0.0", "strip-json-comments": "^5.0.1" diff --git a/packages/jsdoc-ast/lib/ast-node.js b/packages/jsdoc-ast/lib/ast-node.js index 4eff4a5a..e9bde212 100644 --- a/packages/jsdoc-ast/lib/ast-node.js +++ b/packages/jsdoc-ast/lib/ast-node.js @@ -15,7 +15,8 @@ */ // TODO: docs -import { name } from '@jsdoc/core'; +// For unknown reasons, `import { name } from '@jsdoc/core'` causes a `ReferenceError` here. +import * as name from '@jsdoc/core/lib/name.js'; import { cast } from '@jsdoc/util'; import moduleTypes from 'ast-module-types'; diff --git a/packages/jsdoc-core/lib/api.js b/packages/jsdoc-core/lib/api.js index c888b445..08daf0b2 100644 --- a/packages/jsdoc-core/lib/api.js +++ b/packages/jsdoc-core/lib/api.js @@ -15,10 +15,16 @@ */ import EventEmitter from 'node:events'; +import { readFile } from 'node:fs/promises'; import path from 'node:path'; -import { Env } from '@jsdoc/core'; +import { augment, Package, resolveBorrows } from '@jsdoc/doclet'; +import { createParser, handlers } from '@jsdoc/parse'; import glob from 'fast-glob'; +import stripJsonComments from 'strip-json-comments'; + +import Env from './env.js'; +import { installPlugins } from './plugins.js'; const DEFAULT_TEMPLATE = '@jsdoc/template-legacy'; @@ -63,6 +69,18 @@ export default class Api { return sourceFiles; } + async #createParser() { + const parser = createParser(this.env); + + if (this.env.config.plugins) { + await installPlugins(this.env.config.plugins, parser, this.env); + } + + handlers.attachTo(parser); + + return parser; + } + /** * Finds the absolute paths to source files that JSDoc should parse, based on an array of glob * patterns, and adds the list of paths to the JSDoc environment. @@ -151,4 +169,47 @@ export default class Api { return Promise.reject(new Error(message)); } } + + // TODO: docs; mention that filepaths overrides env.sourceFiles + async parseSourceFiles(filepaths) { + const { log, options } = this.env; + const parser = await this.#createParser(); + let packageData = ''; + let packageDocs; + let docletStore; + + docletStore = parser.parse(filepaths ?? this.env.sourceFiles, options.encoding); + + if (options.package) { + packageData = await this.#readPackageJson(options.package); + } + packageDocs = new Package(packageData, this.env); + packageDocs.files = this.env.sourceFiles || []; + docletStore.add(packageDocs); + + log.debug('Adding inherited symbols, mixins, and interface implementations...'); + augment.augmentAll(docletStore); + log.debug('Adding borrowed doclets...'); + resolveBorrows(docletStore); + log.debug('Post-processing complete.'); + if (parser.listenerCount('processingComplete')) { + parser.fireProcessingComplete(Array.from(docletStore.doclets)); + } + + return docletStore; + } + + async #readPackageJson(filepath) { + let data; + + try { + data = await readFile(filepath, 'utf8'); + + return stripJsonComments(data); + } catch (e) { + this.env.log.error(`Unable to read the package file ${filepath}`); + + return null; + } + } } diff --git a/packages/jsdoc-core/package.json b/packages/jsdoc-core/package.json index fef72bdc..c66364a8 100644 --- a/packages/jsdoc-core/package.json +++ b/packages/jsdoc-core/package.json @@ -31,8 +31,11 @@ } }, "dependencies": { + "@jsdoc/doclet": "^0.2.10", + "@jsdoc/parse": "^0.3.10", "cosmiconfig": "^9.0.0", "escape-string-regexp": "^5.0.0", + "fast-glob": "^3.3.2", "lodash": "^4.17.21", "strip-bom": "^5.0.0", "strip-json-comments": "^5.0.1" diff --git a/packages/jsdoc/cli.js b/packages/jsdoc/cli.js index 80efafec..df58fc5c 100644 --- a/packages/jsdoc/cli.js +++ b/packages/jsdoc/cli.js @@ -16,16 +16,11 @@ /* eslint-disable no-process-exit */ import fs from 'node:fs'; -import { readFile } from 'node:fs/promises'; import { fileURLToPath } from 'node:url'; import Engine from '@jsdoc/cli'; -import { plugins } from '@jsdoc/core'; -import { augment, Package, resolveBorrows } from '@jsdoc/doclet'; -import { createParser, handlers } from '@jsdoc/parse'; import { Dictionary } from '@jsdoc/tag'; import stripBom from 'strip-bom'; -import stripJsonComments from 'strip-json-comments'; import test from './test/index.js'; @@ -36,7 +31,7 @@ import test from './test/index.js'; */ export default (() => { const props = { - docs: [], + docs: null, packageJson: null, shouldExitWithError: false, shouldPrintHelp: false, @@ -145,8 +140,7 @@ export default (() => { return Promise.resolve(0); } else { - await cli.createParser(); - await cli.parseFiles(); + props.docs = await api.parseSourceFiles(); return cli.processParseResults().then(() => { env.run.finish = new Date(); @@ -156,61 +150,6 @@ export default (() => { } }; - async function readPackageJson(filepath) { - let data; - - try { - data = await readFile(filepath, 'utf8'); - - return stripJsonComments(data); - } catch (e) { - log.error(`Unable to read the package file ${filepath}`); - - return null; - } - } - - cli.createParser = async () => { - const { config } = env; - - props.parser = createParser(env); - - if (config.plugins) { - await plugins.installPlugins(config.plugins, props.parser, env); - } - - handlers.attachTo(props.parser); - - return cli; - }; - - cli.parseFiles = async () => { - const { options } = env; - let packageData = ''; - let packageDocs; - let docletStore; - - docletStore = props.docs = props.parser.parse(env.sourceFiles, options.encoding); - - if (props.packageJson) { - packageData = await readPackageJson(props.packageJson); - } - packageDocs = new Package(packageData, env); - packageDocs.files = env.sourceFiles || []; - docletStore.add(packageDocs); - - log.debug('Adding inherited symbols, mixins, and interface implementations...'); - augment.augmentAll(docletStore); - log.debug('Adding borrowed doclets...'); - resolveBorrows(docletStore); - log.debug('Post-processing complete.'); - if (props.parser.listenerCount('processingComplete')) { - props.parser.fireProcessingComplete(Array.from(docletStore.doclets)); - } - - return cli; - }; - cli.processParseResults = () => { if (env.options.explain) { cli.dumpParseResults();