rip-lang 3.13.55 → 3.13.56

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/docs/dist/rip.js CHANGED
@@ -3638,6 +3638,11 @@ Expecting ${expected.join(", ")}, got '${this.tokenNames[symbol] || symbol}'`;
3638
3638
  tokens.splice(i + 1, 1, colonToken, valueToken);
3639
3639
  return 1;
3640
3640
  }
3641
+ if (tag === "PROPERTY" && token[1][0] === "$" && token[1].length > 1) {
3642
+ token[0] = "STRING";
3643
+ token[1] = `"data-${token[1].slice(1)}"`;
3644
+ return 1;
3645
+ }
3641
3646
  if (tag === "IDENTIFIER" && !token.spaced) {
3642
3647
  let parts = [token[1]];
3643
3648
  let j = i + 1;
@@ -3654,8 +3659,11 @@ Expecting ${expected.join(", ")}, got '${this.tokenNames[symbol] || symbol}'`;
3654
3659
  }
3655
3660
  }
3656
3661
  if (parts.length > 1 && j > i + 1 && tokens[j - 1][0] === "PROPERTY") {
3662
+ let joined = parts.join("-");
3663
+ if (joined[0] === "$")
3664
+ joined = "data-" + joined.slice(1);
3657
3665
  token[0] = "STRING";
3658
- token[1] = `"${parts.join("-")}"`;
3666
+ token[1] = `"${joined}"`;
3659
3667
  tokens.splice(i + 1, j - i - 1);
3660
3668
  return 1;
3661
3669
  }
