Skip to content
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

Use remark-mdx in core as a syntactic extension to remark #439

Merged
merged 19 commits into from
Mar 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 3 additions & 42 deletions packages/mdx/index.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,26 @@
const unified = require('unified')
const toMDAST = require('remark-parse')
const remarkMdx = require('remark-mdx')
const squeeze = require('remark-squeeze-paragraphs')
const visit = require('unist-util-visit')
const raw = require('hast-util-raw')
const toMDXAST = require('./md-ast-to-mdx-ast')
const mdxAstToMdxHast = require('./mdx-ast-to-mdx-hast')
const mdxHastToJsx = require('./mdx-hast-to-jsx')

const {
isImport,
isExport,
isExportDefault,
BLOCKS_REGEX,
EMPTY_NEWLINE
} = require('./util')

const DEFAULT_OPTIONS = {
footnotes: true,
mdPlugins: [],
hastPlugins: [],
compilers: [],
blocks: [BLOCKS_REGEX]
}

const tokenizeEsSyntax = (eat, value) => {
const index = value.indexOf(EMPTY_NEWLINE)
const subvalue = index !== -1 ? value.slice(0, index) : value

if (isExport(subvalue)) {
return eat(subvalue)({
type: 'export',
default: isExportDefault(subvalue),
value: subvalue
})
}

if (isImport(subvalue)) {
return eat(subvalue)({type: 'import', value: subvalue})
}
}

tokenizeEsSyntax.locator = (value, _fromIndex) => {
return isExport(value) || isImport(value) ? -1 : 1
}

function esSyntax() {
const Parser = this.Parser
const tokenizers = Parser.prototype.blockTokenizers
const methods = Parser.prototype.blockMethods

tokenizers.esSyntax = tokenizeEsSyntax

methods.splice(methods.indexOf('paragraph'), 0, 'esSyntax')
compilers: []
}

function createMdxAstCompiler(options) {
const mdPlugins = options.mdPlugins

const fn = unified()
.use(toMDAST, options)
.use(esSyntax)
.use(remarkMdx, options)
.use(squeeze, options)
.use(toMDXAST, options)

Expand Down
2 changes: 1 addition & 1 deletion packages/mdx/license
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2017-2018 Compositor and Zeit, Inc.
Copyright (c) 2017-2019 Compositor, Inc. and Zeit, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
4 changes: 1 addition & 3 deletions packages/mdx/md-ast-to-mdx-ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ const commentOpen = '<!--'
const commentClose = '-->'

module.exports = _options => tree => {
visit(tree, 'html', node => {
visit(tree, 'jsx', node => {
if (
node.value.startsWith(commentOpen) &&
node.value.endsWith(commentClose)
) {
node.type = 'comment'
node.value = node.value.slice(commentOpen.length, -commentClose.length)
} else {
node.type = node.mdxType || 'jsx'
}
})

Expand Down
41 changes: 0 additions & 41 deletions packages/mdx/mdx-hast-to-jsx.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,47 +49,6 @@ function toJSX(node, parentNode = {}, options = {}) {
continue
}

if (
/^export\s{\s?default\s?}\sfrom/.test(childNode.value) ||
/^export\s{.*?as\sdefault\s?}/.test(childNode.value)
) {
let example

// eslint-disable-next-line max-depth
if (/\}\s*from\s+/.test(childNode.value)) {
example = `
For example, instead of:

export { default } from './Layout'

use:

import Layout from './Layout'
export default Layout
`.trim()
} else {
example = `
For example, instead of:

export { Layout as default }

use:

export default Layout
`.trim()
}

throw new Error(
`
MDX doesn't support using "default" as a named export, use "export default" statement instead.

${example}
`
.trim()
.replace(/^ +/gm, '')
)
}

exportNodes.push(childNode)
continue
}
Expand Down
1 change: 1 addition & 0 deletions packages/mdx/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"detab": "^2.0.0",
"hast-util-raw": "^5.0.0",
"mdast-util-to-hast": "^4.0.0",
"remark-mdx": "^0.18.2",
"remark-parse": "^6.0.0",
"remark-squeeze-paragraphs": "^3.0.1",
"to-style": "^1.3.3",
Expand Down
30 changes: 1 addition & 29 deletions packages/mdx/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,35 +279,6 @@ it('Should support semicolons in default export statement', async () => {
expect(() => parse(result)).not.toThrow()
})

it('Should throw when exporting default via named export', async () => {
await expect(mdx(`export { default } from './Layout'`)).rejects.toThrow()
await expect(mdx(`export { Layout as default }`)).rejects.toThrow()
await expect(
mdx(`export { foo as bar, Layout as default }`)
).rejects.toThrow()

// Ensure that word "default" appearing in export node does not throw
const fixture1 = `export const meta = {
description: 'better default as behavior.'
}`
await expect(mdx(fixture1)).resolves.toContain(fixture1)

// Ensure that a full export pattern within metadata does not throw
const fixture2 = `export const meta = {
decription: 'How to use es6 exports',
examples: [
'export { default } from "./example"',
'export { foo as default }'
]
}`
await expect(mdx(fixture2)).resolves.toContain(fixture2)

// Ensure that `export { default as x }` pattern does not throw
await expect(
mdx(`export { default as MyComp } from './MyComp'`)
).resolves.toContain(`export { default as MyComp } from './MyComp'`)
})

it('Should not include export wrapper if skipExport is true', async () => {
const result = await mdx('> test\n\n> `test`', {skipExport: true})

Expand Down Expand Up @@ -398,6 +369,7 @@ test('Should handle layout props', () => {
expect(result).toMatchInlineSnapshot(`
"/* @jsx mdx */
import { Baz } from './Fixture'

import { Buz } from './Fixture'
export const foo = {
hi: \`Fudge \${Baz.displayName || 'Baz'}\`,
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10482,6 +10482,11 @@ parse5@^5.0.0:
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2"
integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==

parse5@^2.1.5:
version "2.2.3"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-2.2.3.tgz#0c4fc41c1000c5e6b93d48b03f8083837834e9f6"
integrity sha1-DE/EHBAAxea5PUiwP4CDg3g06fY=

parseurl@^1.3.2, parseurl@~1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
Expand Down