From ebd1698b3194412a61897fdd722c6b8091b87725 Mon Sep 17 00:00:00 2001 From: Romain Lenzotti Date: Tue, 29 Oct 2024 07:45:30 +0100 Subject: [PATCH] fix: add id to generate file name BREAKING CHANGE: file are now named by its id (symbolType + symbolName) --- .../code-highlight/code-highlight.js | 2 +- .../code-highlight/highlight.js} | 2 +- .../code-highlight/highlight.spec.js} | 2 +- .../components/symbol-params/symbol-params.js | 2 +- packages/ts-doc/package.json | 3 +- packages/ts-doc/src/models/DocSymbol.js | 13 +++---- packages/ts-doc/src/models/DocSymbol.spec.js | 5 +-- packages/ts-doc/src/parsers/DocParser.js | 35 +++++++++---------- packages/ts-doc/src/scan/scan.js | 27 ++++++++------ packages/ts-doc/src/tasks/build-api.js | 16 +++++---- packages/ts-doc/src/utils/dashCase.js | 5 +++ packages/ts-doc/src/utils/dashCase.spec.js | 13 +++++++ packages/ts-doc/src/write/write.js | 30 ++++++++++++---- .../test/snapshots/ControllerProvider.md | 12 +++---- packages/ts-doc/test/snapshots/Ignore.md | 4 +-- .../ts-doc/test/snapshots/RequestContext.md | 2 +- .../snapshots/ReturnsChainedDecorators.md | 16 ++++----- yarn.lock | 5 +++ 18 files changed, 123 insertions(+), 71 deletions(-) rename packages/ts-doc/{src/highlight/index.js => components/code-highlight/highlight.js} (97%) rename packages/ts-doc/{src/highlight/index.spec.js => components/code-highlight/highlight.spec.js} (95%) create mode 100644 packages/ts-doc/src/utils/dashCase.js create mode 100644 packages/ts-doc/src/utils/dashCase.spec.js diff --git a/packages/ts-doc/components/code-highlight/code-highlight.js b/packages/ts-doc/components/code-highlight/code-highlight.js index 17000f0..713d71a 100644 --- a/packages/ts-doc/components/code-highlight/code-highlight.js +++ b/packages/ts-doc/components/code-highlight/code-highlight.js @@ -1,5 +1,5 @@ const {stripsComments} = require("../../src/utils/strips"); -const {highlight} = require("../../src/highlight"); +const {highlight} = require("./highlight"); module.exports = { name: "codeHighlight", diff --git a/packages/ts-doc/src/highlight/index.js b/packages/ts-doc/components/code-highlight/highlight.js similarity index 97% rename from packages/ts-doc/src/highlight/index.js rename to packages/ts-doc/components/code-highlight/highlight.js index 43d75ff..ab64f40 100644 --- a/packages/ts-doc/src/highlight/index.js +++ b/packages/ts-doc/components/code-highlight/highlight.js @@ -1,6 +1,6 @@ "use strict"; -const {context} = require("../context"); +const {context} = require("../../src/context"); const KEYWORDS = /(\benum\b|\bstatic\b|\bclass\b|\binterface\b|\bprivate\b|\bpublic\b|\bconst\b|\blet\b|\bprotected\b|\bimplements\b|\bconstructor\b|\breadonly\b|\babstract\b|\bimport\b|\bexport\b|\bas\b|\bfrom\b|\bextends\b)/g; const TYPES = /(\bany\b|\bstring\b|\bboolean\b|\bnumber\b|\bDate\b|\bvoid\b)/g; diff --git a/packages/ts-doc/src/highlight/index.spec.js b/packages/ts-doc/components/code-highlight/highlight.spec.js similarity index 95% rename from packages/ts-doc/src/highlight/index.spec.js rename to packages/ts-doc/components/code-highlight/highlight.spec.js index b954325..fae2f7d 100644 --- a/packages/ts-doc/src/highlight/index.spec.js +++ b/packages/ts-doc/components/code-highlight/highlight.spec.js @@ -1,5 +1,5 @@ const {expect} = require("chai"); -const {highlight} = require("./index"); +const {highlight} = require("./highlight"); describe("Highlight", () => { it("should highlight content", () => { diff --git a/packages/ts-doc/components/symbol-params/symbol-params.js b/packages/ts-doc/components/symbol-params/symbol-params.js index c7d0d60..79a5f9d 100644 --- a/packages/ts-doc/components/symbol-params/symbol-params.js +++ b/packages/ts-doc/components/symbol-params/symbol-params.js @@ -1,4 +1,4 @@ -const {bindSymbols} = require("../../src/highlight"); +const {bindSymbols} = require("../code-highlight/highlight"); module.exports = { name: "symbolParams", trim: false, diff --git a/packages/ts-doc/package.json b/packages/ts-doc/package.json index 74ecfcc..d7e0280 100644 --- a/packages/ts-doc/package.json +++ b/packages/ts-doc/package.json @@ -34,10 +34,11 @@ "fs-extra": "8.1.0", "glob": "7.1.6", "globby": "8.0.2", + "lodash": "^4.17.21", "listr": "^0.14.3", "normalize-path": "3.0.0", "read-pkg-up": "7.0.0" }, "devDependencies": {}, "peerDependencies": {} -} \ No newline at end of file +} diff --git a/packages/ts-doc/src/models/DocSymbol.js b/packages/ts-doc/src/models/DocSymbol.js index 7a87878..ea41c6e 100644 --- a/packages/ts-doc/src/models/DocSymbol.js +++ b/packages/ts-doc/src/models/DocSymbol.js @@ -2,6 +2,7 @@ const path = require("path"); const normalizePath = require("normalize-path"); const {context} = require("../context"); const {descriptionParser} = require("../parsers/description-parser.js"); +const {dashCase} = require("../utils/dashCase"); const _filterParams = (labels) => { return labels @@ -45,6 +46,10 @@ class DocSymbol { this.labels = []; } + get id() { + return dashCase([this.symbolType, this.symbolName].filter(Boolean).join("-")); + } + get path() { return this.docFile.path; } @@ -112,11 +117,7 @@ class DocSymbol { * @returns {*} */ get url() { - const url = [ - context.baseUrl, - normalizePath(path.dirname(this.docFile.relativePackagePath)), //.replace(/\.ts$/, '') - `${this.symbolName}.html` - ].join("/"); + const url = [context.baseUrl, normalizePath(path.dirname(this.docFile.relativePackagePath)), `${this.id}.html`].join("/"); return context.outputResolver(url); } @@ -126,7 +127,7 @@ class DocSymbol { * @returns {*} */ get outputPath() { - const file = normalizePath(path.join(context.outputDir, path.dirname(this.docFile.relativePackagePath), `${this.symbolName}.md`)); + const file = normalizePath(path.join(context.outputDir, path.dirname(this.docFile.relativePackagePath), `${this.id}.md`)); return context.outputResolver(file); } diff --git a/packages/ts-doc/src/models/DocSymbol.spec.js b/packages/ts-doc/src/models/DocSymbol.spec.js index e520f20..0f016a8 100644 --- a/packages/ts-doc/src/models/DocSymbol.spec.js +++ b/packages/ts-doc/src/models/DocSymbol.spec.js @@ -26,6 +26,7 @@ describe("DocSymbol", () => { this.docSymbol = new DocSymbol(); this.docSymbol.symbolName = "SymbolName"; + this.docSymbol.symbolType = "Const"; await this.docSymbol.setDocFile({ file: path.join(process.cwd(), "/packages/common/di/lib/file.d.ts"), path: path.join(process.cwd(), "/packages/common/di/lib/file.ts"), @@ -88,10 +89,10 @@ describe("DocSymbol", () => { }); it("should return the url", () => { - expect(this.docSymbol.url).to.eq("/api/common/di/SymbolName.html"); + expect(this.docSymbol.url).to.eq("/api/common/di/const-symbol-name.html"); }); it("should return the outputPath", () => { - expect(this.docSymbol.outputPath).to.eq(path.join(process.cwd(), "/docs/api/common/di/SymbolName.md")); + expect(this.docSymbol.outputPath).to.eq(path.join(process.cwd(), "/docs/api/common/di/const-symbol-name.md")); }); }); diff --git a/packages/ts-doc/src/parsers/DocParser.js b/packages/ts-doc/src/parsers/DocParser.js index ac7ee7a..82d466f 100644 --- a/packages/ts-doc/src/parsers/DocParser.js +++ b/packages/ts-doc/src/parsers/DocParser.js @@ -37,32 +37,31 @@ class DocParser { static async parse(docFile) { const {symbols} = new DocParser(docFile.contents).parse(); - for (const [, symbol] of symbols) { - try { - await symbol.setDocFile(docFile); + const promises = await Promise.all( + [...symbols.values()].map(async (symbol) => { + try { + await symbol.setDocFile(docFile); + + return symbol; + } catch (er) { + logger.error("Fail to process symbol", {symbol, error: er}); + } + }) + ); + + const parsedSymbols = await Promise.all(promises); + + for (const symbol of parsedSymbols) { + if (symbol) { const newSymbol = context.symbols.push(symbol); + docFile.symbols.set(newSymbol.symbolName, newSymbol); - } catch (er) { - logger.error("Fail to process symbol", {symbol, error: er}); } } return docFile.symbols; } - // /** - // * - // * @param str - // * @returns {string} - // */ - // overview (str = '') { - // return stripsTags(stripsComments(str)) - // .split('\n') - // .filter(o => !!o.trim()) - // .join('\n') - // .trim() - // } - /** * */ diff --git a/packages/ts-doc/src/scan/scan.js b/packages/ts-doc/src/scan/scan.js index 8649ac8..c30f212 100644 --- a/packages/ts-doc/src/scan/scan.js +++ b/packages/ts-doc/src/scan/scan.js @@ -58,17 +58,24 @@ module.exports = { let symbolsSize = 0; const files = await globby(patterns); - for (const file of files) { - try { - const symbols = await DocParser.parse(new DocFile(file)); + // paginate files by 5 + for (let i = 0; i < files.length; i += 5) { + const filesChunk = files.slice(i, i + 5); - symbols.forEach((symbol) => { - context.logger(`Scanned symbol '${chalk.cyan(symbol.symbolName)}'`); - symbolsSize++; - }); - } catch (er) { - context.logger.error(chalk.red(er), er.stack); - } + await Promise.all( + filesChunk.map(async (file) => { + try { + const symbols = await DocParser.parse(new DocFile(file)); + + symbols.forEach((symbol) => { + context.logger(`Scanned symbol '${chalk.cyan(symbol.symbolName)}'`); + symbolsSize++; + }); + } catch (er) { + context.logger.error(chalk.red(er), er.stack); + } + }) + ); } context.logger(`${chalk.green(symbolsSize)} scanned symbols`); diff --git a/packages/ts-doc/src/tasks/build-api.js b/packages/ts-doc/src/tasks/build-api.js index 18ac3b3..a86ea1a 100644 --- a/packages/ts-doc/src/tasks/build-api.js +++ b/packages/ts-doc/src/tasks/build-api.js @@ -15,13 +15,17 @@ module.exports = { .then(() => context.readPkg()) .then(() => scanComponents(context.templatesDir)) .then(() => scanFiles(context.scanPatterns)) - .then(() => { + .then(async () => { let symbols = 0; - context.symbols.forEach((symbol) => { - const content = context.components.page(symbol); - symbols++; - return writeSymbol(symbol, content); - }); + + await Promise.all( + context.symbols.toArray().map((symbol) => { + const content = context.components.page(symbol); + symbols++; + return writeSymbol(symbol, content); + }) + ); + logger(chalk.green(symbols) + " symbols write"); }) .then(() => writeJson()) diff --git a/packages/ts-doc/src/utils/dashCase.js b/packages/ts-doc/src/utils/dashCase.js new file mode 100644 index 0000000..97677b6 --- /dev/null +++ b/packages/ts-doc/src/utils/dashCase.js @@ -0,0 +1,5 @@ +const snakeCase = require("lodash/snakeCase"); + +module.exports.dashCase = function dashCase(str) { + return snakeCase(str).replace(/_/g, "-"); +}; diff --git a/packages/ts-doc/src/utils/dashCase.spec.js b/packages/ts-doc/src/utils/dashCase.spec.js new file mode 100644 index 0000000..0d9dcb2 --- /dev/null +++ b/packages/ts-doc/src/utils/dashCase.spec.js @@ -0,0 +1,13 @@ +const {expect} = require("chai"); +const {dashCase} = require("./dashCase"); + +describe("dashCase", () => { + it("should convert camelCase to dash-case", () => { + expect(dashCase("camelCase")).to.equal("camel-case"); + expect(dashCase("camelCase-test")).to.equal("camel-case-test"); + expect(dashCase("")).to.equal(""); + expect(dashCase("XMLHttpRequest")).to.equal("xml-http-request"); + expect(dashCase("__foo_bar__")).to.equal("foo-bar"); + expect(dashCase(" spaced words ")).to.equal("spaced-words"); + }); +}); diff --git a/packages/ts-doc/src/write/write.js b/packages/ts-doc/src/write/write.js index f194622..d212685 100644 --- a/packages/ts-doc/src/write/write.js +++ b/packages/ts-doc/src/write/write.js @@ -5,24 +5,39 @@ const logger = require("fancy-log"); const chalk = require("chalk"); const {context, symbolTypes, symbolStatus} = require("../context"); +let cache = new Set(); + module.exports = { /** * * @param symbol * @param content */ - writeSymbol(symbol, content) { + async writeSymbol(symbol, content) { if (symbol.symbolName.trim() === "") { - console.error("Symbol empty =>", symbol); return; } + // prevent duplicate write + if (cache.has(symbol.outputPath)) { + return; + } + + cache.add(symbol.outputPath); + try { - fsExtra.mkdirsSync(path.dirname(symbol.outputPath), {}); - } catch (er) {} - fsExtra.writeFileSync(symbol.outputPath, content.trim(), { - flag: "w+" + await fsExtra.mkdirs(path.dirname(symbol.outputPath), {}); + } catch (error) { + if (error.code !== "EEXIST") { + logger.warn(`Failed to create directory for ${symbol.outputPath}: ${error.message}`); + throw error; + } + } + + await fsExtra.writeFile(symbol.outputPath, content.trim(), { + flag: "w" }); + logger(`Write '${chalk.cyan(symbol.outputPath.replace(context.rootDir, ""))}'`); }, @@ -35,7 +50,7 @@ module.exports = { const {version, scope} = context; const modules = context.symbols.toArray().reduce((acc, symbol) => { - const {symbolName, module, exported, symbolType, symbolLabel, symbolCode, labels} = symbol; + const {symbolName, module, exported, symbolType, symbolLabel, symbolCode, labels, id} = symbol; const key = module.moduleName; acc[key] = acc[key] || {symbols: [], name: key}; @@ -47,6 +62,7 @@ module.exports = { } acc[key].symbols.push({ + id, path: symbol.url.replace(".html", ""), symbolName, module: module.moduleName, diff --git a/packages/ts-doc/test/snapshots/ControllerProvider.md b/packages/ts-doc/test/snapshots/ControllerProvider.md index 99f72af..9ce2737 100644 --- a/packages/ts-doc/test/snapshots/ControllerProvider.md +++ b/packages/ts-doc/test/snapshots/ControllerProvider.md @@ -15,7 +15,7 @@ meta:
class ControllerProvider<T = any> extends Provider<T> {
-    readonly entity: JsonEntityStore;
+    readonly entity: JsonEntityStore;
     
     
     
@@ -25,9 +25,9 @@ meta:
     
     get endpoints(): EndpointMetadata[];
     
-    get children(): IChildrenController[];
+    get children(): IChildrenController[];
     
-    set children(children: IChildrenController[]);
+    set children(children: IChildrenController[]);
     
     get routerOptions(): any;
     
@@ -82,7 +82,7 @@ Controllers that depend to this controller.
 ::: v-pre
 
 
-
readonly entity: JsonEntityStore;
+
readonly entity: JsonEntityStore;
@@ -150,7 +150,7 @@ Controllers that depend to this controller. ::: v-pre
-
get children(): IChildrenController[];
+
get children(): IChildrenController[];
@@ -167,7 +167,7 @@ Controllers that depend to this controller. ::: v-pre
-
set children(children: IChildrenController[]);
+
set children(children: IChildrenController[]);
diff --git a/packages/ts-doc/test/snapshots/Ignore.md b/packages/ts-doc/test/snapshots/Ignore.md index d272358..72c18fd 100644 --- a/packages/ts-doc/test/snapshots/Ignore.md +++ b/packages/ts-doc/test/snapshots/Ignore.md @@ -14,7 +14,7 @@ meta: ## Overview -
function Ignore(cb?: boolean | IgnoreCallback): (...args: any[]) => any;
+
function Ignore(cb?: boolean | IgnoreCallback): (...args: any[]) => any;
@@ -22,7 +22,7 @@ meta: Param | Type | Description ---|---|--- - cb | `boolean` "|" IgnoreCallback | Optional. Callback to know if the property must be ignored + cb | `boolean` "|" IgnoreCallback | Optional. Callback to know if the property must be ignored diff --git a/packages/ts-doc/test/snapshots/RequestContext.md b/packages/ts-doc/test/snapshots/RequestContext.md index ff08751..b4d94ce 100644 --- a/packages/ts-doc/test/snapshots/RequestContext.md +++ b/packages/ts-doc/test/snapshots/RequestContext.md @@ -33,7 +33,7 @@ meta: request: PlatformRequest; injector: InjectorService; - constructor({ id, injector, logger, response, request, endpoint, ...options }: RequestContextOptions); + constructor({ id, injector, logger, response, request, endpoint, ...options }: RequestContextOptions); destroy(): Promise<void>; emit(eventName: string, ...args: any[]): Promise<void>; }
diff --git a/packages/ts-doc/test/snapshots/ReturnsChainedDecorators.md b/packages/ts-doc/test/snapshots/ReturnsChainedDecorators.md index 1c5f9f8..73e0f3b 100644 --- a/packages/ts-doc/test/snapshots/ReturnsChainedDecorators.md +++ b/packages/ts-doc/test/snapshots/ReturnsChainedDecorators.md @@ -18,7 +18,7 @@ meta: ContentType(value: string): this; - Description(description: string): this; + Description(description: string): this; Examples(examples: any): this; @@ -30,13 +30,13 @@ meta: Nested(...generics: (Type<any> | any)[]): this; - Header(key: string, value: number | string | (JsonHeader & { + Header(key: string, value: number | string | (JsonHeader & { value?: string | number; })): this; - Headers(headers: JsonHeaders): this; + Headers(headers: JsonHeaders): this; - Schema(schema: Partial<JsonSchemaObject>): this; + Schema(schema: Partial<JsonSchemaObject>): this; [key: string]: any; } @@ -74,7 +74,7 @@ Set a Content-Type for the current response ::: v-pre
-
Description(description: string): this;
+
Description(description: string): this;
@@ -200,7 +200,7 @@ Declare a nested generic models ::: v-pre
-
Header(key: string, value: number | string | (JsonHeader & {
+
Header(key: string, value: number | string | (JsonHeader & {
      value?: string | number;
  })): this;
@@ -223,7 +223,7 @@ Add header. ::: v-pre
-
Headers(headers: JsonHeaders): this;
+
Headers(headers: JsonHeaders): this;
@@ -244,7 +244,7 @@ Add headers ::: v-pre
-
Schema(schema: Partial<JsonSchemaObject>): this;
+
Schema(schema: Partial<JsonSchemaObject>): this;
diff --git a/yarn.lock b/yarn.lock index 666e2e4..8f2fb78 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5732,6 +5732,11 @@ lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.4, lodash@^4.2.1 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + log-symbols@4.0.0, log-symbols@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920"