patternfly / patternfly/patternfly-org
ESM Migration Project Plan for @patternfly/documentation-framework [draft]
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 74
- Forks
- 147
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 2
Description
—
ESM Migration Project Plan for @patternfly/documentation-framework
The documentation-framework's build pipeline depends on unified v9, remark-parse v8, and
several remark plugins at versions from 2020-2021. These packages are all CommonJS. The
broader JavaScript ecosystem — including many of these same packages' latest versions — has
moved to ESM-only distribution. This is already causing problems: react-docgen v6 (ESM-only)
broke CI because the framework's CJS code can't require() it, requiring an async workaround.
This will keep happening. As more dependencies release ESM-only versions, each one will need
its own async import() workaround, adding complexity to the codebase. Meanwhile, the old
dependency versions pin the framework to outdated APIs — several custom plugins use
remark-parse internals (this.Parser.prototype.blockTokenizers, eat()) that were removed years
ago, and others import private /lib/ paths that could break at any time.
Converting the framework to ESM and upgrading its unified/remark dependencies to current
versions would:
-
Eliminate the CJS/ESM boundary friction for current and future dependencies
-
Move off deprecated, unsupported plugin APIs to the current remark/micromark architecture
-
Remove reliance on private internal imports that could break without notice
-
Align with the direction the Node.js ecosystem is heading, reducing future maintenance
burden
The tradeoff is a significant one-time migration effort across the markdown processing
pipeline and coordination with 4 consuming repos (patternfly-react, react-topology, chatbot,
react-component-groups) for 2 files each.
Phase 1: Rewrite custom remark plugins (highest risk, do first)
These are the gatekeeping changes. If these can't be ported, the migration is blocked.
1a. Rewrite remove-comments.js (Effort: Small)
-
Currently 22 lines, uses this.Parser.prototype.blockTokenizers + eat() to strip HTML
comments -
Migration: Likely redundant — parseMD.js already does remove(tree, 'comment') later in the
pipeline. May be able to just delete it.
1b. Rewrite auto-link-url.js (Effort: Small-Medium)
-
Currently 33 lines, re-adds https://... autolink support that remark-mdx strips
-
Migration: Check if remark-mdx v3 still strips autolinks. If not, this plugin is
unnecessary. If still needed, convert to an MDAST tree transform or write a micromark
extension.
—
Phase 2: Fix private API dependencies (Medium risk)
2a. Fix mdx-hast-to-jsx.js (Effort: Medium)
-
Uses remark-mdx/lib/serialize/ private internals for serializeTags() and
serializeMdxExpression() -
Uses hast-to-hyperscript and @mdx-js/util (v1) which may not exist in v3
-
Uses this.Compiler pattern (removed in unified v11)
-
Need to find public API replacements or inline the functionality
2b. Fix mdx-ast-to-mdx-hast.js (Effort: Small-Medium)
-
Uses mdast-util-to-hast/lib/all private import
-
Handler API may differ in mdast-util-to-hast v13
—
Phase 3: Update AST node types (Effort: Small)
Rename across 3 files (parseMD.js, mdx-ast-to-mdx-hast.js, mdx-hast-to-jsx.js):
-
mdxBlockElement -> mdxJsxFlowElement
-
mdxSpanElement -> mdxJsxTextElement
-
mdxBlockExpression -> mdxFlowExpression
-
mdxSpanExpression -> mdxTextExpression
-
Check if 'import' node type changed to 'mdxjsEsm' in remark-mdx v3
—
Phase 4: Convert parseMD.js processing pipeline (Effort: Small)
-
.process(vfile, callback) -> await processor.process(vfile)
-
Makes toReactComponent() async, ripples to sourceMDFile() and processMD()
—
Phase 5: Upgrade dependencies in package.json (Effort: Small)
Do this AFTER the code changes in phases 1-4.
-
unified: 9.2.2 -> 11.0.5
-
remark-parse: 8.0.3 -> 11.0.0
-
remark-frontmatter: 2.0.0 -> 5.0.0
-
remark-mdx: 2.0.0-next.8 -> 3.1.1
-
remark-mdxjs: 2.0.0-next.8 -> REMOVE (merged into remark-mdx v3)
-
remark-footnotes: 1.0.0 -> 5.0.0
-
remark-squeeze-paragraphs: 4.0.0 -> 6.0.0
-
unist-util-remove: 2.1.0 -> 4.0.0
-
unist-util-visit: 2.0.3 -> 5.1.0
-
to-vfile: 6.1.0 -> 8.0.0
-
vfile-reporter: 6.0.2 -> 8.1.1
-
glob: 12.0.0 -> 13.0.6
-
mdast-util-to-hast: 9.1.2 -> 13.2.1
-
hast-to-hyperscript: 9.0.1 -> 11.0.0
-
@mdx-js/util: 1.6.22 -> REMOVE or replace
-
parse-entities: 2.0.0 -> 3.0.2 (if still needed)
-
detab: 2.0.4 -> 4.0.2
—
Phase 6: Convert files to ESM (Effort: Medium)
-
Add "type": "module" to package.json
-
Convert all 47 .js files: require() -> import, module.exports -> export
-
Replace __dirname with import.meta.dirname (Node 21+) or
path.dirname(fileURLToPath(import.meta.url)) -
Replace require.resolve() with import.meta.resolve()
-
Rename consumer-facing files that MUST stay CJS to .cjs: routes.js, routes-client.js,
routes-generated.js -
Update webpack alias/resolve config to point to .cjs files
-
CLI entry point (cli.js) can stay as ESM
—
Phase 7: Test across all consumers (Effort: Medium)
-
patternfly/patternfly (HTML docs, no props)
-
patternfly/patternfly-react (React docs with prop tables — most comprehensive)
-
patternfly/react-topology, patternfly/chatbot, patternfly/react-component-groups
-
Verify: build, start, screenshots, a11y tests
—
Risk summary:
-
Phase 1-2: Risky, blocking — if these can't be ported, migration is blocked
-
Phase 3-6: Low risk, mostly mechanical
-
Phase 7: Medium risk — integration issues may surface
Jira Issue: PF-3687
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the current pipeline in parseMD.js and the custom plugins remove-comments.js, auto-link-url.js, mdx-hast-to-jsx.js, and mdx-ast-to-mdx-hast.js, then review package.json. Map the dependency and ESM changes across the listed phases before modifying anything. Done means the framework and its four consuming repositories build and pass their documented screenshots and accessibility checks.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- build-system, documentation
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100