@@ -4494,16 +4502,6 @@ ${blockFactoriesCode}return ${lines.join(`
4494
4502
  const valueCode = this.generateInComponent(value, "value");
4495
4503
  if ((key === "value" || key === "checked") && this.hasReactiveDeps(value)) {
4496
4504
  this._pushEffect(`${elVar}.${key} = ${valueCode};`);
4497
- const rootMemberImplicit = !this.isSimpleAssignable(value) && this.findRootReactiveMember(value);
4498
- if (this.isSimpleAssignable(value) || rootMemberImplicit) {
4499
- const event = key === "checked" ? "change" : "input";
4500
- const accessor = key === "checked" ? "e.target.checked" : inputType === "number" || inputType === "range" ? "e.target.valueAsNumber" : "e.target.value";
4501
- let assignCode = `${valueCode} = ${accessor}`;
4502
- if (rootMemberImplicit) {
4503
- assignCode += `; ${this._self}.${rootMemberImplicit}.touch?.()`;
4504
- }
4505
- this._createLines.push(`${elVar}.addEventListener('${event}', (e) => { ${assignCode}; });`);
4506
- }
4507
4505
  continue;
4508
4506
  }
4509
4507
  if (key === "innerHTML" || key === "textContent" || key === "innerText") {
@@ -4692,7 +4690,18 @@ ${blockFactoriesCode}return ${lines.join(`
4692
4690
  this._createLines.push(`${anchorVar} = document.createComment('for');`);
4693
4691
  const varNames = Array.isArray(vars) ? vars : [vars];
4694
4692
  const itemVar = varNames[0];
4695
- const indexVar = varNames[1] || "i";
4693
+ let indexVar = varNames[1] || null;
4694
+ if (!indexVar) {
4695
+ const usedNames = new Set(this._loopVarStack.flatMap((v) => [v.itemVar, v.indexVar]));
4696
+ usedNames.add(itemVar);
4697
+ for (const candidate of ["i", "j", "k", "l", "m", "n"]) {
4698
+ if (!usedNames.has(candidate)) {
4699
+ indexVar = candidate;
4700
+ break;
4701
+ }
4702
+ }
4703
+ indexVar = indexVar || `_i${this._loopVarStack.length}`;
4704
+ }
4696
4705
  const collectionCode = this.generateInComponent(collection, "value");
4697
4706
  let keyExpr = itemVar;
4698
4707
  if (this.is(body, "block") && body.length > 1) {
@@ -5823,29 +5832,27 @@ if (typeof globalThis !== 'undefined') {
5823
5832
  }
5824
5833
  generateProgram(head, statements, context, sexpr) {
5825
5834
  let code = "";
5826
- let imports = [], exports = [], other = [];
5835
+ let imports = [], body = [];
5827
5836
  for (let stmt of statements) {
5828
5837
  if (!Array.isArray(stmt)) {
5829
- other.push(stmt);
5838
+ body.push(stmt);
5830
5839
  continue;
5831
5840
  }
5832
5841
  let h = stmt[0];
5833
5842
  if (h === "import")
5834
5843
  imports.push(stmt);
5835
- else if (h === "export" || h === "export-default" || h === "export-all" || h === "export-from")
5836
- exports.push(stmt);
5837
5844
  else
5838
- other.push(stmt);
5845
+ body.push(stmt);
5839
5846
  }
5840
5847
  let blockStmts = ["def", "class", "if", "for-in", "for-of", "for-as", "while", "loop", "switch", "try"];
5841
- let stmtEntries = other.map((stmt, index) => {
5842
- let isSingle = other.length === 1 && imports.length === 0 && exports.length === 0;
5848
+ let stmtEntries = body.map((stmt, index) => {
5849
+ let isSingle = body.length === 1 && imports.length === 0;
5843
5850
  let isObj = this.is(stmt, "object");
5844
5851
  let isObjComp = isObj && stmt.length === 2 && Array.isArray(stmt[1]) && Array.isArray(stmt[1][1]) && stmt[1][1][0] === "comprehension";
5845
5852
  let isAlreadyExpr = this.is(stmt, "comprehension") || this.is(stmt, "object-comprehension") || this.is(stmt, "do-iife");
5846
5853
  let hasNoVars = this.programVars.size === 0;
5847
5854
  let needsParens = isSingle && isObj && hasNoVars && !isAlreadyExpr && !isObjComp;
5848
- let isLast = index === other.length - 1;
5855
+ let isLast = index === body.length - 1;
5849
5856
  let isLastComp = isLast && isAlreadyExpr;
5850
5857
  let generated;
5851
5858
  if (needsParens)
@@ -5930,12 +5937,6 @@ if (typeof globalThis !== 'undefined') {
5930
5937
  needsBlank = true;
5931
5938
  }
5932
5939
  }
5933
- let exportsCode = "";
5934
- if (exports.length > 0) {
5935
- exportsCode = `
5936
- ` + exports.map((s) => this.addSemicolon(s, this.generate(s, "statement"))).join(`
5937
- `);
5938
- }
5939
5940
  if (this.usesReactivity && !skip) {
5940
5941
  if (skipRT) {
5941
5942
  code += `var { __state, __computed, __effect, __batch, __readonly, __setErrorHandler, __handleError, __catchErrors } = globalThis.__rip;
@@ -5973,7 +5974,6 @@ _setDataSection();
5973
5974
  this._preambleLines = code.length === 0 ? 0 : code.split(`
5974
5975
  `).length - 1;
5975
5976
  code += statementsCode;
5976
- code += exportsCode;
5977
5977
  if (this.dataSection !== null && this.dataSection !== undefined) {
5978
5978
  code += `
5979
5979
 
@@ -8680,7 +8680,7 @@ globalThis.zip ??= (...a) => a[0].map((_, i) => a.map(b => b[i]));
8680
8680
  }
8681
8681
  // src/browser.js
8682
8682
  var VERSION = "3.13.55";
8683
- var BUILD_DATE = "2026-02-27@09:25:16GMT";
8683
+ var BUILD_DATE = "2026-02-28@19:43:03GMT";
8684
8684
  if (typeof globalThis !== "undefined") {
8685
8685
  if (!globalThis.__rip)
8686
8686
  new Function(getReactiveRuntime())();
@@ -8732,13 +8732,14 @@ globalThis.zip ??= (...a) => a[0].map((_, i) => a.map(b => b[i]));
8732
8732
  if (!s.code)
8733
8733
  continue;
8734
8734
  try {
8735
- compiled.push(compileToJS(s.code, opts));
8735
+ const js = compileToJS(s.code, opts);
8736
+ compiled.push({ js, url: s.url || "inline" });
8736
8737
  } catch (e) {
8737
- console.error("Rip compile error:", e.message);
8738
+ console.error(`Rip compile error in ${s.url || "inline"}:`, e.message);
8738
8739
  }
8739
8740
  }
8740
8741
  if (compiled.length > 0) {
8741
- let js = compiled.join(`
8742
+ let js = compiled.map((c) => c.js).join(`
8742
8743
  `);
8743
8744
  const mount = runtimeTag?.getAttribute("data-mount");
8744
8745
  if (mount) {
@@ -8751,7 +8752,20 @@ ${mount}.mount(${JSON.stringify(target)});`;
8751
8752
  ${js}
8752
8753
  })()`);
8753
8754
  } catch (e) {
8754
- console.error("Rip runtime error:", e);
8755
+ if (e instanceof SyntaxError) {
8756
+ console.error(`Rip syntax error in combined output: ${e.message}`);
8757
+ for (const c of compiled) {
8758
+ try {
8759
+ new Function(`(async()=>{
8760
+ ${c.js}
8761
+ })()`);
8762
+ } catch (e2) {
8763
+ console.error(` → source: ${c.url}`, e2.message);
8764
+ }
8765
+ }
8766
+ } else {
8767
+ console.error("Rip runtime error:", e);
8768
+ }
8755
8769
  }
8756
8770
  }
8757
8771
  }
@@ -9053,252 +9067,6 @@ ${indented}`);
9053
9067
  }
9054
9068
  return value;
9055
9069
  };
9056
- _toFn = function(source) {
9057
- return typeof source === "function" ? source : function() {
9058
- return source.value;
9059
- };
9060
- };
9061
- _proxy = function(out, source) {
9062
- let obj;
9063
- obj = { read: function() {
9064
- return out.read();
9065
- } };
9066
- Object.defineProperty(obj, "value", { get: function() {
9067
- return out.value;
9068
- }, set: function(v) {
9069
- return source.value = v;
9070
- } });
9071
- return obj;
9072
- };
9073
- fileToPattern = function(rel) {
9074
- let pattern;
9075
- pattern = rel.replace(/\.rip$/, "");
9076
- pattern = pattern.replace(/\[\.\.\.(\w+)\]/g, "*$1");
9077
- pattern = pattern.replace(/\[(\w+)\]/g, ":$1");
9078
- if (pattern === "index")
9079
- return "/";
9080
- pattern = pattern.replace(/\/index$/, "");
9081
- return "/" + pattern;
9082
- };
9083
- patternToRegex = function(pattern) {
9084
- let names, str2;
9085
- names = [];
9086
- str2 = pattern.replace(/\*(\w+)/g, function(_, name) {
9087
- names.push(name);
9088
- return "(.+)";
9089
- }).replace(/:(\w+)/g, function(_, name) {
9090
- names.push(name);
9091
- return "([^/]+)";
9092
- });
9093
- return { regex: new RegExp("^" + str2 + "$"), names };
9094
- };
9095
- matchRoute = function(path, routes) {
9096
- let match, params;
9097
- for (const route of routes) {
9098
- match = path.match(route.regex.regex);
9099
- if (match) {
9100
- params = {};
9101
- for (let i = 0;i < route.regex.names.length; i++) {
9102
- const name = route.regex.names[i];
9103
- params[name] = decodeURIComponent(match[i + 1]);
9104
- }
9105
- return { route, params };
9106
- }
9107
- }
9108
- return null;
9109
- };
9110
- buildRoutes = function(components, root = "components") {
9111
- let allFiles, dir, layouts, name, regex, rel, routes, segs, urlPattern;
9112
- routes = [];
9113
- layouts = new Map;
9114
- allFiles = components.listAll(root);
9115
- for (const filePath of allFiles) {
9116
- rel = filePath.slice(root.length + 1);
9117
- if (!rel.endsWith(".rip"))
9118
- continue;
9119
- name = rel.split("/").pop();
9120
- if (name === "_layout.rip") {
9121
- dir = rel === "_layout.rip" ? "" : rel.slice(0, -"/_layout.rip".length);
9122
- layouts.set(dir, filePath);
9123
- continue;
9124
- }
9125
- if (name.startsWith("_"))
9126
- continue;
9127
- segs = rel.split("/");
9128
- if (segs.length > 1 && segs.some(function(s, i) {
9129
- return i < segs.length - 1 && s.startsWith("_");
9130
- }))
9131
- continue;
9132
- urlPattern = fileToPattern(rel);
9133
- regex = patternToRegex(urlPattern);
9134
- routes.push({ pattern: urlPattern, regex, file: filePath, rel });
9135
- }
9136
- routes.sort(function(a, b) {
9137
- let aCatch, aDyn, bCatch, bDyn;
9138
- aDyn = (a.pattern.match(/:/g) || []).length;
9139
- bDyn = (b.pattern.match(/:/g) || []).length;
9140
- aCatch = a.pattern.includes("*") ? 1 : 0;
9141
- bCatch = b.pattern.includes("*") ? 1 : 0;
9142
- if (aCatch !== bCatch)
9143
- return aCatch - bCatch;
9144
- if (aDyn !== bDyn)
9145
- return aDyn - bDyn;
9146
- return a.pattern.localeCompare(b.pattern);
9147
- });
9148
- return { routes, layouts };
9149
- };
9150
- getLayoutChain = function(routeFile, root, layouts) {
9151
- let chain, dir, rel, segments;
9152
- chain = [];
9153
- rel = routeFile.slice(root.length + 1);
9154
- segments = rel.split("/");
9155
- dir = "";
9156
- if (layouts.has(""))
9157
- chain.push(layouts.get(""));
9158
- for (let i = 0;i < segments.length; i++) {
9159
- const seg = segments[i];
9160
- if (i === segments.length - 1)
9161
- break;
9162
- dir = dir ? dir + "/" + seg : seg;
9163
- if (layouts.has(dir))
9164
- chain.push(layouts.get(dir));
9165
- }
9166
- return chain;
9167
- };
9168
- arraysEqual = function(a, b) {
9169
- if (a.length !== b.length)
9170
- return false;
9171
- for (let i = 0;i < a.length; i++) {
9172
- const item = a[i];
9173
- if (item !== b[i])
9174
- return false;
9175
- }
9176
- return true;
9177
- };
9178
- findComponent = function(mod) {
9179
- for (const key in mod) {
9180
- const val = mod[key];
9181
- if (typeof val === "function" && (val.prototype?.mount || val.prototype?._create))
9182
- return val;
9183
- }
9184
- return typeof mod.default === "function" ? mod.default : undefined;
9185
- };
9186
- findAllComponents = function(mod) {
9187
- let result;
9188
- result = {};
9189
- for (const key in mod) {
9190
- const val = mod[key];
9191
- if (typeof val === "function" && (val.prototype?.mount || val.prototype?._create)) {
9192
- result[key] = val;
9193
- }
9194
- }
9195
- return result;
9196
- };
9197
- fileToComponentName = function(filePath) {
9198
- let name;
9199
- name = filePath.split("/").pop().replace(/\.rip$/, "");
9200
- return name.replace(/(^|[-_])([a-z])/g, function(_, sep, ch) {
9201
- return ch.toUpperCase();
9202
- });
9203
- };
9204
- buildComponentMap = function(components, root = "components") {
9205
- let fileName, map, name;
9206
- map = {};
9207
- for (const path of components.listAll(root)) {
9208
- if (!path.endsWith(".rip"))
9209
- continue;
9210
- fileName = path.split("/").pop();
9211
- if (fileName.startsWith("_"))
9212
- continue;
9213
- name = fileToComponentName(path);
9214
- if (map[name]) {
9215
- console.warn(`[Rip] Component name collision: ${name} (${map[name]} vs ${path})`);
9216
- }
9217
- map[name] = path;
9218
- }
9219
- return map;
9220
- };
9221
- compileAndImport = async function(source, compile2, components = null, path = null, resolver = null) {
9222
- let blob, cached, depMod, depSource, found, header, js, mod, names, needed, preamble, url;
9223
- if (components && path) {
9224
- cached = components.getCompiled(path);
9225
- if (cached)
9226
- return cached;
9227
- }
9228
- js = compile2(source);
9229
- if (resolver) {
9230
- needed = {};
9231
- for (const name in resolver.map) {
9232
- const depPath = resolver.map[name];
9233
- if (depPath !== path && js.includes(`new ${name}(`)) {
9234
- if (!resolver.classes[name]) {
9235
- depSource = components.read(depPath);
9236
- if (depSource) {
9237
- depMod = await compileAndImport(depSource, compile2, components, depPath, resolver);
9238
- found = findAllComponents(depMod);
9239
- for (const k in found) {
9240
- const v = found[k];
9241
- resolver.classes[k] = v;
9242
- }
9243
- }
9244
- }
9245
- if (resolver.classes[name])
9246
- needed[name] = true;
9247
- }
9248
- }
9249
- names = Object.keys(needed);
9250
- if (names.length > 0) {
9251
- preamble = `const {${names.join(", ")}} = globalThis['${resolver.key}'];
9252
- `;
9253
- js = preamble + js;
9254
- }
9255
- }
9256
- header = path ? `// ${path}
9257
- ` : "";
9258
- blob = new Blob([header + js], { type: "application/javascript" });
9259
- url = URL.createObjectURL(blob);
9260
- mod = await import(url);
9261
- if (resolver) {
9262
- found = findAllComponents(mod);
9263
- for (const k in found) {
9264
- const v = found[k];
9265
- resolver.classes[k] = v;
9266
- }
9267
- }
9268
- if (components && path)
9269
- components.setCompiled(path, mod);
9270
- return mod;
9271
- };
9272
- connectWatch = function(url) {
9273
- let connect, maxDelay, retryDelay;
9274
- retryDelay = 1000;
9275
- maxDelay = 30000;
9276
- connect = function() {
9277
- let es;
9278
- es = new EventSource(url);
9279
- es.addEventListener("connected", function() {
9280
- retryDelay = 1000;
9281
- return console.log("[Rip] Hot reload connected");
9282
- });
9283
- es.addEventListener("reload", function() {
9284
- console.log("[Rip] Reloading...");
9285
- return location.reload();
9286
- });
9287
- es.addEventListener("css", function() {
9288
- for (const link of document.querySelectorAll('link[rel="stylesheet"]')) {
9289
- url = new URL(link.href);
9290
- url.searchParams.set("_t", Date.now());
9291
- link.href = url.toString();
9292
- }
9293
- });
9294
- return es.onerror = function() {
9295
- es.close();
9296
- setTimeout(connect, retryDelay);
9297
- return retryDelay = Math.min(retryDelay * 2, maxDelay);
9298
- };
9299
- };
9300
- return connect();
9301
- };
9302
9070
  var stash = function(data = {}) {
9303
9071
  return makeProxy(data);
9304
9072
  };
@@ -9342,6 +9110,23 @@ ${indented}`);
9342
9110
  load();
9343
9111
  return resource;
9344
9112
  };
9113
+ _toFn = function(source) {
9114
+ return typeof source === "function" ? source : function() {
9115
+ return source.value;
9116
+ };
9117
+ };
9118
+ _proxy = function(out, source) {
9119
+ let obj;
9120
+ obj = { read: function() {
9121
+ return out.read();
9122
+ } };
9123
+ Object.defineProperty(obj, "value", { get: function() {
9124
+ return out.value;
9125
+ }, set: function(v) {
9126
+ return source.value = v;
9127
+ } });
9128
+ return obj;
9129
+ };
9345
9130
  var delay = function(ms, source) {
9346
9131
  let fn, out;
9347
9132
  fn = _toFn(source);
@@ -9485,6 +9270,101 @@ ${indented}`);
9485
9270
  return compiled.set(path, result);
9486
9271
  } };
9487
9272
  };
9273
+ fileToPattern = function(rel) {
9274
+ let pattern;
9275
+ pattern = rel.replace(/\.rip$/, "");
9276
+ pattern = pattern.replace(/\[\.\.\.(\w+)\]/g, "*$1");
9277
+ pattern = pattern.replace(/\[(\w+)\]/g, ":$1");
9278
+ if (pattern === "index")
9279
+ return "/";
9280
+ pattern = pattern.replace(/\/index$/, "");
9281
+ return "/" + pattern;
9282
+ };
9283
+ patternToRegex = function(pattern) {
9284
+ let names, str2;
9285
+ names = [];
9286
+ str2 = pattern.replace(/\*(\w+)/g, function(_, name) {
9287
+ names.push(name);
9288
+ return "(.+)";
9289
+ }).replace(/:(\w+)/g, function(_, name) {
9290
+ names.push(name);
9291
+ return "([^/]+)";
9292
+ });
9293
+ return { regex: new RegExp("^" + str2 + "$"), names };
9294
+ };
9295
+ matchRoute = function(path, routes) {
9296
+ let match, params;
9297
+ for (const route of routes) {
9298
+ match = path.match(route.regex.regex);
9299
+ if (match) {
9300
+ params = {};
9301
+ for (let i = 0;i < route.regex.names.length; i++) {
9302
+ const name = route.regex.names[i];
9303
+ params[name] = decodeURIComponent(match[i + 1]);
9304
+ }
9305
+ return { route, params };
9306
+ }
9307
+ }
9308
+ return null;
9309
+ };
9310
+ buildRoutes = function(components, root = "components") {
9311
+ let allFiles, dir, layouts, name, regex, rel, routes, segs, urlPattern;
9312
+ routes = [];
9313
+ layouts = new Map;
9314
+ allFiles = components.listAll(root);
9315
+ for (const filePath of allFiles) {
9316
+ rel = filePath.slice(root.length + 1);
9317
+ if (!rel.endsWith(".rip"))
9318
+ continue;
9319
+ name = rel.split("/").pop();
9320
+ if (name === "_layout.rip") {
9321
+ dir = rel === "_layout.rip" ? "" : rel.slice(0, -"/_layout.rip".length);
9322
+ layouts.set(dir, filePath);
9323
+ continue;
9324
+ }
9325
+ if (name.startsWith("_"))
9326
+ continue;
9327
+ segs = rel.split("/");
9328
+ if (segs.length > 1 && segs.some(function(s, i) {
9329
+ return i < segs.length - 1 && s.startsWith("_");
9330
+ }))
9331
+ continue;
9332
+ urlPattern = fileToPattern(rel);
9333
+ regex = patternToRegex(urlPattern);
9334
+ routes.push({ pattern: urlPattern, regex, file: filePath, rel });
9335
+ }
9336
+ routes.sort(function(a, b) {
9337
+ let aCatch, aDyn, bCatch, bDyn;
9338
+ aDyn = (a.pattern.match(/:/g) || []).length;
9339
+ bDyn = (b.pattern.match(/:/g) || []).length;
9340
+ aCatch = a.pattern.includes("*") ? 1 : 0;
9341
+ bCatch = b.pattern.includes("*") ? 1 : 0;
9342
+ if (aCatch !== bCatch)
9343
+ return aCatch - bCatch;
9344
+ if (aDyn !== bDyn)
9345
+ return aDyn - bDyn;
9346
+ return a.pattern.localeCompare(b.pattern);
9347
+ });
9348
+ return { routes, layouts };
9349
+ };
9350
+ getLayoutChain = function(routeFile, root, layouts) {
9351
+ let chain, dir, rel, segments;
9352
+ chain = [];
9353
+ rel = routeFile.slice(root.length + 1);
9354
+ segments = rel.split("/");
9355
+ dir = "";
9356
+ if (layouts.has(""))
9357
+ chain.push(layouts.get(""));
9358
+ for (let i = 0;i < segments.length; i++) {
9359
+ const seg = segments[i];
9360
+ if (i === segments.length - 1)
9361
+ break;
9362
+ dir = dir ? dir + "/" + seg : seg;
9363
+ if (layouts.has(dir))
9364
+ chain.push(layouts.get(dir));
9365
+ }
9366
+ return chain;
9367
+ };
9488
9368
  var createRouter = function(components, opts = {}) {
9489
9369
  let _hash, _layouts, _navigating, _params, _path, _query, _route, addBase, base, hashMode, navCallbacks, onClick, onError, onPopState, readUrl, resolve, root, router, stripBase, tree, writeUrl;
9490
9370
  root = opts.root || "components";
@@ -9633,6 +9513,110 @@ ${indented}`);
9633
9513
  } });
9634
9514
  return router;
9635
9515
  };
9516
+ arraysEqual = function(a, b) {
9517
+ if (a.length !== b.length)
9518
+ return false;
9519
+ for (let i = 0;i < a.length; i++) {
9520
+ const item = a[i];
9521
+ if (item !== b[i])
9522
+ return false;
9523
+ }
9524
+ return true;
9525
+ };
9526
+ findComponent = function(mod) {
9527
+ for (const key in mod) {
9528
+ const val = mod[key];
9529
+ if (typeof val === "function" && (val.prototype?.mount || val.prototype?._create))
9530
+ return val;
9531
+ }
9532
+ return typeof mod.default === "function" ? mod.default : undefined;
9533
+ };
9534
+ findAllComponents = function(mod) {
9535
+ let result;
9536
+ result = {};
9537
+ for (const key in mod) {
9538
+ const val = mod[key];
9539
+ if (typeof val === "function" && (val.prototype?.mount || val.prototype?._create)) {
9540
+ result[key] = val;
9541
+ }
9542
+ }
9543
+ return result;
9544
+ };
9545
+ fileToComponentName = function(filePath) {
9546
+ let name;
9547
+ name = filePath.split("/").pop().replace(/\.rip$/, "");
9548
+ return name.replace(/(^|[-_])([a-z])/g, function(_, sep, ch) {
9549
+ return ch.toUpperCase();
9550
+ });
9551
+ };
9552
+ buildComponentMap = function(components, root = "components") {
9553
+ let fileName, map, name;
9554
+ map = {};
9555
+ for (const path of components.listAll(root)) {
9556
+ if (!path.endsWith(".rip"))
9557
+ continue;
9558
+ fileName = path.split("/").pop();
9559
+ if (fileName.startsWith("_"))
9560
+ continue;
9561
+ name = fileToComponentName(path);
9562
+ if (map[name]) {
9563
+ console.warn(`[Rip] Component name collision: ${name} (${map[name]} vs ${path})`);
9564
+ }
9565
+ map[name] = path;
9566
+ }
9567
+ return map;
9568
+ };
9569
+ compileAndImport = async function(source, compile2, components = null, path = null, resolver = null) {
9570
+ let blob, cached, depMod, depSource, found, header, js, mod, names, needed, preamble, url;
9571
+ if (components && path) {
9572
+ cached = components.getCompiled(path);
9573
+ if (cached)
9574
+ return cached;
9575
+ }
9576
+ js = compile2(source);
9577
+ if (resolver) {
9578
+ needed = {};
9579
+ for (const name in resolver.map) {
9580
+ const depPath = resolver.map[name];
9581
+ if (depPath !== path && js.includes(`new ${name}(`)) {
9582
+ if (!resolver.classes[name]) {
9583
+ depSource = components.read(depPath);
9584
+ if (depSource) {
9585
+ depMod = await compileAndImport(depSource, compile2, components, depPath, resolver);
9586
+ found = findAllComponents(depMod);
9587
+ for (const k in found) {
9588
+ const v = found[k];
9589
+ resolver.classes[k] = v;
9590
+ }
9591
+ }
9592
+ }
9593
+ if (resolver.classes[name])
9594
+ needed[name] = true;
9595
+ }
9596
+ }
9597
+ names = Object.keys(needed);
9598
+ if (names.length > 0) {
9599
+ preamble = `const {${names.join(", ")}} = globalThis['${resolver.key}'];
9600
+ `;
9601
+ js = preamble + js;
9602
+ }
9603
+ }
9604
+ header = path ? `// ${path}
9605
+ ` : "";
9606
+ blob = new Blob([header + js], { type: "application/javascript" });
9607
+ url = URL.createObjectURL(blob);
9608
+ mod = await import(url);
9609
+ if (resolver) {
9610
+ found = findAllComponents(mod);
9611
+ for (const k in found) {
9612
+ const v = found[k];
9613
+ resolver.classes[k] = v;
9614
+ }
9615
+ }
9616
+ if (components && path)
9617
+ components.setCompiled(path, mod);
9618
+ return mod;
9619
+ };
9636
9620
  var createRenderer = function(opts = {}) {
9637
9621
  let app, cacheComponent, compile2, componentCache, components, container, currentComponent, currentLayouts, currentParams, currentRoute, disposeEffect, generation, layoutInstances, maxCacheSize, mountPoint, mountRoute, onError, renderer, resolver, router, target, unmount;
9638
9622
  ({ router, app, components, resolver, compile: compile2, target, onError } = opts);
@@ -9845,6 +9829,36 @@ ${indented}`);
9845
9829
  }, cache: componentCache };
