Skip to content

Commit

Permalink
Use remark-mdx in core as a syntactic extension to remark (#439)
Browse files Browse the repository at this point in the history
* Implement support for Some.Component style JSX blocks

* Add failing test for string interpolation

* Add failing test for js functions as props

* Add failing test for js functions as props with returns

* Make value parsing for JSX props more flexible

* Don't lint fixtures file

* Add nested object props fixture

* Add another fixture for randomly placed brackets

* Add link shortcut to fixture

* Remove object props since it is a subset of js props

* Begin implementing core remark-mdx usage

* Replace MDXTag with custom pragma (#401)

* it works

* commit to be removed: my-site-2

* remove mdxtag for layout

* [remove this] more my-site examples

* remove

* merge-conflict

* snapshots

* Remove my-site-2

* Clean up create element code

* Fix tests

* Fix props handling, remove mdx pragma from JSX output

* Update pragma implementation in loader and parcel plugin

* Update runtime to properly provide components for mdx pragma

* Allow for merging of components passed to context with a function (#411)

If a function is passed to the theme provider it is invoked
with the out context's components. This allows users to opt
in to merging those components.

Related #410

* feat: Convert withMDXComponents to use hooks (#417)

* Continue working on integrating remark-mdx

* Ensure proper remark-mdx is used for workspaces
  • Loading branch information
johno authored Mar 6, 2019
1 parent 74b93a6 commit 3a6e435
Show file tree
Hide file tree
Showing 7 changed files with 12 additions and 116 deletions.
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

0 comments on commit 3a6e435

Please sign in to comment.