From 24b379f51470eef6583a6d18d7d257e1ca9ed8f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Thu, 6 May 2021 14:04:08 +0300 Subject: [PATCH 01/80] chore: Add initial plugin test setup --- .gitignore | 3 +- package.json | 1 + src/__tests__/__fixtures__/index.js | 0 src/__tests__/plugin.test.ts | 53 +++++++++++++++++++++++++++++ yarn.lock | 12 +++++++ 5 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/__tests__/__fixtures__/index.js create mode 100644 src/__tests__/plugin.test.ts diff --git a/.gitignore b/.gitignore index a0d218e..6667779 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules dist -.env \ No newline at end of file +coverage +.env diff --git a/package.json b/package.json index 77ca9f2..0656e23 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-prettier": "3.1.3", "jest": "^26.6.3", + "memfs": "^3.2.2", "prettier": "^2.0.5", "react": "^17.0.1", "ts-jest": "^26.4.4", diff --git a/src/__tests__/__fixtures__/index.js b/src/__tests__/__fixtures__/index.js new file mode 100644 index 0000000..e69de29 diff --git a/src/__tests__/plugin.test.ts b/src/__tests__/plugin.test.ts new file mode 100644 index 0000000..cbcee01 --- /dev/null +++ b/src/__tests__/plugin.test.ts @@ -0,0 +1,53 @@ +import webpack, { Configuration } from 'webpack'; +import { createFsFromVolume, Volume } from 'memfs'; +import ReactDocgenTypeScriptPlugin from '..'; + +function compile(config: Configuration, filenames = ['index.html']) : Promise> { + return new Promise((resolve, reject) => { + const compiler = webpack(config); + + // eslint-disable-next-line + // @ts-ignore: There's a type mismatch but this should work based on webpack source + compiler.outputFileSystem = createFsFromVolume(new Volume()); + const memfs = compiler.outputFileSystem; + + compiler.run((err, stats) => { + if (err) { + return reject(err); + } + + if (stats.hasErrors()) { + return reject(stats.toString('errors-only')); + } + + const ret = {}; + + filenames.forEach((filename) => { + // eslint-disable-next-line + // @ts-ignore: The type is wrong here + ret[filename] = memfs.readFileSync(`./dist/${filename}`, { + encoding: 'utf-8', + }); + }); + + return resolve(ret); + }); + }); +} + +const getConfig = ( + options = {}, + config: { title?: string } = {} +): Configuration => + ({ + entry: { main: './__tests__/__fixtures__/index.js' }, + plugins: [new ReactDocgenTypeScriptPlugin(options)], + ...config + }) + + +test('default options', async () => { + const result = await compile(getConfig({})); + + expect(result['index.html']).toMatchSnapshot(); +}); diff --git a/yarn.lock b/yarn.lock index d0015c5..00127ff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2728,6 +2728,11 @@ fromentries@^1.2.0: resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.2.0.tgz#e6aa06f240d6267f913cea422075ef88b63e7897" integrity sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ== +fs-monkey@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" + integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -4090,6 +4095,13 @@ meant@^1.0.1: resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.1.tgz#66044fea2f23230ec806fb515efea29c44d2115d" integrity sha512-UakVLFjKkbbUwNWJ2frVLnnAtbb7D7DsloxRd3s/gDpI8rdv8W5Hp3NaDb+POBI1fQdeussER6NB8vpcRURvlg== +memfs@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.2.2.tgz#5de461389d596e3f23d48bb7c2afb6161f4df40e" + integrity sha512-RE0CwmIM3CEvpcdK3rZ19BC4E6hv9kADkMN5rPduRak58cNArWLi/9jFLsa4rhsjfVxMP3v0jO7FHXq7SvFY5Q== + dependencies: + fs-monkey "1.0.3" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" From cb280642cccf347d83abde5a3d8c941578c026df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Thu, 6 May 2021 14:05:56 +0300 Subject: [PATCH 02/80] chore: Add webpack 5 as a development dependency --- package.json | 4 +- src/__tests__/plugin.test.ts | 2 +- yarn.lock | 422 +++++++++++++++++++++++++++++++---- 3 files changed, 377 insertions(+), 51 deletions(-) diff --git a/package.json b/package.json index 0656e23..eea1c28 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "@types/micromatch": "^4.0.1", "@types/node": "^14.0.12", "@types/react": "^17.0.0", - "@types/webpack": "^4.41.17", "@typescript-eslint/eslint-plugin": "^4.9.0", "@typescript-eslint/parser": "^4.9.0", "auto": "^10.2.3", @@ -59,7 +58,8 @@ "prettier": "^2.0.5", "react": "^17.0.1", "ts-jest": "^26.4.4", - "typescript": "3.8.3" + "typescript": "3.8.3", + "webpack": "^5.36.2" }, "peerDependencies": { "typescript": ">= 3.x" diff --git a/src/__tests__/plugin.test.ts b/src/__tests__/plugin.test.ts index cbcee01..8999b66 100644 --- a/src/__tests__/plugin.test.ts +++ b/src/__tests__/plugin.test.ts @@ -16,7 +16,7 @@ function compile(config: Configuration, filenames = ['index.html']) : Promise Date: Thu, 6 May 2021 14:07:01 +0300 Subject: [PATCH 03/80] fix: Fix entry path --- .../__snapshots__/generateDocgenCodeBlock.test.ts.snap | 2 ++ src/__tests__/plugin.test.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap b/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap index 316ff3d..649e1fa 100644 --- a/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap +++ b/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap @@ -230,6 +230,8 @@ try { catch (__react_docgen_typescript_loader_error) { }" `; +exports[`component fixture index.js has code block generated 1`] = `""`; + exports[`generates value info for enums 1`] = ` "import * as React from \\"react\\"; diff --git a/src/__tests__/plugin.test.ts b/src/__tests__/plugin.test.ts index 8999b66..4e705ae 100644 --- a/src/__tests__/plugin.test.ts +++ b/src/__tests__/plugin.test.ts @@ -40,7 +40,7 @@ const getConfig = ( config: { title?: string } = {} ): Configuration => ({ - entry: { main: './__tests__/__fixtures__/index.js' }, + entry: { main: './src/__tests__/__fixtures__/index.js' }, plugins: [new ReactDocgenTypeScriptPlugin(options)], ...config }) From 4e7b7637f579c6f15315d368d4f53b7391f11b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Thu, 6 May 2021 14:08:39 +0300 Subject: [PATCH 04/80] chore: Add webpack 5 as a peer dependency --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index eea1c28..e1cac24 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,8 @@ "webpack": "^5.36.2" }, "peerDependencies": { - "typescript": ">= 3.x" + "typescript": ">= 3.x", + "webpack": ">= 5" }, "lint-staged": { "*.{js,css,md}": [ From c10c494dcfb503e7088216ef5b65aa5eebee7117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Thu, 6 May 2021 14:19:36 +0300 Subject: [PATCH 05/80] chore: Add structure needed by the new logic --- src/plugin.ts | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index e769f26..60589db 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -162,25 +162,15 @@ const matchGlob = (globs: string[]) => { export default class DocgenPlugin { private name = "React Docgen Typescript Plugin"; private options: PluginOptions; + private parser; + private compilerOptions; constructor(options: PluginOptions = {}) { - this.options = options; - } - - apply(compiler: webpack.Compiler): void { const { tsconfigPath = "./tsconfig.json", - docgenCollectionName = "STORYBOOK_REACT_CLASSES", - setDisplayName = true, - typePropName = "type", compilerOptions: userCompilerOptions, - exclude = [], - include = ["**/**.tsx"], ...docgenOptions - } = this.options; - - const isExcluded = matchGlob(exclude); - const isIncluded = matchGlob(include); + } = options; let compilerOptions = { jsx: ts.JsxEmit.React, @@ -194,11 +184,31 @@ export default class DocgenPlugin { ...userCompilerOptions, }; } else { - const { options } = getTSConfigFile(tsconfigPath); - compilerOptions = { ...compilerOptions, ...options }; + const { options: tsOptions } = getTSConfigFile(tsconfigPath); + compilerOptions = { ...compilerOptions, ...tsOptions }; } - const parser = docGen.withCompilerOptions(compilerOptions, docgenOptions); + this.options = options; + this.compilerOptions = compilerOptions; + this.parser = docGen.withCompilerOptions(compilerOptions, docgenOptions); + } + + apply(compiler: webpack.Compiler): void { + // TODO: Add new logic here + } + + // TODO: Eliminate this one after the new apply works + oldApply(compiler: webpack.Compiler): void { + const { + docgenCollectionName = "STORYBOOK_REACT_CLASSES", + setDisplayName = true, + typePropName = "type", + exclude = [], + include = ["**/**.tsx"], + } = this.options; + + const isExcluded = matchGlob(exclude); + const isIncluded = matchGlob(include); compiler.hooks.make.tap(this.name, (compilation) => { compilation.hooks.seal.tap(this.name, () => { @@ -242,11 +252,11 @@ export default class DocgenPlugin { const tsProgram = ts.createProgram( modulesToProcess.map((v) => v.userRequest), - compilerOptions + this.compilerOptions ); modulesToProcess.forEach((m) => - processModule(parser, m, tsProgram, { + processModule(this.parser, m, tsProgram, { docgenCollectionName, setDisplayName, typePropName, From 3e20aa8c02a34b17f4f66c01c845881a16b62aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Thu, 6 May 2021 14:22:38 +0300 Subject: [PATCH 06/80] chore: Add prettier config to fix vs code --- .prettierrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/.prettierrc @@ -0,0 +1 @@ +{} From 9fda54263087114b0f9c4f3cc4fd82499621d8e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Thu, 6 May 2021 14:23:10 +0300 Subject: [PATCH 07/80] chore: Add implementation instructions --- src/plugin.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/plugin.ts b/src/plugin.ts index 60589db..8827d35 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -195,6 +195,15 @@ export default class DocgenPlugin { apply(compiler: webpack.Compiler): void { // TODO: Add new logic here + /* +Instead of modifying the source code directly: Add a Dependency to the Module via module.addDependency. Register a DependencyTemplate for that Dependency class (compilation.dependencyTemplates.set(...)). In the DependencyTemplate you can add the code block to the source. Note if you want that modules correctly invalidate and cache you need to add updateHash to your Dependency and hash the type info (because that might change depending on outside factors (other modules). Add a Dependency to the Module via module.addDependency. This should happen during building of modules -> compilation.hooks.buildModule. Dependencies are cached with the Module. The result of the DependencyTemplate is cached when the hash is equal. +*/ + /* +You don't need that tsProgram in buildModule. That can stay in seal. In buildModule you only need to add the Dependency. That's will not need the information from typescript before code generation, which happens during seal (seal hook is the start of seal). +*/ + /* +Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates. They add them during parsing, but adding them in buildModule is also fine +*/ } // TODO: Eliminate this one after the new apply works From 87b1a163d3b7fe5dc572b3bf1902d59a6af520f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Thu, 6 May 2021 14:56:21 +0300 Subject: [PATCH 08/80] chore: Sketch out implementation --- .eslintrc | 12 ++------ src/dependency.ts | 71 +++++++++++++++++++++++++++++++++++++++++++++++ src/plugin.ts | 23 +++++++++++++++ 3 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 src/dependency.ts diff --git a/.eslintrc b/.eslintrc index 23f0da0..7e8d0d5 100644 --- a/.eslintrc +++ b/.eslintrc @@ -8,21 +8,13 @@ "plugin:jest/recommended", "plugin:jest/style" ], - "plugins": [ - "prettier", - "eslint-plugin-jsdoc", - "@typescript-eslint", - "jest" - ], + "plugins": ["prettier", "eslint-plugin-jsdoc", "@typescript-eslint", "jest"], "parser": "@typescript-eslint/parser", "parserOptions": { "project": "./tsconfig.json", "sourceType": "module" }, - "ignorePatterns": [ - "jest.config.js", - "**/__fixtures__" - ], + "ignorePatterns": ["jest.config.js", "**/__fixtures__"], "env": { "jest/globals": true }, diff --git a/src/dependency.ts b/src/dependency.ts new file mode 100644 index 0000000..1b52bf1 --- /dev/null +++ b/src/dependency.ts @@ -0,0 +1,71 @@ +/* eslint-disable max-classes-per-file */ +// eslint-disable-next-line +// @ts-ignore: What's the right way to refer to this one? +import ModuleDependency from "webpack/lib/dependencies/ModuleDependency.js"; + +// eslint-disable-next-line +// @ts-ignore: What's the right way to refer to this one? +import makeSerializable from "webpack/lib/util/makeSerializable.js"; + +class DocGenDependency extends ModuleDependency { + /** + * @param {string} request request + * @param {[number, number]} range range + */ + constructor(request, range) { + super(request); + this.range = range; + } + + // TODO + /** + * Update the hash + * @param {Hash} hash hash to be updated + * @param {UpdateHashContext} context context + * @returns {void} + */ + updateHash(hash, context) { + // TODO: See ConstDependency for reference + hash.update(this.range + ""); + hash.update(this.expression + ""); + // if (this.runtimeRequirements) + // hash.update(Array.from(this.runtimeRequirements).join() + ""); + } + + /** + * Returns list of exports referenced by this dependency + * @param {ModuleGraph} moduleGraph module graph + * @param {RuntimeSpec} runtime the runtime for which the module is analysed + * @returns {(string[] | ReferencedExport)[]} referenced exports + */ + getReferencedExports(moduleGraph, runtime) { + return Dependency.NO_EXPORTS_REFERENCED; + } + + get type() { + return ""; // new Worker()"; + } + + get category() { + return "docs"; // "worker" + } + + // TODO: Does this need serialize/deserialize as well? +} + +// TODO: How to type this? +DocGenDependency.Template = class DocGenTemplate extends ModuleDependency.Template { + /** + * @param {Dependency} dependency the dependency for which the template should be applied + * @param {ReplaceSource} source the current replace source which can be modified + * @param {DependencyTemplateContext} templateContext the context object + * @returns {void} + */ + apply(dependency, source, templateContext) { + // TODO: Write source here - See WorkerDependency.js for reference + } +}; + +makeSerializable(DocGenDependency, "src/dependency"); + +export default DocGenDependency; diff --git a/src/plugin.ts b/src/plugin.ts index 8827d35..42b6f26 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -10,6 +10,7 @@ import findCacheDir from "find-cache-dir"; import flatCache from "flat-cache"; import crypto from "crypto"; +import DocGenDependency from "./dependency"; import { generateDocgenCodeBlock } from "./generateDocgenCodeBlock"; const debugExclude = createDebug("docgen:exclude"); @@ -204,6 +205,28 @@ You don't need that tsProgram in buildModule. That can stay in seal. In buildMod /* Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates. They add them during parsing, but adding them in buildModule is also fine */ + + compiler.hooks.thisCompilation.tap( + "DocGenPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyTemplates.set( + DocGenDependency, + new DocGenDependency.Template() + ); + + // See ProgressPlugin and SourceMapDevToolModuleOptionsPlugin for reference + compilation.hooks.buildModule.tap("DocGenPlugin", (module) => { + const ident = module.identifier(); + + // TODO: Figure out what to do here + if (ident) { + activeModules.add(ident); + lastActiveModule = ident; + update(); + } + }); + } + ); } // TODO: Eliminate this one after the new apply works From 0824af05248823682c0b184fa0a884ca2eb604df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Thu, 6 May 2021 17:03:41 +0300 Subject: [PATCH 09/80] chore: Complete a simple test harness for testing against webpack 5 --- src/__tests__/__fixtures__/index.js | 2 + .../generateDocgenCodeBlock.test.ts.snap | 6 +- src/__tests__/plugin.test.ts | 93 ++++++++++--------- 3 files changed, 54 insertions(+), 47 deletions(-) diff --git a/src/__tests__/__fixtures__/index.js b/src/__tests__/__fixtures__/index.js index e69de29..0da65f2 100644 --- a/src/__tests__/__fixtures__/index.js +++ b/src/__tests__/__fixtures__/index.js @@ -0,0 +1,2 @@ +// TODO: This should contain a simple React component to parse +console.log("hello from index"); diff --git a/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap b/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap index 649e1fa..36c90f7 100644 --- a/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap +++ b/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap @@ -230,7 +230,11 @@ try { catch (__react_docgen_typescript_loader_error) { }" `; -exports[`component fixture index.js has code block generated 1`] = `""`; +exports[`component fixture index.js has code block generated 1`] = ` +"// TODO: This should contain a simple React component to parse +console.log(\\"hello from index\\"); +" +`; exports[`generates value info for enums 1`] = ` "import * as React from \\"react\\"; diff --git a/src/__tests__/plugin.test.ts b/src/__tests__/plugin.test.ts index 4e705ae..82310dd 100644 --- a/src/__tests__/plugin.test.ts +++ b/src/__tests__/plugin.test.ts @@ -1,53 +1,54 @@ -import webpack, { Configuration } from 'webpack'; -import { createFsFromVolume, Volume } from 'memfs'; -import ReactDocgenTypeScriptPlugin from '..'; - -function compile(config: Configuration, filenames = ['index.html']) : Promise> { - return new Promise((resolve, reject) => { - const compiler = webpack(config); - - // eslint-disable-next-line - // @ts-ignore: There's a type mismatch but this should work based on webpack source - compiler.outputFileSystem = createFsFromVolume(new Volume()); - const memfs = compiler.outputFileSystem; - - compiler.run((err, stats) => { - if (err) { - return reject(err); - } - - if (stats?.hasErrors()) { - return reject(stats.toString('errors-only')); - } - - const ret = {}; - - filenames.forEach((filename) => { - // eslint-disable-next-line - // @ts-ignore: The type is wrong here - ret[filename] = memfs.readFileSync(`./dist/${filename}`, { - encoding: 'utf-8', - }); - }); - - return resolve(ret); - }); - }); +import webpack, { Configuration } from "webpack"; +import { createFsFromVolume, Volume } from "memfs"; +import ReactDocgenTypeScriptPlugin from ".."; + +function compile(config: Configuration): Promise { + return new Promise((resolve, reject) => { + const compiler = webpack(config); + + // eslint-disable-next-line + // @ts-ignore: There's a type mismatch but this should work based on webpack source + compiler.outputFileSystem = createFsFromVolume(new Volume()); + const memfs = compiler.outputFileSystem; + + compiler.run((error, stats) => { + if (error) { + return reject(error); + } + + if (stats?.hasErrors()) { + return reject(stats.toString("errors-only")); + } + + memfs.readFile( + "./dist/main.js", + { + encoding: "utf-8", + }, + // eslint-disable-next-line + // @ts-ignore: Type mismatch again + (err, data) => (err ? reject(err) : resolve(data)) + ); + + return undefined; + }); + }); } const getConfig = ( - options = {}, - config: { title?: string } = {} -): Configuration => - ({ - entry: { main: './src/__tests__/__fixtures__/index.js' }, - plugins: [new ReactDocgenTypeScriptPlugin(options)], - ...config - }) + options = {}, + config: { title?: string } = {} +): Configuration => ({ + entry: { main: "./src/__tests__/__fixtures__/index.js" }, + plugins: [new ReactDocgenTypeScriptPlugin(options)], + ...config, +}); +test("default options", async () => { + const result = await compile(getConfig({})); -test('default options', async () => { - const result = await compile(getConfig({})); + console.log("result", result); - expect(result['index.html']).toMatchSnapshot(); + // expect(result).toMatchSnapshot(); + expect(true).toEqual(true); }); From 8ee50031aeb9388cece78aff93cd68df4f1d889c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 14:47:58 +0300 Subject: [PATCH 10/80] chore: Sketch out implementation --- .eslintrc | 3 ++- src/plugin.ts | 32 +++++++++++--------------------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/.eslintrc b/.eslintrc index 7e8d0d5..775337d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -23,6 +23,7 @@ "@typescript-eslint/camelcase": 0, "complexity": 0, "import/no-unresolved": 0, - "import/extensions": 0 + "import/extensions": 0, + "class-methods-use-this": 0 } } diff --git a/src/plugin.ts b/src/plugin.ts index 42b6f26..7f20d64 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -206,27 +206,17 @@ You don't need that tsProgram in buildModule. That can stay in seal. In buildMod Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates. They add them during parsing, but adding them in buildModule is also fine */ - compiler.hooks.thisCompilation.tap( - "DocGenPlugin", - (compilation, { normalModuleFactory }) => { - compilation.dependencyTemplates.set( - DocGenDependency, - new DocGenDependency.Template() - ); - - // See ProgressPlugin and SourceMapDevToolModuleOptionsPlugin for reference - compilation.hooks.buildModule.tap("DocGenPlugin", (module) => { - const ident = module.identifier(); - - // TODO: Figure out what to do here - if (ident) { - activeModules.add(ident); - lastActiveModule = ident; - update(); - } - }); - } - ); + compiler.hooks.thisCompilation.tap("DocGenPlugin", (compilation) => { + compilation.dependencyTemplates.set( + DocGenDependency, + new DocGenDependency.Template() + ); + + compilation.hooks.buildModule.tap("DocGenPlugin", (module) => { + // TODO: Add a dependency now + // module.addDependency(dependency); + }); + }); } // TODO: Eliminate this one after the new apply works From a1c94ae2e2d5aa20868bc67bb99308b966fc4dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 14:51:23 +0300 Subject: [PATCH 11/80] chore: Load simple component for testing --- package.json | 1 + src/__tests__/__fixtures__/index.js | 2 -- src/__tests__/plugin.test.ts | 14 ++++++++++++- yarn.lock | 32 ++++++++++++++++++++++++++++- 4 files changed, 45 insertions(+), 4 deletions(-) delete mode 100644 src/__tests__/__fixtures__/index.js diff --git a/package.json b/package.json index e1cac24..eab9b70 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "prettier": "^2.0.5", "react": "^17.0.1", "ts-jest": "^26.4.4", + "ts-loader": "^9.1.2", "typescript": "3.8.3", "webpack": "^5.36.2" }, diff --git a/src/__tests__/__fixtures__/index.js b/src/__tests__/__fixtures__/index.js deleted file mode 100644 index 0da65f2..0000000 --- a/src/__tests__/__fixtures__/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// TODO: This should contain a simple React component to parse -console.log("hello from index"); diff --git a/src/__tests__/plugin.test.ts b/src/__tests__/plugin.test.ts index 82310dd..cddde1d 100644 --- a/src/__tests__/plugin.test.ts +++ b/src/__tests__/plugin.test.ts @@ -35,12 +35,24 @@ function compile(config: Configuration): Promise { }); } +// TODO: Maybe it's easier for testing to expose a way to write types to the fs const getConfig = ( options = {}, config: { title?: string } = {} ): Configuration => ({ - entry: { main: "./src/__tests__/__fixtures__/index.js" }, + entry: { main: "./src/__tests__/__fixtures__/Simple.tsx" }, plugins: [new ReactDocgenTypeScriptPlugin(options)], + module: { + rules: [ + { + test: /\.tsx?$/, + loader: "ts-loader", + options: { + transpileOnly: true, + }, + }, + ], + }, ...config, }); diff --git a/yarn.lock b/yarn.lock index aac8d6e..b511372 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2249,7 +2249,7 @@ endent@^2.0.1: fast-json-parse "^1.0.3" objectorarray "^1.0.4" -enhanced-resolve@^5.8.0: +enhanced-resolve@^5.0.0, enhanced-resolve@^5.8.0: version "5.8.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.0.tgz#d9deae58f9d3773b6a111a5a46831da5be5c9ac0" integrity sha512-Sl3KRpJA8OpprrtaIswVki3cWPiPKxXuFxJXBp+zNb6s6VwNWwFRUdtmzd2ReUut8n+sCPx7QCtQ7w5wfJhSgQ== @@ -4324,6 +4324,14 @@ micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + micromatch@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" @@ -4850,6 +4858,11 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +picomatch@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.3.tgz#465547f359ccc206d3c48e46a1bcb89bf7ee619d" + integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg== + pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -5318,6 +5331,13 @@ semver@^7.0.0, semver@^7.2.1: resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== +semver@^7.3.4: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + serialize-javascript@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" @@ -5884,6 +5904,16 @@ ts-jest@^26.4.4: semver "7.x" yargs-parser "20.x" +ts-loader@^9.1.2: + version "9.1.2" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.1.2.tgz#ba9b9abb05a514e8ff825791a3f6fcf793272728" + integrity sha512-ryMgATvLLl+z8zQvdlm6Pep0slmwxFWIEnq/5VdiLVjqQXnFJgO+qNLGIIP+d2N2jsFZ9MibZCVDb2bSp7OmEA== + dependencies: + chalk "^4.1.0" + enhanced-resolve "^5.0.0" + micromatch "^4.0.0" + semver "^7.3.4" + tsconfig-paths@^3.9.0: version "3.9.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" From 7499a99fce384eb213ffcfccd637fc2db08e90f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 15:06:35 +0300 Subject: [PATCH 12/80] chore: Clean up implementation --- src/dependency.ts | 43 +++++++++++++------------------------------ src/plugin.ts | 4 ++-- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index 1b52bf1..3c4854c 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -6,54 +6,37 @@ import ModuleDependency from "webpack/lib/dependencies/ModuleDependency.js"; // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? import makeSerializable from "webpack/lib/util/makeSerializable.js"; +import Dependency from "webpack/lib/Dependency.js"; +import Hash from "webpack/lib/util/Hash.js"; class DocGenDependency extends ModuleDependency { + public static Template: ModuleDependency.Template; + /** * @param {string} request request - * @param {[number, number]} range range */ - constructor(request, range) { + /* constructor(request: string) { super(request); - this.range = range; - } + } */ - // TODO - /** - * Update the hash - * @param {Hash} hash hash to be updated - * @param {UpdateHashContext} context context - * @returns {void} - */ - updateHash(hash, context) { + updateHash(hash: Hash, context): void { // TODO: See ConstDependency for reference - hash.update(this.range + ""); - hash.update(this.expression + ""); - // if (this.runtimeRequirements) - // hash.update(Array.from(this.runtimeRequirements).join() + ""); } - /** - * Returns list of exports referenced by this dependency - * @param {ModuleGraph} moduleGraph module graph - * @param {RuntimeSpec} runtime the runtime for which the module is analysed - * @returns {(string[] | ReferencedExport)[]} referenced exports - */ - getReferencedExports(moduleGraph, runtime) { + getReferencedExports(): [] { return Dependency.NO_EXPORTS_REFERENCED; } - get type() { - return ""; // new Worker()"; + get type(): string { + return "__react_docgen__"; } - get category() { - return "docs"; // "worker" + get category(): string { + return "docs"; } - - // TODO: Does this need serialize/deserialize as well? } -// TODO: How to type this? +// eslint-disable-next-line DocGenDependency.Template = class DocGenTemplate extends ModuleDependency.Template { /** * @param {Dependency} dependency the dependency for which the template should be applied diff --git a/src/plugin.ts b/src/plugin.ts index 7f20d64..f38ddd4 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -213,8 +213,8 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates ); compilation.hooks.buildModule.tap("DocGenPlugin", (module) => { - // TODO: Add a dependency now - // module.addDependency(dependency); + const dependency = new DocGenDependency(); + module.addDependency(dependency); }); }); } From 6b78f8a3ff5750feb7ef6dd930174e8badeb66e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 15:10:54 +0300 Subject: [PATCH 13/80] chore: Figure out SourceReplace API --- src/__tests__/plugin.test.ts | 2 +- src/dependency.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/__tests__/plugin.test.ts b/src/__tests__/plugin.test.ts index cddde1d..cae7ef6 100644 --- a/src/__tests__/plugin.test.ts +++ b/src/__tests__/plugin.test.ts @@ -59,7 +59,7 @@ const getConfig = ( test("default options", async () => { const result = await compile(getConfig({})); - console.log("result", result); + // console.log("result", result); // expect(result).toMatchSnapshot(); expect(true).toEqual(true); diff --git a/src/dependency.ts b/src/dependency.ts index 3c4854c..83ee9f5 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -45,7 +45,8 @@ DocGenDependency.Template = class DocGenTemplate extends ModuleDependency.Templa * @returns {void} */ apply(dependency, source, templateContext) { - // TODO: Write source here - See WorkerDependency.js for reference + // TODO: Insert type annotations here + source.insert(0, "hello world"); } }; From e4501140924b8aa3ce60f2ddb9b47e473e6feada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 15:12:41 +0300 Subject: [PATCH 14/80] chore: Add logging to understand code better --- src/plugin.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/plugin.ts b/src/plugin.ts index f38ddd4..9051bab 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -159,6 +159,8 @@ const matchGlob = (globs: string[]) => { Boolean(filename && matchers.find((match) => match(filename))); }; +console.log("hello from plugin"); + /** Inject typescript docgen information into modules at the end of a build */ export default class DocgenPlugin { private name = "React Docgen Typescript Plugin"; @@ -206,13 +208,19 @@ You don't need that tsProgram in buildModule. That can stay in seal. In buildMod Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates. They add them during parsing, but adding them in buildModule is also fine */ + console.log("applying plugin"); + compiler.hooks.thisCompilation.tap("DocGenPlugin", (compilation) => { + console.log("at this compilation"); + compilation.dependencyTemplates.set( DocGenDependency, new DocGenDependency.Template() ); compilation.hooks.buildModule.tap("DocGenPlugin", (module) => { + console.log("at build module"); + const dependency = new DocGenDependency(); module.addDependency(dependency); }); From cbf7e72cb34bcbabeb7cdca96d852e79e7adaa49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 15:14:19 +0300 Subject: [PATCH 15/80] chore: Update Jest related dependencies --- package.json | 4 ++-- yarn.lock | 29 ++++++++++++++--------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index eab9b70..f562459 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@types/debug": "^4.1.5", "@types/find-cache-dir": "^3.2.0", "@types/flat-cache": "^2.0.0", - "@types/jest": "^26.0.16", + "@types/jest": "^26.0.23", "@types/micromatch": "^4.0.1", "@types/node": "^14.0.12", "@types/react": "^17.0.0", @@ -57,7 +57,7 @@ "memfs": "^3.2.2", "prettier": "^2.0.5", "react": "^17.0.1", - "ts-jest": "^26.4.4", + "ts-jest": "^26.5.6", "ts-loader": "^9.1.2", "typescript": "3.8.3", "webpack": "^5.36.2" diff --git a/yarn.lock b/yarn.lock index b511372..fdd48ff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -914,10 +914,10 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@26.x", "@types/jest@^26.0.16": - version "26.0.16" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.16.tgz#b47abd50f6ed0503f589db8e126fc8eb470cf87c" - integrity sha512-Gp12+7tmKCgv9JjtltxUXokohCAEZfpJaEW5tn871SGRp8I+bRWBonQO7vW5NHwnAHe5dd50+Q4zyKuN35i09g== +"@types/jest@^26.0.23": + version "26.0.23" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.23.tgz#a1b7eab3c503b80451d019efb588ec63522ee4e7" + integrity sha512-ZHLmWMJ9jJ9PTiT58juykZpL7KjwJywFN3Rr2pTSkyQfydf/rk22yS7W8p5DaVUMQ2BQC7oYiU3FjbTM/mYrOA== dependencies: jest-diff "^26.0.0" pretty-format "^26.0.0" @@ -4206,16 +4206,16 @@ lodash.chunk@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.chunk/-/lodash.chunk-4.2.0.tgz#66e5ce1f76ed27b4303d8c6512e8d1216e8106bc" integrity sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw= -lodash.memoize@4.x: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= +lodash@4.x: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + lodash@^4.11.2, lodash@^4.17.19: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" @@ -5887,18 +5887,17 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" -ts-jest@^26.4.4: - version "26.4.4" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.4.4.tgz#61f13fb21ab400853c532270e52cc0ed7e502c49" - integrity sha512-3lFWKbLxJm34QxyVNNCgXX1u4o/RV0myvA2y2Bxm46iGIjKlaY0own9gIckbjZJPn+WaJEnfPPJ20HHGpoq4yg== +ts-jest@^26.5.6: + version "26.5.6" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.5.6.tgz#c32e0746425274e1dfe333f43cd3c800e014ec35" + integrity sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA== dependencies: - "@types/jest" "26.x" bs-logger "0.x" buffer-from "1.x" fast-json-stable-stringify "2.x" jest-util "^26.1.0" json5 "2.x" - lodash.memoize "4.x" + lodash "4.x" make-error "1.x" mkdirp "1.x" semver "7.x" From 766374a9f6367840cd73be327116cfafc0df5d41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 15:45:31 +0300 Subject: [PATCH 16/80] chore: Add an initial example to help in debugging --- package.json | 4 +- webpack.config.js | 17 +++++ yarn.lock | 157 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 173 insertions(+), 5 deletions(-) create mode 100644 webpack.config.js diff --git a/package.json b/package.json index f562459..ce5e306 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "author": "Andrew Lisowski ", "main": "dist/index.js", "scripts": { + "build:example": "npm run build && webpack", "build": "tsc -p tsconfig.build.json", "start": "yarn build --watch", "lint": "eslint src --ext .ts,.js", @@ -60,7 +61,8 @@ "ts-jest": "^26.5.6", "ts-loader": "^9.1.2", "typescript": "3.8.3", - "webpack": "^5.36.2" + "webpack": "^5.36.2", + "webpack-cli": "^4.7.0" }, "peerDependencies": { "typescript": ">= 3.x", diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..6735719 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,17 @@ +const { ReactDocgenTypeScriptPlugin } = require("./"); + +module.exports = { + entry: { main: "./src/__tests__/__fixtures__/Simple.tsx" }, + plugins: [new ReactDocgenTypeScriptPlugin()], + module: { + rules: [ + { + test: /\.tsx?$/, + loader: "ts-loader", + options: { + transpileOnly: true, + }, + }, + ], + }, +}; diff --git a/yarn.lock b/yarn.lock index fdd48ff..171d907 100644 --- a/yarn.lock +++ b/yarn.lock @@ -433,6 +433,11 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@discoveryjs/json-ext@^0.5.0": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz#8f03a22a04de437254e8ce8cc84ba39689288752" + integrity sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg== + "@eslint/eslintrc@^0.2.1": version "0.2.1" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.1.tgz#f72069c330461a06684d119384435e12a5d76e3c" @@ -1185,6 +1190,23 @@ "@webassemblyjs/ast" "1.11.0" "@xtuc/long" "4.2.2" +"@webpack-cli/configtest@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.0.3.tgz#204bcff87cda3ea4810881f7ea96e5f5321b87b9" + integrity sha512-WQs0ep98FXX2XBAfQpRbY0Ma6ADw8JR6xoIkaIiJIzClGOMqVRvPCWqndTxf28DgFopWan0EKtHtg/5W1h0Zkw== + +"@webpack-cli/info@^1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.2.4.tgz#7381fd41c9577b2d8f6c2594fad397ef49ad5573" + integrity sha512-ogE2T4+pLhTTPS/8MM3IjHn0IYplKM4HbVNMCWA9N4NrdPzunwenpCsqKEXyejMfRu6K8mhauIPYf8ZxWG5O6g== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.4.0.tgz#f84fd07bcacefe56ce762925798871092f0f228e" + integrity sha512-xgT/HqJ+uLWGX+Mzufusl3cgjAcnqYYskaB7o0vRcwOEfuu6hMzSILQpnIzFMGsTaeaX4Nnekl+6fadLbl1/Vg== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -1820,6 +1842,15 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -1862,7 +1893,7 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^1.2.2: +colorette@^1.2.1, colorette@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== @@ -1913,6 +1944,11 @@ commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + comment-parser@^0.7.4: version "0.7.5" resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.7.5.tgz#06db157a3b34addf8502393743e41897e2c73059" @@ -1997,7 +2033,7 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -2279,6 +2315,11 @@ env-ci@^5.0.1: execa "^4.0.0" java-properties "^1.0.0" +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -2645,6 +2686,21 @@ execa@^4.0.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +execa@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.0.0.tgz#4029b0007998a841fbd1032e5f4de86a3c1e3376" + integrity sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -2765,6 +2821,11 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fastest-levenshtein@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" + integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== + fastq@^1.6.0: version "1.8.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" @@ -2987,6 +3048,11 @@ get-stream@^5.0.0: dependencies: pump "^3.0.0" +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -3182,6 +3248,11 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -3284,6 +3355,11 @@ inquirer@^7.0.4: strip-ansi "^6.0.0" through "^2.3.6" +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + io-ts@^2.1.2: version "2.2.4" resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.4.tgz#c9b5390b8c60b9976ad03f670a6b976fe50d4083" @@ -3342,6 +3418,13 @@ is-core-module@^2.1.0: dependencies: has "^1.0.3" +is-core-module@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.3.0.tgz#d341652e3408bca69c4671b79a0954a3d349f887" + integrity sha512-xSphU2KG9867tsYdLD4RWQ1VqdFl4HTO9Thf3I/3dLEfr0dbPTWKsuCKrgqMljg4nPE+Gq0VCnzT3gr0CyBmsw== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -4519,7 +4602,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npm-run-path@^4.0.0: +npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -4638,6 +4721,13 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -5058,6 +5148,13 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" +rechoir@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.0.tgz#32650fd52c21ab252aa5d65b19310441c7e03aca" + integrity sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q== + dependencies: + resolve "^1.9.0" + reduce-flatten@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" @@ -5202,6 +5299,14 @@ resolve@^1.17.0, resolve@^1.18.1, resolve@^1.3.2: is-core-module "^2.1.0" path-parse "^1.0.6" +resolve@^1.9.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -5360,6 +5465,13 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -5389,7 +5501,7 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -signal-exit@^3.0.0, signal-exit@^3.0.2: +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== @@ -6104,6 +6216,11 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== +v8-compile-cache@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + v8-to-istanbul@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-7.0.0.tgz#b4fe00e35649ef7785a9b7fcebcea05f37c332fc" @@ -6169,6 +6286,33 @@ webidl-conversions@^6.1.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== +webpack-cli@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.7.0.tgz#3195a777f1f802ecda732f6c95d24c0004bc5a35" + integrity sha512-7bKr9182/sGfjFm+xdZSwgQuFjgEcy0iCTIBxRUeteJ2Kr8/Wz0qNJX+jw60LU36jApt4nmMkep6+W5AKhok6g== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.0.3" + "@webpack-cli/info" "^1.2.4" + "@webpack-cli/serve" "^1.4.0" + colorette "^1.2.1" + commander "^7.0.0" + execa "^5.0.0" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + v8-compile-cache "^2.2.0" + webpack-merge "^5.7.3" + +webpack-merge@^5.7.3: + version "5.7.3" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.7.3.tgz#2a0754e1877a25a8bbab3d2475ca70a052708213" + integrity sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + webpack-sources@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.2.0.tgz#058926f39e3d443193b6c31547229806ffd02bac" @@ -6246,6 +6390,11 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + windows-release@^3.1.0: version "3.3.1" resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.1.tgz#cb4e80385f8550f709727287bf71035e209c4ace" From d0795327fd037c7c00c333e5ac1ed21b9d36c056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 15:52:12 +0300 Subject: [PATCH 17/80] chore: Make project compile --- package.json | 4 +++- src/dependency.ts | 15 ++++++++++++--- src/plugin.ts | 11 +++++++++-- yarn.lock | 16 +++++++++++++++- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index ce5e306..6a4f866 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,8 @@ "flat-cache": "^3.0.4", "micromatch": "^4.0.2", "react-docgen-typescript": "^1.20.5", - "tslib": "^2.0.0" + "tslib": "^2.0.0", + "webpack-sources": "^2.2.0" }, "devDependencies": { "@types/debug": "^4.1.5", @@ -41,6 +42,7 @@ "@types/micromatch": "^4.0.1", "@types/node": "^14.0.12", "@types/react": "^17.0.0", + "@types/webpack-sources": "^2.1.0", "@typescript-eslint/eslint-plugin": "^4.9.0", "@typescript-eslint/parser": "^4.9.0", "auto": "^10.2.3", diff --git a/src/dependency.ts b/src/dependency.ts index 83ee9f5..da8a20f 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -1,4 +1,7 @@ /* eslint-disable max-classes-per-file */ + +import { ReplaceSource } from "webpack-sources"; + // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? import ModuleDependency from "webpack/lib/dependencies/ModuleDependency.js"; @@ -6,8 +9,14 @@ import ModuleDependency from "webpack/lib/dependencies/ModuleDependency.js"; // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? import makeSerializable from "webpack/lib/util/makeSerializable.js"; + +// eslint-disable-next-line +// @ts-ignore TODO: Figure out where to find a typed version import Dependency from "webpack/lib/Dependency.js"; -import Hash from "webpack/lib/util/Hash.js"; + +// eslint-disable-next-line +// @ts-ignore TODO: Figure out where to find a typed version +// import Hash from "webpack/lib/util/Hash.js"; class DocGenDependency extends ModuleDependency { public static Template: ModuleDependency.Template; @@ -19,7 +28,7 @@ class DocGenDependency extends ModuleDependency { super(request); } */ - updateHash(hash: Hash, context): void { + updateHash(): void { // TODO: See ConstDependency for reference } @@ -44,7 +53,7 @@ DocGenDependency.Template = class DocGenTemplate extends ModuleDependency.Templa * @param {DependencyTemplateContext} templateContext the context object * @returns {void} */ - apply(dependency, source, templateContext) { + apply(dependency: Dependency, source: ReplaceSource) { // TODO: Insert type annotations here source.insert(0, "hello world"); } diff --git a/src/plugin.ts b/src/plugin.ts index 9051bab..0d0f18d 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -165,8 +165,8 @@ console.log("hello from plugin"); export default class DocgenPlugin { private name = "React Docgen Typescript Plugin"; private options: PluginOptions; - private parser; - private compilerOptions; + private parser: docGen.FileParser; + private compilerOptions: ts.CompilerOptions; constructor(options: PluginOptions = {}) { const { @@ -214,6 +214,8 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates console.log("at this compilation"); compilation.dependencyTemplates.set( + // eslint-disable-next-line + // @ts-ignore TODO: Figure out why this isn't allowed DocGenDependency, new DocGenDependency.Template() ); @@ -222,6 +224,9 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates console.log("at build module"); const dependency = new DocGenDependency(); + + // eslint-disable-next-line + // @ts-ignore TODO: Figure out why assinging a sub-class doesn't work module.addDependency(dependency); }); }); @@ -244,6 +249,8 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates compilation.hooks.seal.tap(this.name, () => { const modulesToProcess: Module[] = []; + // eslint-disable-next-line + // @ts-ignore TODO: Module type compilation.modules.forEach((module: Module) => { if (!module.built) { debugExclude(`Ignoring un-built module: ${module.userRequest}`); diff --git a/yarn.lock b/yarn.lock index 171d907..69cf9e7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -982,11 +982,25 @@ "@types/prop-types" "*" csstype "^3.0.2" +"@types/source-list-map@*": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" + integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== + "@types/stack-utils@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== +"@types/webpack-sources@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-2.1.0.tgz#8882b0bd62d1e0ce62f183d0d01b72e6e82e8c10" + integrity sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg== + dependencies: + "@types/node" "*" + "@types/source-list-map" "*" + source-map "^0.7.3" + "@types/yargs-parser@*": version "15.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" @@ -6313,7 +6327,7 @@ webpack-merge@^5.7.3: clone-deep "^4.0.1" wildcard "^2.0.0" -webpack-sources@^2.1.1: +webpack-sources@^2.1.1, webpack-sources@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.2.0.tgz#058926f39e3d443193b6c31547229806ffd02bac" integrity sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w== From 312dcbb04ccce154fbb724045cae6d35333297da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 15:55:05 +0300 Subject: [PATCH 18/80] chore: Make export more convenient --- src/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 7da3069..5f8937b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ /* eslint-disable */ -import type { DocgenPluginType, PluginOptions } from './plugin' +import type { DocgenPluginType, PluginOptions } from "./plugin"; class EmptyPlugin { constructor(_: PluginOptions) {} @@ -11,10 +11,11 @@ let plugin: DocgenPluginType; try { require.resolve("typescript"); - plugin = require('./plugin').default; + plugin = require("./plugin").default; } catch (error) { plugin = EmptyPlugin as any; } export { PluginOptions } from "./plugin"; +export { plugin as ReactDocgenTypeScriptPlugin }; export default plugin; From 64db51d71e41c9d0ce76ec538a819364ae6cc746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 15:56:08 +0300 Subject: [PATCH 19/80] chore: Mute webpack warning --- webpack.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/webpack.config.js b/webpack.config.js index 6735719..b831324 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,7 @@ const { ReactDocgenTypeScriptPlugin } = require("./"); module.exports = { + mode: "development", entry: { main: "./src/__tests__/__fixtures__/Simple.tsx" }, plugins: [new ReactDocgenTypeScriptPlugin()], module: { From 2ad2b85a97c493a380f4067c324f6a600f27cf3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 15:56:45 +0300 Subject: [PATCH 20/80] chore: Add logging --- src/dependency.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dependency.ts b/src/dependency.ts index da8a20f..e0e3063 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -54,6 +54,8 @@ DocGenDependency.Template = class DocGenTemplate extends ModuleDependency.Templa * @returns {void} */ apply(dependency: Dependency, source: ReplaceSource) { + console.log("applying template"); + // TODO: Insert type annotations here source.insert(0, "hello world"); } From 19a18651c7676540cbe6148c775430c0180e9b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 16:01:05 +0300 Subject: [PATCH 21/80] chore: Improve logging --- src/dependency.ts | 2 +- src/plugin.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index e0e3063..4531994 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -54,7 +54,7 @@ DocGenDependency.Template = class DocGenTemplate extends ModuleDependency.Templa * @returns {void} */ apply(dependency: Dependency, source: ReplaceSource) { - console.log("applying template"); + console.log("APPLYING template"); // TODO: Insert type annotations here source.insert(0, "hello world"); diff --git a/src/plugin.ts b/src/plugin.ts index 0d0f18d..bb300b4 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -221,9 +221,13 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates ); compilation.hooks.buildModule.tap("DocGenPlugin", (module) => { - console.log("at build module"); + // eslint-disable-next-line + // @ts-ignore + console.log("at build module", module.request); - const dependency = new DocGenDependency(); + // eslint-disable-next-line + // @ts-ignore + const dependency = new DocGenDependency(module.request); // eslint-disable-next-line // @ts-ignore TODO: Figure out why assinging a sub-class doesn't work From 8a5f37a96f536e20d81789a3e256f247745a243a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 16:02:43 +0300 Subject: [PATCH 22/80] chore: Add a todo --- src/plugin.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugin.ts b/src/plugin.ts index bb300b4..dbb7774 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -229,6 +229,9 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates // @ts-ignore const dependency = new DocGenDependency(module.request); + // TODO: Add the dependency based on include/exclude. For now, + // we apply for everything. + // eslint-disable-next-line // @ts-ignore TODO: Figure out why assinging a sub-class doesn't work module.addDependency(dependency); From 7fab1671fc5722db2f237a09879c71207c272f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 7 May 2021 16:13:26 +0300 Subject: [PATCH 23/80] fix: Fix type name --- src/dependency.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dependency.ts b/src/dependency.ts index 4531994..be0d2f0 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -37,7 +37,7 @@ class DocGenDependency extends ModuleDependency { } get type(): string { - return "__react_docgen__"; + return "react docgen"; } get category(): string { From ec089f0a9a6c0a68583302119d7f7a86857e9e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 10:39:49 +0300 Subject: [PATCH 24/80] chore: Sketch out the usage of parser api --- .gitignore | 1 + src/dependency.ts | 15 ++++++----- src/plugin.ts | 63 +++++++++++++++++++++++++++++++++++++++-------- webpack.config.js | 4 +++ 4 files changed, 67 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 6667779..3e7c54c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules dist +example-dist coverage .env diff --git a/src/dependency.ts b/src/dependency.ts index be0d2f0..4e8c03d 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -37,16 +37,19 @@ class DocGenDependency extends ModuleDependency { } get type(): string { - return "react docgen"; + return "docgen"; } get category(): string { - return "docs"; + return "esm"; // "docs"; } + + // TODO: updateHash, serialize, deserialize } -// eslint-disable-next-line -DocGenDependency.Template = class DocGenTemplate extends ModuleDependency.Template { +makeSerializable(DocGenDependency, "src/dependency"); + +class DocGenTemplate extends ModuleDependency.Template { /** * @param {Dependency} dependency the dependency for which the template should be applied * @param {ReplaceSource} source the current replace source which can be modified @@ -59,8 +62,8 @@ DocGenDependency.Template = class DocGenTemplate extends ModuleDependency.Templa // TODO: Insert type annotations here source.insert(0, "hello world"); } -}; +} -makeSerializable(DocGenDependency, "src/dependency"); +DocGenDependency.Template = DocGenTemplate; export default DocGenDependency; diff --git a/src/plugin.ts b/src/plugin.ts index dbb7774..a9a8865 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -10,6 +10,10 @@ import findCacheDir from "find-cache-dir"; import flatCache from "flat-cache"; import crypto from "crypto"; +// eslint-disable-next-line +// @ts-ignore TODO: Figure out where to find a typed version +import ConstDependency from "webpack/lib/dependencies/ConstDependency"; + import DocGenDependency from "./dependency"; import { generateDocgenCodeBlock } from "./generateDocgenCodeBlock"; @@ -159,8 +163,6 @@ const matchGlob = (globs: string[]) => { Boolean(filename && matchers.find((match) => match(filename))); }; -console.log("hello from plugin"); - /** Inject typescript docgen information into modules at the end of a build */ export default class DocgenPlugin { private name = "React Docgen Typescript Plugin"; @@ -210,16 +212,55 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates console.log("applying plugin"); - compiler.hooks.thisCompilation.tap("DocGenPlugin", (compilation) => { - console.log("at this compilation"); + compiler.hooks.compilation.tap( + "DocGenPlugin", + (compilation, { normalModuleFactory }) => { + console.log("at compilation"); + + // TODO: What is ConstDependency? Is it needed? + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); + compilation.dependencyFactories.set( + // eslint-disable-next-line + // @ts-ignore TODO: Figure out why this isn't allowed + DocGenDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + // eslint-disable-next-line + // @ts-ignore TODO: Figure out why this isn't allowed + DocGenDependency, + new DocGenDependency.Template() + ); - compilation.dependencyTemplates.set( // eslint-disable-next-line - // @ts-ignore TODO: Figure out why this isn't allowed - DocGenDependency, - new DocGenDependency.Template() - ); + // @ts-ignore: TODO: What's the type of a parser? + const handler = (parser) => { + console.log("parser", parser.state); + if (parser.state) { + console.log("found parser state"); + + // what parameters to pass? + const dependency = new DocGenDependency(); + + parser.state.module.addDependency(dependency); + } + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("ProvidePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("ProvidePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("ProvidePlugin", handler); + + /* compilation.hooks.buildModule.tap("DocGenPlugin", (module) => { // eslint-disable-next-line // @ts-ignore @@ -236,7 +277,9 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates // @ts-ignore TODO: Figure out why assinging a sub-class doesn't work module.addDependency(dependency); }); - }); + */ + } + ); } // TODO: Eliminate this one after the new apply works diff --git a/webpack.config.js b/webpack.config.js index b831324..ad31e25 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,8 +1,12 @@ +const path = require("path"); const { ReactDocgenTypeScriptPlugin } = require("./"); module.exports = { mode: "development", entry: { main: "./src/__tests__/__fixtures__/Simple.tsx" }, + output: { + path: path.join(__dirname, "./example-dist"), + }, plugins: [new ReactDocgenTypeScriptPlugin()], module: { rules: [ From e076106ac0dd9df618dba5a834d11951c8372bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 10:44:25 +0300 Subject: [PATCH 25/80] fix: Use the correct plugin name --- src/plugin.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index a9a8865..c268146 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -212,8 +212,10 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates console.log("applying plugin"); + const pluginName = "DocGenPlugin"; + compiler.hooks.compilation.tap( - "DocGenPlugin", + pluginName, (compilation, { normalModuleFactory }) => { console.log("at compilation"); @@ -252,13 +254,13 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates normalModuleFactory.hooks.parser .for("javascript/auto") - .tap("ProvidePlugin", handler); + .tap(pluginName, handler); normalModuleFactory.hooks.parser .for("javascript/dynamic") - .tap("ProvidePlugin", handler); + .tap(pluginName, handler); normalModuleFactory.hooks.parser .for("javascript/esm") - .tap("ProvidePlugin", handler); + .tap(pluginName, handler); /* compilation.hooks.buildModule.tap("DocGenPlugin", (module) => { From bf0635f013f398e13751e21945d38d466de66703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 10:49:56 +0300 Subject: [PATCH 26/80] fix: Use the right hook to add the module dependency --- src/plugin.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index c268146..70a8e78 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -240,16 +240,12 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates // eslint-disable-next-line // @ts-ignore: TODO: What's the type of a parser? const handler = (parser) => { - console.log("parser", parser.state); - - if (parser.state) { - console.log("found parser state"); - - // what parameters to pass? + parser.hooks.program.tap(pluginName, () => { + // TODO: what parameters to pass? const dependency = new DocGenDependency(); parser.state.module.addDependency(dependency); - } + }); }; normalModuleFactory.hooks.parser From df50685000ded49c71e6f55feecbf1bc838cb634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 10:57:47 +0300 Subject: [PATCH 27/80] fix: Pass the right value to the dependency --- src/dependency.ts | 6 +++-- src/plugin.ts | 66 ++++++++++++++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index 4e8c03d..90a9aac 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -41,12 +41,13 @@ class DocGenDependency extends ModuleDependency { } get category(): string { - return "esm"; // "docs"; + return "docs"; } // TODO: updateHash, serialize, deserialize } +// TODO makeSerializable(DocGenDependency, "src/dependency"); class DocGenTemplate extends ModuleDependency.Template { @@ -60,7 +61,8 @@ class DocGenTemplate extends ModuleDependency.Template { console.log("APPLYING template"); // TODO: Insert type annotations here - source.insert(0, "hello world"); + // source.insert(0, "hello world"); + // source.replace(0, 10, "hello world"); } } diff --git a/src/plugin.ts b/src/plugin.ts index 70a8e78..d05a279 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -241,10 +241,49 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates // @ts-ignore: TODO: What's the type of a parser? const handler = (parser) => { parser.hooks.program.tap(pluginName, () => { - // TODO: what parameters to pass? - const dependency = new DocGenDependency(); - - parser.state.module.addDependency(dependency); + // eslint-disable-next-line + // @ts-ignore + const { module } = parser.state; + + if (!module.built) { + debugExclude(`Ignoring un-built module: ${module.userRequest}`); + return; + } + + if (module.external) { + debugExclude(`Ignoring external module: ${module.userRequest}`); + return; + } + + if (!module.rawRequest) { + debugExclude( + `Ignoring module without "rawRequest": ${module.userRequest}` + ); + return; + } + + // TODO: Re-enable + /* + if (isExcluded(module.userRequest)) { + debugExclude( + `Module not matched in "exclude": ${module.userRequest}` + ); + return; + } + + if (!isIncluded(module.userRequest)) { + debugExclude( + `Module not matched in "include": ${module.userRequest}` + ); + return; + } + */ + + // eslint-disable-next-line + // @ts-ignore + const dependency = new DocGenDependency(module.request); + + module.addDependency(dependency); }); }; @@ -257,25 +296,6 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates normalModuleFactory.hooks.parser .for("javascript/esm") .tap(pluginName, handler); - - /* - compilation.hooks.buildModule.tap("DocGenPlugin", (module) => { - // eslint-disable-next-line - // @ts-ignore - console.log("at build module", module.request); - - // eslint-disable-next-line - // @ts-ignore - const dependency = new DocGenDependency(module.request); - - // TODO: Add the dependency based on include/exclude. For now, - // we apply for everything. - - // eslint-disable-next-line - // @ts-ignore TODO: Figure out why assinging a sub-class doesn't work - module.addDependency(dependency); - }); - */ } ); } From 605dac3540692d47aadd8f7bd08b7f8233698daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 11:39:31 +0300 Subject: [PATCH 28/80] chore: Add logging --- src/dependency.ts | 2 +- src/plugin.ts | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/dependency.ts b/src/dependency.ts index 90a9aac..3a7e33f 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -61,7 +61,7 @@ class DocGenTemplate extends ModuleDependency.Template { console.log("APPLYING template"); // TODO: Insert type annotations here - // source.insert(0, "hello world"); + source.insert(0, "hello world"); // source.replace(0, 10, "hello world"); } } diff --git a/src/plugin.ts b/src/plugin.ts index d05a279..26c6e63 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -245,7 +245,11 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates // @ts-ignore const { module } = parser.state; + console.log("module", module.rawRequest); + if (!module.built) { + console.log("ignoring built"); + debugExclude(`Ignoring un-built module: ${module.userRequest}`); return; } @@ -262,6 +266,8 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates return; } + console.log("adding dependency"); + // TODO: Re-enable /* if (isExcluded(module.userRequest)) { From 6ff78757cdb24300489a9b10a2f8eaeadfc9bbd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 11:42:46 +0300 Subject: [PATCH 29/80] chore: Simplify code --- src/plugin.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index 26c6e63..4ebf57f 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -10,10 +10,6 @@ import findCacheDir from "find-cache-dir"; import flatCache from "flat-cache"; import crypto from "crypto"; -// eslint-disable-next-line -// @ts-ignore TODO: Figure out where to find a typed version -import ConstDependency from "webpack/lib/dependencies/ConstDependency"; - import DocGenDependency from "./dependency"; import { generateDocgenCodeBlock } from "./generateDocgenCodeBlock"; @@ -219,17 +215,6 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates (compilation, { normalModuleFactory }) => { console.log("at compilation"); - // TODO: What is ConstDependency? Is it needed? - compilation.dependencyTemplates.set( - ConstDependency, - new ConstDependency.Template() - ); - compilation.dependencyFactories.set( - // eslint-disable-next-line - // @ts-ignore TODO: Figure out why this isn't allowed - DocGenDependency, - normalModuleFactory - ); compilation.dependencyTemplates.set( // eslint-disable-next-line // @ts-ignore TODO: Figure out why this isn't allowed From 3b5e7bb6c0e2f306756ea22c2ce8af0e777c4b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 11:53:45 +0300 Subject: [PATCH 30/80] fix: Emit hello world demo correctly --- src/dependency.ts | 2 -- src/plugin.ts | 33 ++++++--------------------------- 2 files changed, 6 insertions(+), 29 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index 3a7e33f..b723116 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -47,7 +47,6 @@ class DocGenDependency extends ModuleDependency { // TODO: updateHash, serialize, deserialize } -// TODO makeSerializable(DocGenDependency, "src/dependency"); class DocGenTemplate extends ModuleDependency.Template { @@ -62,7 +61,6 @@ class DocGenTemplate extends ModuleDependency.Template { // TODO: Insert type annotations here source.insert(0, "hello world"); - // source.replace(0, 10, "hello world"); } } diff --git a/src/plugin.ts b/src/plugin.ts index 4ebf57f..a653669 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -195,26 +195,11 @@ export default class DocgenPlugin { } apply(compiler: webpack.Compiler): void { - // TODO: Add new logic here - /* -Instead of modifying the source code directly: Add a Dependency to the Module via module.addDependency. Register a DependencyTemplate for that Dependency class (compilation.dependencyTemplates.set(...)). In the DependencyTemplate you can add the code block to the source. Note if you want that modules correctly invalidate and cache you need to add updateHash to your Dependency and hash the type info (because that might change depending on outside factors (other modules). Add a Dependency to the Module via module.addDependency. This should happen during building of modules -> compilation.hooks.buildModule. Dependencies are cached with the Module. The result of the DependencyTemplate is cached when the hash is equal. -*/ - /* -You don't need that tsProgram in buildModule. That can stay in seal. In buildModule you only need to add the Dependency. That's will not need the information from typescript before code generation, which happens during seal (seal hook is the start of seal). -*/ - /* -Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates. They add them during parsing, but adding them in buildModule is also fine -*/ - - console.log("applying plugin"); - const pluginName = "DocGenPlugin"; compiler.hooks.compilation.tap( pluginName, (compilation, { normalModuleFactory }) => { - console.log("at compilation"); - compilation.dependencyTemplates.set( // eslint-disable-next-line // @ts-ignore TODO: Figure out why this isn't allowed @@ -230,12 +215,10 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates // @ts-ignore const { module } = parser.state; - console.log("module", module.rawRequest); - - if (!module.built) { - console.log("ignoring built"); - - debugExclude(`Ignoring un-built module: ${module.userRequest}`); + // Break the recursion. Without this the plugin will get stuck in + // an eternal loop as dependencies are added. + if (!module.userRequest) { + debugExclude(`Ignoring external module: ${module.userRequest}`); return; } @@ -251,9 +234,7 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates return; } - console.log("adding dependency"); - - // TODO: Re-enable + // TODO: Re-enable these two /* if (isExcluded(module.userRequest)) { debugExclude( @@ -272,9 +253,7 @@ Most plugins in webpack/lib/dependencies/*Plugin.js add Dependency and Templates // eslint-disable-next-line // @ts-ignore - const dependency = new DocGenDependency(module.request); - - module.addDependency(dependency); + module.addDependency(new DocGenDependency(module.request)); }); }; From df2042e1c15ea611eaba72052e980d016e991706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 12:31:51 +0300 Subject: [PATCH 31/80] refactor: Extract documentation generator + fix include/exclude --- package.json | 2 - src/dependency.ts | 17 ++-- src/generateDocs.ts | 35 ++++++++ src/plugin.ts | 193 +++----------------------------------------- src/types.ts | 45 +++++++++++ yarn.lock | 33 +------- 6 files changed, 102 insertions(+), 223 deletions(-) create mode 100644 src/generateDocs.ts create mode 100644 src/types.ts diff --git a/package.json b/package.json index 6a4f866..91fc038 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,6 @@ "dependencies": { "debug": "^4.1.1", "endent": "^2.0.1", - "find-cache-dir": "^3.3.1", - "flat-cache": "^3.0.4", "micromatch": "^4.0.2", "react-docgen-typescript": "^1.20.5", "tslib": "^2.0.0", diff --git a/src/dependency.ts b/src/dependency.ts index b723116..01235c6 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -1,6 +1,7 @@ /* eslint-disable max-classes-per-file */ import { ReplaceSource } from "webpack-sources"; +import * as docGen from "react-docgen-typescript"; // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? @@ -50,13 +51,15 @@ class DocGenDependency extends ModuleDependency { makeSerializable(DocGenDependency, "src/dependency"); class DocGenTemplate extends ModuleDependency.Template { - /** - * @param {Dependency} dependency the dependency for which the template should be applied - * @param {ReplaceSource} source the current replace source which can be modified - * @param {DependencyTemplateContext} templateContext the context object - * @returns {void} - */ - apply(dependency: Dependency, source: ReplaceSource) { + private parser: docGen.FileParser; + + constructor(parser: docGen.FileParser) { + super(); + + this.parser = parser; + } + + apply(dependency: Dependency, source: ReplaceSource): void { console.log("APPLYING template"); // TODO: Insert type annotations here diff --git a/src/generateDocs.ts b/src/generateDocs.ts new file mode 100644 index 0000000..a715dd7 --- /dev/null +++ b/src/generateDocs.ts @@ -0,0 +1,35 @@ +import ts from "typescript"; +import * as docGen from "react-docgen-typescript"; + +import { generateDocgenCodeBlock } from "./generateDocgenCodeBlock"; +import { LoaderOptions, Module } from "./types"; + +/** Run the docgen parser and return the result */ +function generateDocs( + parser: docGen.FileParser, + webpackModule: Module, + tsProgram: ts.Program, + loaderOptions: Required +): string { + if (!webpackModule) { + return ""; + } + + const componentDocs = parser.parseWithProgramProvider( + webpackModule.userRequest, + () => tsProgram + ); + + if (!componentDocs.length) { + return ""; + } + + return generateDocgenCodeBlock({ + filename: webpackModule.userRequest, + source: webpackModule.userRequest, + componentDocs, + ...loaderOptions, + }).substring(webpackModule.userRequest.length); +} + +export default generateDocs; diff --git a/src/plugin.ts b/src/plugin.ts index a653669..f362acc 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -6,20 +6,11 @@ import * as webpack from "webpack"; import ts from "typescript"; import * as docGen from "react-docgen-typescript"; import { matcher } from "micromatch"; -import findCacheDir from "find-cache-dir"; -import flatCache from "flat-cache"; -import crypto from "crypto"; +import { LoaderOptions } from "./types"; import DocGenDependency from "./dependency"; -import { generateDocgenCodeBlock } from "./generateDocgenCodeBlock"; const debugExclude = createDebug("docgen:exclude"); -const debugInclude = createDebug("docgen:include"); -const debugDocs = createDebug("docgen:docs"); - -const cacheId = "ts-docgen"; -const cacheDir = findCacheDir({ name: cacheId }); -const cache = flatCache.load(cacheId, cacheDir); interface TypescriptOptions { /** @@ -31,41 +22,6 @@ interface TypescriptOptions { compilerOptions?: ts.CompilerOptions; } -interface LoaderOptions { - /** - * Specify the docgen collection name to use. All docgen information will - * be collected into this global object. Set to null to disable. - * - * @default STORYBOOK_REACT_CLASSES - * @see https://github.com/gongreg/react-storybook-addon-docgen - **/ - docgenCollectionName?: string | null; - - /** - * Automatically set the component's display name. If you want to set display - * names yourself or are using another plugin to do this, you should disable - * this option. - * - * ``` - * class MyComponent extends React.Component { - * ... - * } - * - * MyComponent.displayName = "MyComponent"; - * ``` - * - * @default true - */ - setDisplayName?: boolean; - - /** - * Specify the name of the property for docgen info prop type. - * - * @default "type" - */ - typePropName?: string; -} - export type PluginOptions = docGen.ParserOptions & LoaderOptions & TypescriptOptions & { @@ -75,65 +31,6 @@ export type PluginOptions = docGen.ParserOptions & include?: string[]; }; -interface Module { - userRequest: string; - request: string; - built?: boolean; - rawRequest?: string; - external?: boolean; - _source: { - _value: string; - }; -} - -/** Run the docgen parser and inject the result into the output */ -function processModule( - parser: docGen.FileParser, - webpackModule: Module, - tsProgram: ts.Program, - loaderOptions: Required -) { - if (!webpackModule) { - return; - } - - const hash = crypto - .createHash("sha1") - .update(webpackModule._source._value) - .digest("hex"); - const cached = cache.getKey(hash); - - if (cached) { - debugInclude(`Got cached docgen for "${webpackModule.request}"`); - webpackModule._source._value = cached; - return; - } - - const componentDocs = parser.parseWithProgramProvider( - webpackModule.userRequest, - () => tsProgram - ); - - if (!componentDocs.length) { - return; - } - - const docs = generateDocgenCodeBlock({ - filename: webpackModule.userRequest, - source: webpackModule.userRequest, - componentDocs, - ...loaderOptions, - }).substring(webpackModule.userRequest.length); - - debugDocs(docs); - - let sourceWithDocs = webpackModule._source._value; - sourceWithDocs += `\n${docs}\n`; - webpackModule._source._value = sourceWithDocs; - - cache.setKey(hash, sourceWithDocs); -} - /** Get the contents of the tsconfig in the system */ function getTSConfigFile(tsconfigPath: string): ts.ParsedCommandLine { try { @@ -153,8 +50,8 @@ function getTSConfigFile(tsconfigPath: string): ts.ParsedCommandLine { } /** Create a glob matching function. */ -const matchGlob = (globs: string[]) => { - const matchers = globs.map((g) => matcher(g)); +const matchGlob = (globs?: string[]) => { + const matchers = (globs || []).map((g) => matcher(g)); return (filename: string) => Boolean(filename && matchers.find((match) => match(filename))); }; @@ -197,6 +94,10 @@ export default class DocgenPlugin { apply(compiler: webpack.Compiler): void { const pluginName = "DocGenPlugin"; + const { exclude, include } = this.options; + const isExcluded = matchGlob(exclude); + const isIncluded = matchGlob(include); + compiler.hooks.compilation.tap( pluginName, (compilation, { normalModuleFactory }) => { @@ -204,7 +105,7 @@ export default class DocgenPlugin { // eslint-disable-next-line // @ts-ignore TODO: Figure out why this isn't allowed DocGenDependency, - new DocGenDependency.Template() + new DocGenDependency.Template(this.parser) ); // eslint-disable-next-line @@ -234,22 +135,19 @@ export default class DocgenPlugin { return; } - // TODO: Re-enable these two - /* if (isExcluded(module.userRequest)) { debugExclude( `Module not matched in "exclude": ${module.userRequest}` ); return; } - + if (!isIncluded(module.userRequest)) { debugExclude( `Module not matched in "include": ${module.userRequest}` ); return; } - */ // eslint-disable-next-line // @ts-ignore @@ -269,79 +167,6 @@ export default class DocgenPlugin { } ); } - - // TODO: Eliminate this one after the new apply works - oldApply(compiler: webpack.Compiler): void { - const { - docgenCollectionName = "STORYBOOK_REACT_CLASSES", - setDisplayName = true, - typePropName = "type", - exclude = [], - include = ["**/**.tsx"], - } = this.options; - - const isExcluded = matchGlob(exclude); - const isIncluded = matchGlob(include); - - compiler.hooks.make.tap(this.name, (compilation) => { - compilation.hooks.seal.tap(this.name, () => { - const modulesToProcess: Module[] = []; - - // eslint-disable-next-line - // @ts-ignore TODO: Module type - compilation.modules.forEach((module: Module) => { - if (!module.built) { - debugExclude(`Ignoring un-built module: ${module.userRequest}`); - return; - } - - if (module.external) { - debugExclude(`Ignoring external module: ${module.userRequest}`); - return; - } - - if (!module.rawRequest) { - debugExclude( - `Ignoring module without "rawRequest": ${module.userRequest}` - ); - return; - } - - if (isExcluded(module.userRequest)) { - debugExclude( - `Module not matched in "exclude": ${module.userRequest}` - ); - return; - } - - if (!isIncluded(module.userRequest)) { - debugExclude( - `Module not matched in "include": ${module.userRequest}` - ); - return; - } - - debugInclude(module.userRequest); - modulesToProcess.push(module); - }); - - const tsProgram = ts.createProgram( - modulesToProcess.map((v) => v.userRequest), - this.compilerOptions - ); - - modulesToProcess.forEach((m) => - processModule(this.parser, m, tsProgram, { - docgenCollectionName, - setDisplayName, - typePropName, - }) - ); - - cache.save(); - }); - }); - } } export type DocgenPluginType = typeof DocgenPlugin; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..f7c0888 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,45 @@ +export interface Module { + userRequest: string; + request: string; + built?: boolean; + rawRequest?: string; + external?: boolean; + _source: { + _value: string; + }; +} + +export interface LoaderOptions { + /** + * Specify the docgen collection name to use. All docgen information will + * be collected into this global object. Set to null to disable. + * + * @default STORYBOOK_REACT_CLASSES + * @see https://github.com/gongreg/react-storybook-addon-docgen + **/ + docgenCollectionName?: string | null; + + /** + * Automatically set the component's display name. If you want to set display + * names yourself or are using another plugin to do this, you should disable + * this option. + * + * ``` + * class MyComponent extends React.Component { + * ... + * } + * + * MyComponent.displayName = "MyComponent"; + * ``` + * + * @default true + */ + setDisplayName?: boolean; + + /** + * Specify the name of the property for docgen info prop type. + * + * @default "type" + */ + typePropName?: string; +} diff --git a/yarn.lock b/yarn.lock index 69cf9e7..744fbcb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1968,11 +1968,6 @@ comment-parser@^0.7.4: resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.7.5.tgz#06db157a3b34addf8502393743e41897e2c73059" integrity sha512-iH9YA35ccw94nx5244GVkpyC9eVTsL71jZz6iz5w6RIf79JLF2AsXHXq9p6Oaohyl3sx5qSMnGsWUDFIAfWL4w== -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -2892,15 +2887,6 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -find-cache-dir@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" - integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - find-replace@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" @@ -2932,24 +2918,11 @@ flat-cache@^2.0.1: rimraf "2.6.3" write "1.0.3" -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - flatted@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== -flatted@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067" - integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA== - for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -4349,7 +4322,7 @@ macos-release@^2.2.0: resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== -make-dir@^3.0.0, make-dir@^3.0.2: +make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -5004,7 +4977,7 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" -pkg-dir@^4.1.0, pkg-dir@^4.2.0: +pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== @@ -5346,7 +5319,7 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" -rimraf@^3.0.0, rimraf@^3.0.2: +rimraf@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== From 927d97bc4aa806869bc68758686263ed1f1e7b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 12:34:00 +0300 Subject: [PATCH 32/80] fix: Use same defaults for include/exclude as before --- src/plugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugin.ts b/src/plugin.ts index f362acc..826ccf7 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -94,7 +94,7 @@ export default class DocgenPlugin { apply(compiler: webpack.Compiler): void { const pluginName = "DocGenPlugin"; - const { exclude, include } = this.options; + const { exclude = [], include = ["**/**.tsx"] } = this.options; const isExcluded = matchGlob(exclude); const isIncluded = matchGlob(include); From 6a0f6099ec6330c2a23c19cb82164d89d47d387e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 12:50:12 +0300 Subject: [PATCH 33/80] chore: Sketch out doc generation through ts --- src/dependency.ts | 48 +++++++++++++++++++++++++++++++++++++-------- src/generateDocs.ts | 35 --------------------------------- src/plugin.ts | 8 +++++++- 3 files changed, 47 insertions(+), 44 deletions(-) delete mode 100644 src/generateDocs.ts diff --git a/src/dependency.ts b/src/dependency.ts index 01235c6..3917c86 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -2,6 +2,7 @@ import { ReplaceSource } from "webpack-sources"; import * as docGen from "react-docgen-typescript"; +import ts from "typescript"; // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? @@ -15,9 +16,8 @@ import makeSerializable from "webpack/lib/util/makeSerializable.js"; // @ts-ignore TODO: Figure out where to find a typed version import Dependency from "webpack/lib/Dependency.js"; -// eslint-disable-next-line -// @ts-ignore TODO: Figure out where to find a typed version -// import Hash from "webpack/lib/util/Hash.js"; +import { generateDocgenCodeBlock } from "./generateDocgenCodeBlock"; +import { LoaderOptions } from "./types"; class DocGenDependency extends ModuleDependency { public static Template: ModuleDependency.Template; @@ -50,20 +50,52 @@ class DocGenDependency extends ModuleDependency { makeSerializable(DocGenDependency, "src/dependency"); +type Options = { + parser: docGen.FileParser; + compilerOptions: ts.CompilerOptions; +} & LoaderOptions; + class DocGenTemplate extends ModuleDependency.Template { - private parser: docGen.FileParser; + private options: Options; - constructor(parser: docGen.FileParser) { + constructor(options: Options) { super(); - this.parser = parser; + this.options = options; } apply(dependency: Dependency, source: ReplaceSource): void { console.log("APPLYING template"); - // TODO: Insert type annotations here - source.insert(0, "hello world"); + const { userRequest } = dependency; + + const tsProgram = ts.createProgram( + userRequest, + this.options.compilerOptions + ); + const componentDocs = this.options.parser.parseWithProgramProvider( + userRequest, + () => tsProgram + ); + + if (!componentDocs.length) { + return; + } + + console.log("GENERATING docgen codeblock"); + + // TODO: Instead of substring, should this replace instead? + const docgenBlock = generateDocgenCodeBlock({ + filename: userRequest, + source: userRequest, + componentDocs, + docgenCollectionName: + this.options.docgenCollectionName || "STORYBOOK_REACT_CLASSES", + setDisplayName: this.options.setDisplayName || true, + typePropName: this.options.typePropName || "type", + }).substring(userRequest.length); + + source.insert(userRequest.length, docgenBlock); } } diff --git a/src/generateDocs.ts b/src/generateDocs.ts deleted file mode 100644 index a715dd7..0000000 --- a/src/generateDocs.ts +++ /dev/null @@ -1,35 +0,0 @@ -import ts from "typescript"; -import * as docGen from "react-docgen-typescript"; - -import { generateDocgenCodeBlock } from "./generateDocgenCodeBlock"; -import { LoaderOptions, Module } from "./types"; - -/** Run the docgen parser and return the result */ -function generateDocs( - parser: docGen.FileParser, - webpackModule: Module, - tsProgram: ts.Program, - loaderOptions: Required -): string { - if (!webpackModule) { - return ""; - } - - const componentDocs = parser.parseWithProgramProvider( - webpackModule.userRequest, - () => tsProgram - ); - - if (!componentDocs.length) { - return ""; - } - - return generateDocgenCodeBlock({ - filename: webpackModule.userRequest, - source: webpackModule.userRequest, - componentDocs, - ...loaderOptions, - }).substring(webpackModule.userRequest.length); -} - -export default generateDocs; diff --git a/src/plugin.ts b/src/plugin.ts index 826ccf7..a0bad86 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -105,7 +105,13 @@ export default class DocgenPlugin { // eslint-disable-next-line // @ts-ignore TODO: Figure out why this isn't allowed DocGenDependency, - new DocGenDependency.Template(this.parser) + new DocGenDependency.Template({ + parser: this.parser, + compilerOptions: this.compilerOptions, + docgenCollectionName: this.options.docgenCollectionName, + setDisplayName: this.options.setDisplayName, + typePropName: this.options.typePropName, + }) ); // eslint-disable-next-line From 49f70cb362d07163b68ea8f12eb381cc62cef910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 12:55:54 +0300 Subject: [PATCH 34/80] chore: Add logging --- src/dependency.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/dependency.ts b/src/dependency.ts index 3917c86..a82a807 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -69,6 +69,8 @@ class DocGenTemplate extends ModuleDependency.Template { const { userRequest } = dependency; + console.log("user request", userRequest); + const tsProgram = ts.createProgram( userRequest, this.options.compilerOptions @@ -95,6 +97,8 @@ class DocGenTemplate extends ModuleDependency.Template { typePropName: this.options.typePropName || "type", }).substring(userRequest.length); + console.log("DOCGEN block", docgenBlock); + source.insert(userRequest.length, docgenBlock); } } From c9faa096319b0f60f8d3fb251dcd79f46fec0b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 12:59:51 +0300 Subject: [PATCH 35/80] fix: Fix type error --- src/dependency.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dependency.ts b/src/dependency.ts index a82a807..a3e51f5 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -72,7 +72,7 @@ class DocGenTemplate extends ModuleDependency.Template { console.log("user request", userRequest); const tsProgram = ts.createProgram( - userRequest, + [userRequest], this.options.compilerOptions ); const componentDocs = this.options.parser.parseWithProgramProvider( @@ -80,6 +80,8 @@ class DocGenTemplate extends ModuleDependency.Template { () => tsProgram ); + console.log("component docs", componentDocs); + if (!componentDocs.length) { return; } From 2fc6014200d02fbefb9676ca4b5d292ea5d982e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 13:04:13 +0300 Subject: [PATCH 36/80] chore: Tidy up --- src/dependency.ts | 10 ++++++---- src/plugin.ts | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index a3e51f5..8b40947 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -53,7 +53,8 @@ makeSerializable(DocGenDependency, "src/dependency"); type Options = { parser: docGen.FileParser; compilerOptions: ts.CompilerOptions; -} & LoaderOptions; + docgenOptions: LoaderOptions; +}; class DocGenTemplate extends ModuleDependency.Template { private options: Options; @@ -94,9 +95,10 @@ class DocGenTemplate extends ModuleDependency.Template { source: userRequest, componentDocs, docgenCollectionName: - this.options.docgenCollectionName || "STORYBOOK_REACT_CLASSES", - setDisplayName: this.options.setDisplayName || true, - typePropName: this.options.typePropName || "type", + this.options.docgenOptions.docgenCollectionName || + "STORYBOOK_REACT_CLASSES", + setDisplayName: this.options.docgenOptions.setDisplayName || true, + typePropName: this.options.docgenOptions.typePropName || "type", }).substring(userRequest.length); console.log("DOCGEN block", docgenBlock); diff --git a/src/plugin.ts b/src/plugin.ts index a0bad86..b5827e4 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -62,6 +62,7 @@ export default class DocgenPlugin { private options: PluginOptions; private parser: docGen.FileParser; private compilerOptions: ts.CompilerOptions; + private docgenOptions: LoaderOptions; constructor(options: PluginOptions = {}) { const { @@ -88,6 +89,7 @@ export default class DocgenPlugin { this.options = options; this.compilerOptions = compilerOptions; + this.docgenOptions = docgenOptions; this.parser = docGen.withCompilerOptions(compilerOptions, docgenOptions); } @@ -108,9 +110,7 @@ export default class DocgenPlugin { new DocGenDependency.Template({ parser: this.parser, compilerOptions: this.compilerOptions, - docgenCollectionName: this.options.docgenCollectionName, - setDisplayName: this.options.setDisplayName, - typePropName: this.options.typePropName, + docgenOptions: this.docgenOptions, }) ); From 8452db51aa802ea3c3b24c64b0a407cad442b1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 13:09:38 +0300 Subject: [PATCH 37/80] chore: Simplify docgen usage --- package.json | 2 +- src/dependency.ts | 10 +--------- src/plugin.ts | 1 - yarn.lock | 8 ++++---- 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 91fc038..d815fa4 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "debug": "^4.1.1", "endent": "^2.0.1", "micromatch": "^4.0.2", - "react-docgen-typescript": "^1.20.5", + "react-docgen-typescript": "^1.22.0", "tslib": "^2.0.0", "webpack-sources": "^2.2.0" }, diff --git a/src/dependency.ts b/src/dependency.ts index 8b40947..db1b583 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -52,7 +52,6 @@ makeSerializable(DocGenDependency, "src/dependency"); type Options = { parser: docGen.FileParser; - compilerOptions: ts.CompilerOptions; docgenOptions: LoaderOptions; }; @@ -72,14 +71,7 @@ class DocGenTemplate extends ModuleDependency.Template { console.log("user request", userRequest); - const tsProgram = ts.createProgram( - [userRequest], - this.options.compilerOptions - ); - const componentDocs = this.options.parser.parseWithProgramProvider( - userRequest, - () => tsProgram - ); + const componentDocs = this.options.parser.parse(userRequest); console.log("component docs", componentDocs); diff --git a/src/plugin.ts b/src/plugin.ts index b5827e4..7441288 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -109,7 +109,6 @@ export default class DocgenPlugin { DocGenDependency, new DocGenDependency.Template({ parser: this.parser, - compilerOptions: this.compilerOptions, docgenOptions: this.docgenOptions, }) ); diff --git a/yarn.lock b/yarn.lock index 744fbcb..6bee0d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5081,10 +5081,10 @@ rc@^1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-docgen-typescript@^1.20.5: - version "1.20.5" - resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.20.5.tgz#fb8d78a707243498436c2952bd3f6f488a68d4f3" - integrity sha512-AbLGMtn76bn7SYBJSSaKJrZ0lgNRRR3qL60PucM5M4v/AXyC8221cKBXW5Pyt9TfDRfe+LDnPNlg7TibxX0ovA== +react-docgen-typescript@^1.22.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.22.0.tgz#00232c8e8e47f4437cac133b879b3e9437284bee" + integrity sha512-MPLbF8vzRwAG3GcjdL+OHQlhgtWsLTXs+7uJiHfEeT3Ur7IsZaNYqRTLQ9sj2nB6M6jylcPCeCmH7qbszJmecg== react-is@^17.0.1: version "17.0.1" From 48ff075309bf636411003482cb96d7f9bf9ded73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 13:13:29 +0300 Subject: [PATCH 38/80] chore: Use Column example --- src/__tests__/__fixtures__/Column.tsx | 27 +++++++++++++++++++++++++++ webpack.config.js | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/__tests__/__fixtures__/Column.tsx diff --git a/src/__tests__/__fixtures__/Column.tsx b/src/__tests__/__fixtures__/Column.tsx new file mode 100644 index 0000000..d99623a --- /dev/null +++ b/src/__tests__/__fixtures__/Column.tsx @@ -0,0 +1,27 @@ +import * as React from "react"; +import { Component } from "react"; + +/** + * Column properties. + */ +export interface IColumnProps { + /** prop1 description */ + prop1?: string; + /** prop2 description */ + prop2: number; + /** + * prop3 description + */ + prop3: () => void; + /** prop4 description */ + prop4: "option1" | "option2" | "option3"; +} + +/** + * Form column. + */ +export class Column extends Component { + render() { + return
Test
; + } +} diff --git a/webpack.config.js b/webpack.config.js index ad31e25..71a8091 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -3,7 +3,7 @@ const { ReactDocgenTypeScriptPlugin } = require("./"); module.exports = { mode: "development", - entry: { main: "./src/__tests__/__fixtures__/Simple.tsx" }, + entry: { main: "./src/__tests__/__fixtures__/Column.tsx" }, output: { path: path.join(__dirname, "./example-dist"), }, From d3bd544a5988f1e2d3c162c3b8a5b20977edcb7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 13:19:44 +0300 Subject: [PATCH 39/80] fix: Make doc generation work --- src/dependency.ts | 15 ++++----------- src/plugin.ts | 2 ++ 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index db1b583..dc428db 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -65,22 +65,17 @@ class DocGenTemplate extends ModuleDependency.Template { } apply(dependency: Dependency, source: ReplaceSource): void { - console.log("APPLYING template"); - const { userRequest } = dependency; - console.log("user request", userRequest); - - const componentDocs = this.options.parser.parse(userRequest); - - console.log("component docs", componentDocs); + // TODO: Make sure this is foolproof. Is there a better way + // to get a pure path? + const modulePath = userRequest.split("!")[1]; + const componentDocs = this.options.parser.parse(modulePath); if (!componentDocs.length) { return; } - console.log("GENERATING docgen codeblock"); - // TODO: Instead of substring, should this replace instead? const docgenBlock = generateDocgenCodeBlock({ filename: userRequest, @@ -93,8 +88,6 @@ class DocGenTemplate extends ModuleDependency.Template { typePropName: this.options.docgenOptions.typePropName || "type", }).substring(userRequest.length); - console.log("DOCGEN block", docgenBlock); - source.insert(userRequest.length, docgenBlock); } } diff --git a/src/plugin.ts b/src/plugin.ts index 7441288..b6993c9 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -90,6 +90,8 @@ export default class DocgenPlugin { this.options = options; this.compilerOptions = compilerOptions; this.docgenOptions = docgenOptions; + + // Maintain the doc gen parser here to save time later this.parser = docGen.withCompilerOptions(compilerOptions, docgenOptions); } From 201dcf0536304989f75cb9b702c756f249a02a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 13:51:30 +0300 Subject: [PATCH 40/80] chore: Drop Column fixture as that's not needed anymore --- src/__tests__/__fixtures__/Column.tsx | 27 --------------------------- webpack.config.js | 2 +- 2 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 src/__tests__/__fixtures__/Column.tsx diff --git a/src/__tests__/__fixtures__/Column.tsx b/src/__tests__/__fixtures__/Column.tsx deleted file mode 100644 index d99623a..0000000 --- a/src/__tests__/__fixtures__/Column.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import * as React from "react"; -import { Component } from "react"; - -/** - * Column properties. - */ -export interface IColumnProps { - /** prop1 description */ - prop1?: string; - /** prop2 description */ - prop2: number; - /** - * prop3 description - */ - prop3: () => void; - /** prop4 description */ - prop4: "option1" | "option2" | "option3"; -} - -/** - * Form column. - */ -export class Column extends Component { - render() { - return
Test
; - } -} diff --git a/webpack.config.js b/webpack.config.js index 71a8091..ad31e25 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -3,7 +3,7 @@ const { ReactDocgenTypeScriptPlugin } = require("./"); module.exports = { mode: "development", - entry: { main: "./src/__tests__/__fixtures__/Column.tsx" }, + entry: { main: "./src/__tests__/__fixtures__/Simple.tsx" }, output: { path: path.join(__dirname, "./example-dist"), }, From 69dc9898838ae220e9f57b6bcf84b80ec0d1ccd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 13:58:53 +0300 Subject: [PATCH 41/80] chore: Improve logic --- src/dependency.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index dc428db..b29f56a 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -67,16 +67,19 @@ class DocGenTemplate extends ModuleDependency.Template { apply(dependency: Dependency, source: ReplaceSource): void { const { userRequest } = dependency; - // TODO: Make sure this is foolproof. Is there a better way - // to get a pure path? - const modulePath = userRequest.split("!")[1]; + // Since parsing fails with a path including !, remove it. + // The problem is that webpack injects that and there doesn't + // seem to be a good way to get only the path itself from + // a dependency. + const modulePath = userRequest.includes("!") + ? userRequest.split("!")[1] + : userRequest; const componentDocs = this.options.parser.parse(modulePath); if (!componentDocs.length) { return; } - // TODO: Instead of substring, should this replace instead? const docgenBlock = generateDocgenCodeBlock({ filename: userRequest, source: userRequest, From cbe836c390c7a9af2958c7d69146087e845b22c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 14:01:54 +0300 Subject: [PATCH 42/80] chore: Drop redundant code --- src/dependency.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index b29f56a..fa18cca 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -2,7 +2,6 @@ import { ReplaceSource } from "webpack-sources"; import * as docGen from "react-docgen-typescript"; -import ts from "typescript"; // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? @@ -22,17 +21,6 @@ import { LoaderOptions } from "./types"; class DocGenDependency extends ModuleDependency { public static Template: ModuleDependency.Template; - /** - * @param {string} request request - */ - /* constructor(request: string) { - super(request); - } */ - - updateHash(): void { - // TODO: See ConstDependency for reference - } - getReferencedExports(): [] { return Dependency.NO_EXPORTS_REFERENCED; } @@ -44,8 +32,6 @@ class DocGenDependency extends ModuleDependency { get category(): string { return "docs"; } - - // TODO: updateHash, serialize, deserialize } makeSerializable(DocGenDependency, "src/dependency"); From 6dd88f25b282947a7b56ae1d795dd0b0587a39e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 14:08:05 +0300 Subject: [PATCH 43/80] chore: Add initial test to make sure docgen emits --- src/__tests__/plugin.test.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/__tests__/plugin.test.ts b/src/__tests__/plugin.test.ts index cae7ef6..8270a92 100644 --- a/src/__tests__/plugin.test.ts +++ b/src/__tests__/plugin.test.ts @@ -35,11 +35,11 @@ function compile(config: Configuration): Promise { }); } -// TODO: Maybe it's easier for testing to expose a way to write types to the fs const getConfig = ( options = {}, config: { title?: string } = {} ): Configuration => ({ + mode: "none", entry: { main: "./src/__tests__/__fixtures__/Simple.tsx" }, plugins: [new ReactDocgenTypeScriptPlugin(options)], module: { @@ -56,11 +56,9 @@ const getConfig = ( ...config, }); +// TODO: What else to test and how? test("default options", async () => { const result = await compile(getConfig({})); - // console.log("result", result); - - // expect(result).toMatchSnapshot(); - expect(true).toEqual(true); + expect(result).toContain("STORYBOOK_REACT_CLASSES"); }); From a0b4c6d9817b7d9a91474312d9d171c95590bc0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 14:09:32 +0300 Subject: [PATCH 44/80] chore: Add a todo --- webpack.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/webpack.config.js b/webpack.config.js index ad31e25..54a6a94 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,3 +1,4 @@ +// TODO: How to resolve ts parser issue? Better port config to ts? const path = require("path"); const { ReactDocgenTypeScriptPlugin } = require("./"); From da1836519e051bfb388dfe40c031d667a44ce170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 10 May 2021 14:09:52 +0300 Subject: [PATCH 45/80] chore: Drop a redundant snapshot --- .../__snapshots__/generateDocgenCodeBlock.test.ts.snap | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap b/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap index 36c90f7..316ff3d 100644 --- a/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap +++ b/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap @@ -230,12 +230,6 @@ try { catch (__react_docgen_typescript_loader_error) { }" `; -exports[`component fixture index.js has code block generated 1`] = ` -"// TODO: This should contain a simple React component to parse -console.log(\\"hello from index\\"); -" -`; - exports[`generates value info for enums 1`] = ` "import * as React from \\"react\\"; From 64f91ef52f4b1ad42a40598948e451fd2a6e6871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 10:37:32 +0300 Subject: [PATCH 46/80] chore: Add a todo --- src/dependency.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dependency.ts b/src/dependency.ts index fa18cca..d4614d5 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -32,6 +32,8 @@ class DocGenDependency extends ModuleDependency { get category(): string { return "docs"; } + + // TODO: Note if you want that modules correctly invalidate and cache you need to add updateHash to your Dependency and hash the type info (because that might change depending on outside factors (other modules) } makeSerializable(DocGenDependency, "src/dependency"); From a3965f6ad353d1beb6266c7336be2f0b1af01468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 14:03:06 +0300 Subject: [PATCH 47/80] fix: Use NullDependency --- src/dependency.ts | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index d4614d5..f5b0a8e 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -5,7 +5,7 @@ import * as docGen from "react-docgen-typescript"; // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? -import ModuleDependency from "webpack/lib/dependencies/ModuleDependency.js"; +import Module from "webpack/lib/Module.js"; // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? @@ -13,25 +13,13 @@ import makeSerializable from "webpack/lib/util/makeSerializable.js"; // eslint-disable-next-line // @ts-ignore TODO: Figure out where to find a typed version -import Dependency from "webpack/lib/Dependency.js"; +import NullDependency from "webpack/lib/dependencies/NullDependency.js"; import { generateDocgenCodeBlock } from "./generateDocgenCodeBlock"; import { LoaderOptions } from "./types"; -class DocGenDependency extends ModuleDependency { - public static Template: ModuleDependency.Template; - - getReferencedExports(): [] { - return Dependency.NO_EXPORTS_REFERENCED; - } - - get type(): string { - return "docgen"; - } - - get category(): string { - return "docs"; - } +class DocGenDependency extends NullDependency { + public static Template: NullDependency.Template; // TODO: Note if you want that modules correctly invalidate and cache you need to add updateHash to your Dependency and hash the type info (because that might change depending on outside factors (other modules) } @@ -43,7 +31,7 @@ type Options = { docgenOptions: LoaderOptions; }; -class DocGenTemplate extends ModuleDependency.Template { +class DocGenTemplate extends NullDependency.Template { private options: Options; constructor(options: Options) { @@ -52,8 +40,12 @@ class DocGenTemplate extends ModuleDependency.Template { this.options = options; } - apply(dependency: Dependency, source: ReplaceSource): void { - const { userRequest } = dependency; + apply( + dependency: NullDependency, + source: ReplaceSource, + { module }: { module: Module } + ): void { + const { userRequest } = module; // Since parsing fails with a path including !, remove it. // The problem is that webpack injects that and there doesn't From 19f789b0ce6c738d0fe0c099d75575d368613551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 14:05:35 +0300 Subject: [PATCH 48/80] fix: Use the correct path for serialization --- src/dependency.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dependency.ts b/src/dependency.ts index f5b0a8e..79c275f 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -24,7 +24,10 @@ class DocGenDependency extends NullDependency { // TODO: Note if you want that modules correctly invalidate and cache you need to add updateHash to your Dependency and hash the type info (because that might change depending on outside factors (other modules) } -makeSerializable(DocGenDependency, "src/dependency"); +makeSerializable( + DocGenDependency, + "react-docgen-typescript-plugin/dist/dependency" +); type Options = { parser: docGen.FileParser; From 521af9c642602df10a57241524035113fd0c9b20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 14:11:46 +0300 Subject: [PATCH 49/80] chore: Drop redundant code --- src/plugin.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index b6993c9..4c48780 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -123,18 +123,6 @@ export default class DocgenPlugin { // @ts-ignore const { module } = parser.state; - // Break the recursion. Without this the plugin will get stuck in - // an eternal loop as dependencies are added. - if (!module.userRequest) { - debugExclude(`Ignoring external module: ${module.userRequest}`); - return; - } - - if (module.external) { - debugExclude(`Ignoring external module: ${module.userRequest}`); - return; - } - if (!module.rawRequest) { debugExclude( `Ignoring module without "rawRequest": ${module.userRequest}` From a0f559fa61fa1d6ce92da19ab5d733e40eac06f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 14:14:22 +0300 Subject: [PATCH 50/80] chore: Simplify logic --- src/plugin.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index 4c48780..da9dbe4 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -122,24 +122,18 @@ export default class DocgenPlugin { // eslint-disable-next-line // @ts-ignore const { module } = parser.state; + const nameForCondition = module.nameForCondition(); - if (!module.rawRequest) { + if (isExcluded(nameForCondition)) { debugExclude( - `Ignoring module without "rawRequest": ${module.userRequest}` + `Module not matched in "exclude": ${nameForCondition}` ); return; } - if (isExcluded(module.userRequest)) { + if (!isIncluded(nameForCondition)) { debugExclude( - `Module not matched in "exclude": ${module.userRequest}` - ); - return; - } - - if (!isIncluded(module.userRequest)) { - debugExclude( - `Module not matched in "include": ${module.userRequest}` + `Module not matched in "include": ${nameForCondition}` ); return; } From ed02af9b74b2dc43dfe485154142175293777fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 14:23:30 +0300 Subject: [PATCH 51/80] fix: Insert code to the beginning This makes more sense. --- src/dependency.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dependency.ts b/src/dependency.ts index 79c275f..bd436d6 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -74,7 +74,7 @@ class DocGenTemplate extends NullDependency.Template { typePropName: this.options.docgenOptions.typePropName || "type", }).substring(userRequest.length); - source.insert(userRequest.length, docgenBlock); + source.insert(0, docgenBlock); } } From cea84f42ba8ce72601c1cef72af73a7d079fd7e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 16:18:55 +0300 Subject: [PATCH 52/80] refactor: Push parsing earlier --- src/dependency.ts | 43 +++++++++++++++++++++---------------------- src/plugin.ts | 7 ++++++- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index bd436d6..db5e9f6 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -20,6 +20,13 @@ import { LoaderOptions } from "./types"; class DocGenDependency extends NullDependency { public static Template: NullDependency.Template; + private componentDocs: docGen.ComponentDoc[]; + + constructor(request: string, componentDocs: docGen.ComponentDoc[]) { + super(request); + + this.componentDocs = componentDocs; + } // TODO: Note if you want that modules correctly invalidate and cache you need to add updateHash to your Dependency and hash the type info (because that might change depending on outside factors (other modules) } @@ -50,31 +57,23 @@ class DocGenTemplate extends NullDependency.Template { ): void { const { userRequest } = module; - // Since parsing fails with a path including !, remove it. - // The problem is that webpack injects that and there doesn't - // seem to be a good way to get only the path itself from - // a dependency. - const modulePath = userRequest.includes("!") - ? userRequest.split("!")[1] - : userRequest; - const componentDocs = this.options.parser.parse(modulePath); - - if (!componentDocs.length) { + if (!dependency.componentDocs.length) { return; } - const docgenBlock = generateDocgenCodeBlock({ - filename: userRequest, - source: userRequest, - componentDocs, - docgenCollectionName: - this.options.docgenOptions.docgenCollectionName || - "STORYBOOK_REACT_CLASSES", - setDisplayName: this.options.docgenOptions.setDisplayName || true, - typePropName: this.options.docgenOptions.typePropName || "type", - }).substring(userRequest.length); - - source.insert(0, docgenBlock); + source.insert( + 0, + generateDocgenCodeBlock({ + filename: userRequest, + source: userRequest, + componentDocs: dependency.componentDocs, + docgenCollectionName: + this.options.docgenOptions.docgenCollectionName || + "STORYBOOK_REACT_CLASSES", + setDisplayName: this.options.docgenOptions.setDisplayName || true, + typePropName: this.options.docgenOptions.typePropName || "type", + }).substring(userRequest.length) + ); } } diff --git a/src/plugin.ts b/src/plugin.ts index da9dbe4..69c4629 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -140,7 +140,12 @@ export default class DocgenPlugin { // eslint-disable-next-line // @ts-ignore - module.addDependency(new DocGenDependency(module.request)); + module.addDependency( + new DocGenDependency( + module.request, + this.parser.parse(nameForCondition) + ) + ); }); }; From 50e5ae4a53fb1875b9e40bd875e685b0a0a9c98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 16:20:34 +0300 Subject: [PATCH 53/80] chore: Drop a ts-ignore --- src/plugin.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index 69c4629..4b8c0df 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -138,8 +138,6 @@ export default class DocgenPlugin { return; } - // eslint-disable-next-line - // @ts-ignore module.addDependency( new DocGenDependency( module.request, From d1b32fceee791efc621ce0ba59a7e3df0de1fb34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 16:30:44 +0300 Subject: [PATCH 54/80] refactor: Push codeblock generation to the right place --- src/dependency.ts | 46 ++++++---------------------------------------- src/plugin.ts | 20 +++++++++++++++----- 2 files changed, 21 insertions(+), 45 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index db5e9f6..05eb1fc 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -20,12 +20,12 @@ import { LoaderOptions } from "./types"; class DocGenDependency extends NullDependency { public static Template: NullDependency.Template; - private componentDocs: docGen.ComponentDoc[]; + private codeBlock: string; - constructor(request: string, componentDocs: docGen.ComponentDoc[]) { + constructor(request: string, codeBlock: string) { super(request); - this.componentDocs = componentDocs; + this.codeBlock = codeBlock; } // TODO: Note if you want that modules correctly invalidate and cache you need to add updateHash to your Dependency and hash the type info (because that might change depending on outside factors (other modules) @@ -35,45 +35,11 @@ makeSerializable( DocGenDependency, "react-docgen-typescript-plugin/dist/dependency" ); - -type Options = { - parser: docGen.FileParser; - docgenOptions: LoaderOptions; -}; - class DocGenTemplate extends NullDependency.Template { - private options: Options; - - constructor(options: Options) { - super(); - - this.options = options; - } - - apply( - dependency: NullDependency, - source: ReplaceSource, - { module }: { module: Module } - ): void { - const { userRequest } = module; - - if (!dependency.componentDocs.length) { - return; + apply(dependency: NullDependency, source: ReplaceSource): void { + if (dependency.codeBlock) { + source.insert(0, dependency.codeBlock); } - - source.insert( - 0, - generateDocgenCodeBlock({ - filename: userRequest, - source: userRequest, - componentDocs: dependency.componentDocs, - docgenCollectionName: - this.options.docgenOptions.docgenCollectionName || - "STORYBOOK_REACT_CLASSES", - setDisplayName: this.options.docgenOptions.setDisplayName || true, - typePropName: this.options.docgenOptions.typePropName || "type", - }).substring(userRequest.length) - ); } } diff --git a/src/plugin.ts b/src/plugin.ts index 4b8c0df..bd99f2b 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -9,6 +9,7 @@ import { matcher } from "micromatch"; import { LoaderOptions } from "./types"; import DocGenDependency from "./dependency"; +import { generateDocgenCodeBlock } from "./generateDocgenCodeBlock"; const debugExclude = createDebug("docgen:exclude"); @@ -109,10 +110,8 @@ export default class DocgenPlugin { // eslint-disable-next-line // @ts-ignore TODO: Figure out why this isn't allowed DocGenDependency, - new DocGenDependency.Template({ - parser: this.parser, - docgenOptions: this.docgenOptions, - }) + // TODO: Use ConstDependency.Template instead? + new DocGenDependency.Template() ); // eslint-disable-next-line @@ -138,10 +137,21 @@ export default class DocgenPlugin { return; } + const componentDocs = this.parser.parse(nameForCondition); + module.addDependency( new DocGenDependency( module.request, - this.parser.parse(nameForCondition) + generateDocgenCodeBlock({ + filename: nameForCondition, + source: nameForCondition, + componentDocs, + docgenCollectionName: + this.docgenOptions.docgenCollectionName || + "STORYBOOK_REACT_CLASSES", + setDisplayName: this.docgenOptions.setDisplayName || true, + typePropName: this.docgenOptions.typePropName || "type", + }).substring(module.userRequest.length) ) ); }); From 688ec3fe82399f4049b44e617089fd133cb02ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 16:32:02 +0300 Subject: [PATCH 55/80] chore: Drop a todo --- src/plugin.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugin.ts b/src/plugin.ts index bd99f2b..3a96a10 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -110,7 +110,6 @@ export default class DocgenPlugin { // eslint-disable-next-line // @ts-ignore TODO: Figure out why this isn't allowed DocGenDependency, - // TODO: Use ConstDependency.Template instead? new DocGenDependency.Template() ); From 2559070f050d05797afc38d7ac113de5681c628b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 16:38:19 +0300 Subject: [PATCH 56/80] chore: Drop dead code --- src/dependency.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index 05eb1fc..50bfad4 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -15,9 +15,6 @@ import makeSerializable from "webpack/lib/util/makeSerializable.js"; // @ts-ignore TODO: Figure out where to find a typed version import NullDependency from "webpack/lib/dependencies/NullDependency.js"; -import { generateDocgenCodeBlock } from "./generateDocgenCodeBlock"; -import { LoaderOptions } from "./types"; - class DocGenDependency extends NullDependency { public static Template: NullDependency.Template; private codeBlock: string; From 4c8165b05ff687b46dbbfd23299ed7328b512216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 16:46:18 +0300 Subject: [PATCH 57/80] chore: Implement updateHash --- src/dependency.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index 50bfad4..b485afd 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -1,11 +1,10 @@ /* eslint-disable max-classes-per-file */ import { ReplaceSource } from "webpack-sources"; -import * as docGen from "react-docgen-typescript"; // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? -import Module from "webpack/lib/Module.js"; +import Hash from "webpack/lib/util/Hash.js"; // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? @@ -25,7 +24,9 @@ class DocGenDependency extends NullDependency { this.codeBlock = codeBlock; } - // TODO: Note if you want that modules correctly invalidate and cache you need to add updateHash to your Dependency and hash the type info (because that might change depending on outside factors (other modules) + updateHash(hash: Hash): void { + hash.update(this.codeBlock); + } } makeSerializable( From 769229e38bf2460a5888e01aa8c7e92e2e3ddd5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 17:41:10 +0300 Subject: [PATCH 58/80] chore: Improve typing --- src/plugin.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index 3a96a10..2a3d2a1 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -2,7 +2,7 @@ import path from "path"; import createDebug from "debug"; -import * as webpack from "webpack"; +import { Compiler, WebpackPluginInstance } from "webpack"; import ts from "typescript"; import * as docGen from "react-docgen-typescript"; import { matcher } from "micromatch"; @@ -58,7 +58,7 @@ const matchGlob = (globs?: string[]) => { }; /** Inject typescript docgen information into modules at the end of a build */ -export default class DocgenPlugin { +export default class DocgenPlugin implements WebpackPluginInstance { private name = "React Docgen Typescript Plugin"; private options: PluginOptions; private parser: docGen.FileParser; @@ -96,7 +96,7 @@ export default class DocgenPlugin { this.parser = docGen.withCompilerOptions(compilerOptions, docgenOptions); } - apply(compiler: webpack.Compiler): void { + apply(compiler: Compiler): void { const pluginName = "DocGenPlugin"; const { exclude = [], include = ["**/**.tsx"] } = this.options; From d7708ef8beb74b077cd1323218c36c7559bef1bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 17:42:14 +0300 Subject: [PATCH 59/80] chore: Drop dead code --- src/plugin.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index 2a3d2a1..3e1334a 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -62,7 +62,6 @@ export default class DocgenPlugin implements WebpackPluginInstance { private name = "React Docgen Typescript Plugin"; private options: PluginOptions; private parser: docGen.FileParser; - private compilerOptions: ts.CompilerOptions; private docgenOptions: LoaderOptions; constructor(options: PluginOptions = {}) { @@ -89,7 +88,6 @@ export default class DocgenPlugin implements WebpackPluginInstance { } this.options = options; - this.compilerOptions = compilerOptions; this.docgenOptions = docgenOptions; // Maintain the doc gen parser here to save time later From f6e213368e61cd1e984dcf41b1900d1fc15a9390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 17:52:03 +0300 Subject: [PATCH 60/80] refactor: Push option logic to apply --- src/plugin.ts | 68 ++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index 3e1334a..38cf019 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -61,42 +61,15 @@ const matchGlob = (globs?: string[]) => { export default class DocgenPlugin implements WebpackPluginInstance { private name = "React Docgen Typescript Plugin"; private options: PluginOptions; - private parser: docGen.FileParser; - private docgenOptions: LoaderOptions; constructor(options: PluginOptions = {}) { - const { - tsconfigPath = "./tsconfig.json", - compilerOptions: userCompilerOptions, - ...docgenOptions - } = options; - - let compilerOptions = { - jsx: ts.JsxEmit.React, - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.Latest, - }; - - if (userCompilerOptions) { - compilerOptions = { - ...compilerOptions, - ...userCompilerOptions, - }; - } else { - const { options: tsOptions } = getTSConfigFile(tsconfigPath); - compilerOptions = { ...compilerOptions, ...tsOptions }; - } - this.options = options; - this.docgenOptions = docgenOptions; - - // Maintain the doc gen parser here to save time later - this.parser = docGen.withCompilerOptions(compilerOptions, docgenOptions); } apply(compiler: Compiler): void { const pluginName = "DocGenPlugin"; - + const { docgenOptions, compilerOptions } = this.getOptions(); + const docGenParser = docGen.withCompilerOptions(compilerOptions); const { exclude = [], include = ["**/**.tsx"] } = this.options; const isExcluded = matchGlob(exclude); const isIncluded = matchGlob(include); @@ -134,7 +107,7 @@ export default class DocgenPlugin implements WebpackPluginInstance { return; } - const componentDocs = this.parser.parse(nameForCondition); + const componentDocs = docGenParser.parse(nameForCondition); module.addDependency( new DocGenDependency( @@ -144,10 +117,10 @@ export default class DocgenPlugin implements WebpackPluginInstance { source: nameForCondition, componentDocs, docgenCollectionName: - this.docgenOptions.docgenCollectionName || + docgenOptions.docgenCollectionName || "STORYBOOK_REACT_CLASSES", - setDisplayName: this.docgenOptions.setDisplayName || true, - typePropName: this.docgenOptions.typePropName || "type", + setDisplayName: docgenOptions.setDisplayName || true, + typePropName: docgenOptions.typePropName || "type", }).substring(module.userRequest.length) ) ); @@ -166,6 +139,35 @@ export default class DocgenPlugin implements WebpackPluginInstance { } ); } + + getOptions(): { + docgenOptions: LoaderOptions; + compilerOptions: ts.CompilerOptions; + } { + const { + tsconfigPath = "./tsconfig.json", + compilerOptions: userCompilerOptions, + ...docgenOptions + } = this.options; + + let compilerOptions = { + jsx: ts.JsxEmit.React, + module: ts.ModuleKind.CommonJS, + target: ts.ScriptTarget.Latest, + }; + + if (userCompilerOptions) { + compilerOptions = { + ...compilerOptions, + ...userCompilerOptions, + }; + } else { + const { options: tsOptions } = getTSConfigFile(tsconfigPath); + compilerOptions = { ...compilerOptions, ...tsOptions }; + } + + return { docgenOptions, compilerOptions }; + } } export type DocgenPluginType = typeof DocgenPlugin; From 2543aa414db9bd67b222a67dbe60a6f0b49ae99b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 18:00:12 +0300 Subject: [PATCH 61/80] fix: Pass generator/parser options correctly --- src/plugin.ts | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index 38cf019..24c962e 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -9,7 +9,10 @@ import { matcher } from "micromatch"; import { LoaderOptions } from "./types"; import DocGenDependency from "./dependency"; -import { generateDocgenCodeBlock } from "./generateDocgenCodeBlock"; +import { + generateDocgenCodeBlock, + GeneratorOptions, +} from "./generateDocgenCodeBlock"; const debugExclude = createDebug("docgen:exclude"); @@ -68,8 +71,15 @@ export default class DocgenPlugin implements WebpackPluginInstance { apply(compiler: Compiler): void { const pluginName = "DocGenPlugin"; - const { docgenOptions, compilerOptions } = this.getOptions(); - const docGenParser = docGen.withCompilerOptions(compilerOptions); + const { + docgenOptions, + compilerOptions, + generateOptions, + } = this.getOptions(); + const docGenParser = docGen.withCompilerOptions( + compilerOptions, + docgenOptions + ); const { exclude = [], include = ["**/**.tsx"] } = this.options; const isExcluded = matchGlob(exclude); const isIncluded = matchGlob(include); @@ -116,11 +126,7 @@ export default class DocgenPlugin implements WebpackPluginInstance { filename: nameForCondition, source: nameForCondition, componentDocs, - docgenCollectionName: - docgenOptions.docgenCollectionName || - "STORYBOOK_REACT_CLASSES", - setDisplayName: docgenOptions.setDisplayName || true, - typePropName: docgenOptions.typePropName || "type", + ...generateOptions, }).substring(module.userRequest.length) ) ); @@ -141,12 +147,20 @@ export default class DocgenPlugin implements WebpackPluginInstance { } getOptions(): { - docgenOptions: LoaderOptions; + docgenOptions: docGen.ParserOptions; + generateOptions: { + docgenCollectionName: GeneratorOptions["docgenCollectionName"]; + setDisplayName: GeneratorOptions["setDisplayName"]; + typePropName: GeneratorOptions["typePropName"]; + }; compilerOptions: ts.CompilerOptions; } { const { tsconfigPath = "./tsconfig.json", compilerOptions: userCompilerOptions, + docgenCollectionName, + setDisplayName, + typePropName, ...docgenOptions } = this.options; @@ -166,7 +180,15 @@ export default class DocgenPlugin implements WebpackPluginInstance { compilerOptions = { ...compilerOptions, ...tsOptions }; } - return { docgenOptions, compilerOptions }; + return { + docgenOptions, + generateOptions: { + docgenCollectionName: docgenCollectionName || "STORYBOOK_REACT_CLASSES", + setDisplayName: setDisplayName || true, + typePropName: typePropName || "type", + }, + compilerOptions, + }; } } From c9a732424ebe76d741bc9baf47e5751bbc1da151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 18:05:11 +0300 Subject: [PATCH 62/80] fix: Fix typing --- src/plugin.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index 24c962e..12d3513 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -7,6 +7,10 @@ import ts from "typescript"; import * as docGen from "react-docgen-typescript"; import { matcher } from "micromatch"; +// eslint-disable-next-line +// @ts-ignore: What's the right way to refer to this one? +import JavascriptParser from "webpack/lib/javascript/JavascriptParser.js"; + import { LoaderOptions } from "./types"; import DocGenDependency from "./dependency"; import { @@ -94,9 +98,7 @@ export default class DocgenPlugin implements WebpackPluginInstance { new DocGenDependency.Template() ); - // eslint-disable-next-line - // @ts-ignore: TODO: What's the type of a parser? - const handler = (parser) => { + const handler = (parser: JavascriptParser) => { parser.hooks.program.tap(pluginName, () => { // eslint-disable-next-line // @ts-ignore From 340a36e3b1747c3f18890459c88538dd7f59c2b0 Mon Sep 17 00:00:00 2001 From: Andrew Lisowski Date: Tue, 11 May 2021 08:57:59 -0700 Subject: [PATCH 63/80] add publish config --- .npmrc | 1 + package.json | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/.npmrc b/.npmrc index 43c97e7..1df2a6d 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,2 @@ +registry=https://registry.npmjs.org/ package-lock=false diff --git a/package.json b/package.json index d815fa4..4cbbfd1 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,10 @@ "repository": "hipstersmoothie/react-docgen-typescript-plugin", "author": "Andrew Lisowski ", "main": "dist/index.js", + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" + }, "scripts": { "build:example": "npm run build && webpack", "build": "tsc -p tsconfig.build.json", From 29e1a62c7eadb06183f37d77985b4b15dcaeff15 Mon Sep 17 00:00:00 2001 From: Andrew Lisowski Date: Tue, 11 May 2021 09:01:00 -0700 Subject: [PATCH 64/80] update matrix --- .github/workflows/push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index b68d6eb..2e8f99e 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - node-version: [10.x, 12.x] + node-version: [12.x, 14.x] steps: - uses: actions/checkout@v1 From ef5131ff3fe53d6bbd3fc8f9be3b0160e5b1fbd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 11 May 2021 19:45:07 +0300 Subject: [PATCH 65/80] fix: Write the types to the end --- src/dependency.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dependency.ts b/src/dependency.ts index b485afd..e28d0c2 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -36,7 +36,8 @@ makeSerializable( class DocGenTemplate extends NullDependency.Template { apply(dependency: NullDependency, source: ReplaceSource): void { if (dependency.codeBlock) { - source.insert(0, dependency.codeBlock); + // Insert to the end + source.insert(Infinity, dependency.codeBlock); } } } From bcfc4893329be48db4054bc0bae97bd139c57fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 14 May 2021 13:43:15 +0300 Subject: [PATCH 66/80] chore: Simplify typing --- src/dependency.ts | 38 ++++++++++++++++++-------------------- src/plugin.ts | 1 - 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index e28d0c2..3664427 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -1,45 +1,43 @@ /* eslint-disable max-classes-per-file */ - -import { ReplaceSource } from "webpack-sources"; - -// eslint-disable-next-line -// @ts-ignore: What's the right way to refer to this one? -import Hash from "webpack/lib/util/Hash.js"; +import * as webpack from "webpack"; // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? import makeSerializable from "webpack/lib/util/makeSerializable.js"; -// eslint-disable-next-line -// @ts-ignore TODO: Figure out where to find a typed version -import NullDependency from "webpack/lib/dependencies/NullDependency.js"; +class DocGenDependency extends webpack.dependencies.NullDependency { + public codeBlock: string; -class DocGenDependency extends NullDependency { - public static Template: NullDependency.Template; - private codeBlock: string; - - constructor(request: string, codeBlock: string) { - super(request); + constructor(codeBlock: string) { + super(); this.codeBlock = codeBlock; } - updateHash(hash: Hash): void { + updateHash: webpack.dependencies.NullDependency["updateHash"] = (hash) => { hash.update(this.codeBlock); - } + }; } makeSerializable( DocGenDependency, "react-docgen-typescript-plugin/dist/dependency" ); -class DocGenTemplate extends NullDependency.Template { - apply(dependency: NullDependency, source: ReplaceSource): void { + +type NullDependencyTemplateType = InstanceType< + typeof webpack.dependencies.NullDependency.Template +>; +class DocGenTemplate extends webpack.dependencies.NullDependency.Template + implements NullDependencyTemplateType { + apply: NullDependencyTemplateType["apply"] = ( + dependency: DocGenDependency, + source + ) => { if (dependency.codeBlock) { // Insert to the end source.insert(Infinity, dependency.codeBlock); } - } + }; } DocGenDependency.Template = DocGenTemplate; diff --git a/src/plugin.ts b/src/plugin.ts index 6c18b12..db145e3 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -124,7 +124,6 @@ export default class DocgenPlugin implements WebpackPluginInstance { module.addDependency( new DocGenDependency( - module.request, generateDocgenCodeBlock({ filename: nameForCondition, source: nameForCondition, From 5b1c571a58664995a97749370bc6e803b3dfcee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 14 May 2021 13:48:32 +0300 Subject: [PATCH 67/80] refactor: Write docs at seal --- src/plugin.ts | 100 +++++++++++++++++++------------------------------- 1 file changed, 38 insertions(+), 62 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index db145e3..ccd1710 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -1,5 +1,3 @@ -/* eslint-disable no-param-reassign, no-underscore-dangle */ - import path from "path"; import createDebug from "debug"; import { Compiler, WebpackPluginInstance } from "webpack"; @@ -7,10 +5,6 @@ import ts from "typescript"; import * as docGen from "react-docgen-typescript"; import { matcher } from "micromatch"; -// eslint-disable-next-line -// @ts-ignore: What's the right way to refer to this one? -import JavascriptParser from "webpack/lib/javascript/JavascriptParser.js"; - import { LoaderOptions } from "./types"; import DocGenDependency from "./dependency"; import { @@ -89,63 +83,45 @@ export default class DocgenPlugin implements WebpackPluginInstance { const isExcluded = matchGlob(exclude); const isIncluded = matchGlob(include); - compiler.hooks.compilation.tap( - pluginName, - (compilation, { normalModuleFactory }) => { - compilation.dependencyTemplates.set( - // eslint-disable-next-line - // @ts-ignore TODO: Figure out why this isn't allowed - DocGenDependency, - new DocGenDependency.Template() - ); - - const handler = (parser: JavascriptParser) => { - parser.hooks.program.tap(pluginName, () => { - // eslint-disable-next-line - // @ts-ignore - const { module } = parser.state; - const nameForCondition = module.nameForCondition(); - - if (isExcluded(nameForCondition)) { - debugExclude( - `Module not matched in "exclude": ${nameForCondition}` - ); - return; - } - - if (!isIncluded(nameForCondition)) { - debugExclude( - `Module not matched in "include": ${nameForCondition}` - ); - return; - } - - const componentDocs = docGenParser.parse(nameForCondition); - - module.addDependency( - new DocGenDependency( - generateDocgenCodeBlock({ - filename: nameForCondition, - source: nameForCondition, - componentDocs, - ...generateOptions, - }).substring(module.userRequest.length) - ) + compiler.hooks.compilation.tap(pluginName, (compilation) => { + compilation.dependencyTemplates.set( + DocGenDependency, + new DocGenDependency.Template() + ); + + compilation.hooks.seal.tap(pluginName, () => { + for (const module of compilation.modules) { + const nameForCondition = module.nameForCondition() || ""; + + if (isExcluded(nameForCondition)) { + debugExclude( + `Module not matched in "exclude": ${nameForCondition}` ); - }); - }; - - normalModuleFactory.hooks.parser - .for("javascript/auto") - .tap(pluginName, handler); - normalModuleFactory.hooks.parser - .for("javascript/dynamic") - .tap(pluginName, handler); - normalModuleFactory.hooks.parser - .for("javascript/esm") - .tap(pluginName, handler); - } - ); + return; + } + + if (!isIncluded(nameForCondition)) { + debugExclude( + `Module not matched in "include": ${nameForCondition}` + ); + return; + } + + const componentDocs = docGenParser.parse(nameForCondition); + + module.addDependency( + new DocGenDependency( + generateDocgenCodeBlock({ + filename: nameForCondition, + source: nameForCondition, + componentDocs, + ...generateOptions, + }) + ) + ); + } + }); + }); } getOptions(): { From 95eb37b46e3de34907d1caf542140a3dfefc366b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 14 May 2021 14:01:13 +0300 Subject: [PATCH 68/80] refactor: Create a single tsProgram to match old logic --- src/plugin.ts | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index ccd1710..5711327 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -4,6 +4,7 @@ import { Compiler, WebpackPluginInstance } from "webpack"; import ts from "typescript"; import * as docGen from "react-docgen-typescript"; import { matcher } from "micromatch"; +import * as webpack from "webpack"; import { LoaderOptions } from "./types"; import DocGenDependency from "./dependency"; @@ -90,7 +91,10 @@ export default class DocgenPlugin implements WebpackPluginInstance { ); compilation.hooks.seal.tap(pluginName, () => { - for (const module of compilation.modules) { + const modulesToProcess: [string, webpack.Module][] = []; + + // 1. Aggregate modules to process + compilation.modules.forEach((module: webpack.Module) => { const nameForCondition = module.nameForCondition() || ""; if (isExcluded(nameForCondition)) { @@ -107,19 +111,32 @@ export default class DocgenPlugin implements WebpackPluginInstance { return; } - const componentDocs = docGenParser.parse(nameForCondition); + modulesToProcess.push([nameForCondition, module]); + }); + + // 2. Create a ts program with the modules + const tsProgram = ts.createProgram( + modulesToProcess.map(([name]) => name), + compilerOptions + ); + // 3. Process and parse each module and add the type information + // as a dependency + modulesToProcess.forEach(([name, module]) => module.addDependency( new DocGenDependency( generateDocgenCodeBlock({ - filename: nameForCondition, - source: nameForCondition, - componentDocs, + filename: name, + source: name, + componentDocs: docGenParser.parseWithProgramProvider( + name, + () => tsProgram + ), ...generateOptions, }) ) - ); - } + ) + ); }); }); } From 8da9df4521fbc04c40093274956fe54407d1a905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Fri, 14 May 2021 15:13:43 +0300 Subject: [PATCH 69/80] feat: Add initial support for webpack 4 I restored the old code paths. Sadly this makes typing tougher. The added code needs to be tested still and the old cache is missing for now. --- package.json | 2 +- src/dependency.ts | 28 +++++++++---- src/plugin.ts | 103 ++++++++++++++++++++++++++++++++++++---------- 3 files changed, 101 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index be971e9..9867943 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ }, "peerDependencies": { "typescript": ">= 3.x", - "webpack": ">= 5" + "webpack": ">= 4" }, "lint-staged": { "*.{js,css,md}": [ diff --git a/src/dependency.ts b/src/dependency.ts index 3664427..ec81174 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -1,11 +1,17 @@ /* eslint-disable max-classes-per-file */ -import * as webpack from "webpack"; - // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? import makeSerializable from "webpack/lib/util/makeSerializable.js"; -class DocGenDependency extends webpack.dependencies.NullDependency { +// This import is compatible with both webpack 4 and 5 +// eslint-disable-next-line +// @ts-ignore: Webpack 4 type +import NullDependency from "webpack/lib/dependencies/NullDependency"; + +// It would be better to extend from webpack.dependencies but that works +// only with webpack 5, not 4 +// class DocGenDependency extends webpack.dependencies.NullDependency +class DocGenDependency extends NullDependency { public codeBlock: string; constructor(codeBlock: string) { @@ -14,7 +20,9 @@ class DocGenDependency extends webpack.dependencies.NullDependency { this.codeBlock = codeBlock; } - updateHash: webpack.dependencies.NullDependency["updateHash"] = (hash) => { + updateHash: NullDependency["updateHash"] = (hash: { + update: (str: string) => void; + }) => { hash.update(this.codeBlock); }; } @@ -24,14 +32,14 @@ makeSerializable( "react-docgen-typescript-plugin/dist/dependency" ); -type NullDependencyTemplateType = InstanceType< - typeof webpack.dependencies.NullDependency.Template ->; -class DocGenTemplate extends webpack.dependencies.NullDependency.Template +type NullDependencyTemplateType = InstanceType; +class DocGenTemplate extends NullDependency.Template implements NullDependencyTemplateType { + // eslint-disable-next-line + // @ts-ignore: Webpack 4 type apply: NullDependencyTemplateType["apply"] = ( dependency: DocGenDependency, - source + source: { insert: (a: number, b: string) => void } ) => { if (dependency.codeBlock) { // Insert to the end @@ -40,6 +48,8 @@ class DocGenTemplate extends webpack.dependencies.NullDependency.Template }; } +// eslint-disable-next-line +// @ts-ignore: Webpack 4 type DocGenDependency.Template = DocGenTemplate; export default DocGenDependency; diff --git a/src/plugin.ts b/src/plugin.ts index 5711327..9c7a18b 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -1,6 +1,5 @@ import path from "path"; import createDebug from "debug"; -import { Compiler, WebpackPluginInstance } from "webpack"; import ts from "typescript"; import * as docGen from "react-docgen-typescript"; import { matcher } from "micromatch"; @@ -60,8 +59,53 @@ const matchGlob = (globs?: string[]) => { Boolean(filename && matchers.find((match) => match(filename))); }; +/** Run the docgen parser and inject the result into the output */ +/** This is used for webpack 4 or earlier */ +function processModule( + parser: docGen.FileParser, + webpackModule: webpack.Module, + tsProgram: ts.Program, + loaderOptions: Required +) { + if (!webpackModule) { + return; + } + + // eslint-disable-next-line + // @ts-ignore: Webpack 4 type + const { userRequest } = webpackModule; + + const componentDocs = parser.parseWithProgramProvider( + userRequest, + () => tsProgram + ); + + if (!componentDocs.length) { + return; + } + + const docs = generateDocgenCodeBlock({ + filename: userRequest, + source: userRequest, + componentDocs, + ...loaderOptions, + }).substring(userRequest.length); + + // eslint-disable-next-line + // @ts-ignore: Webpack 4 type + // eslint-disable-next-line + let sourceWithDocs = webpackModule._source._value; + + sourceWithDocs += `\n${docs}\n`; + + // eslint-disable-next-line + // @ts-ignore: Webpack 4 type + // eslint-disable-next-line + webpackModule._source._value = sourceWithDocs; +} + /** Inject typescript docgen information into modules at the end of a build */ -export default class DocgenPlugin implements WebpackPluginInstance { +export default class DocgenPlugin implements webpack.WebpackPluginInstance { private name = "React Docgen Typescript Plugin"; private options: PluginOptions; @@ -69,7 +113,7 @@ export default class DocgenPlugin implements WebpackPluginInstance { this.options = options; } - apply(compiler: Compiler): void { + apply(compiler: webpack.Compiler): void { const pluginName = "DocGenPlugin"; const { docgenOptions, @@ -83,12 +127,20 @@ export default class DocgenPlugin implements WebpackPluginInstance { const { exclude = [], include = ["**/**.tsx"] } = this.options; const isExcluded = matchGlob(exclude); const isIncluded = matchGlob(include); + const webpackVersion = compiler.webpack.version; + const isWebpack5 = parseInt(webpackVersion.split(".")[0], 10) >= 5; compiler.hooks.compilation.tap(pluginName, (compilation) => { - compilation.dependencyTemplates.set( - DocGenDependency, - new DocGenDependency.Template() - ); + if (isWebpack5) { + compilation.dependencyTemplates.set( + // eslint-disable-next-line + // @ts-ignore: Webpack 4 type + DocGenDependency, + // eslint-disable-next-line + // @ts-ignore: Webpack 4 type + new DocGenDependency.Template() + ); + } compilation.hooks.seal.tap(pluginName, () => { const modulesToProcess: [string, webpack.Module][] = []; @@ -122,21 +174,28 @@ export default class DocgenPlugin implements WebpackPluginInstance { // 3. Process and parse each module and add the type information // as a dependency - modulesToProcess.forEach(([name, module]) => - module.addDependency( - new DocGenDependency( - generateDocgenCodeBlock({ - filename: name, - source: name, - componentDocs: docGenParser.parseWithProgramProvider( - name, - () => tsProgram - ), - ...generateOptions, - }) - ) - ) - ); + modulesToProcess.forEach(([name, module]) => { + if (isWebpack5) { + module.addDependency( + // eslint-disable-next-line + // @ts-ignore: Webpack 4 type + new DocGenDependency( + generateDocgenCodeBlock({ + filename: name, + source: name, + componentDocs: docGenParser.parseWithProgramProvider( + name, + () => tsProgram + ), + ...generateOptions, + }) + ) + ); + } else { + // Assume webpack 4 or earlier + processModule(docGenParser, module, tsProgram, generateOptions); + } + }); }); }); } From 5d2e70675d4b89efbfb87600ebf5e1143773b79a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 18 May 2021 10:19:04 +0300 Subject: [PATCH 70/80] fix: Make dependency portion webpack 5 specific --- package.json | 6 +- src/dependency.ts | 30 ++++------ src/index.ts | 2 + src/plugin.ts | 146 +++++++++++++++++++++++++--------------------- 4 files changed, 99 insertions(+), 85 deletions(-) diff --git a/package.json b/package.json index 9867943..127d442 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,11 @@ "build": "tsc -p tsconfig.build.json", "start": "yarn build --watch", "lint": "eslint src --ext .ts,.js", - "test": "jest", + "test": "npm run test:v4 && npm run test:v5", + "pretest:v4": "npm add @types/webpack ts-loader@8 webpack@4 --no-save", + "test:v4": "jest", + "pretest:v5": "npm add webpack@5 --no-save", + "test:v5": "jest", "release": "auto shipit" }, "keywords": [ diff --git a/src/dependency.ts b/src/dependency.ts index ec81174..2c0cba2 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -1,17 +1,11 @@ /* eslint-disable max-classes-per-file */ +import * as webpack from "webpack"; + // eslint-disable-next-line // @ts-ignore: What's the right way to refer to this one? import makeSerializable from "webpack/lib/util/makeSerializable.js"; -// This import is compatible with both webpack 4 and 5 -// eslint-disable-next-line -// @ts-ignore: Webpack 4 type -import NullDependency from "webpack/lib/dependencies/NullDependency"; - -// It would be better to extend from webpack.dependencies but that works -// only with webpack 5, not 4 -// class DocGenDependency extends webpack.dependencies.NullDependency -class DocGenDependency extends NullDependency { +class DocGenDependency extends webpack.dependencies.NullDependency { public codeBlock: string; constructor(codeBlock: string) { @@ -20,9 +14,7 @@ class DocGenDependency extends NullDependency { this.codeBlock = codeBlock; } - updateHash: NullDependency["updateHash"] = (hash: { - update: (str: string) => void; - }) => { + updateHash: webpack.dependencies.NullDependency["updateHash"] = (hash) => { hash.update(this.codeBlock); }; } @@ -32,14 +24,16 @@ makeSerializable( "react-docgen-typescript-plugin/dist/dependency" ); -type NullDependencyTemplateType = InstanceType; -class DocGenTemplate extends NullDependency.Template +type NullDependencyTemplateType = InstanceType< + typeof webpack.dependencies.NullDependency.Template +>; +class DocGenTemplate extends webpack.dependencies.NullDependency.Template implements NullDependencyTemplateType { // eslint-disable-next-line // @ts-ignore: Webpack 4 type apply: NullDependencyTemplateType["apply"] = ( dependency: DocGenDependency, - source: { insert: (a: number, b: string) => void } + source ) => { if (dependency.codeBlock) { // Insert to the end @@ -48,8 +42,8 @@ class DocGenTemplate extends NullDependency.Template }; } -// eslint-disable-next-line -// @ts-ignore: Webpack 4 type DocGenDependency.Template = DocGenTemplate; -export default DocGenDependency; +// Default imports are tricky with CommonJS +// eslint-disable-next-line +export { DocGenDependency }; diff --git a/src/index.ts b/src/index.ts index 5f8937b..e40100e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,6 +13,8 @@ try { require.resolve("typescript"); plugin = require("./plugin").default; } catch (error) { + console.error(error); + plugin = EmptyPlugin as any; } diff --git a/src/plugin.ts b/src/plugin.ts index 9c7a18b..02291bb 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -6,7 +6,6 @@ import { matcher } from "micromatch"; import * as webpack from "webpack"; import { LoaderOptions } from "./types"; -import DocGenDependency from "./dependency"; import { generateDocgenCodeBlock, GeneratorOptions, @@ -130,74 +129,89 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance { const webpackVersion = compiler.webpack.version; const isWebpack5 = parseInt(webpackVersion.split(".")[0], 10) >= 5; - compiler.hooks.compilation.tap(pluginName, (compilation) => { - if (isWebpack5) { - compilation.dependencyTemplates.set( + compiler.hooks.compilation.tap( + pluginName, + (compilation: webpack.Compilation) => { + if (isWebpack5) { + // Since this file is needed only for webpack 5, load it only then + // to simplify the implementation of the file. + // // eslint-disable-next-line - // @ts-ignore: Webpack 4 type - DocGenDependency, - // eslint-disable-next-line - // @ts-ignore: Webpack 4 type - new DocGenDependency.Template() - ); - } - - compilation.hooks.seal.tap(pluginName, () => { - const modulesToProcess: [string, webpack.Module][] = []; - - // 1. Aggregate modules to process - compilation.modules.forEach((module: webpack.Module) => { - const nameForCondition = module.nameForCondition() || ""; - - if (isExcluded(nameForCondition)) { - debugExclude( - `Module not matched in "exclude": ${nameForCondition}` - ); - return; - } - - if (!isIncluded(nameForCondition)) { - debugExclude( - `Module not matched in "include": ${nameForCondition}` - ); - return; - } - - modulesToProcess.push([nameForCondition, module]); - }); - - // 2. Create a ts program with the modules - const tsProgram = ts.createProgram( - modulesToProcess.map(([name]) => name), - compilerOptions - ); - - // 3. Process and parse each module and add the type information - // as a dependency - modulesToProcess.forEach(([name, module]) => { - if (isWebpack5) { - module.addDependency( + const { DocGenDependency } = require("./dependency"); + + compilation.dependencyTemplates.set( + // eslint-disable-next-line + // @ts-ignore: Webpack 4 type + DocGenDependency, + // eslint-disable-next-line + // @ts-ignore: Webpack 4 type + new DocGenDependency.Template() + ); + } + + compilation.hooks.seal.tap(pluginName, () => { + const modulesToProcess: [string, webpack.Module][] = []; + + // 1. Aggregate modules to process + compilation.modules.forEach((module: webpack.Module) => { + const nameForCondition = module.nameForCondition() || ""; + + if (isExcluded(nameForCondition)) { + debugExclude( + `Module not matched in "exclude": ${nameForCondition}` + ); + return; + } + + if (!isIncluded(nameForCondition)) { + debugExclude( + `Module not matched in "include": ${nameForCondition}` + ); + return; + } + + modulesToProcess.push([nameForCondition, module]); + }); + + // 2. Create a ts program with the modules + const tsProgram = ts.createProgram( + modulesToProcess.map(([name]) => name), + compilerOptions + ); + + // 3. Process and parse each module and add the type information + // as a dependency + modulesToProcess.forEach(([name, module]) => { + if (isWebpack5) { + // Since this file is needed only for webpack 5, load it only then + // to simplify the implementation of the file. + // // eslint-disable-next-line - // @ts-ignore: Webpack 4 type - new DocGenDependency( - generateDocgenCodeBlock({ - filename: name, - source: name, - componentDocs: docGenParser.parseWithProgramProvider( - name, - () => tsProgram - ), - ...generateOptions, - }) - ) - ); - } else { - // Assume webpack 4 or earlier - processModule(docGenParser, module, tsProgram, generateOptions); - } + const { DocGenDependency } = require("./dependency"); + + module.addDependency( + // eslint-disable-next-line + // @ts-ignore: Webpack 4 type + new DocGenDependency( + generateDocgenCodeBlock({ + filename: name, + source: name, + componentDocs: docGenParser.parseWithProgramProvider( + name, + () => tsProgram + ), + ...generateOptions, + }) + ) + ); + } else { + // Assume webpack 4 or earlier + processModule(docGenParser, module, tsProgram, generateOptions); + } + }); }); - }); - }); + } + ); } getOptions(): { From ca236dbf2e13e6bef82abf45bd3e5ec9cd217980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 18 May 2021 10:28:30 +0300 Subject: [PATCH 71/80] fix: Use yarn over npm to avoid mixed usage --- package.json | 7 ++++--- yarn.lock | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 127d442..0bfc522 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,9 @@ "start": "yarn build --watch", "lint": "eslint src --ext .ts,.js", "test": "npm run test:v4 && npm run test:v5", - "pretest:v4": "npm add @types/webpack ts-loader@8 webpack@4 --no-save", + "pretest:v4": "yarn-add-no-save @types/webpack ts-loader@8 webpack@4", "test:v4": "jest", - "pretest:v5": "npm add webpack@5 --no-save", + "pretest:v5": "yarn-add-no-save webpack@5", "test:v5": "jest", "release": "auto shipit" }, @@ -70,7 +70,8 @@ "ts-loader": "^9.1.2", "typescript": "3.8.3", "webpack": "^5.36.2", - "webpack-cli": "^4.7.0" + "webpack-cli": "^4.7.0", + "yarn-add-no-save": "^1.0.3" }, "peerDependencies": { "typescript": ">= 3.x", diff --git a/yarn.lock b/yarn.lock index 6bee0d1..55c03de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6493,6 +6493,13 @@ yargs@^15.0.1, yargs@^15.4.1: y18n "^4.0.0" yargs-parser "^18.1.2" +yarn-add-no-save@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/yarn-add-no-save/-/yarn-add-no-save-1.0.3.tgz#03540f86802a46a86db83bc7357b248cd282315b" + integrity sha512-ngmmxwYOogvYPjFDXGjoj35r/DteDzfiyoq5BI+kKSCCXW/I2gJA3KAgbm/7yFmcDE9CGSaORpNbYfglGYuxtA== + dependencies: + which "^2.0.2" + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" From e08cf7f07440e397491e68c0b86db4d677cd21cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 18 May 2021 10:29:39 +0300 Subject: [PATCH 72/80] fix: Use the right no-save in scripts --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 0bfc522..071fd2f 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,9 @@ "start": "yarn build --watch", "lint": "eslint src --ext .ts,.js", "test": "npm run test:v4 && npm run test:v5", - "pretest:v4": "yarn-add-no-save @types/webpack ts-loader@8 webpack@4", + "pretest:v4": "add-no-save @types/webpack ts-loader@8 webpack@4", "test:v4": "jest", - "pretest:v5": "yarn-add-no-save webpack@5", + "pretest:v5": "add-no-save webpack@5", "test:v5": "jest", "release": "auto shipit" }, From e099d3bcaedc58166d57b9124e5a0652389a1131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 18 May 2021 10:32:18 +0300 Subject: [PATCH 73/80] fix: webpack object might be missing --- src/plugin.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugin.ts b/src/plugin.ts index 02291bb..0b7b6a7 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -126,7 +126,8 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance { const { exclude = [], include = ["**/**.tsx"] } = this.options; const isExcluded = matchGlob(exclude); const isIncluded = matchGlob(include); - const webpackVersion = compiler.webpack.version; + // Property compiler.version is set only starting from webpack 5 + const webpackVersion = compiler.webpack?.version; const isWebpack5 = parseInt(webpackVersion.split(".")[0], 10) >= 5; compiler.hooks.compilation.tap( From 0cac4f2109ed28e12a6b498b47a9e7d7723fb4a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 18 May 2021 10:34:06 +0300 Subject: [PATCH 74/80] fix: Add a splittable default value --- src/plugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugin.ts b/src/plugin.ts index 0b7b6a7..c9663fe 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -127,7 +127,7 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance { const isExcluded = matchGlob(exclude); const isIncluded = matchGlob(include); // Property compiler.version is set only starting from webpack 5 - const webpackVersion = compiler.webpack?.version; + const webpackVersion = compiler.webpack?.version || ""; const isWebpack5 = parseInt(webpackVersion.split(".")[0], 10) >= 5; compiler.hooks.compilation.tap( From 0d2d6e4e49ec898305fc55af3c5829dc3b8c3cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 18 May 2021 11:19:13 +0300 Subject: [PATCH 75/80] fix: Fix tests for webpack 4 --- package.json | 1 + src/__tests__/plugin.test.ts | 26 ++++++++++++++-- yarn.lock | 58 +++++++++++++++++++++++++++++++++--- 3 files changed, 79 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 071fd2f..328e70b 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "eslint-plugin-prettier": "3.1.3", "jest": "^26.6.3", "memfs": "^3.2.2", + "memory-fs": "^0.5.0", "prettier": "^2.0.5", "react": "^17.0.1", "ts-jest": "^26.5.6", diff --git a/src/__tests__/plugin.test.ts b/src/__tests__/plugin.test.ts index 8270a92..b66b277 100644 --- a/src/__tests__/plugin.test.ts +++ b/src/__tests__/plugin.test.ts @@ -1,14 +1,36 @@ import webpack, { Configuration } from "webpack"; -import { createFsFromVolume, Volume } from "memfs"; +import { createFsFromVolume, IFs, Volume } from "memfs"; import ReactDocgenTypeScriptPlugin from ".."; +// eslint-disable-next-line +const joinPath = require("memory-fs/lib/join"); + +// Hack for webpack 4. This isn't needed with 5 +// See more: https://github.com/streamich/memfs/issues/404. +function ensureWebpackMemoryFs(fs: IFs) { + // Return it back, when it has Webpack 'join' method + // eslint-disable-next-line + // @ts-ignore + if (fs.join) { + return fs; + } + + // Create FS proxy, adding `join` method to memfs, but not modifying original object + const nextFs = Object.create(fs); + nextFs.join = joinPath; + + return nextFs; +} + function compile(config: Configuration): Promise { return new Promise((resolve, reject) => { const compiler = webpack(config); // eslint-disable-next-line // @ts-ignore: There's a type mismatch but this should work based on webpack source - compiler.outputFileSystem = createFsFromVolume(new Volume()); + compiler.outputFileSystem = ensureWebpackMemoryFs( + createFsFromVolume(new Volume()) + ); const memfs = compiler.outputFileSystem; compiler.run((error, stats) => { diff --git a/yarn.lock b/yarn.lock index 55c03de..bc63722 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2015,7 +2015,7 @@ core-js@2.4.1: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" integrity sha1-TekR5mew6ukSTjQlS1OupvxhjT4= -core-util-is@1.0.2: +core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= @@ -2329,6 +2329,13 @@ envinfo@^7.7.3: resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== +errno@^0.1.3: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -3313,7 +3320,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2: +inherits@2, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3582,7 +3589,7 @@ is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" -isarray@1.0.0, isarray@^1.0.0: +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -4365,6 +4372,14 @@ memfs@^3.2.2: dependencies: fs-monkey "1.0.3" +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -5028,6 +5043,11 @@ pretty-ms@^7.0.0: dependencies: parse-ms "^2.1.0" +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -5041,6 +5061,11 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + psl@^1.1.28: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" @@ -5135,6 +5160,19 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" +readable-stream@^2.0.1: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + rechoir@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.0.tgz#32650fd52c21ab252aa5d65b19310441c7e03aca" @@ -5353,7 +5391,7 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.1: +safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -5749,6 +5787,13 @@ string.prototype.trimstart@^1.0.1: call-bind "^1.0.0" define-properties "^1.1.3" +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + strip-ansi@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -6188,6 +6233,11 @@ user-home@^2.0.0: dependencies: os-homedir "^1.0.0" +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" From 59e16a7d17e3e0e00ac56d9dbf69d8e2e085b53c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Tue, 18 May 2021 11:33:54 +0300 Subject: [PATCH 76/80] fix: Restore webpack 4 cache --- package.json | 2 ++ src/plugin.ts | 30 ++++++++++++++++++++++++++++++ yarn.lock | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 328e70b..1ab1c99 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,8 @@ "dependencies": { "debug": "^4.1.1", "endent": "^2.0.1", + "find-cache-dir": "^3.3.1", + "flat-cache": "^3.0.4", "micromatch": "^4.0.2", "react-docgen-typescript": "^1.22.0", "tslib": "^2.0.0", diff --git a/src/plugin.ts b/src/plugin.ts index c9663fe..d19914d 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -4,6 +4,9 @@ import ts from "typescript"; import * as docGen from "react-docgen-typescript"; import { matcher } from "micromatch"; import * as webpack from "webpack"; +import findCacheDir from "find-cache-dir"; +import flatCache from "flat-cache"; +import crypto from "crypto"; import { LoaderOptions } from "./types"; import { @@ -12,6 +15,7 @@ import { } from "./generateDocgenCodeBlock"; const debugExclude = createDebug("docgen:exclude"); +const debugInclude = createDebug("docgen:include"); interface TypescriptOptions { /** @@ -58,6 +62,11 @@ const matchGlob = (globs?: string[]) => { Boolean(filename && matchers.find((match) => match(filename))); }; +// The cache is used only with webpack 4 for now as webpack 5 comes with caching of its own +const cacheId = "ts-docgen"; +const cacheDir = findCacheDir({ name: cacheId }); +const cache = flatCache.load(cacheId, cacheDir); + /** Run the docgen parser and inject the result into the output */ /** This is used for webpack 4 or earlier */ function processModule( @@ -70,6 +79,27 @@ function processModule( return; } + const hash = crypto + .createHash("sha1") + // eslint-disable-next-line + // @ts-ignore + // eslint-disable-next-line + .update(webpackModule._source._value) + .digest("hex"); + const cached = cache.getKey(hash); + + if (cached) { + // eslint-disable-next-line + // @ts-ignore + // eslint-disable-next-line + debugInclude(`Got cached docgen for "${webpackModule.request}"`); + // eslint-disable-next-line + // @ts-ignore + // eslint-disable-next-line + webpackModule._source._value = cached; + return; + } + // eslint-disable-next-line // @ts-ignore: Webpack 4 type const { userRequest } = webpackModule; diff --git a/yarn.lock b/yarn.lock index bc63722..a269182 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1968,6 +1968,11 @@ comment-parser@^0.7.4: resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.7.5.tgz#06db157a3b34addf8502393743e41897e2c73059" integrity sha512-iH9YA35ccw94nx5244GVkpyC9eVTsL71jZz6iz5w6RIf79JLF2AsXHXq9p6Oaohyl3sx5qSMnGsWUDFIAfWL4w== +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -2894,6 +2899,15 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +find-cache-dir@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + find-replace@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" @@ -2925,11 +2939,24 @@ flat-cache@^2.0.1: rimraf "2.6.3" write "1.0.3" +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + flatted@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== +flatted@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" + integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -4329,7 +4356,7 @@ macos-release@^2.2.0: resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== -make-dir@^3.0.0: +make-dir@^3.0.0, make-dir@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -4992,7 +5019,7 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" -pkg-dir@^4.2.0: +pkg-dir@^4.1.0, pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== @@ -5357,7 +5384,7 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" -rimraf@^3.0.0: +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== From a6589451bf52a04df83c14302141ce27b58e7583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Thu, 20 May 2021 10:29:52 +0300 Subject: [PATCH 77/80] fix: If module.nameForCondition is missing, do nothing It looks like not all modules have it so it could crash here. --- src/plugin.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugin.ts b/src/plugin.ts index d19914d..981ed6b 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -185,6 +185,10 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance { // 1. Aggregate modules to process compilation.modules.forEach((module: webpack.Module) => { + if (!module.nameForCondition) { + return; + } + const nameForCondition = module.nameForCondition() || ""; if (isExcluded(nameForCondition)) { From 27a93e3c39677bd68f22646ec39793eedad2e69b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Thu, 20 May 2021 14:32:34 +0300 Subject: [PATCH 78/80] fix: Use other type of import for NullDependency It looks like the other type can fail after compiled to JS. --- src/dependency.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dependency.ts b/src/dependency.ts index 2c0cba2..6d9d67a 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -5,7 +5,11 @@ import * as webpack from "webpack"; // @ts-ignore: What's the right way to refer to this one? import makeSerializable from "webpack/lib/util/makeSerializable.js"; -class DocGenDependency extends webpack.dependencies.NullDependency { +// eslint-disable-next-line +// @ts-ignore: What's the right way to refer to this one? +import NullDependency from "webpack/lib/dependencies/NullDependency.js"; + +class DocGenDependency extends NullDependency { public codeBlock: string; constructor(codeBlock: string) { @@ -27,7 +31,7 @@ makeSerializable( type NullDependencyTemplateType = InstanceType< typeof webpack.dependencies.NullDependency.Template >; -class DocGenTemplate extends webpack.dependencies.NullDependency.Template +class DocGenTemplate extends NullDependency.Template implements NullDependencyTemplateType { // eslint-disable-next-line // @ts-ignore: Webpack 4 type @@ -42,6 +46,7 @@ class DocGenTemplate extends webpack.dependencies.NullDependency.Template }; } +// @ts-ignore TODO: How to type this correctly? DocGenDependency.Template = DocGenTemplate; // Default imports are tricky with CommonJS From c1f61e4dbc3dc8bf5ab36e3dd6aa0205912f73f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Thu, 20 May 2021 14:39:14 +0300 Subject: [PATCH 79/80] fix: Don't include file path to the generated code For a reason that's not completely clear webpack emits a path here. Better remove it. --- src/plugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugin.ts b/src/plugin.ts index 981ed6b..d5920e7 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -236,7 +236,7 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance { () => tsProgram ), ...generateOptions, - }) + }).substring(name.length) ) ); } else { From 96267e52b4a88836ad72de49246ef200ec7c0fdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 24 May 2021 11:00:24 +0300 Subject: [PATCH 80/80] fix: Don't console.error if importing ts fails --- src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index e40100e..b699f3a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,12 +9,12 @@ class EmptyPlugin { let plugin: DocgenPluginType; +// It should be possible to use the plugin without TypeScript. +// In that case using it is a no-op. try { require.resolve("typescript"); plugin = require("./plugin").default; } catch (error) { - console.error(error); - plugin = EmptyPlugin as any; }