feat: support MDX (#4975)

* feat: support MDX

* refactor: flip condition
master
Ika 2018-08-13 22:23:09 +08:00 committed by GitHub
parent 2de54dc4d8
commit 1790211f76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 769 additions and 47 deletions

View File

@ -25,6 +25,10 @@ module.exports = [
"json-stringify"
];
},
get __js_expression() {
return eval("require")("../language-js/parser-babylon").parsers
.__js_expression;
},
// JS - Flow
get flow() {
return eval("require")("../language-js/parser-flow").parsers.flow;
@ -93,6 +97,10 @@ module.exports = [
get markdown() {
return eval("require")("../language-markdown/parser-markdown").parsers
.remark;
},
get mdx() {
return eval("require")("../language-markdown/parser-markdown").parsers
.mdx;
}
}
},

View File

@ -40,9 +40,7 @@ function parse(text, parsers, opts) {
};
const parseMethod =
opts && (opts.parser === "json" || opts.parser === "json5")
? "parseExpression"
: "parse";
!opts || opts.parser === "babylon" ? "parse" : "parseExpression";
let ast;
try {
@ -159,6 +157,8 @@ module.exports = {
astFormat: "estree-json"
},
locFns
)
),
/** @internal for mdx to print jsx without semicolon */
__js_expression: babylon
}
};

View File

