rip-lang 3.13.63 → 3.13.65

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.13.63",
3
+ "version": "3.13.65",
4
4
  "description": "A modern language that compiles to JavaScript",
5
5
  "type": "module",
6
6
  "main": "src/compiler.js",
package/src/compiler.js CHANGED
@@ -1072,7 +1072,7 @@ export class CodeGenerator {
1072
1072
  generateReturn(head, rest, context, sexpr) {
1073
1073
  if (rest.length === 0) return 'return';
1074
1074
  let [expr] = rest;
1075
- if (this.sideEffectOnly) return 'return';
1075
+ if (this.sideEffectOnly && !(this.is(expr, '->') || this.is(expr, '=>'))) return 'return';
1076
1076
 
1077
1077
  if (this.is(expr, 'if')) {
1078
1078
  let [, condition, body, ...elseParts] = expr;
package/src/components.js CHANGED
@@ -112,6 +112,8 @@ function isPublicProp(target) {
112
112
 
113
113
  export function installComponentSupport(CodeGenerator, Lexer) {
114
114
 
115
+ let meta = (node, key) => node instanceof String ? node[key] : undefined;
116
+
115
117
  // ==========================================================================
116
118
  // Lexer: Context-sensitive 'offer'/'accept' (only inside component bodies)
117
119
  // ==========================================================================
@@ -261,16 +263,18 @@ export function installComponentSupport(CodeGenerator, Lexer) {
261
263
  if (!inRender) return 1;
262
264
 
263
265
  // ─────────────────────────────────────────────────────────────────────
264
- // Expression output: = expr → "#{expr}" (text node, never a tag)
266
+ // Expression output: = expr → text node (stamp .text, skip tag detection)
265
267
  // ─────────────────────────────────────────────────────────────────────
266
268
  if (tag === '=' && i > 0) {
267
269
  let prev = tokens[i - 1][0];
268
270
  if (prev === 'TERMINATOR' || prev === 'INDENT' || prev === 'RENDER') {
269
- let end = i + 1;
270
- while (end < tokens.length && tokens[end][0] !== 'TERMINATOR' && tokens[end][0] !== 'INDENT' && tokens[end][0] !== 'OUTDENT') end++;
271
- tokens.splice(end, 0, gen('INTERPOLATION_END', ')', token), gen('STRING', '""', token), gen('STRING_END', ')', token));
272
- tokens.splice(i, 1, gen('STRING_START', '(', token), gen('STRING', '""', token), gen('INTERPOLATION_START', '(', token));
273
- return 3;
271
+ tokens.splice(i, 1);
272
+ if (tokens[i] && tokens[i][0] === 'IDENTIFIER') {
273
+ let val = tokens[i][1];
274
+ if (typeof val === 'string') { val = new String(val); tokens[i][1] = val; }
275
+ val.text = true;
276
+ }
277
+ return 0;
274
278
  }
275
279
  }
276
280
 
@@ -485,7 +489,19 @@ export function installComponentSupport(CodeGenerator, Lexer) {
485
489
  }
486
490
 
487
491
  if (isTemplateElement) {
488
- let isClassOrIdTail = tag === 'PROPERTY' && i > 0 && (tokens[i - 1][0] === '.' || tokens[i - 1][0] === '#');
492
+ let isClassOrIdTail = false;
493
+ if (tag === 'PROPERTY' && i > 0 && tokens[i - 1][0] === '.') {
494
+ // Trace backward through the .PROPERTY chain to find its root —
495
+ // only a CSS class tail if the chain starts from a line-starting template tag
496
+ let j = i;
497
+ while (j >= 2 && tokens[j - 1][0] === '.' && tokens[j - 2][0] === 'PROPERTY') j -= 2;
498
+ if (j >= 2 && tokens[j - 1][0] === '.' && tokens[j - 2][0] === 'IDENTIFIER' && isTemplateTag(tokens[j - 2][1])) {
499
+ let before = j >= 3 ? tokens[j - 3][0] : null;
500
+ if (!before || before === 'INDENT' || before === 'OUTDENT' || before === 'TERMINATOR' || before === 'RENDER') {
501
+ isClassOrIdTail = true;
502
+ }
503
+ }
504
+ }
489
505
  let isBareTag = isClsxCallEnd || (tag === 'IDENTIFIER' && isTemplateTag(token[1])) || isClassOrIdTail;
490
506
 
491
507
  if (isBareTag) {
@@ -560,11 +576,11 @@ export function installComponentSupport(CodeGenerator, Lexer) {
560
576
  current = current[1];
561
577
  }
562
578
  let raw = typeof current === 'string' ? current : (current instanceof String ? current.valueOf() : null);
563
- if (raw === null) return { tag: null, classes, id: undefined };
579
+ if (raw === null) return { tag: null, classes, id: undefined, base: current };
564
580
  // Split tag#id — e.g. "div#content" → tag: "div", id: "content"
565
581
  let [tag, id] = raw.split('#');
566
582
  if (!tag) tag = 'div'; // bare #id → div
567
- return { tag, classes, id };
583
+ return { tag, classes, id, base: current };
568
584
  };
569
585
 
570
586
  // ==========================================================================
@@ -1061,7 +1077,7 @@ export function installComponentSupport(CodeGenerator, Lexer) {
1061
1077
  }
1062
1078
 
1063
1079
  // HTML tag (possibly with #id, e.g. div#content)
1064
- if (headStr && this.isHtmlTag(headStr)) {
1080
+ if (headStr && this.isHtmlTag(headStr) && !meta(head, 'text')) {
1065
1081
  let [tagName, id] = headStr.split('#');
1066
1082
  return this.generateTag(tagName || 'div', [], rest, id);
1067
1083
  }
@@ -1084,9 +1100,9 @@ export function installComponentSupport(CodeGenerator, Lexer) {
1084
1100
  return slotVar;
1085
1101
  }
1086
1102
 
1087
- // HTML tag with classes (div.class) and optional #id
1088
- const { tag, classes, id } = this.collectTemplateClasses(sexpr);
1089
- if (tag && this.isHtmlTag(tag)) {
1103
+ // HTML tag with classes (div.class) skip if base is marked .text by = prefix
1104
+ const { tag, classes, id, base } = this.collectTemplateClasses(sexpr);
1105
+ if (!meta(base, 'text') && tag && this.isHtmlTag(tag)) {
1090
1106
  return this.generateTag(tag, classes, [], id);
1091
1107
  }
1092
1108
 
@@ -1438,7 +1454,11 @@ export function installComponentSupport(CodeGenerator, Lexer) {
1438
1454
  this._pushEffect(`${elVar}.setAttribute('${key}', ${valueCode});`);
1439
1455
  }
1440
1456
  } else {
1441
- this._createLines.push(`${elVar}.setAttribute('${key}', ${valueCode});`);
1457
+ if (Array.isArray(value) && value[0] === 'presence') {
1458
+ this._createLines.push(`{ const __v = ${valueCode}; __v == null ? void 0 : ${elVar}.setAttribute('${key}', __v); }`);
1459
+ } else {
1460
+ this._createLines.push(`${elVar}.setAttribute('${key}', ${valueCode});`);
1461
+ }
1442
1462
  }
1443
1463
  }
1444
1464
  }
@@ -1885,6 +1905,15 @@ export function installComponentSupport(CodeGenerator, Lexer) {
1885
1905
  return true;
1886
1906
  }
1887
1907
 
1908
+ // Method call on component: [['.', 'this', method], ...args]
1909
+ // Methods may read reactive state internally — treat as reactive so the
1910
+ // call gets wrapped in __effect and re-runs when dependencies change.
1911
+ if (Array.isArray(sexpr[0]) && sexpr[0][0] === '.' && sexpr[0][1] === 'this') {
1912
+ const m = sexpr[0][2];
1913
+ const name = typeof m === 'string' ? m : m instanceof String ? m.valueOf() : null;
1914
+ if (name && this.componentMembers?.has(name)) return true;
1915
+ }
1916
+
1888
1917
  for (const child of sexpr) {
1889
1918
  if (this.hasReactiveDeps(child)) return true;
1890
1919
  }