-
Notifications
You must be signed in to change notification settings - Fork 11
feat(mdx): Add script for React mdx conversion #67
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
Changes from 4 commits
4d776d8
57d8cd5
de218a9
75f791e
5072c4f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| #!/usr/bin/env ts-node | ||
|
|
||
| import { readFile, writeFile } from 'fs/promises' | ||
| import { glob } from 'glob' | ||
|
|
||
| async function main() { | ||
|
||
| const files = await glob('./testContent/react/examples/*.md') | ||
|
||
| files.forEach(async (file) => { | ||
| const fileContent = await readFile(file, 'utf-8') | ||
|
|
||
| //regex link: https://regexr.com/8f0er | ||
| const importRegex = /(?<!```no[lL]ive\n)import {?[\w\s,\n]*}?.*\n/g | ||
|
|
||
| //removes all top level imports from the md file that the old docs framework used to determine what imports are needed | ||
| const withoutImports = fileContent.replace(importRegex, '') | ||
|
|
||
| //regex link: https://regexr.com/8f0bu | ||
| const ExampleBlockRegex = /```[tj]s file=['"]\.?\/?(\w*)\.(\w*)['"]\s*\n```/g | ||
|
|
||
| //the first capture group is the example file name without the extension or path, the second is the extension | ||
| const replacementString = `\nimport $1 from "./$1.$2?raw"\n\n<LiveExample src={$1} />` | ||
| const examplesConvertedToMDX = withoutImports.replace( | ||
| ExampleBlockRegex, | ||
| replacementString, | ||
| ) | ||
|
|
||
| //we want to strip the nolive/noLive tags from codeblocks as that was custom to the old docs framework | ||
| const noLiveRemoved = examplesConvertedToMDX.replace(/```no[lL]ive/g, '```') | ||
|
|
||
| await writeFile(file + 'x', noLiveRemoved) | ||
| }) | ||
| } | ||
|
|
||
| main() | ||
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 |
|---|---|---|
|
|
@@ -41,15 +41,18 @@ | |
| }, | ||
| "dependencies": { | ||
| "@astrojs/check": "^0.9.4", | ||
| "@astrojs/node": "^9.1.3", | ||
| "@astrojs/mdx": "^4.2.6", | ||
| "@astrojs/node": "^9.1.3", | ||
| "@astrojs/react": "^4.2.1", | ||
| "@nanostores/react": "^0.8.0", | ||
| "@patternfly/ast-helpers": "^1.4.0-alpha.190", | ||
| "@patternfly/patternfly": "^6.0.0", | ||
| "@patternfly/react-code-editor": "^6.2.2", | ||
| "@patternfly/react-core": "^6.0.0", | ||
| "@patternfly/react-icons": "^6.0.0", | ||
| "@patternfly/react-styles": "^6.0.0", | ||
| "@patternfly/react-table": "^6.0.0", | ||
| "@patternfly/react-tokens": "^6.0.0", | ||
| "@types/react": "^18.3.12", | ||
| "@types/react-dom": "^18.3.1", | ||
| "astro": "^5.4.1", | ||
|
|
@@ -60,6 +63,7 @@ | |
| "react": "^18.3.1", | ||
| "react-docgen": "^7.1.1", | ||
| "react-dom": "^18.3.1", | ||
| "react-error-boundary": "^6.0.0", | ||
|
Contributor
Author
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. Using this package as a quick and easy error boundary to wrap the examples in so that errors encountered when trying to render them don't crash the UI while I fine tuned the conversion. It has a few million weekly downloads on NPM so it's probably fine, but I have no strong feeling about keeping it in for the real PR.
Member
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. I've used it and liked it in the past fwiw. |
||
| "sass": "^1.81.0", | ||
| "typescript": "^5.6.3" | ||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,32 @@ | ||
| import React, { useState } from 'react' | ||
| import React, { useState, Fragment, useRef, useEffect, createRef, useReducer } from 'react' | ||
| import { convertToReactComponent } from '@patternfly/ast-helpers' | ||
| import { ErrorBoundary } from 'react-error-boundary' | ||
| import * as reactCoreModule from '@patternfly/react-core' | ||
| import * as reactIconsModule from '@patternfly/react-icons' | ||
| import styles from "@patternfly/react-styles/css/components/_index" | ||
| import * as reactTokensModule from "@patternfly/react-tokens" | ||
|
Comment on lines
+5
to
+7
Contributor
Author
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. I think we'll want to refactor this so that we pass all of these modules via the config, but for now just doing this works. What do yall think?
Contributor
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. That makes sense to me.
Contributor
Author
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. Would you be opposed to that being done in a followup?
Contributor
Author
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. Made this issue to address #72
Collaborator
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. I think this is fine for now. |
||
| import { ExampleToolbar } from './ExampleToolbar' | ||
| interface LiveExampleProps { | ||
| src: string | ||
| } | ||
|
|
||
| function fallbackRender({ error }: any) { | ||
| return ( | ||
| <div role="alert"> | ||
| <p>Something went wrong:</p> | ||
| <pre style={{ color: 'red' }}>{error.message}</pre> | ||
| </div> | ||
| ) | ||
| } | ||
|
|
||
| function getLivePreview(editorCode: string) { | ||
| const scope = { ...reactCoreModule, ...{ useState } } | ||
| const scope = { | ||
| ...reactCoreModule, | ||
| ...reactIconsModule, | ||
| styles, | ||
| ...reactTokensModule, | ||
| ...{ useState, Fragment, useRef, useEffect, createRef, useReducer }, | ||
| } | ||
| const { code: transformedCode } = convertToReactComponent(editorCode) | ||
|
|
||
| const componentNames = Object.keys(scope) | ||
|
|
@@ -28,7 +47,7 @@ export const LiveExample = ({ src }: LiveExampleProps) => { | |
| const livePreview = getLivePreview(code) | ||
|
|
||
| return ( | ||
| <> | ||
| <ErrorBoundary fallbackRender={fallbackRender}> | ||
| {livePreview} | ||
| <ExampleToolbar | ||
| originalCode={src} | ||
|
|
@@ -37,6 +56,6 @@ export const LiveExample = ({ src }: LiveExampleProps) => { | |
| lang="ts" | ||
| isFullscreen={false} | ||
| /> | ||
| </> | ||
| </ErrorBoundary> | ||
| ) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,27 @@ import { componentTabs } from '../../globals' | |
| import PropsTables from '../../components/PropsTables.astro' | ||
| import CSSTable from '../../components/CSSTable.astro' | ||
| import SectionGallery from '../../components/section-gallery/SectionGallery.astro' | ||
| import LiveExample from '../../components/LiveExample.astro' | ||
|
Contributor
Author
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. Changes to this file were needed because by default the examples are rendering at this endpoint rather than
Collaborator
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. I think its because the nav links to |
||
| import { | ||
| h1, | ||
| h2, | ||
| h3, | ||
| h4, | ||
| h5, | ||
| h6, | ||
| p, | ||
| a, | ||
| small, | ||
| blockquote, | ||
| pre, | ||
| hr, | ||
| ul, | ||
| ol, | ||
| dl, | ||
| li, | ||
| dt, | ||
| dd, | ||
| } from '../../components/Content' | ||
|
|
||
| export async function getStaticPaths() { | ||
| const collections = await Promise.all( | ||
|
|
@@ -31,8 +52,9 @@ const { entry, propComponents, cssPrefix } = Astro.props | |
| const { title, id, section } = entry.data | ||
| const { Content } = await render(entry) | ||
|
|
||
| if(section === 'components' && componentTabs[id]) { // if section is components & tab exists, rewrite to first tab content | ||
| return Astro.rewrite(`/components/${kebabCase(id)}/${componentTabs[id][0]}`); | ||
| if (section === 'components' && componentTabs[id]) { | ||
| // if section is components & tab exists, rewrite to first tab content | ||
| return Astro.rewrite(`/components/${kebabCase(id)}/${componentTabs[id][0]}`) | ||
| } | ||
| --- | ||
|
|
||
|
|
@@ -44,17 +66,38 @@ if(section === 'components' && componentTabs[id]) { // if section is components | |
| </Title> | ||
| ) | ||
| } | ||
| <PageSection id="main-content" isFilled> | ||
| <Content components={{ | ||
| SectionGallery | ||
| }}/> | ||
| <Stack hasGutter> | ||
| <StackItem> | ||
| <PropsTables propComponents={propComponents} server:defer /> | ||
| </StackItem> | ||
| <StackItem> | ||
| <CSSTable cssPrefix={cssPrefix} server:defer /> | ||
| </StackItem> | ||
| </Stack> | ||
| <PageSection id="main-content" isFilled> | ||
| <Content | ||
| components={{ | ||
| SectionGallery, | ||
| h1, | ||
| h2, | ||
| h3, | ||
| h4, | ||
| h5, | ||
| h6, | ||
| p, | ||
| a, | ||
| small, | ||
| blockquote, | ||
| pre, | ||
| hr, | ||
| ul, | ||
| ol, | ||
| dl, | ||
| li, | ||
| dt, | ||
| dd, | ||
| LiveExample, | ||
| }} | ||
| /> | ||
| <Stack hasGutter> | ||
| <StackItem> | ||
| <PropsTables propComponents={propComponents} server:defer /> | ||
| </StackItem> | ||
| <StackItem> | ||
| <CSSTable cssPrefix={cssPrefix} server:defer /> | ||
| </StackItem> | ||
| </Stack> | ||
| </PageSection> | ||
| </MainLayout> | ||
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.
Do we need this if we are using tsx instead of ts-node?
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.
Ah nope I don't think so, good catch