diff --git a/packages/analyzer/src/standard/transpile.ts b/packages/analyzer/src/standard/transpile.ts index 1bc8450..97ba874 100644 --- a/packages/analyzer/src/standard/transpile.ts +++ b/packages/analyzer/src/standard/transpile.ts @@ -34,7 +34,9 @@ export function transpile(document: Document) { document.visit( (node) => { - render(node.binding); + for (const binding of node.bindings) { + render(binding); + } }, { filter: KoVirtualElement }, ); diff --git a/packages/location/src/index.ts b/packages/location/src/index.ts index c9b991e..46cc214 100644 --- a/packages/location/src/index.ts +++ b/packages/location/src/index.ts @@ -1,3 +1,3 @@ -export { default as Position } from "./position.js"; -export { default as Range } from "./range.js"; +export { default as Position, type RawPosition } from "./position.js"; +export { default as Range, type RawRange } from "./range.js"; export * from "./utils.js"; diff --git a/packages/parser/src/__snapshots__/parser.test.ts.snap b/packages/parser/src/__snapshots__/parser.test.ts.snap index fb969a1..9a292c5 100644 --- a/packages/parser/src/__snapshots__/parser.test.ts.snap +++ b/packages/parser/src/__snapshots__/parser.test.ts.snap @@ -2,6 +2,251 @@ exports[`parser Deep virtual elements 1`] = ` { + "children": [ + { + "bindings": [ + { + "end": { + "column": 16, + "line": 0, + "offset": 16, + }, + "incomplete": false, + "name": { + "end": { + "column": 11, + "line": 0, + "offset": 11, + }, + "start": { + "column": 8, + "line": 0, + "offset": 8, + }, + "value": "foo", + }, + "param": { + "end": { + "column": 16, + "line": 0, + "offset": 16, + }, + "start": { + "column": 13, + "line": 0, + "offset": 13, + }, + "value": "foo", + }, + "start": { + "column": 8, + "line": 0, + "offset": 8, + }, + }, + ], + "children": [ + { + "bindings": [ + { + "end": { + "column": 36, + "line": 0, + "offset": 36, + }, + "incomplete": false, + "name": { + "end": { + "column": 31, + "line": 0, + "offset": 31, + }, + "start": { + "column": 28, + "line": 0, + "offset": 28, + }, + "value": "bar", + }, + "param": { + "end": { + "column": 36, + "line": 0, + "offset": 36, + }, + "start": { + "column": 33, + "line": 0, + "offset": 33, + }, + "value": "bar", + }, + "start": { + "column": 28, + "line": 0, + "offset": 28, + }, + }, + ], + "children": [], + "end": { + "column": 52, + "line": 0, + "offset": 52, + }, + "endComment": { + "content": " /ko ", + "end": { + "column": 52, + "line": 0, + "offset": 52, + }, + "start": { + "column": 40, + "line": 0, + "offset": 40, + }, + "type": "comment", + }, + "expression": { + "end": { + "column": 36, + "line": 0, + "offset": 36, + }, + "start": { + "column": 28, + "line": 0, + "offset": 28, + }, + "value": "bar: bar", + }, + "inner": { + "end": { + "column": 40, + "line": 0, + "offset": 40, + }, + "start": { + "column": 40, + "line": 0, + "offset": 40, + }, + }, + "namespace": { + "end": { + "column": 27, + "line": 0, + "offset": 27, + }, + "start": { + "column": 25, + "line": 0, + "offset": 25, + }, + "value": "ko", + }, + "start": { + "column": 20, + "line": 0, + "offset": 20, + }, + "startComment": { + "content": " ko bar: bar ", + "end": { + "column": 40, + "line": 0, + "offset": 40, + }, + "start": { + "column": 20, + "line": 0, + "offset": 20, + }, + "type": "comment", + }, + "type": "virtual-element", + }, + ], + "end": { + "column": 64, + "line": 0, + "offset": 64, + }, + "endComment": { + "content": " /ko ", + "end": { + "column": 64, + "line": 0, + "offset": 64, + }, + "start": { + "column": 52, + "line": 0, + "offset": 52, + }, + "type": "comment", + }, + "expression": { + "end": { + "column": 16, + "line": 0, + "offset": 16, + }, + "start": { + "column": 8, + "line": 0, + "offset": 8, + }, + "value": "foo: foo", + }, + "inner": { + "end": { + "column": 52, + "line": 0, + "offset": 52, + }, + "start": { + "column": 20, + "line": 0, + "offset": 20, + }, + }, + "namespace": { + "end": { + "column": 7, + "line": 0, + "offset": 7, + }, + "start": { + "column": 5, + "line": 0, + "offset": 5, + }, + "value": "ko", + }, + "start": { + "column": 0, + "line": 0, + "offset": 0, + }, + "startComment": { + "content": " ko foo: foo ", + "end": { + "column": 20, + "line": 0, + "offset": 20, + }, + "start": { + "column": 0, + "line": 0, + "offset": 0, + }, + "type": "comment", + }, + "type": "virtual-element", + }, + ], "end": { "column": 64, "line": 0, @@ -17,6 +262,143 @@ exports[`parser Deep virtual elements 1`] = ` exports[`parser Element bindings 1`] = ` { + "children": [ + { + "attributes": [ + { + "end": { + "column": 23, + "line": 0, + "offset": 23, + }, + "name": { + "end": { + "column": 14, + "line": 0, + "offset": 14, + }, + "start": { + "column": 5, + "line": 0, + "offset": 5, + }, + "value": "data-bind", + }, + "namespace": null, + "prefix": null, + "start": { + "column": 5, + "line": 0, + "offset": 5, + }, + "value": { + "end": { + "column": 23, + "line": 0, + "offset": 23, + }, + "inner": { + "end": { + "column": 22, + "line": 0, + "offset": 22, + }, + "start": { + "column": 16, + "line": 0, + "offset": 16, + }, + }, + "quote": "'", + "start": { + "column": 15, + "line": 0, + "offset": 15, + }, + "value": "0: bar", + }, + }, + ], + "bindings": [ + { + "end": { + "column": 22, + "line": 0, + "offset": 22, + }, + "incomplete": false, + "name": { + "end": { + "column": 17, + "line": 0, + "offset": 17, + }, + "start": { + "column": 16, + "line": 0, + "offset": 16, + }, + "value": "0", + }, + "param": { + "end": { + "column": 22, + "line": 0, + "offset": 22, + }, + "start": { + "column": 19, + "line": 0, + "offset": 19, + }, + "value": "bar", + }, + "start": { + "column": 16, + "line": 0, + "offset": 16, + }, + }, + ], + "children": [], + "end": { + "column": 30, + "line": 0, + "offset": 30, + }, + "inner": { + "end": { + "column": 24, + "line": 0, + "offset": 24, + }, + "start": { + "column": 24, + "line": 0, + "offset": 24, + }, + }, + "start": { + "column": 0, + "line": 0, + "offset": 0, + }, + "tagName": { + "end": { + "column": 4, + "line": 0, + "offset": 4, + }, + "start": { + "column": 1, + "line": 0, + "offset": 1, + }, + "value": "div", + }, + "type": "element", + }, + ], "end": { "column": 30, "line": 0, @@ -29,3 +411,180 @@ exports[`parser Element bindings 1`] = ` }, } `; + +exports[`parser Multiple bindings on same virtual element 1`] = ` +{ + "children": [ + { + "bindings": [ + { + "end": { + "column": 17, + "line": 0, + "offset": 17, + }, + "incomplete": false, + "name": { + "end": { + "column": 12, + "line": 0, + "offset": 12, + }, + "start": { + "column": 8, + "line": 0, + "offset": 8, + }, + "value": "with", + }, + "param": { + "end": { + "column": 17, + "line": 0, + "offset": 17, + }, + "start": { + "column": 14, + "line": 0, + "offset": 14, + }, + "value": "foo", + }, + "start": { + "column": 8, + "line": 0, + "offset": 8, + }, + }, + { + "end": { + "column": 28, + "line": 0, + "offset": 28, + }, + "incomplete": false, + "name": { + "end": { + "column": 21, + "line": 0, + "offset": 21, + }, + "start": { + "column": 19, + "line": 0, + "offset": 19, + }, + "value": "as", + }, + "param": { + "end": { + "column": 28, + "line": 0, + "offset": 28, + }, + "start": { + "column": 23, + "line": 0, + "offset": 23, + }, + "value": "'bar'", + }, + "start": { + "column": 19, + "line": 0, + "offset": 19, + }, + }, + ], + "children": [], + "end": { + "column": 44, + "line": 0, + "offset": 44, + }, + "endComment": { + "content": " /ko ", + "end": { + "column": 44, + "line": 0, + "offset": 44, + }, + "start": { + "column": 32, + "line": 0, + "offset": 32, + }, + "type": "comment", + }, + "expression": { + "end": { + "column": 28, + "line": 0, + "offset": 28, + }, + "start": { + "column": 8, + "line": 0, + "offset": 8, + }, + "value": "with: foo, as: 'bar'", + }, + "inner": { + "end": { + "column": 32, + "line": 0, + "offset": 32, + }, + "start": { + "column": 32, + "line": 0, + "offset": 32, + }, + }, + "namespace": { + "end": { + "column": 7, + "line": 0, + "offset": 7, + }, + "start": { + "column": 5, + "line": 0, + "offset": 5, + }, + "value": "ko", + }, + "start": { + "column": 0, + "line": 0, + "offset": 0, + }, + "startComment": { + "content": " ko with: foo, as: 'bar' ", + "end": { + "column": 32, + "line": 0, + "offset": 32, + }, + "start": { + "column": 0, + "line": 0, + "offset": 0, + }, + "type": "comment", + }, + "type": "virtual-element", + }, + ], + "end": { + "column": 44, + "line": 0, + "offset": 44, + }, + "start": { + "column": 0, + "line": 0, + "offset": 0, + }, +} +`; diff --git a/packages/parser/src/parser.test.ts b/packages/parser/src/parser.test.ts index 9914b02..ce39059 100644 --- a/packages/parser/src/parser.test.ts +++ b/packages/parser/src/parser.test.ts @@ -22,4 +22,9 @@ describe("parser", () => { test("Import statement with *", () => { parse(""); }); + + test("Multiple bindings on same virtual element", () => { + const { document } = parse(""); + expect(document).toMatchSnapshot(); + }); }); diff --git a/packages/parser/src/parser.ts b/packages/parser/src/parser.ts index b545ea7..130bbe5 100644 --- a/packages/parser/src/parser.ts +++ b/packages/parser/src/parser.ts @@ -24,7 +24,7 @@ import { Identifier, Expression, KoVirtualElement, - WithVirtualElement, + OkVirtualElement, ImportStatement, StringLiteral, } from "@knuckles/syntax-tree"; @@ -32,7 +32,7 @@ import * as acorn from "acorn"; import * as acornLoose from "acorn-loose"; export const VIRTUAL_ELEMENT_START_REGEX = // - /^(\s*)(ko|ok)(\s+)([^\s]+)(\s*:\s*)([^]*?)\s*$/; + /^(\s*)(ko|ok)(\s+)([^]*?)\s*$/; export interface ParserOptions { bindingAttributes?: readonly string[]; @@ -142,14 +142,12 @@ export default class Parser { node: p5t.CommentNode, iter: Iterator, ): VirtualElement { - const [padding1, nsText, padding2, nameText, padding3, paramText] = + const [padding1, nsText, padding3, expressionText] = VIRTUAL_ELEMENT_START_REGEX.exec(node.data)!.slice(1) as [ string, string, string, string, - string, - string, ]; const startComment = new Comment({ @@ -185,8 +183,7 @@ export default class Parser { const dataOffset = node.sourceCodeLocation!.startOffset + "