Skip to content

Commit 6b5b196

Browse files
committed
feat: improve handling of comas, especially for concise mode
1 parent 61e6966 commit 6b5b196

File tree

7 files changed

+171
-2
lines changed

7 files changed

+171
-2
lines changed

.changeset/four-boxes-brush.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"htmljs-parser": minor
3+
---
4+
5+
In concise mode, a new line which starts with a coma will now continue attributes for the current tag.

.changeset/nice-cats-relate.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"htmljs-parser": minor
3+
---
4+
5+
Allow a comma to follow the tag name to begin attributes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
1╭─ div, class="a", id="c"
2+
│ │ │ ││ │ │╰─ attrValue.value "\"c\""
3+
│ │ │ ││ │ ╰─ attrValue "=\"c\""
4+
│ │ │ ││ ╰─ attrName "id"
5+
│ │ │ │╰─ attrValue.value "\"a\""
6+
│ │ │ ╰─ attrValue "=\"a\""
7+
│ │ ╰─ attrName "class"
8+
╰─ ╰─ tagName "div"
9+
2╭─
10+
╰─ ╰─ openTagEnd
11+
3╭─ div,
12+
│ ├─ closeTagEnd(div)
13+
╰─ ╰─ tagName "div"
14+
4╭─ class="a",
15+
│ │ │╰─ attrValue.value "\"a\""
16+
│ │ ╰─ attrValue "=\"a\""
17+
╰─ ╰─ attrName "class"
18+
5╭─ id="c"
19+
│ │ │╰─ attrValue.value "\"c\""
20+
│ │ ╰─ attrValue "=\"c\""
21+
╰─ ╰─ attrName "id"
22+
6╭─
23+
╰─ ╰─ openTagEnd
24+
7╭─ div , class="a", id="c"
25+
│ │ │ ││ │ │╰─ attrValue.value "\"c\""
26+
│ │ │ ││ │ ╰─ attrValue "=\"c\""
27+
│ │ │ ││ ╰─ attrName "id"
28+
│ │ │ │╰─ attrValue.value "\"a\""
29+
│ │ │ ╰─ attrValue "=\"a\""
30+
│ │ ╰─ attrName "class"
31+
│ ├─ closeTagEnd(div)
32+
╰─ ╰─ tagName "div"
33+
8╭─
34+
╰─ ╰─ openTagEnd
35+
9╭─ div ,
36+
│ ├─ closeTagEnd(div)
37+
╰─ ╰─ tagName "div"
38+
10╭─ class="a",
39+
│ │ │╰─ attrValue.value "\"a\""
40+
│ │ ╰─ attrValue "=\"a\""
41+
╰─ ╰─ attrName "class"
42+
11╭─ id="c"
43+
│ │ │╰─ attrValue.value "\"c\""
44+
│ │ ╰─ attrValue "=\"c\""
45+
╰─ ╰─ attrName "id"
46+
12╭─
47+
╰─ ╰─ openTagEnd
48+
13╭─ div
49+
│ ├─ closeTagEnd(div)
50+
╰─ ╰─ tagName "div"
51+
14╭─ ,class="a"
52+
│ │ │╰─ attrValue.value "\"a\""
53+
│ │ ╰─ attrValue "=\"a\""
54+
╰─ ╰─ attrName "class"
55+
15╭─ ,id="c"
56+
│ │ │╰─ attrValue.value "\"c\""
57+
│ │ ╰─ attrValue "=\"c\""
58+
╰─ ╰─ attrName "id"
59+
16╭─
60+
╰─ ╰─ openTagEnd
61+
17╭─ <div, class="a", id="c"/>
62+
│ ││ │ ││ │ ││ ╰─ openTagEnd:selfClosed "/>"
63+
│ ││ │ ││ │ │╰─ attrValue.value "\"c\""
64+
│ ││ │ ││ │ ╰─ attrValue "=\"c\""
65+
│ ││ │ ││ ╰─ attrName "id"
66+
│ ││ │ │╰─ attrValue.value "\"a\""
67+
│ ││ │ ╰─ attrValue "=\"a\""
68+
│ ││ ╰─ attrName "class"
69+
│ │╰─ tagName "div"
70+
│ ├─ closeTagEnd(div)
71+
╰─ ╰─ openTagStart
72+
18├─
73+
19╭─ <div,
74+
│ │╰─ tagName "div"
75+
╰─ ╰─ openTagStart
76+
20╭─ class="a",
77+
│ │ │╰─ attrValue.value "\"a\""
78+
│ │ ╰─ attrValue "=\"a\""
79+
╰─ ╰─ attrName "class"
80+
21╭─ id="c"/>
81+
│ │ ││ ╰─ openTagEnd:selfClosed "/>"
82+
│ │ │╰─ attrValue.value "\"c\""
83+
│ │ ╰─ attrValue "=\"c\""
84+
╰─ ╰─ attrName "id"
85+
22├─
86+
23╭─ <div , class="a", id="c"/>
87+
│ ││ │ ││ │ ││ ╰─ openTagEnd:selfClosed "/>"
88+
│ ││ │ ││ │ │╰─ attrValue.value "\"c\""
89+
│ ││ │ ││ │ ╰─ attrValue "=\"c\""
90+
│ ││ │ ││ ╰─ attrName "id"
91+
│ ││ │ │╰─ attrValue.value "\"a\""
92+
│ ││ │ ╰─ attrValue "=\"a\""
93+
│ ││ ╰─ attrName "class"
94+
│ │╰─ tagName "div"
95+
╰─ ╰─ openTagStart
96+
24├─
97+
25╭─ <div ,
98+
│ │╰─ tagName "div"
99+
╰─ ╰─ openTagStart
100+
26╭─ class="a",
101+
│ │ │╰─ attrValue.value "\"a\""
102+
│ │ ╰─ attrValue "=\"a\""
103+
╰─ ╰─ attrName "class"
104+
27╭─ id="c"/>
105+
│ │ ││ ╰─ openTagEnd:selfClosed "/>"
106+
│ │ │╰─ attrValue.value "\"c\""
107+
│ │ ╰─ attrValue "=\"c\""
108+
╰─ ╰─ attrName "id"
109+
28├─
110+
29╭─ <div
111+
│ │╰─ tagName "div"
112+
╰─ ╰─ openTagStart
113+
30╭─ ,class="a"
114+
│ │ │╰─ attrValue.value "\"a\""
115+
│ │ ╰─ attrValue "=\"a\""
116+
╰─ ╰─ attrName "class"
117+
31╭─ ,id="c"/>
118+
│ │ ││ ╰─ openTagEnd:selfClosed "/>"
119+
│ │ │╰─ attrValue.value "\"c\""
120+
│ │ ╰─ attrValue "=\"c\""
121+
╰─ ╰─ attrName "id"
122+
32╰─
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
div, class="a", id="c"
2+
3+
div,
4+
class="a",
5+
id="c"
6+
7+
div , class="a", id="c"
8+
9+
div ,
10+
class="a",
11+
id="c"
12+
13+
div
14+
,class="a"
15+
,id="c"
16+
17+
<div, class="a", id="c"/>
18+
19+
<div,
20+
class="a",
21+
id="c"/>
22+
23+
<div , class="a", id="c"/>
24+
25+
<div ,
26+
class="a",
27+
id="c"/>
28+
29+
<div
30+
,class="a"
31+
,id="c"/>

