Skip to content

Commit

Permalink
feat: tag var type is continuable expression
Browse files Browse the repository at this point in the history
  • Loading branch information
DylanPiercey committed May 4, 2022
1 parent 01ed0a4 commit 9034f55
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 25 deletions.
5 changes: 5 additions & 0 deletions .changeset/fluffy-emus-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"htmljs-parser": patch
---

Parse tag variable type as an continuable expression.
Original file line number Diff line number Diff line change
Expand Up @@ -33,51 +33,81 @@
│ │ ╰─ tagVar "/foo"
╰─ ╰─ tagName "let"
7╭─ <let/foo + 1/>
│ │ ││ │ │╰─ openTagEnd:selfClosed "/>"
│ │ ││ │ ╰─ attrName
│ │ ││ ╰─ attrName
│ │ │╰─ tagVar.value "foo"
│ │ ╰─ tagVar "/foo"
│ │ ││ ╰─ openTagEnd:selfClosed "/>"
│ │ │╰─ tagVar.value "foo + 1"
│ │ ╰─ tagVar "/foo + 1"
╰─ ╰─ tagName "let"
8╭─ <let/{ x, y }/>
│ │ ││ ╰─ openTagEnd:selfClosed "/>"
│ │ │╰─ tagVar.value "{ x, y }"
│ │ ╰─ tagVar "/{ x, y }"
8╭─ <let/foo:string/>
│ │ ││ ╰─ openTagEnd:selfClosed "/>"
│ │ │╰─ tagVar.value "foo:string"
│ │ ╰─ tagVar "/foo:string"
╰─ ╰─ tagName "let"
9├─
10╭─ <button/loginButton>
9╭─ <let/foo : string/>
│ │ ││ ╰─ openTagEnd:selfClosed "/>"
│ │ │╰─ tagVar.value "foo : string"
│ │ ╰─ tagVar "/foo : string"
╰─ ╰─ tagName "let"
10╭─ <let/foo: typeof bar extends y ? a : b x=2/>
│ │ ││ │││╰─ openTagEnd:selfClosed "/>"
│ │ ││ ││╰─ attrValue.value
│ │ ││ │╰─ attrValue "=2"
│ │ ││ ╰─ attrName
│ │ │╰─ tagVar.value "foo: typeof bar extends y ? a : b"
│ │ ╰─ tagVar "/foo: typeof bar extends y ? a : b"
╰─ ╰─ tagName "let"
11╭─ <let/{ x, y }/>
│ │ ││ ╰─ openTagEnd:selfClosed "/>"
│ │ │╰─ tagVar.value "{ x, y }"
│ │ ╰─ tagVar "/{ x, y }"
╰─ ╰─ tagName "let"
12├─
13╭─ <const/fn:any() {
│ │ ││ ││ ╰─ attrMethod.body "{\n console.log(\"hi\");\n}"
│ │ ││ │╰─ attrMethod.params.value
│ │ ││ ├─ attrMethod.params "()"
│ │ ││ ├─ attrMethod "() {\n console.log(\"hi\");\n}"
│ │ ││ ╰─ attrName
│ │ │╰─ tagVar.value "fn:any"
│ │ ╰─ tagVar "/fn:any"
╰─ ╰─ tagName "const"
14╭─ console.log("hi");
╰─ ╰─ attrMethod.body.value "\n console.log(\"hi\");\n"
15╭─ }/>
╰─ ╰─ openTagEnd:selfClosed "/>"
16├─
17╭─ <button/loginButton>
│ │ ││ ╰─ openTagEnd
│ │ │╰─ tagVar.value "loginButton"
│ │ ╰─ tagVar "/loginButton"
╰─ ╰─ tagName "button"
11╭─ login
18╭─ login
╰─ ╰─ text "\n login\n"
12╭─ </>
19╭─ </>
│ │ ╰─ closeTag(button).value
╰─ ╰─ closeTag(button) "</>"
13╭─ <button/loginButton >
20╭─ <button/loginButton >
│ │ ││ ╰─ openTagEnd
│ │ │╰─ tagVar.value "loginButton"
│ │ ╰─ tagVar "/loginButton"
╰─ ╰─ tagName "button"
14╭─ login
21╭─ login
╰─ ╰─ text "\n login\n"
15╭─ </>
22╭─ </>
│ │ ╰─ closeTag(button).value
╰─ ╰─ closeTag(button) "</>"
16├─
17╭─ <div/ref/>
23├─
24╭─ <div/ref/>
│ │ ││ ╰─ openTagEnd:selfClosed "/>"
│ │ │╰─ tagVar.value "ref"
│ │ ╰─ tagVar "/ref"
╰─ ╰─ tagName "div"
18╭─ <div/ref />
25╭─ <div/ref />
│ │ ││ ╰─ openTagEnd:selfClosed "/>"
│ │ │╰─ tagVar.value "ref"
│ │ ╰─ tagVar "/ref"
╰─ ╰─ tagName "div"
19├─
20╭─ <div#ab.cd/ref/>
26├─
27╭─ <div#ab.cd/ref/>
│ │ ││ ││ ││ ╰─ openTagEnd:selfClosed "/>"
│ │ ││ ││ │╰─ tagVar.value "ref"
│ │ ││ ││ ╰─ tagVar "/ref"
Expand All @@ -86,4 +116,4 @@
│ │ │╰─ tagShorthandId.quasis[0] "ab"
│ │ ╰─ tagShorthandId "#ab"
╰─ ╰─ tagName "div"
21╰─
28╰─
7 changes: 7 additions & 0 deletions src/__tests__/fixtures/tag-var-declaration/input.marko
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,15 @@
<let/foo=1/>
<let/foo = 1/>
<let/foo + 1/>
<let/foo:string/>
<let/foo : string/>
<let/foo: typeof bar extends y ? a : b x=2/>
<let/{ x, y }/>

