From 75eca8779ef0e5fdc1f7a0de0d8c3094242ecebb Mon Sep 17 00:00:00 2001 From: nicolethoen Date: Mon, 9 Mar 2026 17:02:59 -0400 Subject: [PATCH 1/2] fix: Changes for docs-gen v6 ESM compatibility --- .../scripts/cli/build.js | 2 +- .../documentation-framework/scripts/cli/cli.js | 4 ++-- .../scripts/cli/generate.js | 5 +++-- .../scripts/cli/start.js | 2 +- .../scripts/md/parseMD.js | 11 ++++++++--- .../documentation-framework/scripts/tsDocgen.js | 17 +++++++++++++---- 6 files changed, 28 insertions(+), 13 deletions(-) diff --git a/packages/documentation-framework/scripts/cli/build.js b/packages/documentation-framework/scripts/cli/build.js index 220f178aff..50eacc4e4b 100644 --- a/packages/documentation-framework/scripts/cli/build.js +++ b/packages/documentation-framework/scripts/cli/build.js @@ -76,7 +76,7 @@ async function execFile(file, args) { } async function build(cmd, options) { - generate(options); + await generate(options); const toBuild = cmd === 'all' ? ['server', 'client'] : cmd; diff --git a/packages/documentation-framework/scripts/cli/cli.js b/packages/documentation-framework/scripts/cli/cli.js index 17da8d1d2d..e8164f8096 100755 --- a/packages/documentation-framework/scripts/cli/cli.js +++ b/packages/documentation-framework/scripts/cli/cli.js @@ -9,9 +9,9 @@ program program .command('generate') .description('generates source files') - .action(options => { + .action(async options => { const { generate } = require('./generate'); - generate(options); + await generate(options); }); program diff --git a/packages/documentation-framework/scripts/cli/generate.js b/packages/documentation-framework/scripts/cli/generate.js index d649a5823a..24e22f34e9 100644 --- a/packages/documentation-framework/scripts/cli/generate.js +++ b/packages/documentation-framework/scripts/cli/generate.js @@ -1,15 +1,16 @@ const path = require('path'); -const { sourceMD, sourceProps, sourceFunctionDocs, writeIndex } = require('../md/parseMD'); +const { sourceMD, sourceProps, sourceFunctionDocs, writeIndex, waitForProps } = require('../md/parseMD'); function getSource(options) { return require(path.join(process.cwd(), options.parent.source)); } -function generate(options) { +async function generate(options) { const start = new Date(); console.log('write source files to patternfly-docs/generated'); const sourceMDWithOptions = (glob, source, ignore) => sourceMD(glob, source, ignore, options._name); getSource(options)(sourceMDWithOptions, sourceProps, sourceFunctionDocs); + await waitForProps(); const exitCode = writeIndex(); if (exitCode !== 0) { process.exit(exitCode); diff --git a/packages/documentation-framework/scripts/cli/start.js b/packages/documentation-framework/scripts/cli/start.js index 42b0cc0d88..86154b2149 100644 --- a/packages/documentation-framework/scripts/cli/start.js +++ b/packages/documentation-framework/scripts/cli/start.js @@ -19,7 +19,7 @@ function startDevServer(webpackConfig) { } async function start(options) { - generate(options, true); + await generate(options, true); const webpackClientConfig = await clientConfig(null, { mode: 'development', ...getConfig(options) }); console.log('start rspack-dev-server'); watchMD(); diff --git a/packages/documentation-framework/scripts/md/parseMD.js b/packages/documentation-framework/scripts/md/parseMD.js index 1fc5cf8319..81f06efce6 100644 --- a/packages/documentation-framework/scripts/md/parseMD.js +++ b/packages/documentation-framework/scripts/md/parseMD.js @@ -19,6 +19,7 @@ const outputBase = path.join(process.cwd(), `patternfly-docs/generated`); const tsDocs = {}; let functionDocs = {}; const routes = {}; +const pendingProps = []; const globs = { props: [], md: [], @@ -267,8 +268,8 @@ function toReactComponent(mdFilePath, source, buildMode) { }; } -function sourcePropsFile(file) { - tsDocgen(file) +async function sourcePropsFile(file) { + (await tsDocgen(file)) .filter(({ hide }) => !hide) .forEach(({ name, description, props }) => { tsDocs[getTsDocName(name, getTsDocNameVariant(file))] = { name, description, props }; @@ -345,7 +346,11 @@ function getTsDocNameVariant(source) { module.exports = { sourceProps(glob, ignore) { globs.props.push({ glob, ignore }); - globSync(glob, { ignore }).forEach(sourcePropsFile); + const promise = Promise.all(globSync(glob, { ignore }).map(sourcePropsFile)); + pendingProps.push(promise); + }, + async waitForProps() { + await Promise.all(pendingProps); }, sourceMD(glob, source, ignore, buildMode) { globs.md.push({ glob, source, ignore }); diff --git a/packages/documentation-framework/scripts/tsDocgen.js b/packages/documentation-framework/scripts/tsDocgen.js index 8ba8d58281..b023714c72 100644 --- a/packages/documentation-framework/scripts/tsDocgen.js +++ b/packages/documentation-framework/scripts/tsDocgen.js @@ -1,7 +1,15 @@ const fs = require("fs"); -const reactDocgen = require("react-docgen"); const ts = require("typescript"); +// react-docgen v6+ is ESM-only; lazy-load it asynchronously on first use +let reactDocgenReady = null; +function loadReactDocgen() { + if (!reactDocgenReady) { + reactDocgenReady = import("react-docgen"); + } + return reactDocgenReady; +} + const annotations = [ { regex: /@deprecated/, @@ -41,7 +49,8 @@ function addAnnotations(prop) { return prop; } -function getComponentMetadata(filename, sourceText) { +async function getComponentMetadata(filename, sourceText) { + const reactDocgen = await loadReactDocgen(); let parsedComponents = null; try { parsedComponents = reactDocgen.parse(sourceText, { @@ -159,9 +168,9 @@ function normalizeProp([ return res; } -function tsDocgen(file) { +async function tsDocgen(file) { const sourceText = fs.readFileSync(file, "utf8"); - const componentMeta = getComponentMetadata(file, sourceText); // Array of components with props + const componentMeta = await getComponentMetadata(file, sourceText); // Array of components with props const interfaceMeta = getInterfaceMetadata(file, sourceText); // Array of interfaces with props const typeAliasMeta = getTypeAliasMetadata(file, sourceText); // Array of type aliases with props const propsMetaMap = [...interfaceMeta, ...typeAliasMeta].reduce(function ( From 8e17dbe94410e9d76c5892827df38c67882703c8 Mon Sep 17 00:00:00 2001 From: nicolethoen Date: Tue, 10 Mar 2026 16:49:28 -0400 Subject: [PATCH 2/2] fix parseMD race condition --- .../documentation-framework/scripts/cli/cli.js | 4 ++-- .../scripts/cli/generate.js | 3 ++- .../scripts/md/parseMD.js | 17 +++++++++++++---- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/documentation-framework/scripts/cli/cli.js b/packages/documentation-framework/scripts/cli/cli.js index e8164f8096..3ffb99fe6a 100755 --- a/packages/documentation-framework/scripts/cli/cli.js +++ b/packages/documentation-framework/scripts/cli/cli.js @@ -17,9 +17,9 @@ program program .command('start') .description('generates source files and runs webpack-dev-server') - .action(options => { + .action(async options => { const { start } = require('./start'); - start(options); + await start(options); }); program diff --git a/packages/documentation-framework/scripts/cli/generate.js b/packages/documentation-framework/scripts/cli/generate.js index 24e22f34e9..ed37138d78 100644 --- a/packages/documentation-framework/scripts/cli/generate.js +++ b/packages/documentation-framework/scripts/cli/generate.js @@ -1,5 +1,5 @@ const path = require('path'); -const { sourceMD, sourceProps, sourceFunctionDocs, writeIndex, waitForProps } = require('../md/parseMD'); +const { sourceMD, sourceProps, sourceFunctionDocs, writeIndex, waitForProps, processMD } = require('../md/parseMD'); function getSource(options) { return require(path.join(process.cwd(), options.parent.source)); @@ -11,6 +11,7 @@ async function generate(options) { const sourceMDWithOptions = (glob, source, ignore) => sourceMD(glob, source, ignore, options._name); getSource(options)(sourceMDWithOptions, sourceProps, sourceFunctionDocs); await waitForProps(); + processMD(); const exitCode = writeIndex(); if (exitCode !== 0) { process.exit(exitCode); diff --git a/packages/documentation-framework/scripts/md/parseMD.js b/packages/documentation-framework/scripts/md/parseMD.js index 81f06efce6..49967e5460 100644 --- a/packages/documentation-framework/scripts/md/parseMD.js +++ b/packages/documentation-framework/scripts/md/parseMD.js @@ -353,16 +353,25 @@ module.exports = { await Promise.all(pendingProps); }, sourceMD(glob, source, ignore, buildMode) { - globs.md.push({ glob, source, ignore }); - globSync(glob, { ignore }).forEach(file => sourceMDFile(file, source, buildMode)); + globs.md.push({ glob, source, ignore, buildMode }); + }, + processMD() { + globs.md.forEach(({ glob, source, ignore, buildMode }) => { + globSync(glob, { ignore }).forEach(file => sourceMDFile(file, source, buildMode)); + }); }, sourceFunctionDocs, writeIndex, watchMD() { globs.props.forEach(({ glob, ignore }) => { const propWatcher = chokidar.watch(globSync(glob, { ignored: ignore, ignoreInitial: true})); - propWatcher.on('add', sourcePropsFile); - propWatcher.on('change', sourcePropsFile); + const onPropFile = (file) => { + sourcePropsFile(file).catch((err) => { + console.error('Error updating props from', file, err); + }); + }; + propWatcher.on('add', onPropFile); + propWatcher.on('change', onPropFile); }); globs.md.forEach(({ glob, source, ignore }) => { const mdWatcher = chokidar.watch(globSync(glob, { ignored: ignore, ignoreInitial: true }));