docs: generate documentation for UI components (#5849)
* added tool to generate spec files for React components * use typedoc for missing descriptions and types * improvements and fixes * improvements * added doc comments for half of the components * add custom resolver + more doc comments * added all tsdocs * general improvements * add specs to UI docs * added github action * remove unnecessary api route * Added readme for react-docs-generator * remove comment * Update packages/design-system/ui/src/components/currency-input/currency-input.tsx Co-authored-by: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> * remove description of aria fields + add generate script --------- Co-authored-by: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import path from "path"
|
||||
import readFiles from "../utils/read-files.js"
|
||||
import { builtinHandlers, parse } from "react-docgen"
|
||||
import { existsSync, mkdirSync, rmSync, writeFileSync } from "fs"
|
||||
import TypedocManager from "../classes/typedoc-manager.js"
|
||||
import chalk from "chalk"
|
||||
import CustomResolver from "../resolvers/custom-resolver.js"
|
||||
import argsPropHandler from "../handlers/argsPropHandler.js"
|
||||
|
||||
type GenerateOptions = {
|
||||
src: string
|
||||
output: string
|
||||
clean?: boolean
|
||||
tsconfigPath: string
|
||||
disableTypedoc: boolean
|
||||
verboseTypedoc: boolean
|
||||
}
|
||||
|
||||
export default async function ({
|
||||
src,
|
||||
output,
|
||||
clean,
|
||||
tsconfigPath,
|
||||
disableTypedoc,
|
||||
verboseTypedoc,
|
||||
}: GenerateOptions) {
|
||||
const fileContents = readFiles(src)
|
||||
let outputExists = existsSync(output)
|
||||
|
||||
if (clean && outputExists) {
|
||||
// remove the directory which will be created in the next condition block
|
||||
rmSync(output, { recursive: true, force: true })
|
||||
outputExists = false
|
||||
}
|
||||
|
||||
// create output directory if it doesn't exist
|
||||
if (!outputExists) {
|
||||
mkdirSync(output)
|
||||
}
|
||||
|
||||
// optionally use typedoc to add missing props, descriptions
|
||||
// or types.
|
||||
const typedocManager = new TypedocManager({
|
||||
tsconfigPath,
|
||||
disable: disableTypedoc,
|
||||
verbose: verboseTypedoc,
|
||||
})
|
||||
|
||||
await typedocManager.setup(src)
|
||||
|
||||
for (const [filePath, fileContent] of fileContents) {
|
||||
try {
|
||||
const relativePath = path.resolve(filePath)
|
||||
// retrieve the specs of a file
|
||||
const specs = parse(fileContent, {
|
||||
filename: relativePath,
|
||||
resolver: new CustomResolver(typedocManager),
|
||||
handlers: [
|
||||
// Built-in handlers
|
||||
builtinHandlers.childContextTypeHandler,
|
||||
builtinHandlers.codeTypeHandler,
|
||||
builtinHandlers.componentDocblockHandler,
|
||||
builtinHandlers.componentMethodsHandler,
|
||||
builtinHandlers.contextTypeHandler,
|
||||
builtinHandlers.defaultPropsHandler,
|
||||
builtinHandlers.displayNameHandler,
|
||||
builtinHandlers.propDocblockHandler,
|
||||
builtinHandlers.propTypeCompositionHandler,
|
||||
builtinHandlers.propTypeHandler,
|
||||
// Custom handlers
|
||||
(documentation, componentPath) =>
|
||||
argsPropHandler(documentation, componentPath, typedocManager),
|
||||
],
|
||||
babelOptions: {
|
||||
ast: true,
|
||||
},
|
||||
})
|
||||
|
||||
// write each of the specs into output directory
|
||||
specs.forEach((spec) => {
|
||||
if (!spec.displayName) {
|
||||
return
|
||||
}
|
||||
const specNameSplit = spec.displayName.split(".")
|
||||
let filePath = output
|
||||
|
||||
if (spec.description) {
|
||||
spec.description = typedocManager.normalizeDescription(
|
||||
spec.description
|
||||
)
|
||||
}
|
||||
|
||||
// if typedoc isn't disabled, this method will try to fill
|
||||
// missing descriptions and types, and add missing props.
|
||||
spec = typedocManager.tryFillWithTypedocData(spec, specNameSplit)
|
||||
|
||||
// put the spec in a sub-directory
|
||||
filePath = path.join(filePath, specNameSplit[0])
|
||||
if (!existsSync(filePath)) {
|
||||
mkdirSync(filePath)
|
||||
}
|
||||
|
||||
// write spec to output path
|
||||
writeFileSync(
|
||||
path.join(filePath, `${spec.displayName}.json`),
|
||||
JSON.stringify(spec, null, 2)
|
||||
)
|
||||
|
||||
console.log(chalk.green(`Created spec file for ${spec.displayName}.`))
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(chalk.red(`Failed to parse ${filePath}: ${e}`))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user