rip-lang 3.13.28 → 3.13.30
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/RIP-LANG.md +19 -0
- package/docs/dist/rip.js +91 -40
- package/docs/dist/rip.min.js +157 -157
- package/docs/dist/rip.min.js.br +0 -0
- package/package.json +1 -1
- package/src/components.js +56 -3
package/docs/dist/rip.min.js.br
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/src/components.js
CHANGED
|
@@ -433,7 +433,7 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
433
433
|
isTemplateElement = true;
|
|
434
434
|
} else if (tag === 'IDENTIFIER' && !isAfterControlFlow) {
|
|
435
435
|
isTemplateElement = startsWithTag(tokens, i);
|
|
436
|
-
} else if (tag === 'PROPERTY' || tag === 'STRING' || tag === 'STRING_END' || tag === 'NUMBER' || tag === 'BOOL' || tag === 'CALL_END' || tag === ')') {
|
|
436
|
+
} else if (tag === 'PROPERTY' || tag === 'STRING' || tag === 'STRING_END' || tag === 'NUMBER' || tag === 'BOOL' || tag === 'CALL_END' || tag === ')' || tag === 'PRESENCE') {
|
|
437
437
|
isTemplateElement = startsWithTag(tokens, i);
|
|
438
438
|
}
|
|
439
439
|
|
|
@@ -664,11 +664,21 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
664
664
|
}
|
|
665
665
|
}
|
|
666
666
|
|
|
667
|
+
// Auto-event map: onClick → 'click', onKeydown → 'keydown', etc.
|
|
668
|
+
const autoEventHandlers = new Map();
|
|
669
|
+
for (const { name } of methods) {
|
|
670
|
+
if (/^on[A-Z]/.test(name) && !LIFECYCLE_HOOKS.has(name)) {
|
|
671
|
+
autoEventHandlers.set(name[2].toLowerCase() + name.slice(3), name);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
667
675
|
// Save and set component context
|
|
668
676
|
const prevComponentMembers = this.componentMembers;
|
|
669
677
|
const prevReactiveMembers = this.reactiveMembers;
|
|
678
|
+
const prevAutoEventHandlers = this._autoEventHandlers;
|
|
670
679
|
this.componentMembers = memberNames;
|
|
671
680
|
this.reactiveMembers = reactiveMembers;
|
|
681
|
+
this._autoEventHandlers = autoEventHandlers.size > 0 ? autoEventHandlers : null;
|
|
672
682
|
|
|
673
683
|
const lines = [];
|
|
674
684
|
let blockFactoriesCode = '';
|
|
@@ -776,6 +786,7 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
776
786
|
// Restore context
|
|
777
787
|
this.componentMembers = prevComponentMembers;
|
|
778
788
|
this.reactiveMembers = prevReactiveMembers;
|
|
789
|
+
this._autoEventHandlers = prevAutoEventHandlers;
|
|
779
790
|
|
|
780
791
|
// If block factories exist, wrap in IIFE so they're in scope
|
|
781
792
|
if (blockFactoriesCode) {
|
|
@@ -828,6 +839,9 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
828
839
|
this._factoryMode = false;
|
|
829
840
|
this._factoryVars = null;
|
|
830
841
|
this._fragChildren = new Map();
|
|
842
|
+
this._pendingAutoWire = false;
|
|
843
|
+
this._autoWireEl = null;
|
|
844
|
+
this._autoWireExplicit = null;
|
|
831
845
|
|
|
832
846
|
const statements = this.is(body, 'block') ? body.slice(1) : [body];
|
|
833
847
|
|
|
@@ -835,7 +849,9 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
835
849
|
if (statements.length === 0) {
|
|
836
850
|
rootVar = 'null';
|
|
837
851
|
} else if (statements.length === 1) {
|
|
852
|
+
this._pendingAutoWire = !!this._autoEventHandlers;
|
|
838
853
|
rootVar = this.generateNode(statements[0]);
|
|
854
|
+
this._pendingAutoWire = false;
|
|
839
855
|
} else {
|
|
840
856
|
rootVar = this.newElementVar('frag');
|
|
841
857
|
this._createLines.push(`${rootVar} = document.createDocumentFragment();`);
|
|
@@ -1048,8 +1064,8 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1048
1064
|
else if (typeof arg === 'string' || arg instanceof String) {
|
|
1049
1065
|
const val = arg.valueOf();
|
|
1050
1066
|
// Template tag appearing as a string arg (e.g., slot after multi-line attrs)
|
|
1051
|
-
const
|
|
1052
|
-
if (this.isHtmlTag(
|
|
1067
|
+
const baseName = val.split(/[#.]/)[0];
|
|
1068
|
+
if (this.isHtmlTag(baseName || 'div') || this.isComponent(baseName)) {
|
|
1053
1069
|
const childVar = this.generateNode(arg);
|
|
1054
1070
|
this._createLines.push(`${elVar}.appendChild(${childVar});`);
|
|
1055
1071
|
} else {
|
|
@@ -1074,6 +1090,29 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1074
1090
|
}
|
|
1075
1091
|
};
|
|
1076
1092
|
|
|
1093
|
+
// --------------------------------------------------------------------------
|
|
1094
|
+
// Auto-wire event handlers — claim/emit helpers for on* convention
|
|
1095
|
+
// --------------------------------------------------------------------------
|
|
1096
|
+
|
|
1097
|
+
proto._claimAutoWire = function(elVar) {
|
|
1098
|
+
if (!this._pendingAutoWire || !this._autoEventHandlers?.size) return false;
|
|
1099
|
+
this._pendingAutoWire = false;
|
|
1100
|
+
this._autoWireEl = elVar;
|
|
1101
|
+
this._autoWireExplicit = new Set();
|
|
1102
|
+
return true;
|
|
1103
|
+
};
|
|
1104
|
+
|
|
1105
|
+
proto._emitAutoWire = function(elVar, claimed) {
|
|
1106
|
+
if (!claimed) return;
|
|
1107
|
+
for (const [eventName, methodName] of this._autoEventHandlers) {
|
|
1108
|
+
if (!this._autoWireExplicit.has(eventName)) {
|
|
1109
|
+
this._createLines.push(`${elVar}.addEventListener('${eventName}', (e) => __batch(() => ${this._self}.${methodName}(e)));`);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
this._autoWireEl = null;
|
|
1113
|
+
this._autoWireExplicit = null;
|
|
1114
|
+
};
|
|
1115
|
+
|
|
1077
1116
|
// --------------------------------------------------------------------------
|
|
1078
1117
|
// generateTag — HTML element with static classes and children
|
|
1079
1118
|
// --------------------------------------------------------------------------
|
|
@@ -1091,6 +1130,8 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1091
1130
|
this._createLines.push(`${elVar}.id = '${id}';`);
|
|
1092
1131
|
}
|
|
1093
1132
|
|
|
1133
|
+
const autoWireClaimed = this._claimAutoWire(elVar);
|
|
1134
|
+
|
|
1094
1135
|
// Defer class emission when selector classes exist so class: attributes merge
|
|
1095
1136
|
const prevClassArgs = this._pendingClassArgs;
|
|
1096
1137
|
const prevClassEl = this._pendingClassEl;
|
|
@@ -1123,6 +1164,8 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1123
1164
|
this._pendingClassEl = prevClassEl;
|
|
1124
1165
|
}
|
|
1125
1166
|
|
|
1167
|
+
this._emitAutoWire(elVar, autoWireClaimed);
|
|
1168
|
+
|
|
1126
1169
|
return elVar;
|
|
1127
1170
|
};
|
|
1128
1171
|
|
|
@@ -1138,6 +1181,8 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1138
1181
|
this._createLines.push(`${elVar} = document.createElement('${tag}');`);
|
|
1139
1182
|
}
|
|
1140
1183
|
|
|
1184
|
+
const autoWireClaimed = this._claimAutoWire(elVar);
|
|
1185
|
+
|
|
1141
1186
|
// Defer className emission so class: attributes can merge with .() classes
|
|
1142
1187
|
const classArgs = classExprs.map(e => this.generateInComponent(e, 'value'));
|
|
1143
1188
|
const prevClassArgs = this._pendingClassArgs;
|
|
@@ -1161,6 +1206,8 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1161
1206
|
this._pendingClassArgs = prevClassArgs;
|
|
1162
1207
|
this._pendingClassEl = prevClassEl;
|
|
1163
1208
|
|
|
1209
|
+
this._emitAutoWire(elVar, autoWireClaimed);
|
|
1210
|
+
|
|
1164
1211
|
return elVar;
|
|
1165
1212
|
};
|
|
1166
1213
|
|
|
@@ -1177,6 +1224,9 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1177
1224
|
// Event handler: @click or (. this eventName)
|
|
1178
1225
|
if (this.is(key, '.') && key[1] === 'this') {
|
|
1179
1226
|
const eventName = key[2];
|
|
1227
|
+
if (this._autoWireExplicit && this._autoWireEl === elVar) {
|
|
1228
|
+
this._autoWireExplicit.add(eventName);
|
|
1229
|
+
}
|
|
1180
1230
|
if (typeof value === 'string' && this.componentMembers?.has(value)) {
|
|
1181
1231
|
this._createLines.push(`${elVar}.addEventListener('${eventName}', (e) => __batch(() => ${this._self}.${value}(e)));`);
|
|
1182
1232
|
} else {
|
|
@@ -1330,6 +1380,7 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1330
1380
|
// --------------------------------------------------------------------------
|
|
1331
1381
|
|
|
1332
1382
|
proto.generateConditional = function(sexpr) {
|
|
1383
|
+
this._pendingAutoWire = false;
|
|
1333
1384
|
const [, condition, thenBlock, elseBlock] = sexpr;
|
|
1334
1385
|
|
|
1335
1386
|
const anchorVar = this.newElementVar('anchor');
|
|
@@ -1496,6 +1547,7 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1496
1547
|
// --------------------------------------------------------------------------
|
|
1497
1548
|
|
|
1498
1549
|
proto.generateTemplateLoop = function(sexpr) {
|
|
1550
|
+
this._pendingAutoWire = false;
|
|
1499
1551
|
const [head, vars, collection, guard, step, body] = sexpr;
|
|
1500
1552
|
|
|
1501
1553
|
const blockName = this.newBlockVar();
|
|
@@ -1581,6 +1633,7 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1581
1633
|
// --------------------------------------------------------------------------
|
|
1582
1634
|
|
|
1583
1635
|
proto.generateChildComponent = function(componentName, args) {
|
|
1636
|
+
this._pendingAutoWire = false;
|
|
1584
1637
|
const instVar = this.newElementVar('inst');
|
|
1585
1638
|
const elVar = this.newElementVar('el');
|
|
1586
1639
|
const { propsCode, reactiveProps, childrenSetupLines } = this.buildComponentProps(args);
|