-
Notifications
You must be signed in to change notification settings - Fork 536
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automate component documentation #4466
base: main
Are you sure you want to change the base?
Changes from 5 commits
9696cd0
0a813c5
c165dca
f9c73f8
1c9d270
25c7bda
e49af04
54892e7
6cdcf88
1cf0ec0
7eeb894
2169f0b
e73c1c9
12de6ac
1d8a2f4
be24a72
d27318a
f0aac7f
7ef30d2
cdfd5be
af53bed
1eff7b7
89a81fc
2583744
4d417e5
57c9580
5f20543
2be3c85
805b7f1
2536e1d
8629a4b
944d1ec
52f4687
a8ae2c7
e3fda71
ed42983
55639f3
93191c3
a99804b
933ec32
5bed7c6
cd6db28
50ab39e
262aeeb
2b4a9f5
7de1ad0
1a649bb
f34635b
55a28c6
1d19be5
8c40539
c47aa8a
af3b59a
9199194
65e3bd0
4cfd353
4efe0dc
f2f27bd
cc763ad
51ad70f
cc0baf0
d3fcd12
001fac1
4a32951
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
const docgen = require('react-docgen-typescript') | ||
const globby = require('globby') | ||
|
||
const fs = require('node:fs') | ||
|
||
const docgenOptions = { | ||
// savePropValueAsString: true, | ||
// allowSyntheticDefaultImports might let us avoid separately importing types from React | ||
// (e.g.: you can do `React.FC` instead of importing and using `FC` from React) | ||
// allowSyntheticDefaultImports: true, | ||
propFilter: (prop, _component) => { | ||
if (prop.declarations !== undefined && prop.declarations.length > 0) { | ||
const hasPropAdditionalDescription = prop.declarations.find(declaration => { | ||
return !declaration.fileName.includes('node_modules') | ||
}) | ||
|
||
return Boolean(hasPropAdditionalDescription) | ||
} | ||
|
||
return true | ||
}, | ||
} | ||
|
||
// const noPropsWhitelist = [ | ||
// 'ButtonGroup/ButtonGroup.tsx', | ||
// {fileName: 'ConfirmationDialog/ConfirmationDialog.tsx', displayName: 'useConfirm'}, | ||
// 'UnderlineNav/LoadingCounter.tsx', | ||
// {fileName: 'components/LiveRegion.tsx', displayName: 'LiveRegion'}, | ||
// {fileName: 'DataTable/Table.tsx', displayName: 'TableActions'}, | ||
// {fileName: 'DataTable/Table.tsx', displayName: 'TableHead'}, | ||
// {fileName: 'DataTable/Table.tsx', displayName: 'TableBody'}, | ||
// {fileName: 'DataTable/Table.tsx', displayName: 'TableRow'}, | ||
// ] | ||
|
||
// Parse a file for docgen info | ||
const files = globby.sync( | ||
// Glob for testing | ||
// [ | ||
// './packages/react/src/Avatar/*.tsx', | ||
// './packages/react/src/DataTable/*.tsx', | ||
// '!./packages/react/src/**/*.stories.tsx', | ||
// '!./packages/react/src/**/*.test.tsx', | ||
// ], | ||
['./packages/react/src/**/*.tsx', '!./packages/react/src/**/*.stories.tsx', '!./packages/react/src/**/*.test.tsx'], | ||
{ | ||
absolute: true, | ||
}, | ||
) | ||
const docgenOutput = docgen.parse(files, docgenOptions) | ||
|
||
const printSkippedComponents = () => { | ||
console.log('COMPONENTS SKIPPED:') | ||
|
||
files.forEach(file => { | ||
if (!docgenOutput.map(({filePath}) => filePath).includes(file)) { | ||
console.log(file) | ||
} | ||
}) | ||
|
||
console.log('\n') | ||
} | ||
|
||
const printSkippedProps = () => { | ||
console.log('PROPS NOT DOCUMENTED:') | ||
|
||
docgenOutput.forEach(({props, filePath, displayName}) => { | ||
if (Object.keys(props).length === 0) { | ||
console.log(`${filePath} - ${displayName}`) | ||
} | ||
}) | ||
|
||
console.log('\n') | ||
} | ||
|
||
const formatComponentJson = ({description, displayName, props, tags}) => { | ||
const {alias, primerid, primerstatus, primera11yreviewed, primerstories = '', primerparentid} = tags | ||
|
||
return { | ||
id: primerid, // TODO: consider auto-generating an ID if one is not present by parsing `displayName` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just FYI @broccolinisoup and I just worked up this PR and this PR that introduce a |
||
description, | ||
name: primerparentid && alias ? alias : displayName, | ||
status: primerstatus, | ||
a11yReviewed: primera11yreviewed === 'true', | ||
stories: primerstories.split(' '), | ||
props: Object.keys(props).map(propName => { | ||
const {type, required, description, defaultValue} = props[propName] | ||
|
||
return { | ||
name: propName, | ||
type: type.name, | ||
required, | ||
description, | ||
defaultValue: defaultValue ? defaultValue.value : null, | ||
} | ||
}), | ||
} | ||
} | ||
|
||
const transformArray = (docgenOutputData: any[]): any[] => { | ||
return docgenOutputData | ||
.map(outputDatum => { | ||
const {id, primerparentid} = outputDatum.tags | ||
|
||
const subComponents = docgenOutputData.filter(({tags}) => tags.primerparentid && tags.primerparentid === id) | ||
|
||
if (!primerparentid) { | ||
return { | ||
...formatComponentJson(outputDatum), | ||
subcomponents: subComponents.map(formatComponentJson), | ||
} | ||
} | ||
}) | ||
.filter(Boolean) | ||
} | ||
|
||
// write raw docgen output to file | ||
fs.writeFile( | ||
globby.sync('./packages/react/script/prop-docs/docgen-output.json')[0], | ||
JSON.stringify(docgenOutput, null, 2), | ||
err => { | ||
if (err) { | ||
console.error(err) | ||
} else { | ||
console.log( | ||
`Components.json generated at: ${globby.sync('./packages/react/script/prop-docs/docgen-output.json')[0]}`, | ||
) | ||
} | ||
}, | ||
) | ||
|
||
// write formatted docgen output to file ([schema](https://github.com/primer/react/blob/main/packages/react/script/components-json/component.schema.json)) | ||
fs.writeFile( | ||
globby.sync('./packages/react/script/prop-docs/components.json')[0], | ||
JSON.stringify(transformArray(docgenOutput), null, 2), | ||
err => { | ||
if (err) { | ||
console.error(err) | ||
} else { | ||
console.log( | ||
`Components.json generated at: ${globby.sync('./packages/react/script/prop-docs/components.json')[0]}`, | ||
) | ||
} | ||
}, | ||
) | ||
|
||
// log debugging info | ||
|
||
printSkippedComponents() | ||
printSkippedProps() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use module
import
s here instead ofrequire
? I see we're usingtsx
so that should be possible?