diff --git a/changelog_unreleased/api/17339.md b/changelog_unreleased/api/17339.md new file mode 100644 index 000000000..529ee232f --- /dev/null +++ b/changelog_unreleased/api/17339.md @@ -0,0 +1,3 @@ +#### Add `mjml` parser (#17339 by @fisker) + +We already support [MJML](https://mjml.io/) in previous version with `html` parser, in order to distinguish MJML-specific a new `mjml` parser added. diff --git a/changelog_unreleased/mjml/.gitkeep b/changelog_unreleased/mjml/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/docs/options.md b/docs/options.md index 113648163..157110b60 100644 --- a/docs/options.md +++ b/docs/options.md @@ -325,6 +325,7 @@ Valid options: - `"vue"` (same parser as `"html"`, but also formats vue-specific syntax) _First available in 1.10.0_ - `"angular"` (same parser as `"html"`, but also formats angular-specific syntax via [angular-estree-parser](https://github.com/ikatyang/angular-estree-parser)) _First available in 1.15.0_ - `"lwc"` (same parser as `"html"`, but also formats LWC-specific syntax for unquoted template attributes) _First available in 1.17.0_ +- `"mjml"` (same parser as `"html"`, but also formats MJML-specific syntax) _First available in 3.6.0_ - `"yaml"` (via [yaml](https://github.com/eemeli/yaml) and [yaml-unist-parser](https://github.com/ikatyang/yaml-unist-parser)) _First available in 1.14.0_ | Default | CLI Override | API Override | diff --git a/scripts/generate-changelog.js b/scripts/generate-changelog.js index 9a699e66a..ac58cacd3 100755 --- a/scripts/generate-changelog.js +++ b/scripts/generate-changelog.js @@ -134,6 +134,7 @@ function getSyntaxFromCategory(category) { case "angular": case "html": case "lwc": + case "mjml": return "html"; case "cli": return "sh"; diff --git a/scripts/utils/changelog-categories.js b/scripts/utils/changelog-categories.js index a5b25175b..da74b1d41 100644 --- a/scripts/utils/changelog-categories.js +++ b/scripts/utils/changelog-categories.js @@ -11,6 +11,7 @@ export const CHANGELOG_CATEGORIES = [ "json", "less", "lwc", + "mjml", "markdown", "mdx", "scss", diff --git a/scripts/utils/changelog.js b/scripts/utils/changelog.js index 39008cbf8..70ff104b5 100644 --- a/scripts/utils/changelog.js +++ b/scripts/utils/changelog.js @@ -22,6 +22,7 @@ export const categories = [ { dir: "vue", title: "Vue" }, { dir: "angular", title: "Angular" }, { dir: "lwc", title: "LWC" }, + { dir: "mjml", title: "MJML" }, { dir: "handlebars", title: "Ember / Handlebars" }, { dir: "graphql", title: "GraphQL" }, { dir: "markdown", title: "Markdown" }, diff --git a/src/index.d.ts b/src/index.d.ts index 7a7841ec8..8680e32b7 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -296,6 +296,7 @@ export type BuiltInParserName = | "markdown" | "mdx" | "meriyah" + | "mjml" | "scss" | "typescript" | "vue" diff --git a/src/language-html/languages.evaluate.js b/src/language-html/languages.evaluate.js index 130f2743e..2dca2b7f7 100644 --- a/src/language-html/languages.evaluate.js +++ b/src/language-html/languages.evaluate.js @@ -9,13 +9,9 @@ const languages = [ extensions: [".component.html"], filenames: [], })), - createLanguage(linguistLanguages.HTML, (data) => ({ + createLanguage(linguistLanguages.HTML, () => ({ parsers: ["html"], vscodeLanguageIds: ["html"], - extensions: [ - ...data.extensions, - ".mjml", // MJML is considered XML in Linguist but it should be formatted as HTML - ], })), createLanguage(linguistLanguages.HTML, () => ({ name: "Lightning Web Components", @@ -24,6 +20,17 @@ const languages = [ extensions: [], filenames: [], })), + createLanguage(linguistLanguages.HTML, () => ({ + name: "MJML", + parsers: ["mjml"], + extensions: [".mjml"], + filenames: [], + // https://github.com/mjmlio/vscode-mjml/blob/477f030d400fe838d29495f4a432fba57f2198b7/package.json#L226-L238 + vscodeLanguageIds: ["mjml"], + aliases: ["MJML", "mjml"], + // https://github.com/mjmlio/vscode-mjml/blob/477f030d400fe838d29495f4a432fba57f2198b7/package.json#L242 + tmScope: "text.mjml.basic", + })), createLanguage(linguistLanguages.Vue, () => ({ parsers: ["vue"], vscodeLanguageIds: ["vue"], diff --git a/src/language-html/parser-html.js b/src/language-html/parser-html.js index a88ffbb42..57af1d01f 100644 --- a/src/language-html/parser-html.js +++ b/src/language-html/parser-html.js @@ -28,7 +28,7 @@ import isUnknownNamespace from "./utils/is-unknown-namespace.js"; /** * @typedef {AngularHtmlParserParseOptions & { - * name: 'html' | 'angular' | 'vue' | 'lwc'; + * name: 'html' | 'angular' | 'vue' | 'lwc' | 'mjml'; * normalizeTagName?: boolean; * normalizeAttributeName?: boolean; * shouldParseAsRawText?: (tagName: string, prefix: string, hasParent: boolean, attrs: Array<{ @@ -444,6 +444,8 @@ const HTML_PARSE_OPTIONS = { // HTML export const html = createParser(HTML_PARSE_OPTIONS); +// MJML https://mjml.io/ +export const mjml = createParser({ ...HTML_PARSE_OPTIONS, name: "mjml" }); // Angular export const angular = createParser({ name: "angular" }); // Vue diff --git a/src/main/core-options.evaluate.js b/src/main/core-options.evaluate.js index b1b8ae5e7..921b5c549 100644 --- a/src/main/core-options.evaluate.js +++ b/src/main/core-options.evaluate.js @@ -128,6 +128,7 @@ const options = { { value: "html", description: "HTML" }, { value: "angular", description: "Angular" }, { value: "lwc", description: "Lightning Web Components" }, + { value: "mjml", description: "MJML" }, ], }, plugins: { diff --git a/src/plugins/builtin-plugins-proxy.js b/src/plugins/builtin-plugins-proxy.js index 75d30e5b8..8a47a5754 100644 --- a/src/plugins/builtin-plugins-proxy.js +++ b/src/plugins/builtin-plugins-proxy.js @@ -117,7 +117,7 @@ export const { parsers, printers } = createParsersAndPrinters([ }, { importPlugin: () => import("./html.js"), - parsers: ["html", "angular", "vue", "lwc"], + parsers: ["html", "angular", "vue", "lwc", "mjml"], printers: ["html"], }, { diff --git a/tests/config/utils/check-parsers.js b/tests/config/utils/check-parsers.js index 238898b84..02f3717fd 100644 --- a/tests/config/utils/check-parsers.js +++ b/tests/config/utils/check-parsers.js @@ -50,7 +50,7 @@ const categoryParsers = new Map([ "html", { parsers: ["html"], verifyParsers: [], extensions: [".html", ".svg"] }, ], - ["mjml", { parsers: ["html"], verifyParsers: [], extensions: [".mjml"] }], + ["mjml", { parsers: ["mjml"], verifyParsers: [], extensions: [".mjml"] }], [ "js", { diff --git a/tests/dts/unit/cases/parsers.ts b/tests/dts/unit/cases/parsers.ts index 6157ab577..e3a90b22a 100644 --- a/tests/dts/unit/cases/parsers.ts +++ b/tests/dts/unit/cases/parsers.ts @@ -82,6 +82,7 @@ prettierPluginGlimmer.parsers.glimmer.parse("code", options); prettierPluginHtml.parsers.html.parse("code", options); prettierPluginHtml.parsers.vue.parse("code", options); prettierPluginHtml.parsers.lwc.parse("code", options); +prettierPluginHtml.parsers.mjml.parse("code", options); prettierPluginHtml.parsers.angular.parse("code", options); prettierPluginYaml.parsers.yaml.parse("code", options); diff --git a/tests/format/mjml/mjml/__snapshots__/format.test.js.snap b/tests/format/mjml/mjml/__snapshots__/format.test.js.snap index 297ff67b0..eb7bd3760 100644 --- a/tests/format/mjml/mjml/__snapshots__/format.test.js.snap +++ b/tests/format/mjml/mjml/__snapshots__/format.test.js.snap @@ -2,7 +2,7 @@ exports[`empty.mjml format 1`] = ` ====================================options===================================== -parsers: ["html"] +parsers: ["mjml"] printWidth: 80 | printWidth =====================================input====================================== @@ -15,7 +15,7 @@ printWidth: 80 exports[`head.mjml format 1`] = ` ====================================options===================================== -parsers: ["html"] +parsers: ["mjml"] printWidth: 80 | printWidth =====================================input====================================== diff --git a/tests/format/mjml/mjml/format.test.js b/tests/format/mjml/mjml/format.test.js index 88a427864..5af041ec4 100644 --- a/tests/format/mjml/mjml/format.test.js +++ b/tests/format/mjml/mjml/format.test.js @@ -1 +1 @@ -runFormatTest(import.meta, ["html"]); +runFormatTest(import.meta, ["mjml"]); diff --git a/tests/integration/__tests__/__snapshots__/early-exit.js.snap b/tests/integration/__tests__/__snapshots__/early-exit.js.snap index df4b67343..081db3989 100644 --- a/tests/integration/__tests__/__snapshots__/early-exit.js.snap +++ b/tests/integration/__tests__/__snapshots__/early-exit.js.snap @@ -66,7 +66,7 @@ Format options: --object-wrap How to wrap object literals. Defaults to preserve. - --parser + --parser Which parser to use. --print-width The line length where Prettier will try wrap. Defaults to 80. @@ -161,7 +161,7 @@ exports[`show version with --version (write) 1`] = `[]`; exports[`show warning with --help not-found (typo) (stderr) 1`] = `"[warn] Unknown flag "parserr", did you mean "parser"?"`; exports[`show warning with --help not-found (typo) (stdout) 1`] = ` -"--parser +"--parser Which parser to use. @@ -190,7 +190,8 @@ Valid options: glimmer Ember / Handlebars html HTML angular Angular - lwc Lightning Web Components" + lwc Lightning Web Components + mjml MJML" `; exports[`show warning with --help not-found (typo) (write) 1`] = `[]`; @@ -237,7 +238,7 @@ Format options: --object-wrap How to wrap object literals. Defaults to preserve. - --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 f977b7e65..7181ae900 100644 --- a/tests/integration/__tests__/__snapshots__/help-options.js.snap +++ b/tests/integration/__tests__/__snapshots__/help-options.js.snap @@ -438,7 +438,7 @@ exports[`show detailed usage with --help object-wrap (write) 1`] = `[]`; exports[`show detailed usage with --help parser (stderr) 1`] = `""`; exports[`show detailed usage with --help parser (stdout) 1`] = ` -"--parser +"--parser Which parser to use. @@ -467,7 +467,8 @@ Valid options: glimmer Ember / Handlebars html HTML angular Angular - lwc Lightning Web Components" + lwc Lightning Web Components + mjml MJML" `; exports[`show detailed usage with --help parser (write) 1`] = `[]`; diff --git a/tests/integration/__tests__/__snapshots__/plugin-options-string.js.snap b/tests/integration/__tests__/__snapshots__/plugin-options-string.js.snap index 592c82607..ab661da8b 100644 --- a/tests/integration/__tests__/__snapshots__/plugin-options-string.js.snap +++ b/tests/integration/__tests__/__snapshots__/plugin-options-string.js.snap @@ -33,8 +33,8 @@ exports[`show external options with \`--help\` 1`] = ` --object-wrap How to wrap object literals. Defaults to preserve. -- --parser -+ --parser +- --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__/plugin-options.js.snap b/tests/integration/__tests__/__snapshots__/plugin-options.js.snap index 3f2e8148a..7fcf36735 100644 --- a/tests/integration/__tests__/__snapshots__/plugin-options.js.snap +++ b/tests/integration/__tests__/__snapshots__/plugin-options.js.snap @@ -3,7 +3,7 @@ exports[`include plugin's parsers to the values of the \`parser\` option\` (stderr) 1`] = `""`; exports[`include plugin's parsers to the values of the \`parser\` option\` (stdout) 1`] = ` -"--parser +"--parser Which parser to use. @@ -33,6 +33,7 @@ Valid options: html HTML angular Angular lwc Lightning Web Components + mjml MJML foo-parser foo (plugin: ./plugin.cjs)" `; @@ -76,8 +77,8 @@ exports[`show external options with \`--help\` 1`] = ` --object-wrap How to wrap object literals. Defaults to preserve. -- --parser -+ --parser +- --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__/schema.js.snap b/tests/integration/__tests__/__snapshots__/schema.js.snap index ca0815883..a1b8700b6 100644 --- a/tests/integration/__tests__/__snapshots__/schema.js.snap +++ b/tests/integration/__tests__/__snapshots__/schema.js.snap @@ -315,6 +315,12 @@ exports[`schema 1`] = ` "lwc", ], }, + { + "description": "MJML", + "enum": [ + "mjml", + ], + }, { "description": "Custom parser", "type": "string", diff --git a/tests/integration/__tests__/__snapshots__/support-info.js.snap b/tests/integration/__tests__/__snapshots__/support-info.js.snap index 1055f28c3..3b27103b4 100644 --- a/tests/integration/__tests__/__snapshots__/support-info.js.snap +++ b/tests/integration/__tests__/__snapshots__/support-info.js.snap @@ -62,6 +62,9 @@ exports[`API getSupportInfo() 1`] = ` "MDX": [ "mdx", ], + "MJML": [ + "mjml", + ], "Markdown": [ "markdown", ], @@ -197,6 +200,7 @@ exports[`API getSupportInfo() 1`] = ` "html", "angular", "lwc", + "mjml", ], "default": undefined, "type": "choice", @@ -392,8 +396,7 @@ exports[`CLI --support-info (stdout) 1`] = ` ".html.hl", ".inc", ".xht", - ".xhtml", - ".mjml" + ".xhtml" ], "linguistLanguageId": 146, "name": "HTML", @@ -680,6 +683,21 @@ exports[`CLI --support-info (stdout) 1`] = ` "vscodeLanguageIds": ["mdx"], "wrap": true }, + { + "aceMode": "html", + "aliases": ["MJML", "mjml"], + "codemirrorMimeType": "text/html", + "codemirrorMode": "htmlmixed", + "color": "#e34c26", + "extensions": [".mjml"], + "filenames": [], + "linguistLanguageId": 146, + "name": "MJML", + "parsers": ["mjml"], + "tmScope": "text.mjml.basic", + "type": "markup", + "vscodeLanguageIds": ["mjml"] + }, { "aceMode": "text", "color": "#dc3a0c", @@ -994,7 +1012,8 @@ exports[`CLI --support-info (stdout) 1`] = ` { "description": "Ember / Handlebars", "value": "glimmer" }, { "description": "HTML", "value": "html" }, { "description": "Angular", "value": "angular" }, - { "description": "Lightning Web Components", "value": "lwc" } + { "description": "Lightning Web Components", "value": "lwc" }, + { "description": "MJML", "value": "mjml" } ], "description": "Which parser to use.", "name": "parser", diff --git a/tests/unit/builtin-plugins.js b/tests/unit/builtin-plugins.js index dfe3ad5ed..31a11629d 100644 --- a/tests/unit/builtin-plugins.js +++ b/tests/unit/builtin-plugins.js @@ -39,6 +39,7 @@ test("builtin parsers", async () => { "markdown", "mdx", "meriyah", + "mjml", "remark", "scss", "typescript", diff --git a/website/playground/codeSamples.mjs b/website/playground/codeSamples.mjs index 865474ac5..662c6ce42 100644 --- a/website/playground/codeSamples.mjs +++ b/website/playground/codeSamples.mjs @@ -309,6 +309,18 @@ export default function getCodeSamples(parser) { " ", "", ].join("\n"); + case "mjml": + return [ + " ", + " ", + " ", + " Hello World!", + " ", + " ", + " ", + " ", + " ", + ].join("\n"); case "doc-explorer": return [ "group([", diff --git a/website/playground/markdown.js b/website/playground/markdown.js index f7cd649af..a9ba759f3 100644 --- a/website/playground/markdown.js +++ b/website/playground/markdown.js @@ -56,6 +56,7 @@ function getMarkdownSyntax(options) { return "hbs"; case "angular": case "lwc": + case "mjml": return "html"; default: return options.parser; diff --git a/website/playground/util.js b/website/playground/util.js index a836b6695..663444414 100644 --- a/website/playground/util.js +++ b/website/playground/util.js @@ -84,6 +84,7 @@ export function getAstAutoFold(parser) { case "angular": case "vue": case "lwc": + case "mjml": return astAutoFold.html; case "markdown": case "mdx":