diff --git a/.changeset/quick-comments-attrs.md b/.changeset/quick-comments-attrs.md new file mode 100644 index 00000000..4dc48d7e --- /dev/null +++ b/.changeset/quick-comments-attrs.md @@ -0,0 +1,5 @@ +--- +"htmljs-parser": minor +--- + +Support comments between concise mode line attributes. diff --git a/src/__tests__/fixtures/attr-comma-multiline-comment-trailing/__snapshots__/attr-comma-multiline-comment-trailing.expected.txt b/src/__tests__/fixtures/attr-comma-multiline-comment-trailing/__snapshots__/attr-comma-multiline-comment-trailing.expected.txt new file mode 100644 index 00000000..23a23fb0 --- /dev/null +++ b/src/__tests__/fixtures/attr-comma-multiline-comment-trailing/__snapshots__/attr-comma-multiline-comment-trailing.expected.txt @@ -0,0 +1,12 @@ +1╭─ div + ╰─ ╰─ tagName "div" +2╭─ ,foo=bar + │ │ │╰─ attrValue.value "bar" + │ │ ╰─ attrValue "=bar" + ╰─ ╰─ attrName "foo" +3╭─ // trailing comment + │ │ │ ╰─ comment.value " trailing comment" + │ │ ╰─ comment "// trailing comment" + ╰─ ╰─ openTagEnd +4╭─ + ╰─ ╰─ closeTagEnd(div) \ No newline at end of file diff --git a/src/__tests__/fixtures/attr-comma-multiline-comment-trailing/input.marko b/src/__tests__/fixtures/attr-comma-multiline-comment-trailing/input.marko new file mode 100644 index 00000000..aa26689d --- /dev/null +++ b/src/__tests__/fixtures/attr-comma-multiline-comment-trailing/input.marko @@ -0,0 +1,3 @@ +div + ,foo=bar + // trailing comment diff --git a/src/__tests__/fixtures/attr-comma-multiline-comments/__snapshots__/attr-comma-multiline-comments.expected.txt b/src/__tests__/fixtures/attr-comma-multiline-comments/__snapshots__/attr-comma-multiline-comments.expected.txt new file mode 100644 index 00000000..7b8ad8a2 --- /dev/null +++ b/src/__tests__/fixtures/attr-comma-multiline-comments/__snapshots__/attr-comma-multiline-comments.expected.txt @@ -0,0 +1,19 @@ +1╭─ div + ╰─ ╰─ tagName "div" +2╭─ ,foo=bar + │ │ │╰─ attrValue.value "bar" + │ │ ╰─ attrValue "=bar" + ╰─ ╰─ attrName "foo" +3├─ // comment +4╭─ ,bar=baz + │ │ │╰─ attrValue.value "baz" + │ │ ╰─ attrValue "=baz" + ╰─ ╰─ attrName "bar" +5├─ /* block */ +6╭─ ,qux=qux + │ │ │╰─ attrValue.value "qux" + │ │ ╰─ attrValue "=qux" + ╰─ ╰─ attrName "qux" +7╭─ + │ ├─ openTagEnd + ╰─ ╰─ closeTagEnd(div) \ No newline at end of file diff --git a/src/__tests__/fixtures/attr-comma-multiline-comments/input.marko b/src/__tests__/fixtures/attr-comma-multiline-comments/input.marko new file mode 100644 index 00000000..dadff768 --- /dev/null +++ b/src/__tests__/fixtures/attr-comma-multiline-comments/input.marko @@ -0,0 +1,6 @@ +div + ,foo=bar + // comment + ,bar=baz + /* block */ + ,qux=qux diff --git a/src/states/OPEN_TAG.ts b/src/states/OPEN_TAG.ts index 70084621..6ed7d261 100644 --- a/src/states/OPEN_TAG.ts +++ b/src/states/OPEN_TAG.ts @@ -1,5 +1,6 @@ import { isIndentCode, + isLineCode, isWhitespaceCode, matchesCloseAngleBracket, matchesCloseParen, @@ -105,13 +106,40 @@ export const OPEN_TAG: StateDefinition = { : 1; if (this.isConcise && tag.stage !== TAG_STAGE.ATTR_GROUP) { - if (this.consumeWhitespaceIfBefore(",")) { - this.pos++; // skip , + let cur = this.pos; + while (cur < maxPos) { + const peek = data.charCodeAt(cur); + if (isWhitespaceCode(peek)) { + cur++; + } else if ( + peek === CODE.FORWARD_SLASH && + data.charCodeAt(cur + 1) === CODE.FORWARD_SLASH + ) { + // line comment + cur += 2; + while (cur < maxPos && !isLineCode(data.charCodeAt(cur))) cur++; + } else if ( + peek === CODE.FORWARD_SLASH && + data.charCodeAt(cur + 1) === CODE.ASTERISK + ) { + // block comment + const end = data.indexOf("*/", cur + 2); + if (end === -1) break; + cur = end + 2; + } else { + break; + } + } + + // comma continues the open tag with another line attribute + if (data.charCodeAt(cur) === CODE.COMMA) { + this.pos = cur + 1; this.consumeWhitespace(); continue; } + this.exitState(); - return; // parent handles newline + return; } this.pos += len;