From bf3a68b0776fa15fcc2f6efdea104c84b18ac4b6 Mon Sep 17 00:00:00 2001 From: atanasster Date: Mon, 22 Jun 2020 21:14:28 -0400 Subject: [PATCH] feat: mdx|md transclusion --- .../instrument/src/babel/extract-component.ts | 40 ++++++++++--------- core/instrument/src/babel/mdx-stories.ts | 6 +-- core/instrument/src/index.ts | 13 ++++-- core/instrument/src/misc/mdx-exports.ts | 17 ++++++-- core/instrument/src/types.ts | 2 +- core/loader/src/loader.ts | 20 +++++----- core/webpack-configs/src/instrument/index.ts | 24 ++++------- core/webpack-configs/src/react/index.ts | 13 +++--- examples/stories/src/sections/README.MD | 2 + .../stories/src/sections/transclusion.mdx | 2 + .../src/tutorial/write-mdx-stories.mdx | 11 +++++ yarn.lock | 2 +- 12 files changed, 87 insertions(+), 65 deletions(-) create mode 100644 examples/stories/src/sections/README.MD create mode 100644 examples/stories/src/sections/transclusion.mdx create mode 100644 examples/stories/src/tutorial/write-mdx-stories.mdx diff --git a/core/instrument/src/babel/extract-component.ts b/core/instrument/src/babel/extract-component.ts index 7bb67d320..c45e01355 100644 --- a/core/instrument/src/babel/extract-component.ts +++ b/core/instrument/src/babel/extract-component.ts @@ -84,26 +84,28 @@ export const extractStoreComponent = async ( ) => { if (store.doc) { const doc: StoriesDoc = store.doc; - const componentNames = Object.keys(doc.components); - if (componentNames) { - for (const componentName of componentNames) { - const { component, componentPackage } = await extractComponent( - componentName, - filePath, - source, - options, - initialAST, - ); - if (component) { - if (componentPackage) { - store.packages[componentPackage.fileHash] = componentPackage; - component.package = componentPackage.fileHash; - } - const componentKey = hashStoreId( - `${component.request ?? filePath}-${componentName}`, + if (doc.components) { + const componentNames = Object.keys(doc.components); + if (componentNames) { + for (const componentName of componentNames) { + const { component, componentPackage } = await extractComponent( + componentName, + filePath, + source, + options, + initialAST, ); - store.components[componentKey] = component; - doc.components[componentName] = componentKey; + if (component) { + if (componentPackage) { + store.packages[componentPackage.fileHash] = componentPackage; + component.package = componentPackage.fileHash; + } + const componentKey = hashStoreId( + `${component.request ?? filePath}-${componentName}`, + ); + store.components[componentKey] = component; + doc.components[componentName] = componentKey; + } } } } diff --git a/core/instrument/src/babel/mdx-stories.ts b/core/instrument/src/babel/mdx-stories.ts index 981a5cb9d..90f47213e 100644 --- a/core/instrument/src/babel/mdx-stories.ts +++ b/core/instrument/src/babel/mdx-stories.ts @@ -20,7 +20,7 @@ export const extractMDXStories = (props: any) => ( ast: File, _options: Required, { source, filePath }: { source: string; filePath: string }, -): ParseStorieReturnType => { +): ParseStorieReturnType | undefined => { const collectAttributes = (node: any): StoryParameters => { return node.attributes.reduce((acc: StoryParameters, attribute: any) => { if (attribute.value.type === 'StringLiteral') { @@ -197,8 +197,8 @@ export const extractMDXStories = (props: any) => ( if (store.doc && store.doc.title) { //@ts-ignore store.doc.components = components; + return store; } else { - throw new Error(`MDX documenation pages should have at least a title`); + return undefined; } - return store; }; diff --git a/core/instrument/src/index.ts b/core/instrument/src/index.ts index f2b77ce4a..e5bb8601a 100644 --- a/core/instrument/src/index.ts +++ b/core/instrument/src/index.ts @@ -37,7 +37,7 @@ type TraverseFn = ( ast: File, options: Required, more: { source: string; filePath: string }, -) => ParseStorieReturnType; +) => ParseStorieReturnType | undefined; /** * Instrument a source file, with options @@ -53,11 +53,14 @@ const parseSource = async ( originalSource: string, filePath: string, options: Required, -): Promise => { +): Promise => { const source = await prettify(code, filePath, options.prettier); const ast = parser.parse(source, options.parser); const store = traverseFn(ast, options, { source, filePath }); + if (!store) { + return undefined; + } if (store.doc) { const doc = store.doc; if (options.stories.storeSourceFile) { @@ -117,7 +120,9 @@ const parseSource = async ( }; export { LoadingDocStore }; -export type ParseStoriesReturnType = { transformed: string } & LoadingDocStore; +export type ParseStoriesReturnType = { transformed: string } & Partial< + LoadingDocStore +>; /** * Parse and instrument a javascript, typescript or MDX file of stories * @param source Source of the file to be instrumented @@ -178,7 +183,7 @@ export const parseStories = async ( filePath, mergedOptions, ); - const { stories, doc, components, exports, packages } = store; + const { stories, doc, components, exports, packages } = store || {}; const exportsSource = extractStoryExports(exports); let transformed = ` diff --git a/core/instrument/src/misc/mdx-exports.ts b/core/instrument/src/misc/mdx-exports.ts index 5a1b8c52b..9795f4af4 100644 --- a/core/instrument/src/misc/mdx-exports.ts +++ b/core/instrument/src/misc/mdx-exports.ts @@ -21,10 +21,15 @@ export const extractStoryExports = (exports?: MDXExportTypes): string => { if (exports.default) { const expCode = mdxPropertiesExport(exports.default); defaultExportCode = ` + const dmsPageExport = MDXContent; + dmsPageExport.MDXPage = MDXContent; - export default { ${ - expCode ? `...${expCode},` : '' - } MDXPage: MDXContent };`; + export default ${ + expCode + ? `Object.assign(dmsPageExport, ${expCode});` + : 'dmsPageExport;' + } +`; } let storiesExports: string[] = []; @@ -45,5 +50,9 @@ export const extractStoryExports = (exports?: MDXExportTypes): string => { return `${defaultExportCode}\n${storiesExports.join('\n')}`; } } - return 'export default { MDXPage: () => };'; + return ` +const dmsPageExport = MDXContent; +dmsPageExport.MDXPage = MDXContent; +export default dmsPageExport; +`; }; diff --git a/core/instrument/src/types.ts b/core/instrument/src/types.ts index 3db28a698..e9a4f5334 100644 --- a/core/instrument/src/types.ts +++ b/core/instrument/src/types.ts @@ -40,7 +40,7 @@ import { mdx } from '@mdx-js/react'; `; export const defaultMDXOptions: MDXOptions = { - test: /\.mdx$/, + test: /\.(mdx|md)$/i, renderer: DEFAULT_MDX_RENDERER, }; diff --git a/core/loader/src/loader.ts b/core/loader/src/loader.ts index 3a1edaf10..94c5fd745 100644 --- a/core/loader/src/loader.ts +++ b/core/loader/src/loader.ts @@ -21,15 +21,17 @@ module.exports.pitch = async function() { if (store) { if (store.doc) { console.log(chalk.bgRgb(244, 147, 66)('@loaded: '), filePath); - addStoriesDoc(filePath, { - stories: store.stories, - components: store.components, - packages: store.packages, - doc: { - ...store.doc, - fileName: filePath, - }, - }); + if (store.stories && store.components && store.packages) { + addStoriesDoc(filePath, { + stories: store.stories, + components: store.components, + packages: store.packages, + doc: { + ...store.doc, + fileName: filePath, + }, + }); + } } } return transformed; diff --git a/core/webpack-configs/src/instrument/index.ts b/core/webpack-configs/src/instrument/index.ts index 2331cf2b6..062e62405 100644 --- a/core/webpack-configs/src/instrument/index.ts +++ b/core/webpack-configs/src/instrument/index.ts @@ -15,7 +15,8 @@ export const instrument: Configuration = { ], }, { - test: /\.(stories|story).mdx$/, + test: /\.(md|mdx)$/, + exclude: [/node_modules/], use: [ { loader: 'babel-loader', @@ -26,32 +27,21 @@ export const instrument: Configuration = { ], }, }, - ], - }, - { - test: /\.mdx$/, - exclude: /\.(stories|story).mdx$/, - use: [ { - loader: 'babel-loader', + loader: '@component-controls/loader/loader', options: { - presets: [ - [require.resolve('@babel/preset-env'), { modules: 'commonjs' }], - ], + mdx: { + transformMDX: true, + }, }, }, ], }, { - test: /\.(story|stories).(js|jsx|ts|tsx|mdx)$/, + test: /\.(story|stories).(js|jsx|ts|tsx)$/, loader: '@component-controls/loader/loader', exclude: [/node_modules/], enforce: 'pre', - options: { - mdx: { - transformMDX: true, - }, - }, }, ], }, diff --git a/core/webpack-configs/src/react/index.ts b/core/webpack-configs/src/react/index.ts index bba812b0d..7428b0a26 100644 --- a/core/webpack-configs/src/react/index.ts +++ b/core/webpack-configs/src/react/index.ts @@ -41,7 +41,11 @@ export const react: Configuration = { ], }, { - test: /\.mdx$/, + test: /\.txt$/i, + use: require.resolve('raw-loader'), + }, + { + test: /\.(md|mdx)$/i, exclude: [/node_modules/], use: [ { @@ -64,14 +68,9 @@ export const react: Configuration = { ], }, { - test: /\.(story|stories).(js|jsx|ts|tsx)$/, + test: /\.(story|stories|doc|docs).(js|jsx|ts|tsx)$/, loader: '@component-controls/loader/loader', exclude: [/node_modules/], - options: { - mdx: { - transformMDX: true, - }, - }, }, ], }, diff --git a/examples/stories/src/sections/README.MD b/examples/stories/src/sections/README.MD new file mode 100644 index 000000000..96f81a68c --- /dev/null +++ b/examples/stories/src/sections/README.MD @@ -0,0 +1,2 @@ +# Test for uppercase .MD markdown file + diff --git a/examples/stories/src/sections/transclusion.mdx b/examples/stories/src/sections/transclusion.mdx new file mode 100644 index 000000000..83100ecf1 --- /dev/null +++ b/examples/stories/src/sections/transclusion.mdx @@ -0,0 +1,2 @@ +# Transclusion sample section + diff --git a/examples/stories/src/tutorial/write-mdx-stories.mdx b/examples/stories/src/tutorial/write-mdx-stories.mdx new file mode 100644 index 000000000..2f8da9589 --- /dev/null +++ b/examples/stories/src/tutorial/write-mdx-stories.mdx @@ -0,0 +1,11 @@ +--- +title: Introduction/Writing mdx Stories +type: tutorial +--- + +import Transclusion from '../sections/transclusion.mdx'; +import Readme from '../sections/README.MD'; + + + + \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 977b4b604..fa4716d14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2737,7 +2737,7 @@ mkdirp "^0.5.1" rimraf "^2.5.2" -"@mdx-js/loader@^1.5.1", "@mdx-js/loader@^1.5.5": +"@mdx-js/loader@^1.5.1", "@mdx-js/loader@^1.5.5", "@mdx-js/loader@^1.6.6": version "1.6.6" resolved "https://registry.yarnpkg.com/@mdx-js/loader/-/loader-1.6.6.tgz#de7438f3b18b097d66380f8698123a91c587a2f9" integrity sha512-9jTmXGf5DsVM3XFEX6eYuB8DzIRg2Qo13DHMS2uOBYjrU3w1AUa06Tzz/CnDYQcPSPxHCuRy+m0tMXmG2rQ4Xg==