diff --git a/packages/mdx/index.js b/packages/mdx/index.js index a79d3dfcc..b5ea9a823 100644 --- a/packages/mdx/index.js +++ b/packages/mdx/index.js @@ -7,7 +7,8 @@ const mdxAstToMdxHast = require('./mdx-ast-to-mdx-hast') const mdxHastToJsx = require('./mdx-hast-to-jsx') const pragma = `/* @jsxRuntime classic */ -/* @jsx mdx */` +/* @jsx mdx */ +/* @jsxFrag mdx.Fragment */` function createMdxAstCompiler(options = {}) { return unified() diff --git a/packages/mdx/mdx-hast-to-jsx.js b/packages/mdx/mdx-hast-to-jsx.js index a136463fc..d4e26e409 100644 --- a/packages/mdx/mdx-hast-to-jsx.js +++ b/packages/mdx/mdx-hast-to-jsx.js @@ -79,7 +79,8 @@ function serializeEstree(estree, options) { ) const shortcodes = createMakeShortcodeHelper( - uniq(jsxNames).filter(name => !importExportNames.includes(name)) + uniq(jsxNames).filter(name => !importExportNames.includes(name)), + options.mdxFragment === false ) const exports = [] @@ -221,7 +222,7 @@ function createMdxLayout(declaration) { } // Note: this creates a Babel AST, not an estree. -function createMakeShortcodeHelper(names) { +function createMakeShortcodeHelper(names, useElement) { const func = { type: 'VariableDeclaration', declarations: [ @@ -269,22 +270,39 @@ function createMakeShortcodeHelper(names) { }, { type: 'ReturnStatement', - argument: { - type: 'JSXElement', - openingElement: { - type: 'JSXOpeningElement', - attributes: [ - { - type: 'JSXSpreadAttribute', - argument: {type: 'Identifier', name: 'props'} - } - ], - name: {type: 'JSXIdentifier', name: 'div'}, - selfClosing: true - }, - closingElement: null, - children: [] - } + argument: useElement + ? { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + attributes: [ + { + type: 'JSXSpreadAttribute', + argument: {type: 'Identifier', name: 'props'} + } + ], + name: {type: 'JSXIdentifier', name: 'div'}, + selfClosing: true + }, + closingElement: null, + children: [] + } + : { + type: 'JSXFragment', + openingFragment: {type: 'JSXOpeningFragment'}, + closingFragment: {type: 'JSXClosingFragment'}, + children: [ + { + type: 'JSXExpressionContainer', + expression: { + type: 'MemberExpression', + object: {type: 'Identifier', name: 'props'}, + property: {type: 'Identifier', name: 'children'}, + computed: false + } + } + ] + } } ] } diff --git a/packages/mdx/test/index.test.js b/packages/mdx/test/index.test.js index e6db700d1..ac5a3c7eb 100644 --- a/packages/mdx/test/index.test.js +++ b/packages/mdx/test/index.test.js @@ -537,23 +537,17 @@ describe('@mdx-js/mdx', () => { }) it('should not crash but issue a warning when an undefined component is used', async () => { - const Content = await run('x z') + const Content = await run('w y z') const warn = console.warn console.warn = jest.fn() - // To do: a fragment would probably be better? - // Maybe the components children? expect(renderToStaticMarkup()).toEqual( - renderToStaticMarkup( -

- x

z -

- ) + renderToStaticMarkup(

w y z

) ) expect(console.warn).toHaveBeenCalledWith( 'Component `%s` was not imported, exported, or provided by MDXProvider as global scope', - 'Y' + 'X' ) console.warn = warn diff --git a/packages/preact/package.json b/packages/preact/package.json index fee1af567..0a00fee62 100644 --- a/packages/preact/package.json +++ b/packages/preact/package.json @@ -44,8 +44,10 @@ ], "scripts": { "build": "microbundle -f modern,es,cjs src/index.js", - "test": "jest test --coverage", - "test-types": "dtslint types" + "test-api": "jest test", + "test-coverage": "jest test --coverage", + "test-types": "dtslint types", + "test": "yarn test-coverage && yarn test-types" }, "peerDependencies": { "preact": "^10.4.6" diff --git a/packages/preact/src/create-element.js b/packages/preact/src/create-element.js index 93fbd57aa..905c05cc6 100644 --- a/packages/preact/src/create-element.js +++ b/packages/preact/src/create-element.js @@ -41,7 +41,7 @@ const MDXCreateElement = forwardRef((props, ref) => { MDXCreateElement.displayName = 'MDXCreateElement' -export default function (type, props) { +function mdx(type, props) { const args = arguments const mdxType = props && props.mdxType @@ -73,3 +73,7 @@ export default function (type, props) { return h.apply(null, args) } + +mdx.Fragment = Fragment + +export default mdx diff --git a/packages/preact/test/test.js b/packages/preact/test/test.js index c290851a8..dd715e064 100644 --- a/packages/preact/test/test.js +++ b/packages/preact/test/test.js @@ -55,7 +55,7 @@ describe('@mdx-js/preact', () => { const warn = console.warn console.warn = jest.fn() - expect(render()).toEqual('
') + expect(render()).toEqual('') expect(console.warn).toHaveBeenCalledWith( 'Component `%s` was not imported, exported, or provided by MDXProvider as global scope', diff --git a/packages/react/src/create-element.js b/packages/react/src/create-element.js index 4e0aa44f9..ae5c4c48c 100644 --- a/packages/react/src/create-element.js +++ b/packages/react/src/create-element.js @@ -40,7 +40,7 @@ const MDXCreateElement = React.forwardRef((props, ref) => { MDXCreateElement.displayName = 'MDXCreateElement' -export default function (type, props) { +function mdx(type, props) { const args = arguments const mdxType = props && props.mdxType @@ -72,3 +72,7 @@ export default function (type, props) { return React.createElement.apply(null, args) } + +mdx.Fragment = React.Fragment + +export default mdx diff --git a/packages/react/test/test.js b/packages/react/test/test.js index 4cc9b01db..3bf34409d 100644 --- a/packages/react/test/test.js +++ b/packages/react/test/test.js @@ -51,11 +51,11 @@ describe('@mdx-js/react', () => { }) test('should warn on missing components', async () => { - const Content = await run('') + const Content = await run('x') const warn = console.warn console.warn = jest.fn() - expect(renderToString()).toEqual('
') + expect(renderToString()).toEqual('

x

') expect(console.warn).toHaveBeenCalledWith( 'Component `%s` was not imported, exported, or provided by MDXProvider as global scope', diff --git a/packages/vue-loader/index.js b/packages/vue-loader/index.js index deb0f9202..becb39b09 100644 --- a/packages/vue-loader/index.js +++ b/packages/vue-loader/index.js @@ -35,7 +35,11 @@ async function mdxLoader(content) { let result try { - result = await mdx(content, {...options, skipExport: true}) + result = await mdx(content, { + ...options, + skipExport: true, + mdxFragment: false + }) } catch (err) { return callback(err) } diff --git a/packages/vue/test/test.js b/packages/vue/test/test.js index 90651c1e6..ac9894122 100644 --- a/packages/vue/test/test.js +++ b/packages/vue/test/test.js @@ -7,7 +7,7 @@ import {MDXProvider, mdx} from '../src' const run = async value => { // Turn the serialized MDX code into serialized JSX… - const doc = await mdxTransform(value, {skipExport: true}) + const doc = await mdxTransform(value, {skipExport: true, mdxFragment: false}) // …and that into serialized JS. const {code} = await babelTransform(doc, {