@ -48,6 +48,14 @@ function embed(path, print, textToDoc, options) {
);
}
// MDX
switch (node.type) {
case "importExport":
return textToDoc(node.value, { parser: "babylon" });
case "jsx":
return textToDoc(node.value, { parser: "__js_expression" });
}
return null;
function getParserName(lang) {

View File

@ -10,7 +10,14 @@ const languages = [
parsers: ["remark"],
filenames: ["README"],
vscodeLanguageIds: ["markdown"]
})
}),
{
name: "MDX",
since: "1.15.0",
parsers: ["mdx"],
extensions: [".mdx"],
vscodeLanguageIds: ["mdx"]
}
];
const printers = {

View File

@ -0,0 +1,64 @@
"use strict";
/**
* modified from https://github.com/mdx-js/mdx/blob/master/packages/mdx
*
* The MIT License (MIT)
*
* Copyright (c) 2017-2018 Compositor 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
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
const IMPORT_REGEX = /^import/;
const EXPORT_REGEX = /^export/;
const BLOCKS_REGEX = "[a-z\\.]+(\\.){0,1}[a-z\\.]";
const EMPTY_NEWLINE = "\n\n";
const isImport = text => IMPORT_REGEX.test(text);
const isExport = text => EXPORT_REGEX.test(text);
const tokenizeEsSyntax = (eat, value) => {
const index = value.indexOf(EMPTY_NEWLINE);
const subvalue = value.slice(0, index);
if (isExport(subvalue) || isImport(subvalue)) {
return eat(subvalue)({
type: "importExport",
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");
}
module.exports = {
esSyntax,
BLOCKS_REGEX
};

View File

@ -6,6 +6,7 @@ const pragma = require("./pragma");
const parseFrontMatter = require("../utils/front-matter");
const util = require("../common/util");
const { getOrderedListItemInfo } = require("./utils");
const mdx = require("./mdx");
// 0x0 ~ 0x10ffff
const isSingleCharRegex = /^([\u0000-\uffff]|[\ud800-\udbff][\udc00-\udfff])$/;
@ -24,18 +25,32 @@ const isSingleCharRegex = /^([\u0000-\uffff]|[\ud800-\udbff][\udc00-\udfff])$/;
* interface Sentence { children: Array<Word | Whitespace> }
* interface InlineCode { children: Array<Sentence> }
*/
function parse(text, parsers, opts) {
const processor = unified()
.use(remarkParse, { footnotes: true, commonmark: true })
.use(frontMatter)
.use(liquid)
.use(restoreUnescapedCharacter(text))
.use(mergeContinuousTexts)
.use(transformInlineCode)
.use(transformIndentedCodeblockAndMarkItsParentList(text))
.use(markAlignedList(text, opts))
.use(splitText(opts));
return processor.runSync(processor.parse(text));
function createParse({ isMDX }) {
return (text, parsers, opts) => {
const processor = unified()
.use(
remarkParse,
Object.assign(
{
footnotes: true,
commonmark: true
},
isMDX && { blocks: [mdx.BLOCKS_REGEX] }
)
)
.use(frontMatter)
.use(isMDX ? mdx.esSyntax : identity)
.use(liquid)
.use(restoreUnescapedCharacter(text))
.use(mergeContinuousTexts)
.use(transformInlineCode)
.use(transformIndentedCodeblockAndMarkItsParentList(text))
.use(markAlignedList(text, opts))
.use(splitText(opts))
.use(isMDX ? htmlToJsx : identity)
.use(isMDX ? mergeContinuousImportExport : identity);
return processor.runSync(processor.parse(text));
};
}
function map(ast, handler) {
@ -53,6 +68,41 @@ function map(ast, handler) {
})(ast, null, null);
}
function identity(x) {
return x;
}
function htmlToJsx() {
return ast =>
map(ast, (node, index, [parent]) => {
if (
node.type !== "html" ||
/^<!--[\s\S]*-->$/.test(node.value) ||
// inline html
parent.type === "paragraph"
) {
return node;
}
return Object.assign({}, node, { type: "jsx" });
});
}
function mergeContinuousImportExport() {
return mergeChildren(
(prevNode, node) =>
prevNode.type === "importExport" && node.type === "importExport",
(prevNode, node) => ({
type: "importExport",
value: prevNode.value + "\n\n" + node.value,
position: {
start: prevNode.position.start,
end: node.position.end
}
})
);
}
function transformInlineCode() {
return ast =>
map(ast, node => {
@ -87,7 +137,7 @@ function restoreUnescapedCharacter(originalText) {
});
}
function mergeContinuousTexts() {
function mergeChildren(shouldMerge, mergeNode) {
return ast =>
map(ast, node => {
if (!node.children) {
@ -95,15 +145,8 @@ function mergeContinuousTexts() {
}
const children = node.children.reduce((current, child) => {
const lastChild = current[current.length - 1];
if (lastChild && lastChild.type === "text" && child.type === "text") {
current.splice(-1, 1, {
type: "text",
value: lastChild.value + child.value,
position: {
start: lastChild.position.start,
end: child.position.end
}
});
if (lastChild && shouldMerge(lastChild, child)) {
current.splice(-1, 1, mergeNode(lastChild, child));
} else {
current.push(child);
}
@ -113,6 +156,20 @@ function mergeContinuousTexts() {
});
}
function mergeContinuousTexts() {
return mergeChildren(
(prevNode, node) => prevNode.type === "text" && node.type === "text",
(prevNode, node) => ({
type: "text",
value: prevNode.value + node.value,
position: {
start: prevNode.position.start,
end: node.position.end
}
})
);
}
function splitText(options) {
return () => ast =>
map(ast, (node, index, [parentNode]) => {
@ -318,18 +375,26 @@ function markAlignedList(originalText, options) {
}
}
const parser = {
parse,
const baseParser = {
astFormat: "mdast",
hasPragma: pragma.hasPragma,
locStart: node => node.position.start.offset,
locEnd: node => node.position.end.offset
};
const markdownParser = Object.assign({}, baseParser, {
parse: createParse({ isMDX: false })
});
const mdxParser = Object.assign({}, baseParser, {
parse: createParse({ isMDX: true })
});
module.exports = {
parsers: {
remark: parser,
remark: markdownParser,
// TODO: Delete this in 2.0
markdown: parser
markdown: markdownParser,
mdx: mdxParser
}
};

View File

@ -22,6 +22,8 @@ const {
} = require("../doc");
const { getOrderedListItemInfo } = require("./utils");
const TRAILING_HARDLINE_NODES = ["importExport"];
const SINGLE_LINE_NODE_TYPES = ["heading", "tableCell", "link"];
const SIBLING_NODE_TYPES = ["listItem", "definition", "footnoteDefinition"];
@ -79,7 +81,12 @@ function genericPrint(path, options, print) {
if (node.children.length === 0) {
return "";
}
return concat([normalizeDoc(printRoot(path, options, print)), hardline]);
return concat([
normalizeDoc(printRoot(path, options, print)),
TRAILING_HARDLINE_NODES.indexOf(getLastDescendantNode(node).type) === -1
? hardline
: ""
]);
case "paragraph":
return printChildren(path, options, print, {
postprocessor: fill
@ -368,6 +375,11 @@ function genericPrint(path, options, print) {
: concat(["\\", hardline]);
case "liquidNode":
return replaceNewlinesWith(node.value, hardline);
// MDX
case "importExport":
case "jsx":
return node.value; // fallback to the original text if multiparser failed
case "tableRow": // handled in "table"
case "listItem": // handled in "list"
default:
@ -654,14 +666,23 @@ function printChildren(path, options, print, events) {
parts.push(hardline);
if (
shouldPrePrintDoubleHardline(childNode, data) ||
shouldPrePrintTripleHardline(childNode, data)
lastChildNode &&
TRAILING_HARDLINE_NODES.indexOf(lastChildNode.type) !== -1
) {
parts.push(hardline);
}
if (shouldPrePrintTripleHardline(childNode, data)) {
parts.push(hardline);
}
} else {
if (
shouldPrePrintDoubleHardline(childNode, data) ||
shouldPrePrintTripleHardline(childNode, data)
) {
parts.push(hardline);
}
if (shouldPrePrintTripleHardline(childNode, data)) {
parts.push(hardline);
if (shouldPrePrintTripleHardline(childNode, data)) {
parts.push(hardline);
}
}
}
@ -674,6 +695,14 @@ function printChildren(path, options, print, events) {
return postprocessor(parts);
}
function getLastDescendantNode(node) {
let current = node;
while (current.children && current.children.length !== 0) {
current = current.children[current.children.length - 1];
}
return current;
}
/** @return {false | 'next' | 'start' | 'end'} */
function isPrettierIgnore(node) {
if (node.type !== "html") {
@ -831,7 +860,12 @@ function clean(ast, newObj, parent) {
delete newObj.raw; // front-matter
// for codeblock
if (ast.type === "code" || ast.type === "yaml") {
if (
ast.type === "code" ||
ast.type === "yaml" ||
ast.type === "importExport" ||
ast.type === "jsx"
) {
delete newObj.value;
}

View File

@ -115,6 +115,7 @@ const options = {
},
{ value: "graphql", since: "1.5.0", description: "GraphQL" },
{ value: "markdown", since: "1.8.0", description: "Markdown" },
{ value: "mdx", since: "1.15.0", description: "MDX" },
{ value: "vue", since: "1.10.0", description: "Vue" },
{ value: "yaml", since: "1.14.0", description: "YAML" },
{

View File

@ -0,0 +1,365 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`import-export.mdx - mdx-verify 1`] = `
import A from 'a'
import {A,B,C} from "hello-world"
import {AAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBB, CCCCCCCCCCCCCCCCCCCCCCC} from 'xyz';
---
import A from 'a'
import {A,B,C} from "hello-world"
import {AAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBB, CCCCCCCCCCCCCCCCCCCCCCC} from 'xyz';
---
export const meta = {
authors: [fred, sue],
layout: Layout
}
export default () =>
<Doc components={{
h1: ui.Heading,
p: ui.Text,
code: ui.Code
}}
/>
---
export const a = 1;
export const b = 1;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import A from "a";
import { A, B, C } from "hello-world";
import {
AAAAAAAAAAAAAAAAAAAAAAAA,
BBBBBBBBBBBBBBBBBBBBBB,
CCCCCCCCCCCCCCCCCCCCCCC
} from "xyz";
---
import A from "a";
import { A, B, C } from "hello-world";
import {
AAAAAAAAAAAAAAAAAAAAAAAA,
BBBBBBBBBBBBBBBBBBBBBB,
CCCCCCCCCCCCCCCCCCCCCCC
} from "xyz";
---
export const meta = {
authors: [fred, sue],
layout: Layout
};
export default () => (
<Doc
components={{
h1: ui.Heading,
p: ui.Text,
code: ui.Code
}}
/>
);
---
export const a = 1;
export const b = 1;
`;
exports[`import-export.mdx - mdx-verify 2`] = `
import A from 'a'
import {A,B,C} from "hello-world"
import {AAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBB, CCCCCCCCCCCCCCCCCCCCCCC} from 'xyz';
---
import A from 'a'
import {A,B,C} from "hello-world"
import {AAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBB, CCCCCCCCCCCCCCCCCCCCCCC} from 'xyz';
---
export const meta = {
authors: [fred, sue],
layout: Layout
}
export default () =>
<Doc components={{
h1: ui.Heading,
p: ui.Text,
code: ui.Code
}}
/>
---
export const a = 1;
export const b = 1;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import A from "a"
import { A, B, C } from "hello-world"
import {
AAAAAAAAAAAAAAAAAAAAAAAA,
BBBBBBBBBBBBBBBBBBBBBB,
CCCCCCCCCCCCCCCCCCCCCCC
} from "xyz"
---
import A from "a"
import { A, B, C } from "hello-world"
import {
AAAAAAAAAAAAAAAAAAAAAAAA,
BBBBBBBBBBBBBBBBBBBBBB,
CCCCCCCCCCCCCCCCCCCCCCC
} from "xyz"
---
export const meta = {
authors: [fred, sue],
layout: Layout
}
export default () => (
<Doc
components={{
h1: ui.Heading,
p: ui.Text,
code: ui.Code
}}
/>
)
---
export const a = 1
export const b = 1
`;
exports[`jsx.mdx - mdx-verify 1`] = `
<Heading hi='there'>Hello, world!
</Heading>
---
<Hello>
test <World /> test
</Hello>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<Heading hi="there">Hello, world!</Heading>
---
<Hello>
test <World /> test
</Hello>
`;
exports[`jsx.mdx - mdx-verify 2`] = `
<Heading hi='there'>Hello, world!
</Heading>
---
<Hello>
test <World /> test
</Hello>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<Heading hi="there">Hello, world!</Heading>
---
<Hello>
test <World /> test
</Hello>
`;
exports[`mixed.mdx - mdx-verify 1`] = `
import { Baz } from './Fixture'
import { Buz } from './Fixture'
export const foo = {
hi: \`Fudge \${Baz.displayName || 'Baz'}\`,
authors: [
'fred',
'sally'
]
}
# Hello, world!
I'm an awesome paragraph.
<!-- I'm a comment -->
<Foo bg='red'>
<Bar >hi </Bar>
{ hello }
{ /* another commment */}
</Foo>
\`\`\`
test codeblock
\`\`\`
\`\`\`js
module.exports = 'test'
\`\`\`
\`\`\`sh
npm i -g foo
\`\`\`
| Test | Table |
| :--- | :---- |
| Col1 | Col2 |
export default ({children }) => < div>{ children}</div>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import { Baz } from "./Fixture";
import { Buz } from "./Fixture";
export const foo = {
hi: \`Fudge \${Baz.displayName || "Baz"}\`,
authors: ["fred", "sally"]
};
# Hello, world!
I'm an awesome paragraph.
<!-- I'm a comment -->
<Foo bg="red">
<Bar>hi </Bar>
{hello}
{/* another commment */}
</Foo>
\`\`\`
test codeblock
\`\`\`
\`\`\`js
module.exports = "test";
\`\`\`
\`\`\`sh
npm i -g foo
\`\`\`
| Test | Table |
| :--- | :---- |
| Col1 | Col2 |
export default ({ children }) => <div>{children}</div>;
`;
exports[`mixed.mdx - mdx-verify 2`] = `
import { Baz } from './Fixture'
import { Buz } from './Fixture'
export const foo = {
hi: \`Fudge \${Baz.displayName || 'Baz'}\`,
authors: [
'fred',
'sally'
]
}
# Hello, world!
I'm an awesome paragraph.
<!-- I'm a comment -->
<Foo bg='red'>
<Bar >hi </Bar>
{ hello }
{ /* another commment */}
</Foo>
\`\`\`
test codeblock
\`\`\`
\`\`\`js
module.exports = 'test'
\`\`\`
\`\`\`sh
npm i -g foo
\`\`\`
| Test | Table |
| :--- | :---- |
| Col1 | Col2 |
export default ({children }) => < div>{ children}</div>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import { Baz } from "./Fixture"
import { Buz } from "./Fixture"
export const foo = {
hi: \`Fudge \${Baz.displayName || "Baz"}\`,
authors: ["fred", "sally"]
}
# Hello, world!
I'm an awesome paragraph.
<!-- I'm a comment -->
<Foo bg="red">
<Bar>hi </Bar>
{hello}
{/* another commment */}
</Foo>
\`\`\`
test codeblock
\`\`\`
\`\`\`js
module.exports = "test"
\`\`\`
\`\`\`sh
npm i -g foo
\`\`\`
| Test | Table |
| :--- | :---- |
| Col1 | Col2 |
export default ({ children }) => <div>{children}</div>
`;

View File

@ -0,0 +1,33 @@
import A from 'a'
import {A,B,C} from "hello-world"
import {AAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBB, CCCCCCCCCCCCCCCCCCCCCCC} from 'xyz';
---
import A from 'a'
import {A,B,C} from "hello-world"
import {AAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBB, CCCCCCCCCCCCCCCCCCCCCCC} from 'xyz';
---
export const meta = {
authors: [fred, sue],
layout: Layout
}
export default () =>
<Doc components={{
h1: ui.Heading,
p: ui.Text,
code: ui.Code
}}
/>
---
export const a = 1;
export const b = 1;

2
tests/mdx/jsfmt.spec.js Normal file
View File

@ -0,0 +1,2 @@
run_spec(__dirname, ["mdx"]);
run_spec(__dirname, ["mdx"], { semi: false });

8
tests/mdx/jsx.mdx Normal file
View File

@ -0,0 +1,8 @@
<Heading hi='there'>Hello, world!
</Heading>
---
<Hello>
test <World /> test
</Hello>

41
tests/mdx/mixed.mdx Normal file
View File

@ -0,0 +1,41 @@
import { Baz } from './Fixture'
import { Buz } from './Fixture'
export const foo = {
hi: `Fudge ${Baz.displayName || 'Baz'}`,
authors: [
'fred',
'sally'
]
}
# Hello, world!
I'm an awesome paragraph.
<!-- I'm a comment -->
<Foo bg='red'>
<Bar >hi </Bar>
{ hello }
{ /* another commment */}
</Foo>
```
test codeblock
```
```js
module.exports = 'test'
```
```sh
npm i -g foo
```
| Test | Table |
| :--- | :---- |
| Col1 | Col2 |
export default ({children }) => < div>{ children}</div>

View File

@ -62,7 +62,7 @@ Format options:
--no-bracket-spacing Do not print spaces between brackets.
--jsx-bracket-same-line Put > on the last line instead of at a new line.
Defaults to false.
--parser <flow|babylon|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|vue|yaml>
--parser <flow|babylon|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml>
Which parser to use.
--print-width <int> The line length where Prettier will try wrap.
Defaults to 80.
@ -165,7 +165,7 @@ exports[`show warning with --help not-found (typo) (stderr) 1`] = `
`;
exports[`show warning with --help not-found (typo) (stdout) 1`] = `
"--parser <flow|babylon|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|vue|yaml>
"--parser <flow|babylon|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml>
Which parser to use.
@ -182,6 +182,7 @@ Valid options:
json-stringify JSON.stringify
graphql GraphQL
markdown Markdown
mdx MDX
vue Vue
yaml YAML
"
@ -212,7 +213,7 @@ Format options:
--no-bracket-spacing Do not print spaces between brackets.
--jsx-bracket-same-line Put > on the last line instead of at a new line.
Defaults to false.
--parser <flow|babylon|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|vue|yaml>
--parser <flow|babylon|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml>
Which parser to use.
--print-width <int> The line length where Prettier will try wrap.
Defaults to 80.

View File

@ -267,7 +267,7 @@ exports[`show detailed usage with --help no-semi (write) 1`] = `Array []`;
exports[`show detailed usage with --help parser (stderr) 1`] = `""`;
exports[`show detailed usage with --help parser (stdout) 1`] = `
"--parser <flow|babylon|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|vue|yaml>
"--parser <flow|babylon|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml>
Which parser to use.
@ -284,6 +284,7 @@ Valid options:
json-stringify JSON.stringify
graphql GraphQL
markdown Markdown
mdx MDX
vue Vue
yaml YAML
"

View File

@ -15,7 +15,7 @@ exports[` 1`] = `
+ Defaults to bar.
--jsx-bracket-same-line Put > on the last line instead of at a new line.
Defaults to false.
--parser <flow|babylon|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|vue|yaml>
--parser <flow|babylon|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml>
Which parser to use.
--print-width <int> The line length where Prettier will try wrap."
`;

View File

@ -128,6 +128,12 @@ This option cannot be used with --range-start and --range-end.",
"markdown",
],
},
Object {
"description": "MDX",
"enum": Array [
"mdx",
],
},
Object {
"description": "Vue",
"enum": Array [

View File

@ -429,7 +429,21 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = `
\\"flow\\",
],
\\"JavaScript\\": Array [
@@ -37,12 +43,26 @@
@@ -25,10 +31,13 @@
\\"flow\\",
],
\\"Less\\": Array [
\\"less\\",
],
+ \\"MDX\\": Array [
+ \\"mdx\\",
+ ],
\\"Markdown\\": Array [
\\"markdown\\",
],
\\"PostCSS\\": Array [
\\"css\\",
@@ -37,12 +46,26 @@
\\"scss\\",
],
\\"TypeScript\\": Array [
@ -456,7 +470,7 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = `
\\"type\\": \\"boolean\\",
},
\\"cursorOffset\\": Object {
@@ -73,16 +93,28 @@
@@ -73,16 +96,29 @@
\\"typescript\\",
\\"css\\",
\\"less\\",
@ -466,6 +480,7 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = `
+ \\"json-stringify\\",
\\"graphql\\",
\\"markdown\\",
+ \\"mdx\\",
+ \\"vue\\",
+ \\"yaml\\",
],
@ -486,7 +501,7 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = `
\\"range\\": Object {
\\"end\\": Infinity,
\\"start\\": 0,
@@ -90,14 +122,15 @@
@@ -90,14 +126,15 @@
},
\\"type\\": \\"int\\",
},
@ -790,6 +805,13 @@ exports[`CLI --support-info (stdout) 1`] = `
\\"vscodeLanguageIds\\": [\\"markdown\\"],
\\"wrap\\": true
},
{
\\"extensions\\": [\\".mdx\\"],
\\"name\\": \\"MDX\\",
\\"parsers\\": [\\"mdx\\"],
\\"since\\": \\"1.15.0\\",
\\"vscodeLanguageIds\\": [\\"mdx\\"]
},
{
\\"aceMode\\": \\"html\\",
\\"color\\": \\"#2c3e50\\",
@ -916,6 +938,7 @@ exports[`CLI --support-info (stdout) 1`] = `
},
{ \\"description\\": \\"GraphQL\\", \\"since\\": \\"1.5.0\\", \\"value\\": \\"graphql\\" },
{ \\"description\\": \\"Markdown\\", \\"since\\": \\"1.8.0\\", \\"value\\": \\"markdown\\" },
{ \\"description\\": \\"MDX\\", \\"since\\": \\"1.15.0\\", \\"value\\": \\"mdx\\" },
{ \\"description\\": \\"Vue\\", \\"since\\": \\"1.10.0\\", \\"value\\": \\"vue\\" },
{ \\"description\\": \\"YAML\\", \\"since\\": \\"1.14.0\\", \\"value\\": \\"yaml\\" }
],

View File

@ -29,6 +29,7 @@
variants:
- "[`CommonMark`](http://commonmark.org/)"
- "[`GitHub Flavored Markdown`](https://github.github.com/gfm/)"
- "[`MDX`](https://mdxjs.com/)"
- name: YAML
showName: false
image: /images/languages/tools_yaml.svg

View File

@ -169,6 +169,52 @@ export default function(parser) {
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
"Curabitur consectetur maximus risus, sed maximus tellus tincidunt et."
].join("\n");
case "mdx":
// modified from https://github.com/mdx-js/mdx/blob/master/packages/mdx/test/fixtures/blog-post.md
return [
"import { Baz } from './Fixture'",
"import { Buz } from './Fixture'",
"",
"export const foo = {",
" hi: `Fudge ${Baz.displayName || 'Baz'}`,",
" authors: [",
" 'fred',",
" 'sally'",
" ]",
"}",
"",
"# Hello, world!",
"",
"",
" I'm an awesome paragraph.",
"",
"<!-- I'm a comment -->",
"",
"<Foo bg='red'>",
" <Bar >hi </Bar>",
" { hello }",
" { /* another commment */}",
"</Foo>",
"",
"```",
"test codeblock",
"```",
"",
"```js",
"module.exports = 'test'",
"```",
"",
"```sh",
"npm i -g foo",
"```",
"",
"| Test | Table |",
"| :--- | :---- |",
"| Col1 | Col2 |",
"",
"export default ({children }) => < div>{ children}</div>",
""
].join("\n");
case "vue":
return [
"<template>",

View File

@ -29,6 +29,10 @@ var parsers = {
importScriptOnce("lib/parser-babylon.js");
return prettierPlugins.babylon.parsers["json-stringify"];
},
get __js_expression() {
importScriptOnce("lib/parser-babylon.js");
return prettierPlugins.babylon.parsers.__js_expression;
},
// JS - Flow
get flow() {
importScriptOnce("lib/parser-flow.js");
@ -65,6 +69,10 @@ var parsers = {
importScriptOnce("lib/parser-markdown.js");
return prettierPlugins.markdown.parsers.remark;
},
get mdx() {
importScriptOnce("lib/parser-markdown.js");
return prettierPlugins.markdown.parsers.mdx;
},
// Vue
get vue() {