From f2159620eee51b7bfe611cd59f9087c43cc1c62d Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Tue, 5 May 2026 19:18:27 +0200 Subject: [PATCH 1/4] Add security warnings for cli options --- .../src/commands/parse/command.ts | 6 ++--- .../src/app/docs/getting-started/cli/page.mdx | 13 +++++++++-- .../src/app/docs/reference/cli/page.mdx | 22 ++++++++++++++----- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/packages/react-docgen-cli/src/commands/parse/command.ts b/packages/react-docgen-cli/src/commands/parse/command.ts index 6a53701d238..a6f86792c65 100644 --- a/packages/react-docgen-cli/src/commands/parse/command.ts +++ b/packages/react-docgen-cli/src/commands/parse/command.ts @@ -79,18 +79,18 @@ program '--resolver ', `Built-in resolver config (${Object.values(ResolverConfigs).join( ', ', - )}), package name or path to a module that exports a resolver. Can also be used multiple times. When used, no default handlers will be added.`, + )}), package name or path to a trusted module that exports a resolver. Can also be used multiple times. When used, no default handlers will be added.`, collect, defaultResolvers, ) .option( '--importer ', - 'Built-in importer name (fsImport, ignoreImporter), package name or path to a module that exports an importer.', + 'Built-in importer name (fsImporter, ignoreImporter), package name or path to a trusted module that exports an importer.', 'fsImporter', ) .option( '--handler ', - 'Comma separated list of handlers to use. Can also be used multiple times. When used, no default handlers will be added.', + 'Comma separated list of trusted handlers to use. Can also be used multiple times. When used, no default handlers will be added.', collect, defaultHandlers, ) diff --git a/packages/website/src/app/docs/getting-started/cli/page.mdx b/packages/website/src/app/docs/getting-started/cli/page.mdx index 7e6971c6151..1fc62f04778 100644 --- a/packages/website/src/app/docs/getting-started/cli/page.mdx +++ b/packages/website/src/app/docs/getting-started/cli/page.mdx @@ -1,4 +1,5 @@ import { Tabs } from 'nextra/components'; +import { Callout } from 'nextra/components'; # Getting started with the Command Line Interface (CLI) @@ -70,8 +71,9 @@ react component. The result will be printed to the `stdout` and in case there are errors or warnings while analyzing the file, these will be printed to `stderr`. -The result will be an array of [Documentation](../reference/documentation/basic.mdx) -objects, stringified to JSON. +The result will be an array of +[Documentation](../reference/documentation/basic.mdx) objects, stringified to +JSON. ```shell filename="Terminal" copy react-docgen ./src/components/Button.tsx @@ -98,3 +100,10 @@ react-docgen -o output.json ./src/components/Button.tsx The CLI supports a lot more advanced options and for a full list checkout the [reference page](../reference/cli) + + + Options that load custom modules, such as `--handler`, `--resolver`, and + `--importer`, execute trusted JavaScript code in the current Node.js process. + Do not pass values from untrusted input, user-provided configuration, or + unreviewed shared configuration to these options. + diff --git a/packages/website/src/app/docs/reference/cli/page.mdx b/packages/website/src/app/docs/reference/cli/page.mdx index 75cad1ffb1d..7b96db609d1 100644 --- a/packages/website/src/app/docs/reference/cli/page.mdx +++ b/packages/website/src/app/docs/reference/cli/page.mdx @@ -1,3 +1,5 @@ +import { Callout } from 'nextra/components'; + # Command Line Interface (CLI) Reference This is the complete reference of all available options for the CLI. A basic @@ -21,6 +23,14 @@ If you want to know more about glob patterns, check the documentation of ## Options + + The `--handler`, `--resolver`, and `--importer` options can load JavaScript + modules from paths or package names. These modules are executed as trusted + code with the same privileges as the current Node.js process. Do not populate + these options from untrusted input, user-provided configuration, or unreviewed + shared configuration. + + ### `--failOnWarning` **Default**: `false` @@ -65,12 +75,12 @@ The name of one of the A path can be specified to your handler. The path can be absolute (recommended) or relative and in the later case the path will be resolved from the current -working directory. +working directory. The handler module is executed as trusted JavaScript code. #### Module name of handler An npm module name can be specified. The default export of this module needs to -be the handler function. +be the handler function. Only use modules you trust. ### `--help` @@ -101,12 +111,12 @@ Possible values are: A path can be specified to your importer. The path can be absolute (recommended) or relative and in the later case the path will be resolved from the current -working directory. +working directory. The importer module is executed as trusted JavaScript code. #### Module name of importer An npm module name can be specified. The default export of this module needs to -be the importer. +be the importer. Only use modules you trust. ### `--no-default-ignore` @@ -160,9 +170,9 @@ Possible values are: A path can be specified to your resolver. The path can be absolute (recommended) or relative and in the later case the path will be resolved from the current -working directory. +working directory. The resolver module is executed as trusted JavaScript code. #### Module name of resolver An npm module name can be specified. The default export of this module needs to -be an instance of the resolver. +be an instance of the resolver. Only use modules you trust. From b66793020fc7871f8e0f473fb30b4718a5907ee2 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Tue, 5 May 2026 19:25:49 +0200 Subject: [PATCH 2/4] Fix docs --- packages/react-docgen-cli/src/commands/parse/command.ts | 4 ++-- packages/website/src/app/docs/getting-started/cli/page.mdx | 2 +- .../website/src/app/docs/getting-started/nodejs/page.mdx | 4 ++-- packages/website/src/app/docs/reference/cli/page.mdx | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/react-docgen-cli/src/commands/parse/command.ts b/packages/react-docgen-cli/src/commands/parse/command.ts index a6f86792c65..be172ee989d 100644 --- a/packages/react-docgen-cli/src/commands/parse/command.ts +++ b/packages/react-docgen-cli/src/commands/parse/command.ts @@ -79,7 +79,7 @@ program '--resolver ', `Built-in resolver config (${Object.values(ResolverConfigs).join( ', ', - )}), package name or path to a trusted module that exports a resolver. Can also be used multiple times. When used, no default handlers will be added.`, + )}), package name or path to a trusted module that exports a resolver. Can also be used multiple times. When used, no default resolvers will be added.`, collect, defaultResolvers, ) @@ -109,7 +109,7 @@ program let finalIgnores = ignore; - // Push the default ignores unless the --no-default-ignore is set + // Push the default ignores unless the --no-default-ignores is set if (defaultIgnores === true && ignore !== defaultIgnoreGlobs) { finalIgnores.push(...defaultIgnoreGlobs); } else if (defaultIgnores === false && ignore === defaultIgnoreGlobs) { diff --git a/packages/website/src/app/docs/getting-started/cli/page.mdx b/packages/website/src/app/docs/getting-started/cli/page.mdx index 1fc62f04778..f3f342279b4 100644 --- a/packages/website/src/app/docs/getting-started/cli/page.mdx +++ b/packages/website/src/app/docs/getting-started/cli/page.mdx @@ -71,7 +71,7 @@ react component. The result will be printed to the `stdout` and in case there are errors or warnings while analyzing the file, these will be printed to `stderr`. -The result will be an array of +The result will be an object keyed by file path. Each value will be an array of [Documentation](../reference/documentation/basic.mdx) objects, stringified to JSON. diff --git a/packages/website/src/app/docs/getting-started/nodejs/page.mdx b/packages/website/src/app/docs/getting-started/nodejs/page.mdx index a1a818a1aaf..7f40316585a 100644 --- a/packages/website/src/app/docs/getting-started/nodejs/page.mdx +++ b/packages/website/src/app/docs/getting-started/nodejs/page.mdx @@ -39,10 +39,10 @@ import { parse } from 'react-docgen'; const code = ` /** My first component */ -export default ({ name }: { name: string }) =>
{{name}}
; +export default ({ name }: { name: string }) =>
{name}
; `; -const documentation = parse(code); +const documentation = parse(code, { filename: 'index.tsx' }); console.log(documentation); ``` diff --git a/packages/website/src/app/docs/reference/cli/page.mdx b/packages/website/src/app/docs/reference/cli/page.mdx index 7b96db609d1..c29ddc50125 100644 --- a/packages/website/src/app/docs/reference/cli/page.mdx +++ b/packages/website/src/app/docs/reference/cli/page.mdx @@ -102,7 +102,7 @@ files. Possible values are: -#### Built-in resolvers +#### Built-in importers - `ignoreImporter` (disable importing) - `fsImporter` @@ -118,7 +118,7 @@ working directory. The importer module is executed as trusted JavaScript code. An npm module name can be specified. The default export of this module needs to be the importer. Only use modules you trust. -### `--no-default-ignore` +### `--no-default-ignores` **Default**: `false` @@ -143,7 +143,7 @@ newlines. ### `--resolver ` -**Default**: `["find-exported-component", "find-all-annotated-components"]` +**Default**: `["find-exported-component"]` Allows to specify the resolvers that find react components in the code. When multiple resolvers are specified they are all executed in order and all found From eb6759427a9f9e13f08311c587f8cadabacf945a Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Tue, 5 May 2026 19:50:42 +0200 Subject: [PATCH 3/4] More docs --- .../app/docs/extending/architecture/page.mdx | 55 ++++++++- .../src/app/docs/extending/handler/page.mdx | 70 +++++++++++- .../src/app/docs/extending/importer/page.mdx | 66 ++++++++++- .../src/app/docs/extending/resolver/page.mdx | 69 ++++++++++- .../website/src/app/docs/reference/_meta.js | 1 + .../src/app/docs/reference/api/page.mdx | 103 ++++++++++++++++- .../src/app/docs/reference/cli/page.mdx | 4 +- .../src/app/docs/reference/config/page.mdx | 73 +++++++++++- .../reference/documentation/basic/page.mdx | 87 +++++++++++++- .../reference/documentation/flow/page.mdx | 70 +++++++++++- .../documentation/prop-types/page.mdx | 108 +++++++++++++++++- .../documentation/typescript/page.mdx | 70 +++++++++++- .../child-context-type-handler/page.mdx | 69 ++++++++++- .../handlers/code-type-handler/page.mdx | 72 +++++++++++- .../component-docblock-handler/page.mdx | 5 + .../component-methods-handler/page.mdx | 5 + .../handlers/context-type-handler/page.mdx | 69 ++++++++++- .../handlers/default-props-handler/page.mdx | 5 + .../handlers/display-name-handler/page.mdx | 5 + .../handlers/prop-docblock-handler/page.mdx | 5 + .../prop-type-composition-handler/page.mdx | 5 + .../handlers/prop-type-handler/page.mdx | 5 + .../src/app/docs/reference/resolvers/_meta.js | 6 + .../resolvers/chain-resolver/page.mdx | 56 +++++++++ .../find-all-definitions-resolver/page.mdx | 38 ++++++ .../page.mdx | 44 +++++++ .../page.mdx | 51 +++++++++ packages/website/src/app/globals.css | 6 +- 28 files changed, 1176 insertions(+), 46 deletions(-) create mode 100644 packages/website/src/app/docs/reference/resolvers/_meta.js create mode 100644 packages/website/src/app/docs/reference/resolvers/chain-resolver/page.mdx create mode 100644 packages/website/src/app/docs/reference/resolvers/find-all-definitions-resolver/page.mdx create mode 100644 packages/website/src/app/docs/reference/resolvers/find-annotated-definitions-resolver/page.mdx create mode 100644 packages/website/src/app/docs/reference/resolvers/find-exported-definitions-resolver/page.mdx diff --git a/packages/website/src/app/docs/extending/architecture/page.mdx b/packages/website/src/app/docs/extending/architecture/page.mdx index 33deda4cec1..cae6c283443 100644 --- a/packages/website/src/app/docs/extending/architecture/page.mdx +++ b/packages/website/src/app/docs/extending/architecture/page.mdx @@ -1,5 +1,54 @@ -import ContentMissing from '@/components/ContentMissing'; - # Architecture - +react-docgen works in four steps: + +1. Parse the source code with Babel. +2. Build a [`FileState`](../reference/file-state) object around the AST. +3. Run a resolver to find React component definitions. +4. Run handlers on each component definition and build the final documentation. + +## Parsing + +`parse()` accepts source code and a config object. The source is parsed with +Babel. If no Babel config file is found, react-docgen applies default parser +plugins for JSX and either TypeScript or Flow. + +TypeScript syntax is enabled by default for filenames ending in `.ts`, `.tsx`, +`.mts`, or `.cts`. Other files use Flow syntax by default. + +## FileState + +`FileState` stores the AST, root program path, source code, parser options, and +the configured importer. It also provides helpers used by resolvers, handlers, +and utilities: + +- `file.traverse()` to walk the AST +- `file.import()` to resolve imported values +- `file.parse()` to parse another file with the same importer + +## Resolvers + +The resolver receives the `FileState` and returns component definition paths. + +The default parser config uses a chain of built-in resolvers to find exported +components and annotated components. Custom resolvers can replace that behavior. + +## Handlers + +Handlers receive a `DocumentationBuilder` and one component definition. Each +handler adds one kind of information, such as prop types, default props, display +name, or component methods. + +When all handlers have run, the builder produces a `Documentation` object. + +## Importers + +Importers are used when react-docgen needs to follow imports. The default +filesystem importer resolves imported source files from disk. The ignore +importer disables cross-file resolution. + +## Output + +The JavaScript API returns an array of `Documentation` objects. The CLI returns +a JSON object keyed by file path, where each value is an array of +`Documentation` objects for that file. diff --git a/packages/website/src/app/docs/extending/handler/page.mdx b/packages/website/src/app/docs/extending/handler/page.mdx index 94df3360b20..cd62a307fac 100644 --- a/packages/website/src/app/docs/extending/handler/page.mdx +++ b/packages/website/src/app/docs/extending/handler/page.mdx @@ -1,5 +1,69 @@ -import ContentMissing from '@/components/ContentMissing'; - # Handler - +Handlers extract information from every component found by the resolver. A +handler receives a `DocumentationBuilder` and the Babel `NodePath` for the +component definition. + +```ts +import type { Handler } from 'react-docgen'; + +const handler: Handler = (documentation, componentDefinition) => { + documentation.set('customValue', componentDefinition.node.type); +}; +``` + +## Signature + +```ts +type Handler = ( + documentation: DocumentationBuilder, + componentDefinition: NodePath, +) => void; +``` + +## Writing data + +Use the methods on `DocumentationBuilder` to add data. + +```ts +documentation.set('displayName', 'Button'); +documentation.addComposes('./otherProps'); + +const prop = documentation.getPropDescriptor('label'); +prop.description = 'Text shown inside the button.'; +``` + +For context-related handlers, use: + +```ts +documentation.getContextDescriptor('theme'); +documentation.getChildContextDescriptor('theme'); +``` + +## Using a custom handler + +Pass handlers directly to `parse()`. + +```ts +import { defaultHandlers, parse } from 'react-docgen'; +import myHandler from './myHandler.js'; + +const docs = parse(code, { + filename: 'Button.tsx', + handlers: [...defaultHandlers, myHandler], +}); +``` + +When `handlers` is provided, the default handlers are not added automatically. +Include `defaultHandlers` yourself if you want to extend the default behavior. + +## CLI + +The CLI can load a handler by built-in name, package name, or path. + +```shell filename="Terminal" +react-docgen --handler ./myHandler.js ./src/Button.tsx +``` + +Custom handler modules are executed as JavaScript in the current Node.js +process. Only load handlers you trust. diff --git a/packages/website/src/app/docs/extending/importer/page.mdx b/packages/website/src/app/docs/extending/importer/page.mdx index c594ba5b9f8..237262a6571 100644 --- a/packages/website/src/app/docs/extending/importer/page.mdx +++ b/packages/website/src/app/docs/extending/importer/page.mdx @@ -1,5 +1,65 @@ -import ContentMissing from '@/components/ContentMissing'; - # Importer - +Importers resolve imported values for handlers and utilities that need to follow +references across files. + +## Signature + +```ts +import type { Importer } from 'react-docgen'; + +const importer: Importer = (path, name, file) => { + return null; +}; +``` + +The importer receives: + +- `path`: the import or export declaration being resolved +- `name`: the imported or exported name to find +- `file`: the current [`FileState`](../reference/file-state) + +It returns a Babel `NodePath` for the resolved value, or `null` when the value +cannot be resolved. + +## Built-in importers + +### fsImporter + +The default importer. It resolves modules from disk using Node.js resolution +rules, reads the resolved file, parses it, and looks for the requested exported +value. + +It supports JavaScript and TypeScript source extensions, including `.js`, `.ts`, +`.tsx`, `.mjs`, `.cjs`, `.mts`, `.cts`, and `.jsx`. + +### ignoreImporter + +Always returns `null`. Use this when imported values should not be followed. + +## makeFsImporter + +`makeFsImporter()` creates a new filesystem importer. You can use it to provide +separate caches or a custom module lookup function. + +```ts +import { makeFsImporter, parse } from 'react-docgen'; + +const importer = makeFsImporter(); + +parse(code, { + filename: '/absolute/path/Button.tsx', + importer, +}); +``` + +## CLI + +The CLI can load an importer by built-in name, package name, or path. + +```shell filename="Terminal" +react-docgen --importer ignoreImporter ./src/Button.tsx +``` + +Custom importer modules are executed as JavaScript in the current Node.js +process. Only load importers you trust. diff --git a/packages/website/src/app/docs/extending/resolver/page.mdx b/packages/website/src/app/docs/extending/resolver/page.mdx index c3f67954fef..0bc478f7510 100644 --- a/packages/website/src/app/docs/extending/resolver/page.mdx +++ b/packages/website/src/app/docs/extending/resolver/page.mdx @@ -1,5 +1,68 @@ -import ContentMissing from '@/components/ContentMissing'; - # Resolver - +Resolvers decide which AST nodes are React component definitions. Handlers are +then run for each node returned by the resolver. + +## Signature + +A resolver can be a function: + +```ts +import type { ResolverFunction } from 'react-docgen'; + +const resolver: ResolverFunction = (file) => { + return []; +}; +``` + +Or an object with a `resolve()` method: + +```ts +import type { ResolverClass } from 'react-docgen'; + +const resolver: ResolverClass = { + resolve(file) { + return []; + }, +}; +``` + +Both forms return an array of `NodePath`. + +## FileState + +Resolvers receive a [`FileState`](../reference/file-state) object. The resolver +can inspect `file.path`, traverse the AST with `file.traverse()`, or parse and +import related files through the configured importer. + +## Built-in resolvers + +react-docgen exports these resolver classes through `builtinResolvers`: + +- `FindExportedDefinitionsResolver` +- `FindAllDefinitionsResolver` +- `FindAnnotatedDefinitionsResolver` +- `ChainResolver` + +## Using a custom resolver + +```ts +import { parse } from 'react-docgen'; +import myResolver from './myResolver.js'; + +const docs = parse(code, { + filename: 'Button.tsx', + resolver: myResolver, +}); +``` + +## CLI + +The CLI can load a resolver by built-in config name, package name, or path. + +```shell filename="Terminal" +react-docgen --resolver ./myResolver.js ./src/Button.tsx +``` + +Custom resolver modules are executed as JavaScript in the current Node.js +process. Only load resolvers you trust. diff --git a/packages/website/src/app/docs/reference/_meta.js b/packages/website/src/app/docs/reference/_meta.js index 56e48080933..187cb0cbe21 100644 --- a/packages/website/src/app/docs/reference/_meta.js +++ b/packages/website/src/app/docs/reference/_meta.js @@ -4,4 +4,5 @@ export default { documentation: 'Documentation', 'file-state': 'FileState', handlers: 'Handlers', + resolvers: 'Resolvers', }; diff --git a/packages/website/src/app/docs/reference/api/page.mdx b/packages/website/src/app/docs/reference/api/page.mdx index 778b85c92da..c97be78b51c 100644 --- a/packages/website/src/app/docs/reference/api/page.mdx +++ b/packages/website/src/app/docs/reference/api/page.mdx @@ -1,5 +1,102 @@ -import ContentMissing from '@/components/ContentMissing'; - # API - +The public API is exported from the `react-docgen` package. + +## parse + +```ts +function parse(src: Buffer | string, config?: Config): Documentation[]; +``` + +Parses JavaScript, TypeScript, JSX, or TSX source code and returns one +documentation object for each component found by the configured resolver. + +```ts filename="parse.ts" +import { parse } from 'react-docgen'; + +const docs = parse( + ` + /** Button component */ + export function Button({ label }: { label: string }) { + return ; + } +`, + { filename: 'Button.tsx' }, +); +``` + +The `filename` option is recommended. It lets react-docgen choose the right +parser mode for TypeScript files and lets the default importer resolve relative +imports. + +## builtinHandlers + +Contains all built-in handlers keyed by their export name. + +```ts +import { builtinHandlers } from 'react-docgen'; +``` + +These handlers can be passed to `parse()` with the `handlers` config option. + +## builtinImporters + +Contains the built-in importers: + +- `fsImporter` +- `ignoreImporter` + +```ts +import { builtinImporters } from 'react-docgen'; +``` + +## builtinResolvers + +Contains the built-in resolver classes: + +- `ChainResolver` +- `FindAllDefinitionsResolver` +- `FindAnnotatedDefinitionsResolver` +- `FindExportedDefinitionsResolver` + +```ts +import { builtinResolvers } from 'react-docgen'; +``` + +## defaultHandlers + +The list of handlers used when no `handlers` config option is provided. + +```ts +import { defaultHandlers } from 'react-docgen'; +``` + +## makeFsImporter + +Creates a filesystem importer. This is useful when you want separate importer +caches, or when you want to provide a custom module lookup function. + +```ts +import { makeFsImporter } from 'react-docgen'; + +const importer = makeFsImporter(); +``` + +## ERROR_CODES + +Contains the error code constants used by react-docgen errors: + +- `ERR_REACTDOCGEN_MISSING_DEFINITION` +- `ERR_REACTDOCGEN_MULTIPLE_DEFINITIONS` + +## utils + +Exports internal utility functions used by the built-in handlers and resolvers. +These are useful for custom extensions, but they are lower-level APIs than +handlers, importers, and resolvers. + +## Types + +The package also exports the TypeScript types used by the public API, including +`Config`, `Documentation`, `DocumentationBuilder`, `FileState`, `Handler`, +`Importer`, `Resolver`, `ResolverClass`, and `ResolverFunction`. diff --git a/packages/website/src/app/docs/reference/cli/page.mdx b/packages/website/src/app/docs/reference/cli/page.mdx index c29ddc50125..deffca44b34 100644 --- a/packages/website/src/app/docs/reference/cli/page.mdx +++ b/packages/website/src/app/docs/reference/cli/page.mdx @@ -132,7 +132,9 @@ Store extracted information in the specified file instead of printing to **Examples** -**TODO** +```shell filename="Terminal" +react-docgen -o output.json ./src/components/Button.tsx +``` ### `--pretty` diff --git a/packages/website/src/app/docs/reference/config/page.mdx b/packages/website/src/app/docs/reference/config/page.mdx index 78005f1491a..272e2bb7fbb 100644 --- a/packages/website/src/app/docs/reference/config/page.mdx +++ b/packages/website/src/app/docs/reference/config/page.mdx @@ -1,5 +1,72 @@ -import ContentMissing from '@/components/ContentMissing'; - # Config - +The `Config` object controls how `parse()` finds components, resolves imports, +and extracts documentation. + +```ts +interface Config { + handlers?: Handler[]; + importer?: Importer; + resolver?: Resolver; + filename?: string; + babelOptions?: TransformOptions; +} +``` + +## handlers + +**Default**: all built-in handlers + +An array of handlers that extract information from every component found by the +resolver. If this option is provided, only the handlers in the array are used. + +```ts +import { builtinHandlers, parse } from 'react-docgen'; + +parse(code, { + handlers: [builtinHandlers.componentDocblockHandler], +}); +``` + +## importer + +**Default**: `fsImporter` + +The importer used when react-docgen needs to follow imports while resolving prop +types or values. The default importer reads files from disk using Node.js +resolution rules. + +Use `builtinImporters.ignoreImporter` when imported values should not be +resolved. + +## resolver + +**Default**: exported components and annotated components + +The resolver decides which AST nodes are React component definitions. The +default resolver combines: + +- `FindExportedDefinitionsResolver` with `limit: 1` +- `FindAnnotatedDefinitionsResolver` + +This means `parse()` finds the exported component in a file and components +marked with the default `@component` annotation. + +## filename + +Shortcut for `babelOptions.filename`. + +Set this to the absolute path of the file being parsed when possible. A relative +path is resolved by Babel relative to `babelOptions.cwd`. + +The filename affects parser behavior. Files ending in `.ts`, `.tsx`, `.mts`, or +`.cts` use the TypeScript parser plugin by default. Other files use the Flow +parser plugin by default. + +## babelOptions + +Options passed to Babel while parsing. If Babel finds a filesystem config file, +react-docgen uses that config instead of applying its default parser plugins. + +The `estree` parser plugin is always removed because react-docgen expects Babel +AST nodes. diff --git a/packages/website/src/app/docs/reference/documentation/basic/page.mdx b/packages/website/src/app/docs/reference/documentation/basic/page.mdx index 9350d53d78e..783a65584c3 100644 --- a/packages/website/src/app/docs/reference/documentation/basic/page.mdx +++ b/packages/website/src/app/docs/reference/documentation/basic/page.mdx @@ -1,5 +1,3 @@ -import { Callout } from 'nextra/components'; - # Basic This describes the return value of react-docgen either from the `parse()` method @@ -24,6 +22,11 @@ interface Documentation { ### childContext +**Type**: `Record | undefined` + +If the [`childContextTypeHandler`](../handlers/child-context-type-handler) is +active this property will contain legacy React child context descriptors. + ### composes **Type**: `string[] | undefined` @@ -31,12 +34,19 @@ interface Documentation { If the props of the React component are composed of props which react-docgen was unable to resolve, the name of types will be listed here. - - Create examples - +```json filename="JSON" +{ + "composes": ["./sharedProps"] +} +``` ### context +**Type**: `Record | undefined` + +If the [`contextTypeHandler`](../handlers/context-type-handler) is active this +property will contain legacy React context descriptors. + ### description **Type**: `string | undefined` @@ -53,4 +63,71 @@ property will be set to the name of the React component. ### methods +**Type**: `MethodDescriptor[] | undefined` + +If the [`componentMethodsHandler`](../handlers/component-methods-handler) or +`componentMethodsJsDocHandler` is active this property will contain documented +component methods. + ### props + +**Type**: `Record | undefined` + +Contains prop descriptors collected by handlers such as +[`propTypeHandler`](../handlers/prop-type-handler), +[`codeTypeHandler`](../handlers/code-type-handler), +[`propDocblockHandler`](../handlers/prop-docblock-handler), and +[`defaultPropsHandler`](../handlers/default-props-handler). + +## PropDescriptor + +```ts +interface PropDescriptor { + type?: PropTypeDescriptor; + flowType?: TypeDescriptor; + tsType?: TypeDescriptor; + required?: boolean; + defaultValue?: DefaultValueDescriptor; + description?: string; +} +``` + +### type + +**Type**: `PropTypeDescriptor | undefined` + +Set by PropTypes-based handlers. See the [PropTypes documentation](./prop-types) +for details. + +### flowType + +**Type**: `TypeDescriptor | undefined` + +Set by [`codeTypeHandler`](../handlers/code-type-handler) when Flow props are +found. + +### tsType + +**Type**: `TypeDescriptor | undefined` + +Set by [`codeTypeHandler`](../handlers/code-type-handler) when TypeScript props +are found. + +### required + +**Type**: `boolean | undefined` + +Indicates whether the prop is required according to the handler that found it. + +### defaultValue + +**Type**: `DefaultValueDescriptor | undefined` + +Set by [`defaultPropsHandler`](../handlers/default-props-handler) when a default +value is found. + +### description + +**Type**: `string | undefined` + +Set by docblock handlers or by comments in Flow and TypeScript prop definitions. diff --git a/packages/website/src/app/docs/reference/documentation/flow/page.mdx b/packages/website/src/app/docs/reference/documentation/flow/page.mdx index a28de0100db..24c99a5a28f 100644 --- a/packages/website/src/app/docs/reference/documentation/flow/page.mdx +++ b/packages/website/src/app/docs/reference/documentation/flow/page.mdx @@ -1,5 +1,69 @@ -import ContentMissing from '@/components/ContentMissing'; - # Flow - +When [`codeTypeHandler`](../handlers/code-type-handler) extracts Flow props, the +type information is written to `flowType`. + +```ts +interface PropDescriptor { + flowType?: TypeDescriptor; + required?: boolean; + description?: string; + defaultValue?: DefaultValueDescriptor; +} +``` + +## Example + +```js filename="component.js" +type Props = { + label: string, + disabled?: boolean, + size: 'small' | 'large', +}; + +export function Button(props: Props) { + return ; +} +``` + +```json filename="JSON" +{ + "label": { + "required": true, + "flowType": { + "name": "string" + } + }, + "disabled": { + "required": false, + "flowType": { + "name": "boolean" + } + }, + "size": { + "required": true, + "flowType": { + "name": "union", + "raw": "'small' | 'large'", + "elements": [ + { "name": "literal", "value": "'small'" }, + { "name": "literal", "value": "'large'" } + ] + } + } +} +``` + +## Type descriptors + +Most Flow values are represented with the shared +`TypeDescriptor` shape. Common descriptors are: + +- Simple descriptors, such as `{ "name": "string" }` +- Literal descriptors, such as `{ "name": "literal", "value": "'small'" }` +- Element descriptors, such as unions, intersections, arrays, and tuples +- Function signatures with `type: "function"` +- Object signatures with `type: "object"` + +Files that are not parsed as TypeScript use Flow syntax by default unless a +Babel configuration changes the parser plugins. diff --git a/packages/website/src/app/docs/reference/documentation/prop-types/page.mdx b/packages/website/src/app/docs/reference/documentation/prop-types/page.mdx index 35aa67af956..1404db187c6 100644 --- a/packages/website/src/app/docs/reference/documentation/prop-types/page.mdx +++ b/packages/website/src/app/docs/reference/documentation/prop-types/page.mdx @@ -1,5 +1,107 @@ -import ContentMissing from '@/components/ContentMissing'; - # PropTypes - +When [`propTypeHandler`](../handlers/prop-type-handler) is active, PropTypes +declarations are written to the `type` field of a prop, context, or child +context descriptor. + +```ts +interface PropTypeDescriptor { + name: + | 'any' + | 'array' + | 'arrayOf' + | 'bool' + | 'custom' + | 'element' + | 'elementType' + | 'enum' + | 'exact' + | 'func' + | 'instanceOf' + | 'node' + | 'number' + | 'object' + | 'objectOf' + | 'shape' + | 'string' + | 'symbol' + | 'union'; + value?: unknown; + raw?: string; + computed?: boolean; + description?: string; + required?: boolean; +} +``` + +## Simple types + +```ts filename="component.tsx" +Button.propTypes = { + label: PropTypes.string, + disabled: PropTypes.bool.isRequired, +}; +``` + +```json filename="JSON" +{ + "label": { + "type": { + "name": "string" + }, + "required": false + }, + "disabled": { + "type": { + "name": "bool" + }, + "required": true + } +} +``` + +## Complex types + +Some PropTypes include nested values. For example, `oneOf()` produces an `enum`, +`oneOfType()` produces a `union`, and `shape()` or `exact()` produce nested +descriptors in `value`. + +```ts filename="component.tsx" +Button.propTypes = { + size: PropTypes.oneOf(['small', 'large']), + icon: PropTypes.shape({ + name: PropTypes.string.isRequired, + }), +}; +``` + +```json filename="JSON" +{ + "size": { + "type": { + "name": "enum", + "value": [ + { "value": "'small'", "computed": false }, + { "value": "'large'", "computed": false } + ] + }, + "required": false + }, + "icon": { + "type": { + "name": "shape", + "value": { + "name": { + "name": "string", + "required": true + } + } + }, + "required": false + } +} +``` + +If a PropTypes expression cannot be recognized as a built-in PropType, the +handler records it as a `custom` type and stores the printed expression in +`raw`. diff --git a/packages/website/src/app/docs/reference/documentation/typescript/page.mdx b/packages/website/src/app/docs/reference/documentation/typescript/page.mdx index 4c119172ca2..4c35af1057d 100644 --- a/packages/website/src/app/docs/reference/documentation/typescript/page.mdx +++ b/packages/website/src/app/docs/reference/documentation/typescript/page.mdx @@ -1,5 +1,69 @@ -import ContentMissing from '@/components/ContentMissing'; - # TypeScript - +When [`codeTypeHandler`](../handlers/code-type-handler) extracts TypeScript +props, the type information is written to `tsType`. + +```ts +interface PropDescriptor { + tsType?: TypeDescriptor; + required?: boolean; + description?: string; + defaultValue?: DefaultValueDescriptor; +} +``` + +## Example + +```ts filename="component.tsx" +interface Props { + label: string; + disabled?: boolean; + size: 'small' | 'large'; +} + +export function Button(props: Props) { + return ; +} +``` + +```json filename="JSON" +{ + "label": { + "required": true, + "tsType": { + "name": "string" + } + }, + "disabled": { + "required": false, + "tsType": { + "name": "boolean" + } + }, + "size": { + "required": true, + "tsType": { + "name": "union", + "raw": "'small' | 'large'", + "elements": [ + { "name": "literal", "value": "'small'" }, + { "name": "literal", "value": "'large'" } + ] + } + } +} +``` + +## Type descriptors + +Most TypeScript values are represented with the shared +`TypeDescriptor` shape. Common descriptors are: + +- Simple descriptors, such as `{ "name": "string" }` +- Literal descriptors, such as `{ "name": "literal", "value": "'small'" }` +- Element descriptors, such as unions, intersections, arrays, and tuples +- Function signatures with `type: "function"` +- Object signatures with `type: "object"` + +Set `filename` to a TypeScript extension, such as `.ts` or `.tsx`, when calling +`parse()` so the default parser enables TypeScript syntax. diff --git a/packages/website/src/app/docs/reference/handlers/child-context-type-handler/page.mdx b/packages/website/src/app/docs/reference/handlers/child-context-type-handler/page.mdx index 8ce4e4e4648..2fec6ab31c2 100644 --- a/packages/website/src/app/docs/reference/handlers/child-context-type-handler/page.mdx +++ b/packages/website/src/app/docs/reference/handlers/child-context-type-handler/page.mdx @@ -1,5 +1,68 @@ -import ContentMissing from '@/components/ContentMissing'; - # childContextTypeHandler - +Finds legacy React `childContextTypes` declarations and adds them to the +documentation under the `childContext` field. + +It uses the same PropTypes parsing logic as +[`propTypeHandler`](./prop-type-handler.mdx), but writes descriptors to +`childContext` instead of `props`. + +## Examples + +When the `childContextTypeHandler` is active either of these components will +result in the output below. + +```ts {1,4-7} filename="component.tsx" +import PropTypes from 'prop-types'; + +class MyComponent extends React.Component { + static childContextTypes = { + theme: PropTypes.string, + disabled: PropTypes.bool.isRequired, + }; + render() { + return
; + } +} +``` + +```ts {1,7-10} filename="component.tsx" +import PropTypes from 'prop-types'; + +function MyComponent() { + return
; +} + +MyComponent.childContextTypes = { + theme: PropTypes.string, + disabled: PropTypes.bool.isRequired, +}; +``` + +## Output + +```json {3-16} filename="JSON" +[ + { + "childContext": { + "theme": { + "type": { + "name": "string" + }, + "required": false + }, + "disabled": { + "type": { + "name": "bool" + }, + "required": true + } + } + } +] +``` + +## Source + +- [Implementation](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/propTypeHandler.ts) +- [Tests](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/__tests__/propTypeHandler-test.ts) diff --git a/packages/website/src/app/docs/reference/handlers/code-type-handler/page.mdx b/packages/website/src/app/docs/reference/handlers/code-type-handler/page.mdx index 61f59a88cfb..4d9452f7739 100644 --- a/packages/website/src/app/docs/reference/handlers/code-type-handler/page.mdx +++ b/packages/website/src/app/docs/reference/handlers/code-type-handler/page.mdx @@ -1,5 +1,71 @@ -import ContentMissing from '@/components/ContentMissing'; - # codeTypeHandler - +Extracts Flow and TypeScript prop types from component type annotations. + +The handler writes Flow types to `flowType` and TypeScript types to `tsType`. It +also sets `required` and extracts prop descriptions from comments inside the +type definition. + +Supported component shapes include: + +- Class components with generic props, such as `React.Component` +- Class components with a typed `props` member +- Function components with a typed first argument +- `React.FC`, `React.FunctionComponent`, `React.VFC`, and + `React.VoidFunctionComponent` variable annotations +- `forwardRef()` calls with typed props + +## Examples + +When the `codeTypeHandler` is active this TypeScript component will result in +the output below. + +```ts {3-7,9} filename="component.tsx" +import React from 'react'; + +interface Props { + /** Text shown inside the button. */ + label: string; + disabled?: boolean; +} + +export function Button(props: Props) { + return ; +} +``` + +## Output + +```json {5-9,12-16} filename="JSON" +[ + { + "props": { + "label": { + "required": true, + "tsType": { + "name": "string" + }, + "description": "Text shown inside the button." + }, + "disabled": { + "required": false, + "tsType": { + "name": "boolean" + }, + "description": "" + } + } + } +] +``` + +## Notes + +Intersection types are expanded when their members can be resolved. Union types +at the props-object level are not expanded because the documentation format does +not describe alternate prop object shapes. + +## Source + +- [Implementation](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/codeTypeHandler.ts) +- [Tests](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/__tests__/codeTypeHandler-test.ts) diff --git a/packages/website/src/app/docs/reference/handlers/component-docblock-handler/page.mdx b/packages/website/src/app/docs/reference/handlers/component-docblock-handler/page.mdx index b22d14a3f42..b818ea42005 100644 --- a/packages/website/src/app/docs/reference/handlers/component-docblock-handler/page.mdx +++ b/packages/website/src/app/docs/reference/handlers/component-docblock-handler/page.mdx @@ -24,3 +24,8 @@ result in the output below } ] ``` + +## Source + +- [Implementation](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/componentDocblockHandler.ts) +- [Tests](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/__tests__/componentDocblockHandler-test.ts) diff --git a/packages/website/src/app/docs/reference/handlers/component-methods-handler/page.mdx b/packages/website/src/app/docs/reference/handlers/component-methods-handler/page.mdx index 08c1ade98ad..9c0bdeed023 100644 --- a/packages/website/src/app/docs/reference/handlers/component-methods-handler/page.mdx +++ b/packages/website/src/app/docs/reference/handlers/component-methods-handler/page.mdx @@ -91,3 +91,8 @@ forwardRef(function MyComponent(_, ref) { } ] ``` + +## Source + +- [Implementation](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/componentMethodsHandler.ts) +- [Tests](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/__tests__/componentMethodsHandler-test.ts) diff --git a/packages/website/src/app/docs/reference/handlers/context-type-handler/page.mdx b/packages/website/src/app/docs/reference/handlers/context-type-handler/page.mdx index 3956425b740..e37cca7030a 100644 --- a/packages/website/src/app/docs/reference/handlers/context-type-handler/page.mdx +++ b/packages/website/src/app/docs/reference/handlers/context-type-handler/page.mdx @@ -1,5 +1,68 @@ -import ContentMissing from '@/components/ContentMissing'; - # contextTypeHandler - +Finds legacy React `contextTypes` declarations and adds them to the +documentation under the `context` field. + +It uses the same PropTypes parsing logic as +[`propTypeHandler`](./prop-type-handler.mdx), but writes descriptors to +`context` instead of `props`. + +## Examples + +When the `contextTypeHandler` is active either of these components will result +in the output below. + +```ts {1,4-7} filename="component.tsx" +import PropTypes from 'prop-types'; + +class MyComponent extends React.Component { + static contextTypes = { + theme: PropTypes.string, + disabled: PropTypes.bool.isRequired, + }; + render() { + return
; + } +} +``` + +```ts {1,7-10} filename="component.tsx" +import PropTypes from 'prop-types'; + +function MyComponent() { + return
; +} + +MyComponent.contextTypes = { + theme: PropTypes.string, + disabled: PropTypes.bool.isRequired, +}; +``` + +## Output + +```json {3-16} filename="JSON" +[ + { + "context": { + "theme": { + "type": { + "name": "string" + }, + "required": false + }, + "disabled": { + "type": { + "name": "bool" + }, + "required": true + } + } + } +] +``` + +## Source + +- [Implementation](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/propTypeHandler.ts) +- [Tests](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/__tests__/propTypeHandler-test.ts) diff --git a/packages/website/src/app/docs/reference/handlers/default-props-handler/page.mdx b/packages/website/src/app/docs/reference/handlers/default-props-handler/page.mdx index f083a9bc283..a13e85b1dad 100644 --- a/packages/website/src/app/docs/reference/handlers/default-props-handler/page.mdx +++ b/packages/website/src/app/docs/reference/handlers/default-props-handler/page.mdx @@ -65,3 +65,8 @@ MyComponent.defaultProps = { } ] ``` + +## Source + +- [Implementation](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/defaultPropsHandler.ts) +- [Tests](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/__tests__/defaultPropsHandler-test.ts) diff --git a/packages/website/src/app/docs/reference/handlers/display-name-handler/page.mdx b/packages/website/src/app/docs/reference/handlers/display-name-handler/page.mdx index 59280d97225..ca02ef097b5 100644 --- a/packages/website/src/app/docs/reference/handlers/display-name-handler/page.mdx +++ b/packages/website/src/app/docs/reference/handlers/display-name-handler/page.mdx @@ -68,3 +68,8 @@ const DisplayName = () =>
; } ] ``` + +## Source + +- [Implementation](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/displayNameHandler.ts) +- [Tests](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/__tests__/displayNameHandler-test.ts) diff --git a/packages/website/src/app/docs/reference/handlers/prop-docblock-handler/page.mdx b/packages/website/src/app/docs/reference/handlers/prop-docblock-handler/page.mdx index dd64bfa5aad..9f22c7c47b6 100644 --- a/packages/website/src/app/docs/reference/handlers/prop-docblock-handler/page.mdx +++ b/packages/website/src/app/docs/reference/handlers/prop-docblock-handler/page.mdx @@ -68,3 +68,8 @@ MyComponent.propTypes = { } ] ``` + +## Source + +- [Implementation](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/propDocblockHandler.ts) +- [Tests](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/__tests__/propDocblockHandler-test.ts) diff --git a/packages/website/src/app/docs/reference/handlers/prop-type-composition-handler/page.mdx b/packages/website/src/app/docs/reference/handlers/prop-type-composition-handler/page.mdx index 4773c98f33e..c6831dd9bfc 100644 --- a/packages/website/src/app/docs/reference/handlers/prop-type-composition-handler/page.mdx +++ b/packages/website/src/app/docs/reference/handlers/prop-type-composition-handler/page.mdx @@ -59,3 +59,8 @@ Button.propTypes = { } ] ``` + +## Source + +- [Implementation](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/propTypeCompositionHandler.ts) +- [Tests](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/__tests__/propTypeCompositionHandler-test.ts) diff --git a/packages/website/src/app/docs/reference/handlers/prop-type-handler/page.mdx b/packages/website/src/app/docs/reference/handlers/prop-type-handler/page.mdx index c5184f6a35c..ff45c5d6578 100644 --- a/packages/website/src/app/docs/reference/handlers/prop-type-handler/page.mdx +++ b/packages/website/src/app/docs/reference/handlers/prop-type-handler/page.mdx @@ -75,3 +75,8 @@ MyComponent.propTypes = { } ] ``` + +## Source + +- [Implementation](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/propTypeHandler.ts) +- [Tests](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/handlers/__tests__/propTypeHandler-test.ts) diff --git a/packages/website/src/app/docs/reference/resolvers/_meta.js b/packages/website/src/app/docs/reference/resolvers/_meta.js new file mode 100644 index 00000000000..71b9b98b693 --- /dev/null +++ b/packages/website/src/app/docs/reference/resolvers/_meta.js @@ -0,0 +1,6 @@ +export default { + 'chain-resolver': 'Chain', + 'find-all-definitions-resolver': 'FindAllDefinitions', + 'find-annotated-definitions-resolver': 'FindAnnotatedDefinitions', + 'find-exported-definitions-resolver': 'FindExportedDefinitions', +}; diff --git a/packages/website/src/app/docs/reference/resolvers/chain-resolver/page.mdx b/packages/website/src/app/docs/reference/resolvers/chain-resolver/page.mdx new file mode 100644 index 00000000000..d4da4200fa8 --- /dev/null +++ b/packages/website/src/app/docs/reference/resolvers/chain-resolver/page.mdx @@ -0,0 +1,56 @@ +# ChainResolver + +Runs multiple resolvers as one resolver. + +This is useful when more than one strategy should be used to find components in +the same file. + +## Options + +```ts +new ChainResolver(resolvers, { + chainingLogic?: ChainResolver.Logic; +}); +``` + +### resolvers + +**Type**: `Resolver[]` + +The resolvers to run. + +### chainingLogic + +**Default**: `ChainResolver.Logic.ALL` + +Controls how resolver results are combined. + +- `ChainResolver.Logic.ALL` runs every resolver and returns all unique + components. +- `ChainResolver.Logic.FIRST_FOUND` runs resolvers in order and returns the + first non-empty result. + +## Example + +```ts filename="resolver.ts" +import { builtinResolvers } from 'react-docgen'; + +const { + ChainResolver, + FindAnnotatedDefinitionsResolver, + FindExportedDefinitionsResolver, +} = builtinResolvers; + +const resolver = new ChainResolver( + [ + new FindExportedDefinitionsResolver({ limit: 1 }), + new FindAnnotatedDefinitionsResolver(), + ], + { chainingLogic: ChainResolver.Logic.ALL }, +); +``` + +## Source + +- [Implementation](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/resolver/ChainResolver.ts) +- [Tests](https://github.com/reactjs/react-docgen/blob/main/packages/react-docgen/src/resolver/__tests__/ChainResolver-test.ts) diff --git a/packages/website/src/app/docs/reference/resolvers/find-all-definitions-resolver/page.mdx b/packages/website/src/app/docs/reference/resolvers/find-all-definitions-resolver/page.mdx new file mode 100644 index 00000000000..c4e158ee3b4 --- /dev/null +++ b/packages/website/src/app/docs/reference/resolvers/find-all-definitions-resolver/page.mdx @@ -0,0 +1,38 @@ +# FindAllDefinitionsResolver + +Finds all React component definitions in a file, regardless of whether they are +exported. + +It detects: + +- `React.createClass()` calls +- Class components extending `React.Component` or `React.PureComponent` +- Classes with a `render()` method +- Function components that return JSX or `React.createElement()` +- `React.forwardRef()` components + +The resolver can follow imported references with the configured importer. + +## Examples + +When the `FindAllDefinitionsResolver` is active, both components in this file +are returned. + +```ts {3-5,7-9} filename="component.tsx" +import React from 'react'; + +function Button() { + return