<const/fn:any() {
console.log("hi");
}/>

<button/loginButton>
login
</>
Expand Down
5 changes: 3 additions & 2 deletions src/states/EXPRESSION.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,9 @@ export const EXPRESSION: StateDefinition<ExpressionMeta> = {

function buildOperatorPattern(isConcise: boolean) {
const binary =
"(?:[!~*%&^|?:<]+=*)+" + // Any of these characters can always continue an expression
"|[>/+-=]+=|=>" + // Match equality and multi char assignment operators w/o matching equals by itself
"(?:[!~*%&^|?<]+=*)+" + // Any of these characters can always continue an expression
"|:+(?!=)" + // Match a colon without matching a bound attribute
"|[>/+=-]+=|=>" + // Match equality and multi char assignment operators w/o matching equals by itself
"|(?<!\\+)[ \\t]*\\+(?:[ \\t]*\\+[ \\t]*\\+)*[ \\t]*(?!\\+)" + // We only match an odd number of plus's
`|(?<!-)-${isConcise ? "" : "(?:[ \\t]*-[ \\t]*-)*[ \\t]*"}(?!-)` + // In concise mode we can't match multiple hyphens otherwise we can match an even number of hyphens
`|(?<![/*])/(?![/*${isConcise ? "" : ">"}])` + // We only continue after a forward slash if it isn't //, /* (or /> in html mode)
Expand Down
10 changes: 9 additions & 1 deletion src/states/OPEN_TAG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,16 @@ export const OPEN_TAG: StateDefinition<OpenTagMeta> = {
} else if (code === CODE.FORWARD_SLASH && !tag.hasAttrs) {
tag.stage = TAG_STAGE.VAR;
this.pos++; // skip /

if (isWhitespaceCode(this.lookAtCharCodeAhead(0))) {
return this.emitError(
this.pos,
ErrorCode.MISSING_TAG_VARIABLE,
"A slash was found that was not followed by a variable name or lhs expression"
);
}

const expr = this.enterState(STATE.EXPRESSION);
expr.skipOperators = true;
expr.terminatedByWhitespace = true;
expr.terminator = this.isConcise
? CONCISE_TAG_VAR_TERMINATORS
Expand Down

0 comments on commit 9034f55

Please sign in to comment.