rip-lang 3.9.2 → 3.9.3

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.
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rip-lang",
3
- "version": "3.9.2",
3
+ "version": "3.9.3",
4
4
  "description": "A modern language that compiles to JavaScript",
5
5
  "type": "module",
6
6
  "main": "src/compiler.js",
@@ -65,9 +65,5 @@
65
65
  },
66
66
  "homepage": "https://github.com/shreeve/rip-lang#readme",
67
67
  "author": "Steve Shreeve <steve.shreeve@gmail.com>",
68
- "license": "MIT",
69
- "devDependencies": {
70
- "@rip-lang/api": "1.1.5",
71
- "@rip-lang/ui": "0.2.0"
72
- }
68
+ "license": "MIT"
73
69
  }
package/src/components.js CHANGED
@@ -333,6 +333,10 @@ export function installComponentSupport(CodeGenerator, Lexer) {
333
333
  tokens.splice(i, 0, divToken);
334
334
  tokens.splice(i + 2, 0, cxToken);
335
335
  return 3;
336
+ } else if (prevTag === ':') {
337
+ // class: .('active', ...) → class: __clsx('active', ...)
338
+ tokens[i] = gen('IDENTIFIER', '__clsx', token);
339
+ return 1;
336
340
  } else {
337
341
  tokens.splice(i + 1, 0, cxToken);
338
342
  return 2;
@@ -939,8 +943,12 @@ export function installComponentSupport(CodeGenerator, Lexer) {
939
943
  const block = arg[2];
940
944
  if (this.is(block, 'block')) {
941
945
  for (const child of block.slice(1)) {
942
- const childVar = this.generateNode(child);
943
- this._createLines.push(`${elVar}.appendChild(${childVar});`);
946
+ if (this.is(child, 'object')) {
947
+ this.generateAttributes(elVar, child);
948
+ } else {
949
+ const childVar = this.generateNode(child);
950
+ this._createLines.push(`${elVar}.appendChild(${childVar});`);
951
+ }
944
952
  }
945
953
  } else if (block) {
946
954
  const childVar = this.generateNode(block);
@@ -999,15 +1007,22 @@ export function installComponentSupport(CodeGenerator, Lexer) {
999
1007
  const elVar = this.newElementVar();
1000
1008
  this._createLines.push(`${elVar} = document.createElement('${tag}');`);
1001
1009
 
1002
- if (classExprs.length > 0) {
1003
- const classArgs = classExprs.map(e => this.generateInComponent(e, 'value')).join(', ');
1004
- // Dynamic classes are always wrapped in __effect — the .() syntax exists
1005
- // precisely for reactive class expressions. If a class were static, you'd
1006
- // just write div.foo.bar instead. The effect tracks signal reads at runtime.
1007
- this._setupLines.push(`__effect(() => { ${elVar}.className = __clsx(${classArgs}); });`);
1008
- }
1010
+ // Defer className emission so class: attributes can merge with .() classes
1011
+ const classArgs = classExprs.map(e => this.generateInComponent(e, 'value'));
1012
+ const prevClassArgs = this._pendingClassArgs;
1013
+ const prevClassEl = this._pendingClassEl;
1014
+ this._pendingClassArgs = classArgs;
1015
+ this._pendingClassEl = elVar;
1009
1016
 
1010
1017
  this.appendChildren(elVar, children);
1018
+
1019
+ if (this._pendingClassArgs.length > 0) {
1020
+ const combined = this._pendingClassArgs.join(', ');
1021
+ this._setupLines.push(`__effect(() => { ${elVar}.className = __clsx(${combined}); });`);
1022
+ }
1023
+ this._pendingClassArgs = prevClassArgs;
1024
+ this._pendingClassEl = prevClassEl;
1025
+
1011
1026
  return elVar;
1012
1027
  };
1013
1028
 
@@ -1041,6 +1056,19 @@ export function installComponentSupport(CodeGenerator, Lexer) {
1041
1056
  key = key.slice(1, -1);
1042
1057
  }
1043
1058
 
1059
+ // Class merging: class: values merge with .() dynamic classes
1060
+ if (key === 'class' || key === 'className') {
1061
+ const valueCode = this.generateInComponent(value, 'value');
1062
+ if (this._pendingClassArgs && this._pendingClassEl === elVar) {
1063
+ this._pendingClassArgs.push(valueCode);
1064
+ } else if (this.hasReactiveDeps(value)) {
1065
+ this._setupLines.push(`__effect(() => { ${elVar}.className = __clsx(${valueCode}); });`);
1066
+ } else {
1067
+ this._createLines.push(`${elVar}.className = ${valueCode};`);
1068
+ }
1069
+ continue;
1070
+ }
1071
+
1044
1072
  // Element ref: ref: "name" → this.name = element
1045
1073
  if (key === 'ref') {
1046
1074
  const refName = String(value).replace(/^["']|["']$/g, '');
@@ -1493,26 +1521,50 @@ export function installComponentSupport(CodeGenerator, Lexer) {
1493
1521
  }
1494
1522
  }
1495
1523
  } else if (Array.isArray(arg) && (arg[0] === '->' || arg[0] === '=>')) {
1496
- const block = arg[2];
1524
+ let block = arg[2];
1497
1525
  if (block) {
1498
- const savedCreateLines = this._createLines;
1499
- const savedSetupLines = this._setupLines;
1500
- this._createLines = [];
1501
- this._setupLines = [];
1526
+ // Indented attributes: extract object nodes from block as props
1527
+ if (this.is(block, 'block')) {
1528
+ const domChildren = [];
1529
+ for (const child of block.slice(1)) {
1530
+ if (this.is(child, 'object')) {
1531
+ for (let i = 1; i < child.length; i++) {
1532
+ const [key, value] = child[i];
1533
+ if (typeof key === 'string') {
1534
+ const prevReactive = this.reactiveMembers;
1535
+ this.reactiveMembers = new Set();
1536
+ const valueCode = this.generateInComponent(value, 'value');
1537
+ this.reactiveMembers = prevReactive;
1538
+ props.push(`${key}: ${valueCode}`);
1539
+ }
1540
+ }
1541
+ } else {
1542
+ domChildren.push(child);
1543
+ }
1544
+ }
1545
+ block = domChildren.length > 0 ? ['block', ...domChildren] : null;
1546
+ }
1502
1547
 
1503
- childrenVar = this.generateTemplateBlock(block);
1548
+ if (block) {
1549
+ const savedCreateLines = this._createLines;
1550
+ const savedSetupLines = this._setupLines;
1551
+ this._createLines = [];
1552
+ this._setupLines = [];
1504
1553
 
1505
- const childCreateLines = this._createLines;
1506
- const childSetupLinesCopy = this._setupLines;
1554
+ childrenVar = this.generateTemplateBlock(block);
1507
1555
 
1508
- this._createLines = savedCreateLines;
1509
- this._setupLines = savedSetupLines;
1556
+ const childCreateLines = this._createLines;
1557
+ const childSetupLinesCopy = this._setupLines;
1510
1558
 
1511
- for (const line of childCreateLines) {
1512
- this._createLines.push(line);
1559
+ this._createLines = savedCreateLines;
1560
+ this._setupLines = savedSetupLines;
1561
+
1562
+ for (const line of childCreateLines) {
1563
+ this._createLines.push(line);
1564
+ }
1565
+ childrenSetupLines.push(...childSetupLinesCopy);
1566
+ props.push(`children: ${childrenVar}`);
1513
1567
  }
1514
- childrenSetupLines.push(...childSetupLinesCopy);
1515
- props.push(`children: ${childrenVar}`);
1516
1568
  }
1517
1569
  }
1518
1570
  }