From d63a44c097dce95be4f1236b4ea75783cc8969e0 Mon Sep 17 00:00:00 2001 From: Christopher Biscardi Date: Fri, 9 Nov 2018 16:35:37 -0800 Subject: [PATCH 1/4] Stabilize UserLayout Fixes https://github.com/mdx-js/mdx/issues/307 Pulls the layout for an MDX file into a reference that will be stable across renders. Previously, a layout defined in MDX content as an inline arrow function: ```js export default ({ children, ...props }) =>
{children}
``` would result in function defined inline in render, causing the reference to be created each time resulting in a remounting. This PR stablizes the reference by pulling the layout outside of render, resulting in no remount. try class approach works, but need to make it so that the runtime also has the fix --- packages/mdx/mdx-hast-to-jsx.js | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/mdx/mdx-hast-to-jsx.js b/packages/mdx/mdx-hast-to-jsx.js index 7a6ebb476..68fbc0969 100644 --- a/packages/mdx/mdx-hast-to-jsx.js +++ b/packages/mdx/mdx-hast-to-jsx.js @@ -95,18 +95,29 @@ function toJSX(node, parentNode = {}, options = {}) { jsxNodes.push(childNode) } - return ( importNodes.map(childNode => toJSX(childNode, node)).join('\n') + '\n' + exportNodes.map(childNode => toJSX(childNode, node)).join('\n') + '\n' + - (skipExport ? '' : 'export default ({components, ...props}) => ') + - `${jsxNodes - .map(childNode => toJSX(childNode, node)) - .join('')}` + (skipExport + ? '' + : `export default class MDXContent extends React.Component { + constructor() { + this.layout = ${layout} + } + render() { + const {components, ...props} = this.props;`) + + `${skipExport ? '' : 'return '}${jsxNodes + .map(childNode => toJSX(childNode, node)) + .join('')} +${skipExport ? '' : '}}'}` ) } From 61bdc980d615f8d28da82644e35248d00652a1e0 Mon Sep 17 00:00:00 2001 From: Christopher Biscardi Date: Wed, 14 Nov 2018 18:17:30 -0800 Subject: [PATCH 2/4] classes work --- packages/mdx/mdx-hast-to-jsx.js | 25 +++++++++++-------------- packages/runtime/src/index.js | 9 ++++++++- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/packages/mdx/mdx-hast-to-jsx.js b/packages/mdx/mdx-hast-to-jsx.js index 68fbc0969..1b86a15ce 100644 --- a/packages/mdx/mdx-hast-to-jsx.js +++ b/packages/mdx/mdx-hast-to-jsx.js @@ -100,27 +100,24 @@ function toJSX(node, parentNode = {}, options = {}) { '\n' + exportNodes.map(childNode => toJSX(childNode, node)).join('\n') + '\n' + - (skipExport - ? '' - : `export default class MDXContent extends React.Component { + `${ + skipExport ? '' : 'export default' + } class MDXContent extends React.Component { constructor() { this.layout = ${layout} } render() { - const {components, ...props} = this.props;`) + - `${skipExport ? '' : 'return '}${jsxNodes + .map(childNode => toJSX(childNode, node)) + .join('')} + } - components={components}>${jsxNodes - .map(childNode => toJSX(childNode, node)) - .join('')} -${skipExport ? '' : '}}'}` +}` ) } - // Recursively walk through children if (node.children) { children = node.children diff --git a/packages/runtime/src/index.js b/packages/runtime/src/index.js index 28e170b4c..978be120f 100644 --- a/packages/runtime/src/index.js +++ b/packages/runtime/src/index.js @@ -31,7 +31,14 @@ export default ({ const keys = Object.keys(fullScope) const values = keys.map(key => fullScope[key]) // eslint-disable-next-line no-new-func - const fn = new Function('_fn', 'React', ...keys, `return ${code}`) + const fn = new Function( + '_fn', + 'React', + ...keys, + `${code} + + return React.createElement(MDXContent);` + ) return fn({}, React, ...values) } From 60b8a73c4e086a4ac9f14ba59fd7413678c8243d Mon Sep 17 00:00:00 2001 From: Christopher Biscardi Date: Wed, 14 Nov 2018 18:43:09 -0800 Subject: [PATCH 3/4] add snapshot test --- packages/mdx/package.json | 3 +- packages/mdx/test/index.test.js | 103 ++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/packages/mdx/package.json b/packages/mdx/package.json index 4a5336c36..2f9301d9e 100644 --- a/packages/mdx/package.json +++ b/packages/mdx/package.json @@ -45,7 +45,8 @@ "@babel/plugin-syntax-jsx": "^7.0.0", "@mapbox/rehype-prism": "^0.3.0", "hast-util-select": "^3.0.0", - "jest": "^23.0.0", + "jest": "^23.6.0", + "prettier": "^1.14.2", "rehype-katex": "^1.1.1", "remark-math": "^1.0.4" }, diff --git a/packages/mdx/test/index.test.js b/packages/mdx/test/index.test.js index fce6034e9..7dc13b592 100644 --- a/packages/mdx/test/index.test.js +++ b/packages/mdx/test/index.test.js @@ -7,6 +7,7 @@ const {select} = require('hast-util-select') const prism = require('@mapbox/rehype-prism') const math = require('remark-math') const katex = require('rehype-katex') +const prettier = require('prettier') const fixtureBlogPost = fs.readFileSync( path.join(__dirname, './fixtures/blog-post.md') @@ -42,6 +43,108 @@ it('Should compile sample blog post', async () => { parse(result) }) +it('Should match sample blog post snapshot', async () => { + const result = await mdx(fixtureBlogPost) + + expect(prettier.format(result, {parser: 'babylon'})).toMatchInlineSnapshot(` +"import { Baz } from \\"./Fixture\\"; +import { Buz } from \\"./Fixture\\"; +export const foo = { + hi: \`Fudge \${Baz.displayName || \\"Baz\\"}\`, + authors: [\\"fred\\", \\"sally\\"] +}; +export default class MDXContent extends React.Component { + constructor() { + this.layout = ({ children }) =>
{children}
; + } + render() { + return ( + + {\`Hello, world!\`} + {\`I'm an awesome paragraph.\`} + {/* I'm a comment */} + + hi + {hello} + {/* another commment */} + + + {\`test codeblock +\`} + + + {\`module.exports = 'test' +\`} + + + {\`npm i -g foo +\`} + + + + + {\`Test\`} + {\`Table\`} + + + + + {\`Col1\`} + {\`Col2\`} + + + + + ); + } +} +" +`) +}) + it('Should render blockquote correctly', async () => { const result = await mdx('> test\n\n> `test`') From 3c2dc149597adc4a9c699a4f4d2433b7116dc4ac Mon Sep 17 00:00:00 2001 From: Christopher Biscardi Date: Sat, 17 Nov 2018 23:00:42 -0800 Subject: [PATCH 4/4] make inline snapshot smaller --- packages/mdx/test/index.test.js | 92 ++------------------------------- 1 file changed, 5 insertions(+), 87 deletions(-) diff --git a/packages/mdx/test/index.test.js b/packages/mdx/test/index.test.js index 7dc13b592..984e83da5 100644 --- a/packages/mdx/test/index.test.js +++ b/packages/mdx/test/index.test.js @@ -44,99 +44,17 @@ it('Should compile sample blog post', async () => { }) it('Should match sample blog post snapshot', async () => { - const result = await mdx(fixtureBlogPost) + const result = await mdx(`# Hello World`) expect(prettier.format(result, {parser: 'babylon'})).toMatchInlineSnapshot(` -"import { Baz } from \\"./Fixture\\"; -import { Buz } from \\"./Fixture\\"; -export const foo = { - hi: \`Fudge \${Baz.displayName || \\"Baz\\"}\`, - authors: [\\"fred\\", \\"sally\\"] -}; -export default class MDXContent extends React.Component { +"export default class MDXContent extends React.Component { constructor() { - this.layout = ({ children }) =>
{children}
; + this.layout = undefined; } render() { return ( - - {\`Hello, world!\`} - {\`I'm an awesome paragraph.\`} - {/* I'm a comment */} - - hi - {hello} - {/* another commment */} - - - {\`test codeblock -\`} - - - {\`module.exports = 'test' -\`} - - - {\`npm i -g foo -\`} - - - - - {\`Test\`} - {\`Table\`} - - - - - {\`Col1\`} - {\`Col2\`} - - - + + {\`Hello World\`} ); }