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;
}
};