Skip to content

Commit c45fef1

Browse files
kovsufiskerautofix-ci[bot]
authored
Fix LWC attribute with --embedded-language-formatting off (#18383)
Co-authored-by: fisker <[email protected]> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 363a20e commit c45fef1

File tree

6 files changed

+93
-17
lines changed

6 files changed

+93
-17
lines changed

changelog_unreleased/lwc/18383.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#### Avoid quote around interpolations (#18383 by @kovsu)
2+
3+
<!-- prettier-ignore -->
4+
```html
5+
<!-- Input -->
6+
<div foo={bar}> </div>
7+
8+
<!-- Prettier stable (--embedded-language-formatting off) -->
9+
<div foo="{bar}"></div>
10+
11+
<!-- Prettier main (--embedded-language-formatting off) -->
12+
<div foo={bar}></div>
13+
```

src/language-html/embed/attribute.js

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { group, mapDoc } from "../../document/index.js";
2+
import { shouldUnquoteAttributeValue } from "../utilities/index.js";
23
import angularAttributePrinters from "./angular-attributes.js";
34
import { isClassNames, printClassNames } from "./class-names.js";
45
import { isEventHandler, printEventHandler } from "./event-handler.js";
@@ -43,19 +44,7 @@ function printAttribute(path, options) {
4344
return;
4445
}
4546

46-
const { valueSpan } = node;
47-
const isQuoted =
48-
valueSpan.end.offset - valueSpan.start.offset === value.length + 2;
49-
50-
if (
51-
!isQuoted &&
52-
// lit-html: html`<my-element obj=${obj}></my-element>`
53-
(/^PRETTIER_HTML_PLACEHOLDER_\d+_\d+_IN_JS$/u.test(value) ||
54-
// lwc: html`<my-element data-for={value}></my-element>`
55-
(options.parser === "lwc" &&
56-
value.startsWith("{") &&
57-
value.endsWith("}")))
58-
) {
47+
if (shouldUnquoteAttributeValue(node, options)) {
5948
return [node.rawName, "=", value];
6049
}
6150

src/language-html/printer-html.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ import {
3535
printOpeningTagStart,
3636
} from "./print/tag.js";
3737
import preprocess from "./print-preprocess.js";
38-
import { getTextValueParts, unescapeQuoteEntities } from "./utilities/index.js";
38+
import {
39+
getTextValueParts,
40+
shouldUnquoteAttributeValue,
41+
unescapeQuoteEntities,
42+
} from "./utilities/index.js";
3943

4044
function genericPrint(path, options, print) {
4145
const { node } = path;
@@ -128,8 +132,12 @@ function genericPrint(path, options, print) {
128132
if (node.value === null) {
129133
return node.rawName;
130134
}
135+
131136
const value = unescapeQuoteEntities(node.value);
132-
const quote = getPreferredQuote(value, '"');
137+
const quote = shouldUnquoteAttributeValue(node, options)
138+
? ""
139+
: getPreferredQuote(value, '"');
140+
133141
return [
134142
node.rawName,
135143
"=",

src/language-html/utilities/index.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,26 @@ function isVueScriptTag(node, options) {
600600
return isVueSfcBlock(node, options) && node.name === "script";
601601
}
602602

603+
function isAttributeValueQuoted(node) {
604+
const { valueSpan, value } = node;
605+
return valueSpan.end.offset - valueSpan.start.offset === value.length + 2;
606+
}
607+
608+
function shouldUnquoteAttributeValue(node, options) {
609+
if (isAttributeValueQuoted(node)) {
610+
return false;
611+
}
612+
613+
const { value } = node;
614+
615+
return (
616+
// Embedded HTML in JS: `` /* HTML */ `<my-element data-for={value}></my-element>` ``
617+
/^PRETTIER_HTML_PLACEHOLDER_\d+_\d+_IN_JS$/u.test(value) ||
618+
// LWC `<div foo={value}></div>`
619+
(options.parser === "lwc" && value.startsWith("{") && value.endsWith("}"))
620+
);
621+
}
622+
603623
export {
604624
canHaveInterpolation,
605625
forceBreakChildren,
@@ -629,5 +649,6 @@ export {
629649
isWhitespaceSensitiveNode,
630650
preferHardlineAsLeadingSpaces,
631651
shouldPreserveContent,
652+
shouldUnquoteAttributeValue,
632653
unescapeQuoteEntities,
633654
};

tests/format/lwc/attribute/quotes/__snapshots__/format.test.js.snap

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,28 @@ unquoted={data}> </div>
1313
<div class="{data}" class='{data}'
1414
class={data}> </div>
1515
16+
<div
17+
in-single-quote="'&apos;&quot;"
18+
in-double-quote='"&apos;&quot;'
19+
escaped-unquoted=&apos;&quot;
20+
escaped-in-single-quote='&apos;&quot;'
21+
escaped-in-double-quote="&apos;&quot;"
22+
style="width: 100px;"
23+
></div>
24+
1625
=====================================output=====================================
17-
<div double-quoted="{data}" single-quoted="{data}" unquoted="{data}"></div>
26+
<div double-quoted="{data}" single-quoted="{data}" unquoted={data}></div>
27+
28+
<div class="{data}" class="{data}" class={data}></div>
1829
19-
<div class="{data}" class="{data}" class="{data}"></div>
30+
<div
31+
in-single-quote="''&quot;"
32+
in-double-quote='"&apos;"'
33+
escaped-unquoted="'&quot;"
34+
escaped-in-single-quote="'&quot;"
35+
escaped-in-double-quote="'&quot;"
36+
style="width: 100px;"
37+
></div>
2038
2139
================================================================================
2240
`;
@@ -33,10 +51,28 @@ unquoted={data}> </div>
3351
<div class="{data}" class='{data}'
3452
class={data}> </div>
3553
54+
<div
55+
in-single-quote="'&apos;&quot;"
56+
in-double-quote='"&apos;&quot;'
57+
escaped-unquoted=&apos;&quot;
58+
escaped-in-single-quote='&apos;&quot;'
59+
escaped-in-double-quote="&apos;&quot;"
60+
style="width: 100px;"
61+
></div>
62+
3663
=====================================output=====================================
3764
<div double-quoted="{data}" single-quoted="{data}" unquoted={data}></div>
3865
3966
<div class="{data}" class="{data}" class={data}></div>
4067
68+
<div
69+
in-single-quote="''&quot;"
70+
in-double-quote='"&apos;"'
71+
escaped-unquoted="'&quot;"
72+
escaped-in-single-quote="'&quot;"
73+
escaped-in-double-quote="'&quot;"
74+
style="width: 100px"
75+
></div>
76+
4177
================================================================================
4278
`;

tests/format/lwc/attribute/quotes/quotes.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,12 @@
33

44
<div class="{data}" class='{data}'
55
class={data}> </div>
6+
7+
<div
8+
in-single-quote="'&apos;&quot;"
9+
in-double-quote='"&apos;&quot;'
10+
escaped-unquoted=&apos;&quot;
11+
escaped-in-single-quote='&apos;&quot;'
12+
escaped-in-double-quote="&apos;&quot;"
13+
style="width: 100px;"
14+
></div>

0 commit comments

Comments
 (0)