From 902977724f70e77a26fb4913e08c8c9f48bbff97 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 4 Jun 2022 10:17:25 -0600 Subject: [PATCH] Support for specifying globs in entry points Resolves #1926. --- CHANGELOG.md | 1 + src/lib/utils/entry-point.ts | 18 +++++++++-- src/lib/utils/fs.ts | 23 +++++++++----- src/lib/utils/options/sources/typedoc.ts | 2 +- src/test/slow/entry-point.test.ts | 38 +++++++++++++++++++++--- src/test/slow/entry-points/extra.ts | 3 -- src/test/slow/entry-points/index.ts | 3 -- src/test/slow/entry-points/tsconfig.json | 3 -- 8 files changed, 67 insertions(+), 24 deletions(-) delete mode 100644 src/test/slow/entry-points/extra.ts delete mode 100644 src/test/slow/entry-points/index.ts delete mode 100644 src/test/slow/entry-points/tsconfig.json diff --git a/CHANGELOG.md b/CHANGELOG.md index cfbb06b23..2a9641724 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - TypeDoc now supports the `@group` tag to group reflections in a page. If no `@group` tag is specified, reflections will be grouped according to their kind, #1652. - TypeDoc will now search for `typedoc.js(on)` in the `.config` folder in the current working directory. +- Entry point strategies `Resolve` and `Expand` may now specify globs, #1926. - `typedoc.json` now supports comments like `tsconfig.json`. - TypeDoc will now read the `blockTags`, `inlineTags`, and `modifierTags` out of `tsdoc.json` in the same directory as `tsconfig.json` if it exists. It is recommended to add `"extends": ["typedoc/tsdoc.json"]`, which defines TypeDoc specific tags to your `tsdoc.json` if you create one. diff --git a/src/lib/utils/entry-point.ts b/src/lib/utils/entry-point.ts index 85cf808d3..fdb2e5de3 100644 --- a/src/lib/utils/entry-point.ts +++ b/src/lib/utils/entry-point.ts @@ -10,7 +10,7 @@ import { import { createMinimatch, matchesAny } from "./paths"; import type { Logger } from "./loggers"; import type { Options } from "./options"; -import { getCommonDirectory, normalizePath } from "./fs"; +import { getCommonDirectory, glob, normalizePath } from "./fs"; /** * Defines how entry points are interpreted. @@ -52,13 +52,17 @@ export function getEntryPoints( let result: DocumentationEntryPoint[] | undefined; switch (options.getValue("entryPointStrategy")) { case EntryPointStrategy.Resolve: - result = getEntryPointsForPaths(logger, entryPoints, options); + result = getEntryPointsForPaths( + logger, + expandGlobs(entryPoints), + options + ); break; case EntryPointStrategy.Expand: result = getExpandedEntryPointsForPaths( logger, - entryPoints, + expandGlobs(entryPoints), options ); break; @@ -185,6 +189,14 @@ export function getExpandedEntryPointsForPaths( ); } +function expandGlobs(inputFiles: string[]) { + const base = getCommonDirectory(inputFiles); + const result = inputFiles.flatMap((entry) => + glob(entry, base, { includeDirectories: true }) + ); + return result; +} + function getEntryPrograms(logger: Logger, options: Options) { const rootProgram = ts.createProgram({ rootNames: options.getFileNames(), diff --git a/src/lib/utils/fs.ts b/src/lib/utils/fs.ts index 8e0ecf658..e761b9f30 100644 --- a/src/lib/utils/fs.ts +++ b/src/lib/utils/fs.ts @@ -134,9 +134,13 @@ export function copySync(src: string, dest: string): void { } /** - * Simpler version of `glob.sync` that only covers our use cases, only ever matching files, and ignoring node_modules. + * Simpler version of `glob.sync` that only covers our use cases, always ignoring node_modules. */ -export function glob(pattern: string, root: string): string[] { +export function glob( + pattern: string, + root: string, + options?: { includeDirectories?: boolean } +): string[] { const result: string[] = []; const mini = new Minimatch(normalizePath(pattern)); const dirs: string[][] = [normalizePath(root).split("/")]; @@ -147,6 +151,16 @@ export function glob(pattern: string, root: string): string[] { for (const child of fs.readdirSync(dir.join("/"), { withFileTypes: true, })) { + if ( + child.isFile() || + (options?.includeDirectories && child.isDirectory()) + ) { + const childPath = [...dir, child.name].join("/"); + if (mini.match(childPath)) { + result.push(childPath); + } + } + if (child.isDirectory() && child.name !== "node_modules") { const childPath = dir.concat(child.name); if ( @@ -156,11 +170,6 @@ export function glob(pattern: string, root: string): string[] { ) { dirs.push(childPath); } - } else if (child.isFile()) { - const childPath = [...dir, child.name].join("/"); - if (mini.match(childPath)) { - result.push(childPath); - } } } } while (dirs.length); diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 8f6a49b6e..8996e3ae8 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -26,7 +26,7 @@ export function addTypeDocOptions(options: Pick) { options.addDeclaration({ name: "entryPoints", help: "The entry points of your documentation.", - type: ParameterType.PathArray, + type: ParameterType.GlobArray, }); options.addDeclaration({ name: "entryPointStrategy", diff --git a/src/test/slow/entry-point.test.ts b/src/test/slow/entry-point.test.ts index a7ed33528..fb884e75f 100644 --- a/src/test/slow/entry-point.test.ts +++ b/src/test/slow/entry-point.test.ts @@ -1,18 +1,48 @@ +import { tempdirProject } from "@typestrong/fs-fixture-builder"; import { deepStrictEqual as equal, ok } from "assert"; import { join } from "path"; import { Application, EntryPointStrategy, TSConfigReader } from "../.."; -const root = join(__dirname, "entry-points"); +const fixture = tempdirProject(); +fixture.addJsonFile("tsconfig.json", { + include: ["."], +}); +fixture.addFile("index.ts", "export function fromIndex() {}"); +fixture.addFile("extra.ts", "export function extra() {}"); describe("Entry Points", () => { + beforeEach(() => { + fixture.write(); + }); + + afterEach(() => { + fixture.rm(); + }); + const app = new Application(); - const tsconfig = join(root, "tsconfig.json"); + const tsconfig = join(fixture.cwd, "tsconfig.json"); app.options.addReader(new TSConfigReader()); it("Supports expanding existing paths", () => { app.bootstrap({ tsconfig, - entryPoints: [root], + entryPoints: [fixture.cwd], + entryPointStrategy: EntryPointStrategy.Expand, + }); + + const entryPoints = app.getEntryPoints(); + ok(entryPoints); + equal( + entryPoints.length, + 2, + "There are two files, so both should be expanded" + ); + }); + + it("Supports expanding globs in paths", () => { + app.bootstrap({ + tsconfig, + entryPoints: [`${fixture.cwd}/*.ts`], entryPointStrategy: EntryPointStrategy.Expand, }); @@ -28,7 +58,7 @@ describe("Entry Points", () => { it("Supports resolving directories", () => { app.bootstrap({ tsconfig, - entryPoints: [root], + entryPoints: [fixture.cwd], entryPointStrategy: EntryPointStrategy.Resolve, }); diff --git a/src/test/slow/entry-points/extra.ts b/src/test/slow/entry-points/extra.ts deleted file mode 100644 index 3a30be6ae..000000000 --- a/src/test/slow/entry-points/extra.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function extra() { - // -} diff --git a/src/test/slow/entry-points/index.ts b/src/test/slow/entry-points/index.ts deleted file mode 100644 index d1f6b0a22..000000000 --- a/src/test/slow/entry-points/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function fromIndex() { - // -} diff --git a/src/test/slow/entry-points/tsconfig.json b/src/test/slow/entry-points/tsconfig.json deleted file mode 100644 index 82194fc7a..000000000 --- a/src/test/slow/entry-points/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "include": ["."] -}