diff --git a/src/common/internal-plugins.js b/src/common/internal-plugins.js index 05cebcb8..d22252f7 100644 --- a/src/common/internal-plugins.js +++ b/src/common/internal-plugins.js @@ -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; } } }, diff --git a/src/language-js/parser-babylon.js b/src/language-js/parser-babylon.js index be002339..7de93391 100644 --- a/src/language-js/parser-babylon.js +++ b/src/language-js/parser-babylon.js @@ -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 } }; diff --git a/src/language-markdown/embed.js b/src/language-markdown/embed.js index eb8ace06..53ed16c7 100644 --- a/src/language-markdown/embed.js +++ b/src/language-markdown/embed.js @@ -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) { diff --git a/src/language-markdown/index.js b/src/language-markdown/index.js index d971d374..d98a3672 100644 --- a/src/language-markdown/index.js +++ b/src/language-markdown/index.js @@ -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 = { diff --git a/src/language-markdown/mdx.js b/src/language-markdown/mdx.js new file mode 100644 index 00000000..988e7bec --- /dev/null +++ b/src/language-markdown/mdx.js @@ -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 +}; diff --git a/src/language-markdown/parser-markdown.js b/src/language-markdown/parser-markdown.js index 801c27c7..ffaa0085 100644 --- a/src/language-markdown/parser-markdown.js +++ b/src/language-markdown/parser-markdown.js @@ -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 } * interface InlineCode { children: Array } */ -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" || + /^$/.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 } }; diff --git a/src/language-markdown/printer-markdown.js b/src/language-markdown/printer-markdown.js index a660def2..b6e66b2f 100644 --- a/src/language-markdown/printer-markdown.js +++ b/src/language-markdown/printer-markdown.js @@ -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; } diff --git a/src/main/core-options.js b/src/main/core-options.js index aed75743..688f45c7 100644 --- a/src/main/core-options.js +++ b/src/main/core-options.js @@ -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" }, { diff --git a/tests/mdx/__snapshots__/jsfmt.spec.js.snap b/tests/mdx/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 00000000..8aa75609 --- /dev/null +++ b/tests/mdx/__snapshots__/jsfmt.spec.js.snap @@ -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 () => + + +--- + +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 () => ( + +); + +--- + +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 () => + + +--- + +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 () => ( + +) + +--- + +export const a = 1 +export const b = 1 + +`; + +exports[`jsx.mdx - mdx-verify 1`] = ` +Hello, world! + + +--- + + + test test + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Hello, world! + +--- + + + test test + + +`; + +exports[`jsx.mdx - mdx-verify 2`] = ` +Hello, world! + + +--- + + + test test + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Hello, world! + +--- + + + test test + + +`; + +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. + + + + + hi + { hello } + { /* another commment */} + + +\`\`\` +test codeblock +\`\`\` + +\`\`\`js +module.exports = 'test' +\`\`\` + +\`\`\`sh +npm i -g foo +\`\`\` + +| Test | Table | +| :--- | :---- | +| Col1 | Col2 | + +export default ({children }) => < div>{ children} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +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. + + + + + hi + {hello} + {/* another commment */} + + +\`\`\` +test codeblock +\`\`\` + +\`\`\`js +module.exports = "test"; +\`\`\` + +\`\`\`sh +npm i -g foo +\`\`\` + +| Test | Table | +| :--- | :---- | +| Col1 | Col2 | + +export default ({ children }) =>
{children}
; + +`; + +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. + + + + + hi + { hello } + { /* another commment */} + + +\`\`\` +test codeblock +\`\`\` + +\`\`\`js +module.exports = 'test' +\`\`\` + +\`\`\`sh +npm i -g foo +\`\`\` + +| Test | Table | +| :--- | :---- | +| Col1 | Col2 | + +export default ({children }) => < div>{ children} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +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. + + + + + hi + {hello} + {/* another commment */} + + +\`\`\` +test codeblock +\`\`\` + +\`\`\`js +module.exports = "test" +\`\`\` + +\`\`\`sh +npm i -g foo +\`\`\` + +| Test | Table | +| :--- | :---- | +| Col1 | Col2 | + +export default ({ children }) =>
{children}
+ +`; diff --git a/tests/mdx/import-export.mdx b/tests/mdx/import-export.mdx new file mode 100644 index 00000000..02d17ef1 --- /dev/null +++ b/tests/mdx/import-export.mdx @@ -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 () => + + +--- + +export const a = 1; +export const b = 1; diff --git a/tests/mdx/jsfmt.spec.js b/tests/mdx/jsfmt.spec.js new file mode 100644 index 00000000..2b230e14 --- /dev/null +++ b/tests/mdx/jsfmt.spec.js @@ -0,0 +1,2 @@ +run_spec(__dirname, ["mdx"]); +run_spec(__dirname, ["mdx"], { semi: false }); diff --git a/tests/mdx/jsx.mdx b/tests/mdx/jsx.mdx new file mode 100644 index 00000000..2b09061f --- /dev/null +++ b/tests/mdx/jsx.mdx @@ -0,0 +1,8 @@ +Hello, world! + + +--- + + + test test + diff --git a/tests/mdx/mixed.mdx b/tests/mdx/mixed.mdx new file mode 100644 index 00000000..efe333f3 --- /dev/null +++ b/tests/mdx/mixed.mdx @@ -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. + + + + + hi + { hello } + { /* another commment */} + + +``` +test codeblock +``` + +```js +module.exports = 'test' +``` + +```sh +npm i -g foo +``` + +| Test | Table | +| :--- | :---- | +| Col1 | Col2 | + +export default ({children }) => < div>{ children} diff --git a/tests_integration/__tests__/__snapshots__/early-exit.js.snap b/tests_integration/__tests__/__snapshots__/early-exit.js.snap index a56ea03d..a648c4e9 100644 --- a/tests_integration/__tests__/__snapshots__/early-exit.js.snap +++ b/tests_integration/__tests__/__snapshots__/early-exit.js.snap @@ -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 + --parser Which parser to use. --print-width 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 +"--parser 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 + --parser Which parser to use. --print-width The line length where Prettier will try wrap. Defaults to 80. diff --git a/tests_integration/__tests__/__snapshots__/help-options.js.snap b/tests_integration/__tests__/__snapshots__/help-options.js.snap index 56510d54..afa3d2ed 100644 --- a/tests_integration/__tests__/__snapshots__/help-options.js.snap +++ b/tests_integration/__tests__/__snapshots__/help-options.js.snap @@ -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 +"--parser Which parser to use. @@ -284,6 +284,7 @@ Valid options: json-stringify JSON.stringify graphql GraphQL markdown Markdown + mdx MDX vue Vue yaml YAML " diff --git a/tests_integration/__tests__/__snapshots__/plugin-options.js.snap b/tests_integration/__tests__/__snapshots__/plugin-options.js.snap index f3088198..28eb2b85 100644 --- a/tests_integration/__tests__/__snapshots__/plugin-options.js.snap +++ b/tests_integration/__tests__/__snapshots__/plugin-options.js.snap @@ -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 + --parser Which parser to use. --print-width The line length where Prettier will try wrap." `; diff --git a/tests_integration/__tests__/__snapshots__/schema.js.snap b/tests_integration/__tests__/__snapshots__/schema.js.snap index dc14a1e5..dade9ecc 100644 --- a/tests_integration/__tests__/__snapshots__/schema.js.snap +++ b/tests_integration/__tests__/__snapshots__/schema.js.snap @@ -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 [ diff --git a/tests_integration/__tests__/__snapshots__/support-info.js.snap b/tests_integration/__tests__/__snapshots__/support-info.js.snap index 64208692..cb32162c 100644 --- a/tests_integration/__tests__/__snapshots__/support-info.js.snap +++ b/tests_integration/__tests__/__snapshots__/support-info.js.snap @@ -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\\" } ], diff --git a/website/data/languages.yml b/website/data/languages.yml index f9b2fd5c..874f91a4 100644 --- a/website/data/languages.yml +++ b/website/data/languages.yml @@ -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 diff --git a/website/playground/codeSamples.js b/website/playground/codeSamples.js index 0a5fd5ba..c8205690 100644 --- a/website/playground/codeSamples.js +++ b/website/playground/codeSamples.js @@ -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.", + "", + "", + "", + "", + " hi ", + " { hello }", + " { /* another commment */}", + "", + "", + "```", + "test codeblock", + "```", + "", + "```js", + "module.exports = 'test'", + "```", + "", + "```sh", + "npm i -g foo", + "```", + "", + "| Test | Table |", + "| :--- | :---- |", + "| Col1 | Col2 |", + "", + "export default ({children }) => < div>{ children}", + "" + ].join("\n"); case "vue": return [ "