-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create / use react-docgen vite plugin to show docsPage info (#299)
Fixes #103 Closes #190 Fixes #2 This takes a slightly different approach from #190. Instead of using a babel transform, this creates a vite plugin, similar to the vue-docgen plugin, but based on the babel-plugin-react-docgen. This gives us the chance to rely directly on react-docgen, without needing another package in between, and it avoids being accidentally overwritten if users replace our @vitejs/plugin-react with their own config. This new vite plugin is not configurable like the babel plugin is, but I'm not certain those configurations are necessary in the first place. If we hear from users that it's something they need, we can find a way to make them customizable, but I prefer to avoid extra options if possible. This version does not create a global list of all the docs, like the babel plugin does (`DOC_GEN_COLLECTION_NAME`). I looked through the storybook source, and it doesn't seem like anything still relies on it, so I think it's just a legacy detail for now that we can probably avoid supporting. I've updated the react example to demonstrate the use of the plugin, so feel free to check this out there.
- Loading branch information
Showing
8 changed files
with
166 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export const parameters = { | ||
actions: { argTypesRegex: '^on[A-Z].*' }, | ||
controls: { | ||
matchers: { | ||
color: /(background|color)$/i, | ||
date: /Date$/, | ||
}, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
packages/builder-vite/plugins/docgen-handlers/actualNameHandler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/** | ||
* This is heavily based on the react-docgen `displayNameHandler` | ||
* (https://github.com/reactjs/react-docgen/blob/26c90c0dd105bf83499a83826f2a6ff7a724620d/src/handlers/displayNameHandler.ts) | ||
* but instead defines an `actualName` property on the generated docs that is taken first from the component's actual name. | ||
* This addresses an issue where the name that the generated docs are stored under is incorrectly named with the `displayName` | ||
* and not the component's actual name. | ||
* | ||
* This is inspired by `actualNameHandler` from https://github.com/storybookjs/babel-plugin-react-docgen, but is modified | ||
* directly from displayNameHandler, using the same approach as babel-plugin-react-docgen. | ||
*/ | ||
|
||
import { namedTypes as t } from 'ast-types'; | ||
import type { NodePath } from 'ast-types/lib/node-path'; | ||
import { getNameOrValue, isReactForwardRefCall } from 'react-docgen/dist/utils'; | ||
// import { getNameOrValue, isReactForwardRefCall } from 'react-docgen/lib/utils'; | ||
import type { Importer } from 'react-docgen/dist/parse'; | ||
// import type { Importer } from 'react-docgen/lib/parse'; | ||
import type Documentation from 'react-docgen/lib/Documentation'; | ||
|
||
export default function actualNameHandler(documentation: Documentation, path: NodePath, importer: Importer): void { | ||
if (t.ClassDeclaration.check(path.node) || t.FunctionDeclaration.check(path.node)) { | ||
documentation.set('actualName', getNameOrValue(path.get('id'))); | ||
} else if ( | ||
t.ArrowFunctionExpression.check(path.node) || | ||
t.FunctionExpression.check(path.node) || | ||
isReactForwardRefCall(path, importer) | ||
) { | ||
let currentPath = path; | ||
while (currentPath.parent) { | ||
if (t.VariableDeclarator.check(currentPath.parent.node)) { | ||
documentation.set('actualName', getNameOrValue(currentPath.parent.get('id'))); | ||
return; | ||
} else if (t.AssignmentExpression.check(currentPath.parent.node)) { | ||
const leftPath = currentPath.parent.get('left'); | ||
if (t.Identifier.check(leftPath.node) || t.Literal.check(leftPath.node)) { | ||
documentation.set('actualName', getNameOrValue(leftPath)); | ||
return; | ||
} | ||
} | ||
currentPath = currentPath.parent; | ||
} | ||
// Could not find an actual name | ||
documentation.set('actualName', ''); | ||
} | ||
return; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { | ||
parse, | ||
handlers as docgenHandlers, | ||
resolver as docgenResolver, | ||
importers as docgenImporters, | ||
} from 'react-docgen'; | ||
import type { DocumentationObject } from 'react-docgen/lib/Documentation'; | ||
import MagicString from 'magic-string'; | ||
import type { Plugin } from 'vite'; | ||
import actualNameHandler from './docgen-handlers/actualNameHandler'; | ||
|
||
type DocObj = DocumentationObject & { actualName: string }; | ||
|
||
// TODO: None of these are able to be overridden, so `default` is aspirational here. | ||
const defaultHandlers = Object.values(docgenHandlers).map((handler) => handler); | ||
const defaultResolver = docgenResolver.findAllExportedComponentDefinitions; | ||
const defaultImporter = docgenImporters.makeFsImporter(); | ||
const handlers = [...defaultHandlers, actualNameHandler]; | ||
|
||
export function reactDocgen(): Plugin { | ||
return { | ||
name: 'react-docgen', | ||
enforce: 'pre', | ||
async transform(src: string, id: string) { | ||
// JSX syntax is only allowed in .tsx and .jsx, but components can technically be created without JSX | ||
if (/\.(mjs|tsx?|jsx?)$/.test(id)) { | ||
try { | ||
// Since we're using `findAllExportedComponentDefinitions`, this will always be an array. | ||
const docgenResults = parse(src, defaultResolver, handlers, { importer: defaultImporter, filename: id }) as | ||
| DocObj[]; | ||
const s = new MagicString(src); | ||
|
||
docgenResults.forEach((info) => { | ||
const { actualName, ...docgenInfo } = info; | ||
if (actualName) { | ||
const docNode = JSON.stringify(docgenInfo); | ||
s.append(`;${actualName}.__docgenInfo=${docNode}`); | ||
} | ||
}); | ||
|
||
return { | ||
code: s.toString(), | ||
map: s.generateMap(), | ||
}; | ||
} catch (e) { | ||
// Usually this is just an error from react-docgen that it couldn't find a component | ||
// Only uncomment for troubleshooting | ||
// console.error(e); | ||
} | ||
} | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// TODO: delete this stub file once a new alpha of react-docgen is released (will include ts types). | ||
|
||
declare module 'react-docgen' { | ||
declare const parse; | ||
declare const handlers; | ||
declare const resolver; | ||
declare const importers; | ||
} | ||
|
||
declare module 'react-docgen/lib/Documentation' { | ||
export type DocumentationObject = Record<string, any>; | ||
export default Documentation; | ||
} | ||
|
||
declare module 'react-docgen/dist/utils' { | ||
declare const getNameOrValue; | ||
declare const isReactForwardRefCall; | ||
} | ||
|
||
declare module 'react-docgen/dist/parse' { | ||
declare type Importer = any; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters