diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 62792873..3b7624d0 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -68,3 +68,19 @@ Examples: | bordered | Toggles rendering of the border around the list | boolean | false | | itemLayout | The layout of list, default is `horizontal`, If a vertical list is desired, set the itemLayout property to `vertical` | string | - | ``` + +- LWC: Add support for Lightning Web Components ([#5800] by [@ntotten]) + + Supports [Lightning Web Components (LWC)](https://developer.salesforce.com/docs/component-library/documentation/lwc) template format for HTML attributes by adding a new parser called `lwc`. + + + ```html + // Input + + + // Output (Prettier stable) + + + // Output (Prettier master) + + ``` diff --git a/docs/options.md b/docs/options.md index 4d4dfc27..a28cbd04 100644 --- a/docs/options.md +++ b/docs/options.md @@ -196,6 +196,7 @@ Valid options: - `"html"` (via [angular-html-parser](https://github.com/ikatyang/angular-html-parser/tree/master/packages/angular-html-parser)) _First available in 1.15.0_ - `"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_ - `"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_ [Custom parsers](api.md#custom-parser-api) are also supported. _First available in v1.5.0_ diff --git a/src/common/internal-plugins.js b/src/common/internal-plugins.js index 43e85e46..188c3833 100644 --- a/src/common/internal-plugins.js +++ b/src/common/internal-plugins.js @@ -157,6 +157,10 @@ module.exports = [ // Angular get angular() { return eval("require")("../language-html/parser-html").parsers.angular; + }, + // Lightning Web Components + get lwc() { + return eval("require")("../language-html/parser-html").parsers.lwc; } } }, diff --git a/src/common/util.js b/src/common/util.js index e4b035dc..1b767049 100644 --- a/src/common/util.js +++ b/src/common/util.js @@ -508,7 +508,8 @@ function printString(raw, options, isDirectiveLiteral) { options.parser === "scss" || options.parentParser === "html" || options.parentParser === "vue" || - options.parentParser === "angular" + options.parentParser === "angular" || + options.parentParser === "lwc" ) ); } diff --git a/src/language-html/index.js b/src/language-html/index.js index f8a819ae..12709365 100644 --- a/src/language-html/index.js +++ b/src/language-html/index.js @@ -28,6 +28,17 @@ const languages = [ ] } }), + createLanguage(require("linguist-languages/data/html"), { + override: { + name: "Lightning Web Components", + since: "1.17.0", + parsers: ["lwc"], + vscodeLanguageIds: ["html"], + + extensions: [], + filenames: [] + } + }), createLanguage(require("linguist-languages/data/vue"), { override: { since: "1.10.0", diff --git a/src/language-html/parser-html.js b/src/language-html/parser-html.js index cf192061..150f0723 100644 --- a/src/language-html/parser-html.js +++ b/src/language-html/parser-html.js @@ -297,6 +297,7 @@ module.exports = { vue: createParser({ recognizeSelfClosing: true, isTagNameCaseSensitive: true - }) + }), + lwc: createParser() } }; diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index 20f4bc1b..ce5a8fab 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -123,6 +123,21 @@ function embed(path, print, textToDoc, options) { return concat([node.rawName, "=", node.value]); } + // lwc: html`` + if (options.parser === "lwc") { + const interpolationRegex = /^\{[\s\S]*\}$/; + if ( + interpolationRegex.test( + options.originalText.slice( + node.valueSpan.start.offset, + node.valueSpan.end.offset + ) + ) + ) { + return concat([node.rawName, "=", node.value]); + } + } + const embeddedAttributeValueDoc = printEmbeddedAttributeValue( node, (code, opts) => diff --git a/src/main/core-options.js b/src/main/core-options.js index d4582ec3..f90bcd1d 100644 --- a/src/main/core-options.js +++ b/src/main/core-options.js @@ -160,7 +160,8 @@ const options = { description: "Handlebars" }, { value: "html", since: "1.15.0", description: "HTML" }, - { value: "angular", since: "1.15.0", description: "Angular" } + { value: "angular", since: "1.15.0", description: "Angular" }, + { value: "lwc", since: "1.17.0", description: "Lightning Web Components" } ] }, plugins: { diff --git a/tests/empty/__snapshots__/jsfmt.spec.js.snap b/tests/empty/__snapshots__/jsfmt.spec.js.snap index 4ec19365..fc67ad24 100644 --- a/tests/empty/__snapshots__/jsfmt.spec.js.snap +++ b/tests/empty/__snapshots__/jsfmt.spec.js.snap @@ -2,7 +2,7 @@ exports[`empty 1`] = ` ====================================options===================================== -parsers: ["flow", "babel", "babel-flow", "typescript", "css", "less", "scss", "json", "json5", "json-stringify", "graphql", "markdown", "mdx", "vue", "yaml", "html", "angular"] +parsers: ["flow", "babel", "babel-flow", "typescript", "css", "less", "scss", "json", "json5", "json-stringify", "graphql", "markdown", "mdx", "vue", "yaml", "html", "angular", "lwc"] printWidth: 80 | printWidth =====================================input====================================== @@ -14,7 +14,7 @@ printWidth: 80 exports[`newline 1`] = ` ====================================options===================================== -parsers: ["flow", "babel", "babel-flow", "typescript", "css", "less", "scss", "json", "json5", "json-stringify", "graphql", "markdown", "mdx", "vue", "yaml", "html", "angular"] +parsers: ["flow", "babel", "babel-flow", "typescript", "css", "less", "scss", "json", "json5", "json-stringify", "graphql", "markdown", "mdx", "vue", "yaml", "html", "angular", "lwc"] printWidth: 80 | printWidth =====================================input====================================== @@ -27,7 +27,7 @@ printWidth: 80 exports[`space 1`] = ` ====================================options===================================== -parsers: ["flow", "babel", "babel-flow", "typescript", "css", "less", "scss", "json", "json5", "json-stringify", "graphql", "markdown", "mdx", "vue", "yaml", "html", "angular"] +parsers: ["flow", "babel", "babel-flow", "typescript", "css", "less", "scss", "json", "json5", "json-stringify", "graphql", "markdown", "mdx", "vue", "yaml", "html", "angular", "lwc"] printWidth: 80 | printWidth =====================================input====================================== @@ -40,7 +40,7 @@ printWidth: 80 exports[`space-newline 1`] = ` ====================================options===================================== -parsers: ["flow", "babel", "babel-flow", "typescript", "css", "less", "scss", "json", "json5", "json-stringify", "graphql", "markdown", "mdx", "vue", "yaml", "html", "angular"] +parsers: ["flow", "babel", "babel-flow", "typescript", "css", "less", "scss", "json", "json5", "json-stringify", "graphql", "markdown", "mdx", "vue", "yaml", "html", "angular", "lwc"] printWidth: 80 | printWidth =====================================input====================================== diff --git a/tests/html_lwc/__snapshots__/jsfmt.spec.js.snap b/tests/html_lwc/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 00000000..63197acf --- /dev/null +++ b/tests/html_lwc/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,117 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`attributes.html 1`] = ` +====================================options===================================== +parser: "lwc" +parsers: ["lwc"] +printWidth: 80 + | printWidth +=====================================input====================================== + + + +=====================================output===================================== + + + + +================================================================================ +`; + +exports[`attributes.html 2`] = ` +====================================options===================================== +parser: "lwc" +parsers: ["lwc"] +printWidth: 80 +trailingComma: "es5" + | printWidth +=====================================input====================================== + + + +=====================================output===================================== + + + + +================================================================================ +`; + +exports[`attributes.html 3`] = ` +====================================options===================================== +parser: "lwc" +parsers: ["lwc"] +printWidth: 80 +semi: false + | printWidth +=====================================input====================================== + + + +=====================================output===================================== + + + + +================================================================================ +`; diff --git a/tests/html_lwc/attributes.html b/tests/html_lwc/attributes.html new file mode 100644 index 00000000..0ab586fe --- /dev/null +++ b/tests/html_lwc/attributes.html @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/tests/html_lwc/jsfmt.spec.js b/tests/html_lwc/jsfmt.spec.js new file mode 100644 index 00000000..8286bbff --- /dev/null +++ b/tests/html_lwc/jsfmt.spec.js @@ -0,0 +1,3 @@ +run_spec(__dirname, ["lwc"], { parser: "lwc" }); +run_spec(__dirname, ["lwc"], { parser: "lwc", trailingComma: "es5" }); +run_spec(__dirname, ["lwc"], { parser: "lwc", semi: false }); diff --git a/tests_integration/__tests__/__snapshots__/early-exit.js.snap b/tests_integration/__tests__/__snapshots__/early-exit.js.snap index 4c4d5ad5..1cb09a26 100644 --- a/tests_integration/__tests__/__snapshots__/early-exit.js.snap +++ b/tests_integration/__tests__/__snapshots__/early-exit.js.snap @@ -72,7 +72,7 @@ Format options: Defaults to false. --jsx-single-quote Use single quotes in JSX. Defaults to false. - --parser + --parser Which parser to use. --print-width The line length where Prettier will try wrap. Defaults to 80. @@ -162,7 +162,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. @@ -185,6 +185,7 @@ Valid options: yaml YAML html HTML angular Angular + lwc Lightning Web Components " `; @@ -221,7 +222,7 @@ Format options: Defaults to false. --jsx-single-quote Use single quotes in JSX. 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 fdfe0ba5..9a0ffd45 100644 --- a/tests_integration/__tests__/__snapshots__/help-options.js.snap +++ b/tests_integration/__tests__/__snapshots__/help-options.js.snap @@ -332,7 +332,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. @@ -355,6 +355,7 @@ Valid options: yaml YAML html HTML angular Angular + lwc Lightning Web Components " `; diff --git a/tests_integration/__tests__/__snapshots__/schema.js.snap b/tests_integration/__tests__/__snapshots__/schema.js.snap index e72c7c0e..75a5705d 100644 --- a/tests_integration/__tests__/__snapshots__/schema.js.snap +++ b/tests_integration/__tests__/__snapshots__/schema.js.snap @@ -224,6 +224,12 @@ This option cannot be used with --range-start and --range-end.", "angular", ], }, + Object { + "description": "Lightning Web Components", + "enum": Array [ + "lwc", + ], + }, ], }, "pluginSearchDirs": Object { diff --git a/tests_integration/__tests__/__snapshots__/support-info.js.snap b/tests_integration/__tests__/__snapshots__/support-info.js.snap index dfa9251b..33450f09 100644 --- a/tests_integration/__tests__/__snapshots__/support-info.js.snap +++ b/tests_integration/__tests__/__snapshots__/support-info.js.snap @@ -448,12 +448,15 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = ` \\"flow\\", ], \\"JavaScript\\": Array [ -@@ -25,10 +37,13 @@ +@@ -25,10 +37,16 @@ \\"flow\\", ], \\"Less\\": Array [ \\"less\\", ], ++ \\"Lightning Web Components\\": Array [ ++ \\"lwc\\", ++ ], + \\"MDX\\": Array [ + \\"mdx\\", + ], @@ -462,7 +465,7 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = ` ], \\"PostCSS\\": Array [ \\"css\\", -@@ -37,12 +52,26 @@ +@@ -37,12 +55,26 @@ \\"scss\\", ], \\"TypeScript\\": Array [ @@ -489,7 +492,7 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = ` \\"type\\": \\"boolean\\", }, \\"cursorOffset\\": Object { -@@ -52,37 +81,76 @@ +@@ -52,37 +84,77 @@ \\"start\\": -1, \\"step\\": 1, }, @@ -550,6 +553,7 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = ` + \\"yaml\\", + \\"html\\", + \\"angular\\", ++ \\"lwc\\", ], - \\"default\\": \\"babylon\\", + \\"default\\": undefined, @@ -568,7 +572,7 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = ` \\"range\\": Object { \\"end\\": Infinity, \\"start\\": 0, -@@ -90,14 +158,15 @@ +@@ -90,14 +162,15 @@ }, \\"type\\": \\"int\\", }, @@ -919,6 +923,22 @@ exports[`CLI --support-info (stdout) 1`] = ` \\"type\\": \\"markup\\", \\"vscodeLanguageIds\\": [\\"html\\"] }, + { + \\"aceMode\\": \\"html\\", + \\"aliases\\": [\\"xhtml\\"], + \\"codemirrorMimeType\\": \\"text/html\\", + \\"codemirrorMode\\": \\"htmlmixed\\", + \\"color\\": \\"#e34c26\\", + \\"extensions\\": [], + \\"filenames\\": [], + \\"linguistLanguageId\\": 146, + \\"name\\": \\"Lightning Web Components\\", + \\"parsers\\": [\\"lwc\\"], + \\"since\\": \\"1.17.0\\", + \\"tmScope\\": \\"text.html.basic\\", + \\"type\\": \\"markup\\", + \\"vscodeLanguageIds\\": [\\"html\\"] + }, { \\"aceMode\\": \\"html\\", \\"color\\": \\"#2c3e50\\", @@ -1109,7 +1129,12 @@ exports[`CLI --support-info (stdout) 1`] = ` { \\"description\\": \\"Vue\\", \\"since\\": \\"1.10.0\\", \\"value\\": \\"vue\\" }, { \\"description\\": \\"YAML\\", \\"since\\": \\"1.14.0\\", \\"value\\": \\"yaml\\" }, { \\"description\\": \\"HTML\\", \\"since\\": \\"1.15.0\\", \\"value\\": \\"html\\" }, - { \\"description\\": \\"Angular\\", \\"since\\": \\"1.15.0\\", \\"value\\": \\"angular\\" } + { \\"description\\": \\"Angular\\", \\"since\\": \\"1.15.0\\", \\"value\\": \\"angular\\" }, + { + \\"description\\": \\"Lightning Web Components\\", + \\"since\\": \\"1.17.0\\", + \\"value\\": \\"lwc\\" + } ], \\"description\\": \\"Which parser to use.\\", \\"name\\": \\"parser\\", diff --git a/website/playground/codeSamples.js b/website/playground/codeSamples.js index 9eec1101..cb0a1682 100644 --- a/website/playground/codeSamples.js +++ b/website/playground/codeSamples.js @@ -285,6 +285,7 @@ export default function(parser) { ].join("\n"); case "html": case "angular": + case "lwc": return [ "", '', diff --git a/website/playground/markdown.js b/website/playground/markdown.js index 63b204c3..15706a09 100644 --- a/website/playground/markdown.js +++ b/website/playground/markdown.js @@ -47,6 +47,7 @@ function getMarkdownSyntax(options) { case "glimmer": return "hbs"; case "angular": + case "lwc": return "html"; default: return options.parser; diff --git a/website/static/worker.js b/website/static/worker.js index 87902c01..cd762770 100644 --- a/website/static/worker.js +++ b/website/static/worker.js @@ -137,6 +137,11 @@ var parsers = { get angular() { importScriptOnce("lib/parser-html.js"); return prettierPlugins.html.parsers.angular; + }, + // Lightning Web Components + get lwc() { + importScriptOnce("lib/parser-html.js"); + return prettierPlugins.html.parsers.lwc; } };