@canvasengine/compiler 2.0.0-beta.5 → 2.0.0-beta.6

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 CHANGED
@@ -72,15 +72,17 @@ eventHandler
72
72
 
73
73
  dynamicAttribute
74
74
  = attributeName:attributeName _ "=" _ "{" _ attributeValue:attributeValue _ "}" {
75
- if (attributeValue.trim().match(/^[a-zA-Z_]\w*$/)) {
75
+ if (attributeValue.startsWith('h(') || attributeValue.includes('=>')) {
76
+ return `${attributeName}: ${attributeValue}`;
77
+ } else if (attributeValue.trim().match(/^[a-zA-Z_]\w*$/)) {
76
78
  return `${attributeName}: ${attributeValue}`;
77
79
  } else {
78
- let foundSignal = false
80
+ let foundSignal = false;
79
81
  const computedValue = attributeValue.replace(/@?[a-zA-Z_][a-zA-Z0-9_]*(?!:)/g, (match) => {
80
82
  if (match.startsWith('@')) {
81
83
  return match.substring(1);
82
84
  }
83
- foundSignal = true
85
+ foundSignal = true;
84
86
  return `${match}()`;
85
87
  });
86
88
  if (foundSignal) {
@@ -94,7 +96,9 @@ dynamicAttribute
94
96
  }
95
97
 
96
98
  attributeValue
97
- = $([^{}]* ("{" [^{}]* "}" [^{}]*)*) {
99
+ = element
100
+ / functionWithElement
101
+ / $([^{}]* ("{" [^{}]* "}" [^{}]*)*) {
98
102
  const t = text().trim()
99
103
  if (t.startsWith("{") && t.endsWith("}")) {
100
104
  return `(${t})`;
@@ -102,6 +106,25 @@ attributeValue
102
106
  return t
103
107
  }
104
108
 
109
+ functionWithElement
110
+ = "(" _ params:functionParams? _ ")" _ "=>" _ elem:element {
111
+ return `${params ? `(${params}) =>` : '() =>'} ${elem}`;
112
+ }
113
+
114
+ functionParams
115
+ = destructuredParams
116
+ / simpleParams
117
+
118
+ destructuredParams
119
+ = "{" _ param:identifier rest:(_ "," _ identifier)* _ "}" {
120
+ return `{${[param].concat(rest.map(r => r[3])).join(', ')}}`;
121
+ }
122
+
123
+ simpleParams
124
+ = param:identifier rest:(_ "," _ identifier)* {
125
+ return [param].concat(rest.map(r => r[3])).join(', ');
126
+ }
127
+
105
128
  staticAttribute
106
129
  = attributeName:attributeName _ "=" _ "\"" attributeValue:staticValue "\"" {
107
130
  return `${attributeName}: ${attributeValue}`;
@@ -164,7 +187,30 @@ iterable
164
187
  = [a-zA-Z_][a-zA-Z0-9_]* { return text(); }
165
188
 
166
189
  condition
167
- = $([^)]*) { return text().trim(); }
190
+ = functionCall
191
+ / $([^)]*) { return text().trim(); }
192
+
193
+ functionCall
194
+ = name:identifier "(" args:functionArgs? ")" {
195
+ return `${name}(${args || ''})`;
196
+ }
197
+
198
+ functionArgs
199
+ = arg:functionArg rest:("," _ functionArg)* {
200
+ return [arg].concat(rest.map(r => r[2])).join(', ');
201
+ }
202
+
203
+ functionArg
204
+ = _ value:(identifier / number / string) _ {
205
+ return value;
206
+ }
207
+
208
+ number
209
+ = [0-9]+ ("." [0-9]+)? { return text(); }
210
+
211
+ string
212
+ = '"' chars:[^"]* '"' { return text(); }
213
+ / "'" chars:[^']* "'" { return text(); }
168
214
 
169
215
  eventAction
170
216
  = [^"]* { return text(); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canvasengine/compiler",
3
- "version": "2.0.0-beta.5",
3
+ "version": "2.0.0-beta.6",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -177,11 +177,52 @@ describe("Compiler", () => {
177
177
  expect(output).toBe(`h(Sprite, { click: () => console.log('click') })`);
178
178
  });
179
179
 
180
- // test("should compile component with component attribute", () => {
181
- // const input = `<Canvas child={<Sprite />} />`;
182
- // const output = parser.parse(input);
183
- // expect(output).toBe(`h(Canvas, { child: h(Sprite) })`);
184
- // });
180
+ test("should compile component with component attribute", () => {
181
+ const input = `<Canvas child={<Sprite />} />`;
182
+ const output = parser.parse(input);
183
+ expect(output).toBe(`h(Canvas, { child: h(Sprite) })`);
184
+ });
185
+
186
+ test("should compile component with function returns component attribute", () => {
187
+ const input = `<Canvas child={() => <Sprite />} />`;
188
+ const output = parser.parse(input);
189
+ expect(output).toBe(`h(Canvas, { child: () => h(Sprite) })`);
190
+ });
191
+
192
+ test("should compile component with function (with params) returns component attribute", () => {
193
+ const input = `<Canvas child={(x, y) => <Sprite />} />`;
194
+ const output = parser.parse(input);
195
+ expect(output).toBe(`h(Canvas, { child: (x, y) => h(Sprite) })`);
196
+ });
197
+
198
+ test("should compile component with destructuring function (with params)", () => {
199
+ const input = `<Canvas child={({ x, y }) => <Sprite />} />`;
200
+ const output = parser.parse(input);
201
+ expect(output).toBe(`h(Canvas, { child: ({x, y}) => h(Sprite) })`);
202
+ });
203
+
204
+ test("should compile component with function returns component attribute and data", () => {
205
+ const input = `<Canvas child={() => <Text text="Hello" />} />`;
206
+ const output = parser.parse(input);
207
+ expect(output).toBe(`h(Canvas, { child: () => h(Text, { text: 'Hello' }) })`);
208
+ });
209
+
210
+ test("should compile component with function returns component attribute and child", () => {
211
+ const input = `<Canvas child={() => <Container>
212
+ <Text text="Hello" />
213
+ </Container>} />`;
214
+ const output = parser.parse(input);
215
+ expect(output).toBe(`h(Canvas, { child: () => h(Container, null, h(Text, { text: 'Hello' })) })`);
216
+ });
217
+
218
+ test("should compile component with function returns component attribute and children", () => {
219
+ const input = `<Canvas child={() => <Container>
220
+ <Text text="Hello 1" />
221
+ <Text text="Hello 2" />
222
+ </Container>} />`;
223
+ const output = parser.parse(input);
224
+ expect(output).toBe(`h(Canvas, { child: () => h(Container, null, [h(Text, { text: 'Hello 1' }), h(Text, { text: 'Hello 2' })]) })`);
225
+ });
185
226
  });
186
227
 
187
228
  describe("Loop", () => {
@@ -240,6 +281,16 @@ describe("Condition", () => {
240
281
  expect(output).toBe(`cond(sprite.visible, () => h(Sprite))`);
241
282
  });
242
283
 
284
+ test("should compile condition when function value", () => {
285
+ const input = `
286
+ @if (val()) {
287
+ <Sprite />
288
+ }
289
+ `;
290
+ const output = parser.parse(input);
291
+ expect(output).toBe(`cond(val(), () => h(Sprite))`);
292
+ });
293
+
243
294
  test("should compile condition for multiple sprites", () => {
244
295
  const input = `
245
296
  @if (sprite) {