@matthesketh/utopia-compiler 0.0.1 → 0.0.2

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/dist/index.cjs CHANGED
@@ -415,7 +415,7 @@ var CodeGenerator = class {
415
415
 
416
416
  ` : "";
417
417
  const fnBody = this.code.map((l) => ` ${l}`).join("\n");
418
- const moduleCode = `${importLine}export default function render(_ctx) {
418
+ const moduleCode = `${importLine}function __render() {
419
419
  ${fnBody}
420
420
  }
421
421
  `;
@@ -562,12 +562,13 @@ ${fnBody}
562
562
  const anchorVar = this.freshVar();
563
563
  this.helpers.add("createComment");
564
564
  this.emit(`const ${anchorVar} = createComment('u-for')`);
565
- const forMatch = dir.expression.match(/^\s*(\w+)\s+in\s+(.+)$/);
565
+ const forMatch = dir.expression.match(/^\s*(?:\(\s*(\w+)\s*(?:,\s*(\w+)\s*)?\)|(\w+))\s+in\s+(.+)$/);
566
566
  if (!forMatch) {
567
567
  throw new Error(`Invalid u-for expression: "${dir.expression}"`);
568
568
  }
569
- const itemName = forMatch[1];
570
- const listExpr = this.resolveExpression(forMatch[2].trim(), scope);
569
+ const itemName = forMatch[1] ?? forMatch[3];
570
+ const indexName = forMatch[2] ?? "_index";
571
+ const listExpr = this.resolveExpression(forMatch[4].trim(), scope);
571
572
  const innerScope = new Set(scope);
572
573
  innerScope.add(itemName);
573
574
  const strippedNode = {
@@ -580,7 +581,7 @@ ${fnBody}
580
581
  const innerLines = [...this.code];
581
582
  this.code = savedCode;
582
583
  const renderFnVar = this.freshVar();
583
- this.emit(`const ${renderFnVar} = (${itemName}, _index) => {`);
584
+ this.emit(`const ${renderFnVar} = (${itemName}, ${indexName}) => {`);
584
585
  for (const line of innerLines) {
585
586
  this.emit(` ${line}`);
586
587
  }
@@ -606,32 +607,21 @@ ${fnBody}
606
607
  }
607
608
  }
608
609
  const propsStr = propEntries.length > 0 ? `{ ${propEntries.join(", ")} }` : "{}";
609
- this.emit(`const ${compVar} = _ctx.${node.tag}(${propsStr})`);
610
+ this.helpers.add("createComponent");
611
+ this.emit(`const ${compVar} = createComponent(${node.tag}, ${propsStr})`);
610
612
  return compVar;
611
613
  }
612
614
  // ---- Expression resolution ----------------------------------------------
613
615
  /**
614
616
  * Resolve a template expression to a JS expression.
615
617
  *
616
- * If the leading identifier is in `scope` (a u-for item variable), it is
617
- * emitted as a bare variable reference. Otherwise it is prefixed with
618
- * `_ctx.` to access the component context.
618
+ * All identifiers are emitted as bare references user script variables
619
+ * live at module scope and are accessible via closure.
619
620
  */
