Skip to content

Commit

Permalink
Adds LWC Parser to support unquoted interop attributes (#5800)
Browse files Browse the repository at this point in the history
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: #5627
  • Loading branch information
ntotten authored and ikatyang committed Feb 1, 2019
1 parent 154435b commit a093bb3
Show file tree
Hide file tree
Showing 19 changed files with 239 additions and 16 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.unreleased.md
Expand Up @@ -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>
```
1 change: 1 addition & 0 deletions docs/options.md
Expand Up @@ -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_
Expand Down
4 changes: 4 additions & 0 deletions src/common/internal-plugins.js
Expand Up @@ -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;
}
}
},
Expand Down
3 changes: 2 additions & 1 deletion src/common/util.js
Expand Up @@ -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"
)
);
}
Expand Down
11 changes: 11 additions & 0 deletions src/language-html/index.js
Expand Up @@ -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",
Expand Down
3 changes: 2 additions & 1 deletion src/language-html/parser-html.js
Expand Up @@ -297,6 +297,7 @@ module.exports = {
vue: createParser({
recognizeSelfClosing: true,
isTagNameCaseSensitive: true
})
}),
lwc: createParser()
}
};
15 changes: 15 additions & 0 deletions src/language-html/printer-html.js
Expand Up @@ -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) =>
Expand Down
3 changes: 2 additions & 1 deletion src/main/core-options.js
Expand Up @@ -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: {
Expand Down
8 changes: 4 additions & 4 deletions tests/empty/__snapshots__/jsfmt.spec.js.snap
Expand Up @@ -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======================================
Expand All @@ -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======================================
Expand All @@ -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======================================
Expand All @@ -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======================================
Expand Down
117 changes: 117 additions & 0 deletions 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======================================
<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>
================================================================================
`;
13 changes: 13 additions & 0 deletions tests/html_lwc/attributes.html
@@ -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}>
3 changes: 3 additions & 0 deletions 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 });
7 changes: 4 additions & 3 deletions tests_integration/__tests__/__snapshots__/early-exit.js.snap
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -185,6 +185,7 @@ Valid options:
yaml YAML
html HTML
angular Angular
lwc Lightning Web Components
"
`;
Expand Down Expand Up @@ -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.
Expand Down
Expand Up @@ -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.
Expand All @@ -355,6 +355,7 @@ Valid options:
yaml YAML
html HTML
angular Angular
lwc Lightning Web Components
"
`;
Expand Down
6 changes: 6 additions & 0 deletions tests_integration/__tests__/__snapshots__/schema.js.snap
Expand Up @@ -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 {
Expand Down

0 comments on commit a093bb3

Please sign in to comment.