Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: tag var type is continuable expression #101

Merged
merged 1 commit into from
May 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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