620
- resolveExpression(expr, scope) {
621
+ resolveExpression(expr, _scope) {
621
622
  const trimmed = expr.trim();
622
623
  if (!trimmed) return "''";
623
- const leadIdMatch = trimmed.match(/^([a-zA-Z_$][\w$]*)/);
624
- if (!leadIdMatch) {
625
- return trimmed;
626
- }
627
- const leadId = leadIdMatch[1];
628
- if (scope.has(leadId)) {
629
- return trimmed;
630
- }
631
- if (trimmed.includes("=>")) {
632
- return trimmed;
633
- }
634
- return `_ctx.${trimmed}`;
624
+ return trimmed;
635
625
  }
636
626
  // ---- Utilities ----------------------------------------------------------
637
627
  freshVar() {
@@ -810,6 +800,7 @@ function compile(source, options = {}) {
810
800
  if (body) {
811
801
  parts.push(body);
812
802
  }
803
+ parts.push("export default { render: __render }");
813
804
  const code = parts.join("\n\n") + "\n";
814
805
  return { code, css };
815
806
  }
package/dist/index.js CHANGED
@@ -383,7 +383,7 @@ var CodeGenerator = class {
383
383
 
384
384
  ` : "";
385
385
  const fnBody = this.code.map((l) => ` ${l}`).join("\n");
386
- const moduleCode = `${importLine}export default function render(_ctx) {
386
+ const moduleCode = `${importLine}function __render() {
387
387
  ${fnBody}
388
388
  }
389
389
  `;
@@ -530,12 +530,13 @@ ${fnBody}
530
530
  const anchorVar = this.freshVar();
531
531
  this.helpers.add("createComment");
532
532
  this.emit(`const ${anchorVar} = createComment('u-for')`);
533
- const forMatch = dir.expression.match(/^\s*(\w+)\s+in\s+(.+)$/);
533
+ const forMatch = dir.expression.match(/^\s*(?:\(\s*(\w+)\s*(?:,\s*(\w+)\s*)?\)|(\w+))\s+in\s+(.+)$/);
534
534
  if (!forMatch) {
535
535
  throw new Error(`Invalid u-for expression: "${dir.expression}"`);
536
536
  }
537
- const itemName = forMatch[1];
538
- const listExpr = this.resolveExpression(forMatch[2].trim(), scope);
537
+ const itemName = forMatch[1] ?? forMatch[3];
538
+ const indexName = forMatch[2] ?? "_index";
539
+ const listExpr = this.resolveExpression(forMatch[4].trim(), scope);
539
540
  const innerScope = new Set(scope);
540
541
  innerScope.add(itemName);
541
542
  const strippedNode = {
@@ -548,7 +549,7 @@ ${fnBody}
548
549
  const innerLines = [...this.code];
549
550
  this.code = savedCode;
550
551
  const renderFnVar = this.freshVar();
551
- this.emit(`const ${renderFnVar} = (${itemName}, _index) => {`);
552
+ this.emit(`const ${renderFnVar} = (${itemName}, ${indexName}) => {`);
552
553
  for (const line of innerLines) {
553
554
  this.emit(` ${line}`);
554
555
  }
@@ -574,32 +575,21 @@ ${fnBody}
574
575
  }
575
576
  }
576
577
  const propsStr = propEntries.length > 0 ? `{ ${propEntries.join(", ")} }` : "{}";
577
- this.emit(`const ${compVar} = _ctx.${node.tag}(${propsStr})`);
578
+ this.helpers.add("createComponent");
579
+ this.emit(`const ${compVar} = createComponent(${node.tag}, ${propsStr})`);
578
580
  return compVar;
579
581
  }
580
582
  // ---- Expression resolution ----------------------------------------------
581
583
  /**
582
584
  * Resolve a template expression to a JS expression.
583
585
  *
584
- * If the leading identifier is in `scope` (a u-for item variable), it is
585
- * emitted as a bare variable reference. Otherwise it is prefixed with
586
- * `_ctx.` to access the component context.
586
+ * All identifiers are emitted as bare references user script variables
587
+ * live at module scope and are accessible via closure.
587
588
  */
588
- resolveExpression(expr, scope) {
589
+ resolveExpression(expr, _scope) {
589
590
  const trimmed = expr.trim();
590
591
  if (!trimmed) return "''";
591
- const leadIdMatch = trimmed.match(/^([a-zA-Z_$][\w$]*)/);
592
- if (!leadIdMatch) {
593
- return trimmed;
594
- }
595
- const leadId = leadIdMatch[1];
596
- if (scope.has(leadId)) {
597
- return trimmed;
598
- }
599
- if (trimmed.includes("=>")) {
600
- return trimmed;
601
- }
602
- return `_ctx.${trimmed}`;
592
+ return trimmed;
603
593
  }
604
594
  // ---- Utilities ----------------------------------------------------------
605
595
  freshVar() {
@@ -778,6 +768,7 @@ function compile(source, options = {}) {
778
768
  if (body) {
779
769
  parts.push(body);
780
770
  }
771
+ parts.push("export default { render: __render }");
781
772
  const code = parts.join("\n\n") + "\n";
782
773
  return { code, css };
783
774
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matthesketh/utopia-compiler",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Compiler for .utopia single-file components",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -39,7 +39,7 @@
39
39
  "dist"
40
40
  ],
41
41
  "dependencies": {
42
- "@matthesketh/utopia-core": "0.0.1"
42
+ "@matthesketh/utopia-core": "0.0.2"
43
43
  },
44
44
  "scripts": {
45
45
  "build": "tsup src/index.ts --format esm,cjs --dts",