Skip to content

Commit 61e6966

Browse files
committed
fix: avoid expr continuations for period when not followed by identifier
1 parent 33d280d commit 61e6966

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

.changeset/bright-clouds-yawn.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"htmljs-parser": patch
3+
---
4+
5+
Avoid continuing expressions after a period if after the whitespace is something that could not be an identifier.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
1╭─ $ $global.
2+
│ │╰─ scriptlet.value "$global."
3+
╰─ ╰─ scriptlet " $global."
4+
2├─
5+
3╭─ <header>
6+
│ ││ ╰─ openTagEnd
7+
│ │╰─ tagName "header"
8+
╰─ ╰─ openTagStart
9+
4╭─ <img.logo src=logo alt="Marko"/>
10+
│ │ ││ ││ │ ││ │ ││ ╰─ openTagEnd:selfClosed "/>"
11+
│ │ ││ ││ │ ││ │ │╰─ attrValue.value "\"Marko\""
12+
│ │ ││ ││ │ ││ │ ╰─ attrValue "=\"Marko\""
13+
│ │ ││ ││ │ ││ ╰─ attrName "alt"
14+
│ │ ││ ││ │ │╰─ attrValue.value "logo"
15+
│ │ ││ ││ │ ╰─ attrValue "=logo"
16+
│ │ ││ ││ ╰─ attrName "src"
17+
│ │ ││ │╰─ tagShorthandClass.quasis[0] "logo"
18+
│ │ ││ ╰─ tagShorthandClass ".logo"
19+
│ │ │╰─ tagName "img"
20+
│ │ ╰─ openTagStart
21+
╰─ ╰─ text "\n "
22+
5╭─ </header>
23+
│ │ │ ╰─ closeTagEnd(header)
24+
│ │ ╰─ closeTagName "header"
25+
│ ├─ text "\n"
26+
╰─ ╰─ closeTagStart "</"
27+
6╰─
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
$ $global.
2+
3+
<header>
4+
<img.logo src=logo alt="Marko"/>
5+
</header>

src/states/EXPRESSION.ts

+12-4
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,17 @@ function lookBehindForOperator(data: string, pos: number): number {
266266
case CODE.OPEN_ANGLE_BRACKET:
267267
case CODE.CLOSE_ANGLE_BRACKET:
268268
case CODE.PERCENT:
269-
case CODE.PERIOD:
270269
case CODE.PIPE:
271270
case CODE.QUESTION:
272271
case CODE.TILDE:
273272
return curPos;
274273

274+
case CODE.PERIOD: {
275+
// Only matches `.` followed by something that could be an identifier.
276+
const nextPos = lookAheadWhile(isWhitespaceCode, data, pos);
277+
return isWordCode(data.charCodeAt(nextPos)) ? nextPos : -1;
278+
}
279+
275280
// special case -- and ++
276281
case CODE.PLUS:
277282
case CODE.HYPHEN: {
@@ -324,9 +329,11 @@ function lookAheadForOperator(data: string, pos: number): number {
324329
case CODE.OPEN_PAREN:
325330
return pos; // defers to base expression state to track block groups.
326331

327-
case CODE.PERIOD:
328-
// Only match a dot if its not ...
329-
return data.charCodeAt(pos + 1) === CODE.PERIOD ? -1 : pos + 1;
332+
case CODE.PERIOD: {
333+
// Only matches `.` followed by something that could be an identifier.
334+
const nextPos = lookAheadWhile(isWhitespaceCode, data, pos + 1);
335+
return isWordCode(data.charCodeAt(nextPos)) ? nextPos : -1;
336+
}
330337

331338
default: {
332339
for (const keyword of binaryKeywords) {
@@ -383,6 +390,7 @@ function isWordCode(code: number) {
383390
(code >= CODE.UPPER_A && code <= CODE.UPPER_Z) ||
384391
(code >= CODE.LOWER_A && code <= CODE.LOWER_Z) ||
385392
(code >= CODE.NUMBER_0 && code <= CODE.NUMBER_9) ||
393+
code == CODE.DOLLAR ||
386394
code === CODE.UNDERSCORE
387395
);
388396
}

0 commit comments

Comments
 (0)