Skip to content

Commit 0e42acb

Browse files
authored
feat: added singleAttributePerLine option (#5501) (#6644)
1 parent 16b6825 commit 0e42acb

19 files changed

Lines changed: 594 additions & 5 deletions

File tree

docs/options.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,8 @@ Whether or not to indent the code inside `<script>` and `<style>` tags in Vue fi
388388

389389
Valid options:
390390

391-
- `"false"` - Do not indent script and style tags in Vue files.
392-
- `"true"` - Indent script and style tags in Vue files.
391+
- `false` - Do not indent script and style tags in Vue files.
392+
- `true` - Indent script and style tags in Vue files.
393393

394394
| Default | CLI Override | API Override |
395395
| ------- | ------------------------------- | --------------------------------- |
@@ -451,3 +451,18 @@ Valid options:
451451
| Default | CLI Override | API Override |
452452
| -------- | ------------------------------------ | ----------------------------------- |
453453
| `"auto"` | `--embedded-language-formatting=off` | `embeddedLanguageFormatting: "off"` |
454+
455+
## Single Attribute Per Line
456+
457+
_First available in v2.3.3_
458+
459+
Enforce single attribute per line in HTML, Vue and JSX.
460+
461+
Valid options:
462+
463+
- `false` - Do not enforce single attribute per line.
464+
- `true` - Enforce single attribute per line.
465+
466+
| Default | CLI Override | API Override |
467+
| ------- | ----------------------------- | -------------------------------- |
468+
| `false` | `--single-attribute-per-line` | `singleAttributePerLine: <bool>` |

src/common/common-options.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,11 @@ module.exports = {
5454
description:
5555
"Put > of opening tags on the last line instead of on a new line.",
5656
},
57+
singleAttributePerLine: {
58+
since: "2.3.3",
59+
category: CATEGORY_COMMON,
60+
type: "boolean",
61+
default: false,
62+
description: "Enforce single attribute per line in HTML, Vue and JSX.",
63+
},
5764
};

src/language-html/options.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ module.exports = {
2828
},
2929
],
3030
},
31+
singleAttributePerLine: commonOptions.singleAttributePerLine,
3132
vueIndentScriptAndStyle: {
3233
since: "1.19.0",
3334
category: CATEGORY_HTML,

src/language-html/print/tag.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
const assert = require("assert");
88
const { isNonEmptyArray } = require("../../common/util.js");
99
const {
10-
builders: { indent, join, line, softline },
10+
builders: { indent, join, line, softline, hardline },
1111
utils: { replaceTextEndOfLine },
1212
} = require("../../document/index.js");
1313
const { locStart, locEnd } = require("../loc.js");
@@ -251,11 +251,14 @@ function printAttributes(path, options, print) {
251251
node.attrs[0].fullName === "src" &&
252252
node.children.length === 0;
253253

254+
const attributeLine =
255+
options.singleAttributePerLine && node.attrs.length > 1 ? hardline : line;
256+
254257
/** @type {Doc[]} */
255258
const parts = [
256259
indent([
257260
forceNotToBreakAttrContent ? " " : line,
258-
join(line, printedAttributes),
261+
join(attributeLine, printedAttributes),
259262
]),
260263
];
261264

src/language-js/options.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,5 @@ module.exports = {
9898
},
9999
],
100100
},
101+
singleAttributePerLine: commonOptions.singleAttributePerLine,
101102
};

src/language-js/print/jsx.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,12 +605,17 @@ function printJsxOpeningElement(path, options, print) {
605605
attr.value.value.includes("\n")
606606
);
607607