src/core/Parser.ts

+1
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ export class Parser {
213213

214214
if (this.lookAheadFor(str, cur)) {
215215
this.pos = cur;
216+
if (this.forward > 1) this.forward = 1;
216217
return true;
217218
}
218219

src/states/OPEN_TAG.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,12 @@ export const OPEN_TAG: StateDefinition<OpenTagMeta> = {
9999
},
100100

101101
eol(_, tag) {
102-
if (this.isConcise && tag.stage !== TAG_STAGE.ATTR_GROUP) {
103-
// In concise mode we always end the open tag
102+
if (
103+
this.isConcise &&
104+
tag.stage !== TAG_STAGE.ATTR_GROUP &&
105+
!this.consumeWhitespaceIfBefore(",")
106+
) {
107+
// In concise mode we always end the open tag unless we're in an attr group or the next line starts with ",".
104108
this.exitState();
105109
}
106110
},

src/states/TAG_NAME.ts

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ export const TAG_NAME: StateDefinition<TagNameMeta> = {
124124
code === CODE.FORWARD_SLASH ||
125125
code === CODE.PIPE ||
126126
code === CODE.OPEN_ANGLE_BRACKET ||
127+
code === CODE.COMMA ||
127128
(this.isConcise
128129
? code === CODE.SEMICOLON
129130
: code === CODE.CLOSE_ANGLE_BRACKET)

0 commit comments

Comments
 (0)