@canvasengine/compiler 2.0.0-beta.11 → 2.0.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/grammar.pegjs +44 -8
- package/package.json +1 -1
- package/tests/compiler.spec.ts +12 -0
package/grammar.pegjs
CHANGED
|
@@ -5,6 +5,34 @@
|
|
|
5
5
|
`at line ${start.line}, column ${start.column} to line ${end.line}, column ${end.column}`;
|
|
6
6
|
throw new Error(errorMessage);
|
|
7
7
|
}
|
|
8
|
+
|
|
9
|
+
function formatAttributes(attributes) {
|
|
10
|
+
if (attributes.length === 0) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Check if there's exactly one attribute and it's a spread attribute
|
|
15
|
+
if (attributes.length === 1 && attributes[0].startsWith('...')) {
|
|
16
|
+
// Return the identifier directly, removing the '...'
|
|
17
|
+
return attributes[0].substring(3);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Otherwise, format as an object literal
|
|
21
|
+
const formattedAttrs = attributes.map(attr => {
|
|
22
|
+
// If it's a spread attribute, keep it as is
|
|
23
|
+
if (attr.startsWith('...')) {
|
|
24
|
+
return attr;
|
|
25
|
+
}
|
|
26
|
+
// If it's a standalone attribute (doesn't contain ':'), format as shorthand property 'name'
|
|
27
|
+
if (!attr.includes(':')) {
|
|
28
|
+
return attr; // JS object literal shorthand
|
|
29
|
+
}
|
|
30
|
+
// Otherwise (key: value), keep it as is
|
|
31
|
+
return attr;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return `{ ${formattedAttrs.join(', ')} }`;
|
|
35
|
+
}
|
|
8
36
|
}
|
|
9
37
|
|
|
10
38
|
start
|
|
@@ -24,8 +52,8 @@ element
|
|
|
24
52
|
|
|
25
53
|
selfClosingElement
|
|
26
54
|
= _ "<" _ tagName:tagName _ attributes:attributes _ "/>" _ {
|
|
27
|
-
const
|
|
28
|
-
return
|
|
55
|
+
const attrsString = formatAttributes(attributes);
|
|
56
|
+
return attrsString ? `h(${tagName}, ${attrsString})` : `h(${tagName})`;
|
|
29
57
|
}
|
|
30
58
|
|
|
31
59
|
openCloseElement
|
|
@@ -33,12 +61,12 @@ openCloseElement
|
|
|
33
61
|
if (tagName !== closingTagName) {
|
|
34
62
|
error("Mismatched opening and closing tags");
|
|
35
63
|
}
|
|
36
|
-
const
|
|
64
|
+
const attrsString = formatAttributes(attributes);
|
|
37
65
|
const children = content ? content : null;
|
|
38
|
-
if (
|
|
39
|
-
return `h(${tagName}, ${
|
|
40
|
-
} else if (
|
|
41
|
-
return `h(${tagName}, ${
|
|
66
|
+
if (attrsString && children) {
|
|
67
|
+
return `h(${tagName}, ${attrsString}, ${children})`;
|
|
68
|
+
} else if (attrsString) {
|
|
69
|
+
return `h(${tagName}, ${attrsString})`;
|
|
42
70
|
} else if (children) {
|
|
43
71
|
return `h(${tagName}, null, ${children})`;
|
|
44
72
|
} else {
|
|
@@ -61,6 +89,12 @@ attribute
|
|
|
61
89
|
= staticAttribute
|
|
62
90
|
/ dynamicAttribute
|
|
63
91
|
/ eventHandler
|
|
92
|
+
/ spreadAttribute
|
|
93
|
+
|
|
94
|
+
spreadAttribute
|
|
95
|
+
= "..." objectName:identifier {
|
|
96
|
+
return "..." + objectName;
|
|
97
|
+
}
|
|
64
98
|
|
|
65
99
|
eventHandler
|
|
66
100
|
= "@" eventName:identifier _ "=" _ "{" _ handlerName:attributeValue _ "}" {
|
|
@@ -177,7 +211,9 @@ ifCondition
|
|
|
177
211
|
}
|
|
178
212
|
|
|
179
213
|
tagName
|
|
180
|
-
= [a-zA-Z][a-zA-Z0-9]*
|
|
214
|
+
= segments:([a-zA-Z][a-zA-Z0-9]* ("." [a-zA-Z][a-zA-Z0-9]*)*) {
|
|
215
|
+
return text();
|
|
216
|
+
}
|
|
181
217
|
|
|
182
218
|
attributeName
|
|
183
219
|
= [a-zA-Z][a-zA-Z0-9-]* { return text(); }
|
package/package.json
CHANGED
package/tests/compiler.spec.ts
CHANGED
|
@@ -51,12 +51,24 @@ describe("Compiler", () => {
|
|
|
51
51
|
expect(output).toBe(`h(Canvas)`);
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
test("should compile component with dot notation", () => {
|
|
55
|
+
const input = `<MyComp.test />`;
|
|
56
|
+
const output = parser.parse(input);
|
|
57
|
+
expect(output).toBe(`h(MyComp.test)`);
|
|
58
|
+
});
|
|
59
|
+
|
|
54
60
|
test("should compile component with dynamic attribute", () => {
|
|
55
61
|
const input = `<Canvas width={x} />`;
|
|
56
62
|
const output = parser.parse(input);
|
|
57
63
|
expect(output).toBe(`h(Canvas, { width: x })`);
|
|
58
64
|
});
|
|
59
65
|
|
|
66
|
+
test("should compile component with spread operator", () => {
|
|
67
|
+
const input = `<Canvas ...obj />`;
|
|
68
|
+
const output = parser.parse(input);
|
|
69
|
+
expect(output).toBe(`h(Canvas, obj)`);
|
|
70
|
+
});
|
|
71
|
+
|
|
60
72
|
test("should compile component with dynamic attribute but is not a signal", () => {
|
|
61
73
|
const input = `<Canvas width={20} />`;
|
|
62
74
|
const output = parser.parse(input);
|