Adds LWC Parser to support unquoted interop attributes (#5800)
This pull requests adds a new parser option `lwc`. This is the same as the HTML parser, but it adds support for unquoted HTML attributes per the needs of LWC. See: #5627master
parent
154435bb36
commit
a093bb3f7b
|
@ -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`.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```html
|
||||
// Input
|
||||
<my-element data-for={value}></my-element>
|
||||
|
||||
// Output (Prettier stable)
|
||||
<my-element data-for="{value}"></my-element>
|
||||
|
||||
// Output (Prettier master)
|
||||
<my-element data-for={value}></my-element>
|
||||
```
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -297,6 +297,7 @@ module.exports = {
|
|||
vue: createParser({
|
||||
recognizeSelfClosing: true,
|
||||
isTagNameCaseSensitive: true
|
||||
})
|
||||
}),
|
||||
lwc: createParser()
|
||||
}
|
||||
};
|
||||
|
|
|
@ -123,6 +123,21 @@ function embed(path, print, textToDoc, options) {
|
|||
return concat([node.rawName, "=", node.value]);
|
||||
}
|
||||
|
||||
// lwc: html`<my-element data-for={value}></my-elememt>`
|
||||
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) =>
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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======================================
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`attributes.html 1`] = `
|
||||
====================================options=====================================
|
||||
parser: "lwc"
|
||||
parsers: ["lwc"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
<template>
|
||||
<div
|
||||
data-for={value}
|
||||
data-for={value[0]}
|
||||
data-for={value.toString()}
|
||||
data-for={value()}
|
||||
class="test"
|
||||
></div>
|
||||
</template>
|
||||
<template if:true={value.error}>
|
||||
<c-error-panel errors={value.error}></c-error-panel>
|
||||
</template>
|
||||
<a href="#" onclick={aFunction}>
|
||||
=====================================output=====================================
|
||||
<template>
|
||||
<div
|
||||
data-for={value}
|
||||
data-for={value[0]}
|
||||
data-for={value.toString()}
|
||||
data-for={value()}
|
||||
class="test"
|
||||
></div>
|
||||
</template>
|
||||
<template if:true={value.error}>
|
||||
<c-error-panel errors={value.error}></c-error-panel>
|
||||
</template>
|
||||
<a href="#" onclick={aFunction}></a>
|
||||
|
||||
================================================================================
|
||||
`;
|
||||
|
||||
exports[`attributes.html 2`] = `
|
||||
====================================options=====================================
|
||||
parser: "lwc"
|
||||
parsers: ["lwc"]
|
||||
printWidth: 80
|
||||
trailingComma: "es5"
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
<template>
|
||||
<div
|
||||
data-for={value}
|
||||
data-for={value[0]}
|
||||
data-for={value.toString()}
|
||||
data-for={value()}
|
||||
class="test"
|
||||
></div>
|
||||
</template>
|
||||
<template if:true={value.error}>
|
||||
<c-error-panel errors={value.error}></c-error-panel>
|
||||
</template>
|
||||
<a href="#" onclick={aFunction}>
|
||||
=====================================output=====================================
|
||||
<template>
|
||||
<div
|
||||
data-for={value}
|
||||
data-for={value[0]}
|
||||
data-for={value.toString()}
|
||||
data-for={value()}
|
||||
class="test"
|
||||
></div>
|
||||
</template>
|
||||
<template if:true={value.error}>
|
||||
<c-error-panel errors={value.error}></c-error-panel>
|
||||
</template>
|
||||
<a href="#" onclick={aFunction}></a>
|
||||
|
||||
================================================================================
|
||||
`;
|
||||
|
||||
exports[`attributes.html 3`] = `
|
||||
====================================options=====================================
|
||||
parser: "lwc"
|
||||
parsers: ["lwc"]
|
||||
printWidth: 80
|
||||
semi: false
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
<template>
|
||||
<div
|
||||
data-for={value}
|
||||
data-for={value[0]}
|
||||
data-for={value.toString()}
|
||||
data-for={value()}
|
||||
class="test"
|
||||
></div>
|
||||
</template>
|
||||
<template if:true={value.error}>
|
||||
<c-error-panel errors={value.error}></c-error-panel>
|
||||
</template>
|
||||
<a href="#" onclick={aFunction}>
|
||||
=====================================output=====================================
|
||||
<template>
|
||||
<div
|
||||
data-for={value}
|
||||
data-for={value[0]}
|
||||
data-for={value.toString()}
|
||||
data-for={value()}
|
||||
class="test"
|
||||
></div>
|
||||
</template>
|
||||
<template if:true={value.error}>
|
||||
<c-error-panel errors={value.error}></c-error-panel>
|
||||
</template>
|
||||
<a href="#" onclick={aFunction}></a>
|
||||
|
||||
================================================================================
|
||||
`;
|
|
@ -0,0 +1,13 @@
|
|||
<template>
|
||||
<div
|
||||
data-for={value}
|
||||
data-for={value[0]}
|
||||
data-for={value.toString()}
|
||||
data-for={value()}
|
||||
class="test"
|
||||
></div>
|
||||
</template>
|
||||
<template if:true={value.error}>
|
||||
<c-error-panel errors={value.error}></c-error-panel>
|
||||
</template>
|
||||
<a href="#" onclick={aFunction}>
|
|
@ -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 });
|
|
@ -72,7 +72,7 @@ Format options:
|
|||
Defaults to false.
|
||||
--jsx-single-quote Use single quotes in JSX.
|
||||
Defaults to false.
|
||||
--parser <flow|babel|babel-flow|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml|html|angular>
|
||||
--parser <flow|babel|babel-flow|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml|html|angular|lwc>
|
||||
Which parser to use.
|
||||
--print-width <int> 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 <flow|babel|babel-flow|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml|html|angular>
|
||||
"--parser <flow|babel|babel-flow|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml|html|angular|lwc>
|
||||
|
||||
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 <flow|babel|babel-flow|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml|html|angular>
|
||||
--parser <flow|babel|babel-flow|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml|html|angular|lwc>
|
||||
Which parser to use.
|
||||
--print-width <int> The line length where Prettier will try wrap.
|
||||
Defaults to 80.
|
||||
|
|
|
@ -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 <flow|babel|babel-flow|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml|html|angular>
|
||||
"--parser <flow|babel|babel-flow|typescript|css|less|scss|json|json5|json-stringify|graphql|markdown|mdx|vue|yaml|html|angular|lwc>
|
||||
|
||||
Which parser to use.
|
||||
|
||||
|
@ -355,6 +355,7 @@ Valid options:
|
|||
yaml YAML
|
||||
html HTML
|
||||
angular Angular
|
||||
lwc Lightning Web Components
|
||||
"
|
||||
`;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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\\",
|
||||
|
|
|
@ -285,6 +285,7 @@ export default function(parser) {
|
|||
].join("\n");
|
||||
case "html":
|
||||
case "angular":
|
||||
case "lwc":
|
||||
return [
|
||||
"<!DOCTYPE html>",
|
||||
'<HTML CLASS="no-js mY-ClAsS">',
|
||||
|
|
|
@ -47,6 +47,7 @@ function getMarkdownSyntax(options) {
|
|||
case "glimmer":
|
||||
return "hbs";
|
||||
case "angular":
|
||||
case "lwc":
|
||||
return "html";
|
||||
default:
|
||||
return options.parser;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue