diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 4c04dfa..f3a993d 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -3,12 +3,12 @@ name: Node CI on: push: branches: - - main - - next + - main + - next pull_request: branches: - - main - - next + - main + - next jobs: build: @@ -19,17 +19,17 @@ jobs: node-version: [12.x, 14.x] steps: - - uses: actions/checkout@v1 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - name: npm install, build, and lint - run: | - yarn - yarn build - yarn lint - yarn test + - uses: actions/checkout@v1 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: npm install, build, and lint + run: | + yarn + yarn build + yarn lint + yarn test release: runs-on: ubuntu-latest diff --git a/README.md b/README.md index 34a14b9..01f59f8 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@
-

react-docgen-typescript-plugin

+

@storybook/react-docgen-typescript-plugin

A webpack plugin to inject react typescript docgen information

## Install ```sh -npm install --save-dev react-docgen-typescript-plugin +npm install --save-dev @storybook/react-docgen-typescript-plugin # or -yarn add -D react-docgen-typescript-plugin +yarn add -D @storybook/react-docgen-typescript-plugin ``` ## Usage @@ -19,8 +19,9 @@ yarn add -D react-docgen-typescript-plugin > `react-docgen-typescript-plugin` a lot harder! Turn them off for faster build times. ```ts -const ts = require('typescript'); -const ReactDocgenTypescriptPlugin = require("react-docgen-typescript-plugin").default; +const ts = require("typescript"); +const ReactDocgenTypescriptPlugin = require("react-docgen-typescript-plugin") + .default; module.exports = { plugins: [ @@ -29,7 +30,9 @@ module.exports = { // or with a specific tsconfig new ReactDocgenTypescriptPlugin({ tsconfigPath: "./tsconfig.dev.json" }), // or with compiler options - new ReactDocgenTypescriptPlugin({ compilerOptions: { jsx: ts.JsxEmit.Preserve } }), + new ReactDocgenTypescriptPlugin({ + compilerOptions: { jsx: ts.JsxEmit.Preserve }, + }), ], }; ``` @@ -45,8 +48,8 @@ This plugins support all parser options from [react-docgen-typescript](https://g | docgenCollectionName | string or null | Specify the docgen collection name to use. All docgen information will be collected into this global object. Set to `null` to disable. | `STORYBOOK_REACT_CLASSES` | | setDisplayName | boolean | Set the components' display name. If you want to set display names yourself or are using another plugin to do this, you should disable this option. | `true` | | typePropName | string | Specify the name of the property for docgen info prop type. | `type` | -| exclude | glob[] | Glob patterns to ignore and not generate docgen information for. (Great for ignoring large icon libraries) | `[]` | -| include | glob[] | Glob patterns to generate docgen information for | `['**/**.tsx']` | +| exclude | glob[] | Glob patterns to ignore and not generate docgen information for. (Great for ignoring large icon libraries) | `[]` | +| include | glob[] | Glob patterns to generate docgen information for | `['**/**.tsx']` | ## Debugging @@ -90,4 +93,4 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d -This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! \ No newline at end of file +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! diff --git a/package.json b/package.json index 72a3a36..00b2663 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { - "name": "react-docgen-typescript-plugin", - "version": "1.0.0", + "name": "@storybook/react-docgen-typescript-plugin", + "version": "1.0.1", "description": "A webpack plugin to inject react typescript docgen information.", "license": "MIT", - "repository": "hipstersmoothie/react-docgen-typescript-plugin", + "repository": "storybookjs/react-docgen-typescript-plugin", "author": "Andrew Lisowski ", "main": "dist/index.js", "publishConfig": { @@ -38,7 +38,7 @@ "find-cache-dir": "^3.3.1", "flat-cache": "^3.0.4", "micromatch": "^4.0.2", - "react-docgen-typescript": "^1.22.0", + "react-docgen-typescript": "^2.1.1", "tslib": "^2.0.0" }, "devDependencies": { diff --git a/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap b/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap index 316ff3d..3371a7c 100644 --- a/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap +++ b/src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap @@ -71,7 +71,7 @@ try { // @ts-ignore DefaultPropValueComponent.displayName = \\"DefaultPropValueComponent\\"; // @ts-ignore - DefaultPropValueComponent.__docgenInfo = { \\"description\\": \\"Component with a prop with a default value.\\", \\"displayName\\": \\"DefaultPropValueComponent\\", \\"props\\": { \\"color\\": { \\"defaultValue\\": { value: \\"blue\\" }, \\"description\\": \\"Button color.\\", \\"name\\": \\"color\\", \\"required\\": true, \\"type\\": { \\"name\\": \\"\\\\\\"blue\\\\\\" | \\\\\\"green\\\\\\"\\" } }, \\"counter\\": { \\"defaultValue\\": { value: 123 }, \\"description\\": \\"Button counter.\\", \\"name\\": \\"counter\\", \\"required\\": false, \\"type\\": { \\"name\\": \\"number\\" } }, \\"disabled\\": { \\"defaultValue\\": { value: false }, \\"description\\": \\"Button disabled.\\", \\"name\\": \\"disabled\\", \\"required\\": false, \\"type\\": { \\"name\\": \\"boolean\\" } } } }; + DefaultPropValueComponent.__docgenInfo = { \\"description\\": \\"Component with a prop with a default value.\\", \\"displayName\\": \\"DefaultPropValueComponent\\", \\"props\\": { \\"color\\": { \\"defaultValue\\": null, \\"description\\": \\"Button color.\\", \\"name\\": \\"color\\", \\"required\\": true, \\"type\\": { \\"name\\": \\"\\\\\\"blue\\\\\\" | \\\\\\"green\\\\\\"\\" } }, \\"counter\\": { \\"defaultValue\\": { value: 123 }, \\"description\\": \\"Button counter.\\", \\"name\\": \\"counter\\", \\"required\\": false, \\"type\\": { \\"name\\": \\"number\\" } }, \\"disabled\\": { \\"defaultValue\\": { value: false }, \\"description\\": \\"Button disabled.\\", \\"name\\": \\"disabled\\", \\"required\\": false, \\"type\\": { \\"name\\": \\"boolean\\" } } } }; } catch (__react_docgen_typescript_loader_error) { }" `; @@ -273,7 +273,7 @@ try { // @ts-ignore DefaultPropValueComponent.displayName = \\"DefaultPropValueComponent\\"; // @ts-ignore - DefaultPropValueComponent.__docgenInfo = { \\"description\\": \\"Component with a prop with a default value.\\", \\"displayName\\": \\"DefaultPropValueComponent\\", \\"props\\": { \\"color\\": { \\"defaultValue\\": { value: \\"blue\\" }, \\"description\\": \\"Button color.\\", \\"name\\": \\"color\\", \\"required\\": true, \\"type\\": { \\"name\\": \\"enum\\", \\"value\\": [{ \\"value\\": \\"\\\\\\"blue\\\\\\"\\" }, { \\"value\\": \\"\\\\\\"green\\\\\\"\\" }] } }, \\"counter\\": { \\"defaultValue\\": { value: 123 }, \\"description\\": \\"Button counter.\\", \\"name\\": \\"counter\\", \\"required\\": false, \\"type\\": { \\"name\\": \\"number\\" } }, \\"disabled\\": { \\"defaultValue\\": { value: false }, \\"description\\": \\"Button disabled.\\", \\"name\\": \\"disabled\\", \\"required\\": false, \\"type\\": { \\"name\\": \\"boolean\\" } } } }; + DefaultPropValueComponent.__docgenInfo = { \\"description\\": \\"Component with a prop with a default value.\\", \\"displayName\\": \\"DefaultPropValueComponent\\", \\"props\\": { \\"color\\": { \\"defaultValue\\": null, \\"description\\": \\"Button color.\\", \\"name\\": \\"color\\", \\"required\\": true, \\"type\\": { \\"name\\": \\"enum\\", \\"value\\": [{ \\"value\\": \\"\\\\\\"blue\\\\\\"\\" }, { \\"value\\": \\"\\\\\\"green\\\\\\"\\" }] } }, \\"counter\\": { \\"defaultValue\\": { value: 123 }, \\"description\\": \\"Button counter.\\", \\"name\\": \\"counter\\", \\"required\\": false, \\"type\\": { \\"name\\": \\"number\\" } }, \\"disabled\\": { \\"defaultValue\\": { value: false }, \\"description\\": \\"Button disabled.\\", \\"name\\": \\"disabled\\", \\"required\\": false, \\"type\\": { \\"name\\": \\"boolean\\" } } } }; } catch (__react_docgen_typescript_loader_error) { }" `; diff --git a/src/__tests__/plugin.test.ts b/src/__tests__/plugin.test.ts index b66b277..e610ad5 100644 --- a/src/__tests__/plugin.test.ts +++ b/src/__tests__/plugin.test.ts @@ -1,6 +1,7 @@ import webpack, { Configuration } from "webpack"; import { createFsFromVolume, IFs, Volume } from "memfs"; import ReactDocgenTypeScriptPlugin from ".."; +import { LoaderOptions } from "../types"; // eslint-disable-next-line const joinPath = require("memory-fs/lib/join"); @@ -84,3 +85,34 @@ test("default options", async () => { expect(result).toContain("STORYBOOK_REACT_CLASSES"); }); + +describe("custom options", () => { + describe("loader options", () => { + const options: Record< + keyof LoaderOptions, + Array + > = { + setDisplayName: [true, false, undefined], + typePropName: ["customValue", undefined], + docgenCollectionName: ["customValue", null, undefined], + }; + const { defaultOptions } = ReactDocgenTypeScriptPlugin; + + (Object.keys(options) as Array).forEach( + (optionName) => { + const values = options[optionName]; + + test.each(values)(`${optionName}: %p`, (value) => { + const plugin = new ReactDocgenTypeScriptPlugin({ + [optionName]: value, + }); + const { generateOptions: resultOptions } = plugin.getOptions(); + + expect(resultOptions[optionName]).toBe( + value === undefined ? defaultOptions[optionName] : value + ); + }); + } + ); + }); +}); diff --git a/src/dependency.ts b/src/dependency.ts index 5057baf..1db3bf3 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -9,6 +9,9 @@ import makeSerializable from "webpack/lib/util/makeSerializable.js"; // @ts-ignore: What's the right way to refer to this one? import NullDependency from "webpack/lib/dependencies/NullDependency.js"; +// This won't be needed when only webpack 5+ can be supported. Patching for now. +type Context = { write: (a: string) => void; read: () => string }; + class DocGenDependency extends NullDependency { public codeBlock: string; @@ -18,6 +21,10 @@ class DocGenDependency extends NullDependency { this.codeBlock = codeBlock; } + get type(): string { + return "docgen"; + } + getModuleEvaluationSideEffectsState(): boolean { return false; } @@ -25,6 +32,16 @@ class DocGenDependency extends NullDependency { updateHash: webpack.dependencies.NullDependency["updateHash"] = (hash) => { hash.update(this.codeBlock); }; + + serialize(context: Context): void { + const { write } = context; + write(this.codeBlock); + } + + deserialize(context: Context): void { + const { read } = context; + this.codeBlock = read(); + } } makeSerializable( diff --git a/src/plugin.ts b/src/plugin.ts index d0384cb..8573211 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -135,6 +135,12 @@ function processModule( /** Inject typescript docgen information into modules at the end of a build */ export default class DocgenPlugin implements webpack.WebpackPluginInstance { + public static defaultOptions = { + setDisplayName: true, + typePropName: "type", + docgenCollectionName: "STORYBOOK_REACT_CLASSES", + }; + private name = "React Docgen Typescript Plugin"; private options: PluginOptions; @@ -381,6 +387,7 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance { typePropName, ...docgenOptions } = this.options; + const { defaultOptions } = DocgenPlugin; let compilerOptions = { jsx: ts.JsxEmit.React, @@ -401,9 +408,12 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance { return { docgenOptions, generateOptions: { - docgenCollectionName: docgenCollectionName || "STORYBOOK_REACT_CLASSES", - setDisplayName: setDisplayName || true, - typePropName: typePropName || "type", + docgenCollectionName: + docgenCollectionName === undefined + ? defaultOptions.docgenCollectionName + : docgenCollectionName, + setDisplayName: setDisplayName ?? defaultOptions.setDisplayName, + typePropName: typePropName ?? defaultOptions.typePropName, }, compilerOptions, }; diff --git a/yarn.lock b/yarn.lock index b77f79d..1afc514 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5119,10 +5119,10 @@ rc@^1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" -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-docgen-typescript@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-2.1.1.tgz#c9f9ccb1fa67e0f4caf3b12f2a07512a201c2dcf" + integrity sha512-XWe8bsYqVjxciKdpNoufaHiB7FgUHIOnVQgxUolRL3Zlof2zkdTzuQH6SU2n3Ek9kfy3O1c63ojMtNfpiuNeZQ== react-is@^17.0.1: version "17.0.1"