rip-lang 3.13.124 → 3.13.126
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/README.md +1 -1
- package/docs/dist/rip.js +69 -18
- package/docs/dist/rip.min.js +125 -124
- package/docs/dist/rip.min.js.br +0 -0
- package/package.json +1 -1
- package/src/compiler.js +9 -4
- package/src/components.js +26 -9
- package/src/lexer.js +31 -1
package/docs/dist/rip.min.js.br
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/src/compiler.js
CHANGED
|
@@ -2709,11 +2709,11 @@ export class CodeGenerator {
|
|
|
2709
2709
|
generateSwitchCaseBody(body, context) {
|
|
2710
2710
|
let code = '';
|
|
2711
2711
|
let hasFlow = this.hasExplicitControlFlow(body);
|
|
2712
|
+
let stmts = this.unwrapBlock(body);
|
|
2712
2713
|
if (hasFlow) {
|
|
2713
|
-
for (let s of
|
|
2714
|
+
for (let s of stmts) code += this.indent() + this.generate(s, 'statement') + ';\n';
|
|
2714
2715
|
} else if (context === 'value') {
|
|
2715
2716
|
if (this.is(body, 'block') && body.length > 2) {
|
|
2716
|
-
let stmts = body.slice(1);
|
|
2717
2717
|
for (let i = 0; i < stmts.length; i++) {
|
|
2718
2718
|
if (i === stmts.length - 1) code += this.indent() + `return ${this.generate(stmts[i], 'value')};\n`;
|
|
2719
2719
|
else code += this.indent() + this.generate(stmts[i], 'statement') + ';\n';
|
|
@@ -2722,8 +2722,13 @@ export class CodeGenerator {
|
|
|
2722
2722
|
code += this.indent() + `return ${this.extractExpression(body)};\n`;
|
|
2723
2723
|
}
|
|
2724
2724
|
} else {
|
|
2725
|
-
if (this.is(
|
|
2726
|
-
|
|
2725
|
+
if (stmts.length === 1 && this.is(stmts[0], 'if') && !this.hasStatementInBranch(stmts[0]) && !this.hasNestedMultiStatement(stmts[0])) {
|
|
2726
|
+
let [_, condition, thenBranch, ...elseBranches] = stmts[0];
|
|
2727
|
+
let thenExpr = this.extractExpression(this.unwrapIfBranch(thenBranch));
|
|
2728
|
+
let elseExpr = this.buildTernaryChain(elseBranches);
|
|
2729
|
+
code += this.indent() + `(${this.unwrap(this.generate(condition, 'value'))} ? ${thenExpr} : ${elseExpr});\n`;
|
|
2730
|
+
} else if (this.is(body, 'block') && body.length > 1) {
|
|
2731
|
+
for (let s of stmts) code += this.indent() + this.generate(s, 'statement') + ';\n';
|
|
2727
2732
|
} else {
|
|
2728
2733
|
code += this.indent() + this.generate(body, 'statement') + ';\n';
|
|
2729
2734
|
}
|
package/src/components.js
CHANGED
|
@@ -236,18 +236,20 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
236
236
|
if (!inRender) return 1;
|
|
237
237
|
|
|
238
238
|
// ─────────────────────────────────────────────────────────────────────
|
|
239
|
-
// Expression output: = expr → text node (
|
|
239
|
+
// Expression output: = expr → synthetic text node __text__(expr)
|
|
240
240
|
// ─────────────────────────────────────────────────────────────────────
|
|
241
241
|
if (tag === '=' && i > 0) {
|
|
242
242
|
let prev = tokens[i - 1][0];
|
|
243
243
|
if (prev === 'TERMINATOR' || prev === 'INDENT' || prev === 'RENDER') {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
244
|
+
const textToken = gen('IDENTIFIER', '__text__', token);
|
|
245
|
+
const callStart = gen('CALL_START', '(', token);
|
|
246
|
+
tokens.splice(i, 1, textToken, callStart);
|
|
247
|
+
this.detectEnd(i + 2,
|
|
248
|
+
(t) => t[0] === 'TERMINATOR' || t[0] === 'OUTDENT',
|
|
249
|
+
(t, j) => tokens.splice(j, 0, gen('CALL_END', ')', t)),
|
|
250
|
+
{ returnOnNegativeLevel: true }
|
|
251
|
+
);
|
|
252
|
+
return 2;
|
|
251
253
|
}
|
|
252
254
|
}
|
|
253
255
|
|
|
@@ -432,7 +434,8 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
432
434
|
|
|
433
435
|
let isTemplateElement = false;
|
|
434
436
|
let prevTag = i > 0 ? tokens[i - 1][0] : null;
|
|
435
|
-
let isAfterControlFlow = prevTag === 'IF' || prevTag === 'UNLESS' || prevTag === 'WHILE' || prevTag === 'UNTIL' || prevTag === 'WHEN'
|
|
437
|
+
let isAfterControlFlow = prevTag === 'IF' || prevTag === 'UNLESS' || prevTag === 'WHILE' || prevTag === 'UNTIL' || prevTag === 'WHEN' ||
|
|
438
|
+
prevTag === 'FORIN' || prevTag === 'FOROF' || prevTag === 'FORAS' || prevTag === 'FORASAWAIT' || prevTag === 'BY';
|
|
436
439
|
|
|
437
440
|
// Detect __clsx CALL_END early — OUTDENT tokens inside multi-line .()
|
|
438
441
|
// args prevent startsWithTag from seeing the template tag, so we check
|
|
@@ -1604,6 +1607,20 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1604
1607
|
return this.generateTemplateLoop(sexpr);
|
|
1605
1608
|
}
|
|
1606
1609
|
|
|
1610
|
+
// Synthetic text node inserted by rewriteRender for `= expr`
|
|
1611
|
+
if (headStr === '__text__') {
|
|
1612
|
+
const expr = rest[0] ?? 'undefined';
|
|
1613
|
+
const textVar = this.newTextVar();
|
|
1614
|
+
const exprCode = this.generateInComponent(expr, 'value');
|
|
1615
|
+
if (this.hasReactiveDeps(expr)) {
|
|
1616
|
+
this._createLines.push(`${textVar} = document.createTextNode('');`);
|
|
1617
|
+
this._pushEffect(`${textVar}.data = String(${exprCode});`);
|
|
1618
|
+
} else {
|
|
1619
|
+
this._createLines.push(`${textVar} = document.createTextNode(String(${exprCode}));`);
|
|
1620
|
+
}
|
|
1621
|
+
return textVar;
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1607
1624
|
// General expression (computed value, function call, binary op, etc.)
|
|
1608
1625
|
const textVar = this.newTextVar();
|
|
1609
1626
|
const exprCode = this.generateInComponent(sexpr, 'value');
|
package/src/lexer.js
CHANGED
|
@@ -1476,7 +1476,8 @@ export class Lexer {
|
|
|
1476
1476
|
[indent, outdent] = this.makeIndentation();
|
|
1477
1477
|
if (tag === 'THEN') indent.fromThen = true;
|
|
1478
1478
|
tokens.splice(i + 1, 0, indent);
|
|
1479
|
-
this.
|
|
1479
|
+
if (tag === 'THEN' && this.singleLineOwner(i) === 'LEADING_WHEN') this.detectWhenThenEnd(i + 2, condition, action);
|
|
1480
|
+
else this.detectEnd(i + 2, condition, action);
|
|
1480
1481
|
if (tag === 'THEN') tokens.splice(i, 1);
|
|
1481
1482
|
return 1;
|
|
1482
1483
|
}
|
|
@@ -1485,6 +1486,35 @@ export class Lexer {
|
|
|
1485
1486
|
});
|
|
1486
1487
|
}
|
|
1487
1488
|
|
|
1489
|
+
singleLineOwner(i) {
|
|
1490
|
+
let starters = new Set(['LEADING_WHEN', 'IF', 'POST_IF', 'UNLESS', 'POST_UNLESS', 'ELSE', 'CATCH', 'TRY', 'FINALLY', '->', '=>']);
|
|
1491
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
1492
|
+
let token = this.tokens[j];
|
|
1493
|
+
let tag = token?.[0];
|
|
1494
|
+
if (starters.has(tag)) return tag;
|
|
1495
|
+
if (LINE_BREAK.has(tag) || token?.newLine) return null;
|
|
1496
|
+
}
|
|
1497
|
+
return null;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
detectWhenThenEnd(i, condition, action) {
|
|
1501
|
+
let levels = 0;
|
|
1502
|
+
let nestedInlineBranches = 0;
|
|
1503
|
+
while (i < this.tokens.length) {
|
|
1504
|
+
let token = this.tokens[i];
|
|
1505
|
+
let tag = token[0];
|
|
1506
|
+
if (levels === 0) {
|
|
1507
|
+
if (tag === 'THEN' && this.singleLineOwner(i) !== 'LEADING_WHEN') nestedInlineBranches++;
|
|
1508
|
+
else if (tag === 'ELSE' && nestedInlineBranches > 0) nestedInlineBranches--;
|
|
1509
|
+
else if (condition.call(this, token, i)) return action.call(this, token, i);
|
|
1510
|
+
}
|
|
1511
|
+
if (EXPRESSION_START.has(tag)) levels++;
|
|
1512
|
+
if (EXPRESSION_END.has(tag)) levels--;
|
|
1513
|
+
if (levels < 0) return action.call(this, token, i);
|
|
1514
|
+
i++;
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1488
1518
|
tagPostfixConditionals() {
|
|
1489
1519
|
let original = null;
|
|
1490
1520
|
|