9846
9830
  return renderer;
9847
9831
  };
9832
+ connectWatch = function(url) {
9833
+ let connect, maxDelay, retryDelay;
9834
+ retryDelay = 1000;
9835
+ maxDelay = 30000;
9836
+ connect = function() {
9837
+ let es;
9838
+ es = new EventSource(url);
9839
+ es.addEventListener("connected", function() {
9840
+ retryDelay = 1000;
9841
+ return console.log("[Rip] Hot reload connected");
9842
+ });
9843
+ es.addEventListener("reload", function() {
9844
+ console.log("[Rip] Reloading...");
9845
+ return location.reload();
9846
+ });
9847
+ es.addEventListener("css", function() {
9848
+ for (const link of document.querySelectorAll('link[rel="stylesheet"]')) {
9849
+ url = new URL(link.href);
9850
+ url.searchParams.set("_t", Date.now());
9851
+ link.href = url.toString();
9852
+ }
9853
+ });
9854
+ return es.onerror = function() {
9855
+ es.close();
9856
+ setTimeout(connect, retryDelay);
9857
+ return retryDelay = Math.min(retryDelay * 2, maxDelay);
9858
+ };
9859
+ };
9860
+ return connect();
9861
+ };
9848
9862
  var launch = async function(appBase = "", opts = {}) {
9849
9863
  let _save, _storage, _storageKey, app, appComponents, bundle, cached, classesKey, compile2, el, etag, etagKey, hash, headers, persist, renderer, res, resolver, router, saved, savedData, target;
9850
9864
  globalThis.__ripLaunched = true;