608+
const attributeLine =
609+
options.singleAttributePerLine && node.attributes.length > 1
610+
? hardline
611+
: line;
612+
608613
return group(
609614
[
610615
"<",
611616
print("name"),
612617
print("typeParameters"),
613-
indent(path.map(() => [line, print()], "attributes")),
618+
indent(path.map(() => [attributeLine, print()], "attributes")),
614619
node.selfClosing ? line : bracketSameLine ? ">" : softline,
615620
node.selfClosing ? "/>" : bracketSameLine ? "" : ">",
616621
],
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`single-attribute-per-line.html - {"singleAttributePerLine":true} format 1`] = `
4+
====================================options=====================================
5+
parsers: ["html"]
6+
printWidth: 80
7+
singleAttributePerLine: true
8+
| printWidth
9+
=====================================input======================================
10+
<div data-a="1">
11+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
12+
</div>
13+
14+
<div data-a="1" data-b="2" data-c="3">
15+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
16+
</div>
17+
18+
<div data-a="Lorem ipsum dolor sit amet" data-b="Lorem ipsum dolor sit amet" data-c="Lorem ipsum dolor sit amet">
19+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
20+
</div>
21+
22+
<div data-long-attribute-a="1" data-long-attribute-b="2" data-long-attribute-c="3">
23+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
24+
</div>
25+
26+
<img src="/images/foo.png" />
27+
28+
<img src="/images/foo.png" alt="bar" />
29+
30+
<img src="/images/foo.png" alt="Lorem ipsum dolor sit amet, consectetur adipiscing elit." />
31+
32+
=====================================output=====================================
33+
<div data-a="1">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
34+
35+
<div
36+
data-a="1"
37+
data-b="2"
38+
data-c="3"
39+
>
40+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
41+
</div>
42+
43+
<div
44+
data-a="Lorem ipsum dolor sit amet"
45+
data-b="Lorem ipsum dolor sit amet"
46+
data-c="Lorem ipsum dolor sit amet"
47+
>
48+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
49+
</div>
50+
51+
<div
52+
data-long-attribute-a="1"
53+
data-long-attribute-b="2"
54+
data-long-attribute-c="3"
55+
>
56+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
57+
</div>
58+
59+
<img src="/images/foo.png" />
60+
61+
<img
62+
src="/images/foo.png"
63+
alt="bar"
64+
/>
65+
66+
<img
67+
src="/images/foo.png"
68+
alt="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
69+
/>
70+
71+
================================================================================
72+
`;
73+
74+
exports[`single-attribute-per-line.html format 1`] = `
75+
====================================options=====================================
76+
parsers: ["html"]
77+
printWidth: 80
78+
| printWidth
79+
=====================================input======================================
80+
<div data-a="1">
81+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
82+
</div>
83+
84+
<div data-a="1" data-b="2" data-c="3">
85+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
86+
</div>
87+
88+
<div data-a="Lorem ipsum dolor sit amet" data-b="Lorem ipsum dolor sit amet" data-c="Lorem ipsum dolor sit amet">
89+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
90+
</div>
91+
92+
<div data-long-attribute-a="1" data-long-attribute-b="2" data-long-attribute-c="3">
93+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
94+
</div>
95+
96+
<img src="/images/foo.png" />
97+
98+
<img src="/images/foo.png" alt="bar" />
99+
100+
<img src="/images/foo.png" alt="Lorem ipsum dolor sit amet, consectetur adipiscing elit." />
101+
102+
=====================================output=====================================
103+
<div data-a="1">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
104+
105+
<div data-a="1" data-b="2" data-c="3">
106+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
107+
</div>
108+
109+
<div
110+
data-a="Lorem ipsum dolor sit amet"
111+
data-b="Lorem ipsum dolor sit amet"
112+
data-c="Lorem ipsum dolor sit amet"
113+
>
114+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
115+
</div>
116+
117+
<div
118+
data-long-attribute-a="1"
119+
data-long-attribute-b="2"
120+
data-long-attribute-c="3"
121+
>
122+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
123+
</div>
124+
125+
<img src="/images/foo.png" />
126+
127+
<img src="/images/foo.png" alt="bar" />
128+
129+
<img
130+
src="/images/foo.png"
131+
alt="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
132+
/>
133+
134+
================================================================================
135+
`;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
run_spec(__dirname, ["html"]);
2+
run_spec(__dirname, ["html"], { singleAttributePerLine: true });
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<div data-a="1">
2+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
3+
</div>
4+
5+
<div data-a="1" data-b="2" data-c="3">
6+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
7+
</div>
8+
9+
<div data-a="Lorem ipsum dolor sit amet" data-b="Lorem ipsum dolor sit amet" data-c="Lorem ipsum dolor sit amet">
10+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
11+
</div>
12+
13+
<div data-long-attribute-a="1" data-long-attribute-b="2" data-long-attribute-c="3">
14+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
15+
</div>
16+
17+
<img src="/images/foo.png" />
18+
19+
<img src="/images/foo.png" alt="bar" />
20+
21+
<img src="/images/foo.png" alt="Lorem ipsum dolor sit amet, consectetur adipiscing elit." />

0 commit comments

Comments
 (0)