rip-lang 3.13.83 → 3.13.85

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 CHANGED
@@ -9,7 +9,7 @@
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
- <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.13.83-blue.svg" alt="Version"></a>
12
+ <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.13.85-blue.svg" alt="Version"></a>
13
13
  <a href="#zero-dependencies"><img src="https://img.shields.io/badge/dependencies-ZERO-brightgreen.svg" alt="Dependencies"></a>
14
14
  <a href="#"><img src="https://img.shields.io/badge/tests-1%2C436%2F1%2C436-brightgreen.svg" alt="Tests"></a>
15
15
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
@@ -332,14 +332,14 @@ That's it. All `<script type="text/rip">` tags share scope — `export` makes na
332
332
  <script type="text/rip" src="components/header.rip"></script>
333
333
  <script type="text/rip" src="app.rip"></script>
334
334
 
335
- <!-- Server mode with full app lifecycle (router, stash, hot reload) -->
336
- <script defer src="/rip/rip.min.js" data-launch="bundle"></script>
335
+ <!-- Bundle fetch all components from a server endpoint -->
336
+ <script defer src="/rip/rip.min.js" data-src="bundle" data-mount="App"></script>
337
337
 
338
- <!-- Server mode with stash persistence (sessionStorage) -->
339
- <script defer src="/rip/rip.min.js" data-launch="bundle" data-persist></script>
338
+ <!-- Bundle with stash persistence (sessionStorage) -->
339
+ <script defer src="/rip/rip.min.js" data-src="bundle" data-mount="App" data-persist></script>
340
340
 
341
- <!-- Server mode with localStorage persistence -->
342
- <script defer src="/rip/rip.min.js" data-launch="bundle" data-persist="local"></script>
341
+ <!-- Mix bundles and individual files -->
342
+ <script defer src="/rip/rip.min.js" data-src="/rip/ui bundle header.rip" data-mount="App"></script>
343
343
  ```
344
344
 
345
345
  Every component has a static `mount(target)` method — `App.mount '#app'` is shorthand for `App.new().mount('#app')`. Target defaults to `'body'`.
package/docs/dist/rip.js CHANGED
@@ -3510,6 +3510,13 @@ Expecting ${expected.join(", ")}, got '${this.tokenNames[symbol] || symbol}'`;
3510
3510
  function isPublicProp(target) {
3511
3511
  return Array.isArray(target) && target[0] === "." && target[1] === "this";
3512
3512
  }
3513
+ function getMemberType(target) {
3514
+ if (target instanceof String && target.type)
3515
+ return target.type;
3516
+ if (Array.isArray(target) && target[2] instanceof String && target[2].type)
3517
+ return target[2].type;
3518
+ return null;
3519
+ }
3513
3520
  function installComponentSupport(CodeGenerator, Lexer2) {
3514
3521
  let meta = (node, key) => node instanceof String ? node[key] : undefined;
3515
3522
  const origClassify = Lexer2.prototype.classifyKeyword;
@@ -3918,6 +3925,8 @@ Expecting ${expected.join(", ")}, got '${this.tokenNames[symbol] || symbol}'`;
3918
3925
  return sexpr.map((item) => this.transformComponentMembers(item));
3919
3926
  };
3920
3927
  proto.generateComponent = function(head, rest, context, sexpr) {
3928
+ if (this.options.stubComponents)
3929
+ return "class {}";
3921
3930
  const [, body] = rest;
3922
3931
  this.usesTemplates = true;
3923
3932
  this.usesReactivity = true;
@@ -3956,7 +3965,7 @@ Expecting ${expected.join(", ")}, got '${this.tokenNames[symbol] || symbol}'`;
3956
3965
  } else if (op === "state") {
3957
3966
  const varName = getMemberName(stmt[1]);
3958
3967
  if (varName) {
3959
- stateVars.push({ name: varName, value: stmt[2], isPublic: isPublicProp(stmt[1]) });
3968
+ stateVars.push({ name: varName, value: stmt[2], isPublic: isPublicProp(stmt[1]), type: getMemberType(stmt[1]) });
3960
3969
  memberNames.add(varName);
3961
3970
  reactiveMembers.add(varName);
3962
3971
  }
@@ -3970,7 +3979,7 @@ Expecting ${expected.join(", ")}, got '${this.tokenNames[symbol] || symbol}'`;
3970
3979
  } else if (op === "readonly") {
3971
3980
  const varName = getMemberName(stmt[1]);
3972
3981
  if (varName) {
3973
- readonlyVars.push({ name: varName, value: stmt[2], isPublic: isPublicProp(stmt[1]) });
3982
+ readonlyVars.push({ name: varName, value: stmt[2], isPublic: isPublicProp(stmt[1]), type: getMemberType(stmt[1]) });
3974
3983
  memberNames.add(varName);
3975
3984
  }
3976
3985
  } else if (op === "=") {
@@ -5989,37 +5998,29 @@ if (typeof globalThis !== 'undefined') {
5989
5998
  needsBlank = true;
5990
5999
  }
5991
6000
  }
5992
- if (this.options.lspMode && (this.usesReactivity || this.usesTemplates)) {
5993
- if (needsBlank)
5994
- code += `
6001
+ if (this.usesReactivity && !skip) {
6002
+ if (skipRT) {
6003
+ code += `var { __state, __computed, __effect, __batch, __readonly, __setErrorHandler, __handleError, __catchErrors } = globalThis.__rip;
5995
6004
  `;
5996
- code += getLspRuntimeDeclarations();
5997
- needsBlank = true;
5998
- } else {
5999
- if (this.usesReactivity && !skip) {
6000
- if (skipRT) {
6001
- code += `var { __state, __computed, __effect, __batch, __readonly, __setErrorHandler, __handleError, __catchErrors } = globalThis.__rip;
6005
+ } else if (typeof globalThis !== "undefined" && globalThis.__rip) {
6006
+ code += `const { __state, __computed, __effect, __batch, __readonly, __setErrorHandler, __handleError, __catchErrors } = globalThis.__rip;
6002
6007
  `;
6003
- } else if (typeof globalThis !== "undefined" && globalThis.__rip) {
6004
- code += `const { __state, __computed, __effect, __batch, __readonly, __setErrorHandler, __handleError, __catchErrors } = globalThis.__rip;
6005
- `;
6006
- } else {
6007
- code += this.getReactiveRuntime();
6008
- }
6009
- needsBlank = true;
6008
+ } else {
6009
+ code += this.getReactiveRuntime();
6010
6010
  }
6011
- if (this.usesTemplates && !skip) {
6012
- if (skipRT) {
6013
- code += `var { __pushComponent, __popComponent, setContext, getContext, hasContext, __clsx, __lis, __reconcile, __transition, __handleComponentError, __Component } = globalThis.__ripComponent;
6011
+ needsBlank = true;
6012
+ }
6013
+ if (this.usesTemplates && !skip) {
6014
+ if (skipRT) {
6015
+ code += `var { __pushComponent, __popComponent, setContext, getContext, hasContext, __clsx, __lis, __reconcile, __transition, __handleComponentError, __Component } = globalThis.__ripComponent;
6014
6016
  `;
6015
- } else if (typeof globalThis !== "undefined" && globalThis.__ripComponent) {
6016
- code += `const { __pushComponent, __popComponent, setContext, getContext, hasContext, __clsx, __lis, __reconcile, __transition, __handleComponentError, __Component } = globalThis.__ripComponent;
6017
+ } else if (typeof globalThis !== "undefined" && globalThis.__ripComponent) {
6018
+ code += `const { __pushComponent, __popComponent, setContext, getContext, hasContext, __clsx, __lis, __reconcile, __transition, __handleComponentError, __Component } = globalThis.__ripComponent;
6017
6019
  `;
6018
- } else {
6019
- code += this.getComponentRuntime();
6020
- }
6021
- needsBlank = true;
6020
+ } else {
6021
+ code += this.getComponentRuntime();
6022
6022
  }
6023
+ needsBlank = true;
6023
6024
  }
6024
6025
  if (this.dataSection !== null && this.dataSection !== undefined && !skip) {
6025
6026
  code += `var DATA;
@@ -8701,14 +8702,13 @@ if (typeof globalThis !== 'undefined') {
8701
8702
  let sourceFile = this.options.filename || "input.rip";
8702
8703
  sourceMap = new SourceMapGenerator(file, sourceFile, source);
8703
8704
  }
8704
- let lspMode = this.options.mode === "lsp";
8705
8705
  let generator = new CodeGenerator({
8706
8706
  dataSection,
8707
- skipPreamble: lspMode || this.options.skipPreamble,
8707
+ skipPreamble: this.options.skipPreamble,
8708
8708
  skipRuntimes: this.options.skipRuntimes,
8709
8709
  skipExports: this.options.skipExports,
8710
+ stubComponents: this.options.stubComponents,
8710
8711
  reactiveVars: this.options.reactiveVars,
8711
- lspMode,
8712
8712
  sourceMap
8713
8713
  });
8714
8714
  let code = generator.compile(sexpr);
@@ -8725,11 +8725,6 @@ if (typeof globalThis !== 'undefined') {
8725
8725
  if (typeTokens) {
8726
8726
  dts = emitTypes(typeTokens, sexpr);
8727
8727
  }
8728
- if (lspMode && dts) {
8729
- code = dts.trimEnd() + `
8730
-
8731
- ` + code;
8732
- }
8733
8728
  return { tokens, sexpr, code, dts, map, reverseMap, data: dataSection, reactiveVars: generator.reactiveVars };
8734
8729
  }
8735
8730
  compileToJS(source) {
@@ -8769,33 +8764,9 @@ globalThis.zip ??= (...a) => a[0].map((_, i) => a.map(b => b[i]));
8769
8764
  function getComponentRuntime() {
8770
8765
  return new CodeGenerator({}).getComponentRuntime();
8771
8766
  }
8772
- function getLspRuntimeDeclarations() {
8773
- return `interface Signal<T> { value: T; read(): T; lock(): Signal<T>; free(): Signal<T>; kill(): T; }
8774
- interface Computed<T> { readonly value: T; read(): T; lock(): Computed<T>; free(): Computed<T>; kill(): T; }
8775
- declare function __state<T>(v: T): Signal<T>;
8776
- declare function __computed<T>(fn: () => T): Computed<T>;
8777
- declare function __effect(fn: () => void | (() => void)): () => void;
8778
- declare function __batch<T>(fn: () => T): T;
8779
- declare function __readonly<T>(v: T): Readonly<{ value: T }>;
8780
- declare function __setErrorHandler(handler: ((err: any) => void) | null): ((err: any) => void) | null;
8781
- declare function __handleError(error: any): void;
8782
- declare function __catchErrors<T extends (...args: any[]) => any>(fn: T): T;
8783
- declare function __pushComponent(component: any): any;
8784
- declare function __popComponent(prev: any): void;
8785
- declare function setContext(key: string, value: any): void;
8786
- declare function getContext(key: string): any;
8787
- declare function hasContext(key: string): boolean;
8788
- declare function __clsx(...args: any[]): string;
8789
- declare function __lis(arr: number[]): number[];
8790
- declare function __reconcile(anchor: any, state: any, items: any[], ctx: any, factory: any, keyFn: any, ...outer: any[]): void;
8791
- declare function __transition(el: any, name: string, dir: string, done?: () => void): void;
8792
- declare function __handleComponentError(error: any, component: any): void;
8793
- declare class __Component { constructor(props?: any); mount(target?: any): any; unmount(): void; emit(name: string, detail?: any): void; static mount(target?: any): any; [key: string]: any; }
8794
- `;
8795
- }
8796
8767
  // src/browser.js
8797
- var VERSION = "3.13.77";
8798
- var BUILD_DATE = "2026-03-03@07:30:00GMT";
8768
+ var VERSION = "3.13.84";
8769
+ var BUILD_DATE = "2026-03-04@03:00:25GMT";
8799
8770
  if (typeof globalThis !== "undefined") {
8800
8771
  if (!globalThis.__rip)
8801
8772
  new Function(getReactiveRuntime())();
@@ -8827,102 +8798,151 @@ declare class __Component { constructor(props?: any); mount(target?: any): any;
8827
8798
  }
8828
8799
  }
8829
8800
  if (sources.length > 0) {
8830
- await Promise.all(sources.map(async (s) => {
8801
+ const results = await Promise.allSettled(sources.map(async (s) => {
8831
8802
  if (!s.url)
8832
8803
  return;
8833
- try {
8834
- const res = await fetch(s.url);
8835
- if (!res.ok) {
8836
- console.error(`Rip: failed to fetch ${s.url} (${res.status})`);
8837
- return;
8838
- }
8804
+ const res = await fetch(s.url);
8805
+ if (!res.ok)
8806
+ throw new Error(`${s.url} (${res.status})`);
8807
+ if (s.url.endsWith(".rip")) {
8839
8808
  s.code = await res.text();
8840
- } catch (e) {
8841
- console.error(`Rip: failed to fetch ${s.url}:`, e.message);
8809
+ } else {
8810
+ const bundle = await res.json();
8811
+ s.bundle = bundle;
8842
8812
  }
8843
8813
  }));
8844
- const opts = { skipRuntimes: true, skipExports: true };
8845
- const compiled = [];
8814
+ for (const r of results) {
8815
+ if (r.status === "rejected")
8816
+ console.warn("Rip: fetch failed:", r.reason.message);
8817
+ }
8818
+ const bundles = [];
8819
+ const individual = [];
8846
8820
  for (const s of sources) {
8847
- if (!s.code)
8848
- continue;
8849
- try {
8850
- const js = compileToJS(s.code, opts);
8851
- compiled.push({ js, url: s.url || "inline" });
8852
- } catch (e) {
8853
- console.error(`Rip compile error in ${s.url || "inline"}:`, e.message);
8854
- }
8855
- }
8856
- if (!globalThis.__ripApp && runtimeTag && !document.querySelector("script[data-launch]")) {
8857
- const stashFn = globalThis.stash;
8858
- if (stashFn) {
8859
- let initial = {};
8860
- const stateAttr = runtimeTag.getAttribute("data-state");
8861
- if (stateAttr) {
8821
+ if (s.bundle)
8822
+ bundles.push(s.bundle);
8823
+ else if (s.code)
8824
+ individual.push(s);
8825
+ }
8826
+ const routerAttr = runtimeTag?.getAttribute("data-router");
8827
+ const hasRouter = routerAttr != null;
8828
+ if (hasRouter && bundles.length > 0) {
8829
+ const opts = { skipRuntimes: true, skipExports: true };
8830
+ if (individual.length > 0) {
8831
+ let js = "";
8832
+ for (const s of individual) {
8862
8833
  try {
8863
- initial = JSON.parse(stateAttr);
8834
+ js += compileToJS(s.code, opts) + `
8835
+ `;
8836
+ } catch (e) {
8837
+ console.error(`Rip compile error in ${s.url || "inline"}:`, e.message);
8838
+ }
8839
+ }
8840
+ if (js) {
8841
+ try {
8842
+ await (0, eval)(`(async()=>{
8843
+ ${js}
8844
+ })()`);
8864
8845
  } catch (e) {
8865
- console.error("Rip: invalid data-state JSON:", e.message);
8846
+ console.error("Rip runtime error:", e);
8866
8847
  }
8867
8848
  }
8868
- const app = stashFn({ data: initial });
8869
- globalThis.__ripApp = app;
8870
- if (typeof window !== "undefined")
8871
- window.app = app;
8849
+ }
8850
+ const ui = importRip.modules?.["ui.rip"];
8851
+ if (ui?.launch) {
8852
+ const appBundle = bundles[bundles.length - 1];
8872
8853
  const persistAttr = runtimeTag.getAttribute("data-persist");
8873
- if (persistAttr != null && globalThis.persistStash) {
8874
- globalThis.persistStash(app, { local: persistAttr === "local" });
8854
+ const launchOpts = { bundle: appBundle, hash: routerAttr === "hash" };
8855
+ if (persistAttr != null)
8856
+ launchOpts.persist = persistAttr === "local" ? "local" : true;
8857
+ await ui.launch("", launchOpts);
8858
+ }
8859
+ } else {
8860
+ const expanded = [];
8861
+ for (const b of bundles) {
8862
+ for (const [name, code] of Object.entries(b.components || {})) {
8863
+ expanded.push({ code, url: name });
8864
+ }
8865
+ if (b.data) {
8866
+ const stateAttr = runtimeTag?.getAttribute("data-state");
8867
+ let initial = {};
8868
+ if (stateAttr) {
8869
+ try {
8870
+ initial = JSON.parse(stateAttr);
8871
+ } catch {}
8872
+ }
8873
+ Object.assign(initial, b.data);
8874
+ runtimeTag?.setAttribute("data-state", JSON.stringify(initial));
8875
8875
  }
8876
8876
  }
8877
- }
8878
- if (compiled.length > 0) {
8879
- let js = compiled.map((c) => c.js).join(`
8877
+ expanded.push(...individual);
8878
+ const opts = { skipRuntimes: true, skipExports: true };
8879
+ const compiled = [];
8880
+ for (const s of expanded) {
8881
+ if (!s.code)
8882
+ continue;
8883
+ try {
8884
+ const js = compileToJS(s.code, opts);
8885
+ compiled.push({ js, url: s.url || "inline" });
8886
+ } catch (e) {
8887
+ console.error(`Rip compile error in ${s.url || "inline"}:`, e.message);
8888
+ }
8889
+ }
8890
+ if (!globalThis.__ripApp && runtimeTag) {
8891
+ const stashFn = globalThis.stash;
8892
+ if (stashFn) {
8893
+ let initial = {};
8894
+ const stateAttr = runtimeTag.getAttribute("data-state");
8895
+ if (stateAttr) {
8896
+ try {
8897
+ initial = JSON.parse(stateAttr);
8898
+ } catch (e) {
8899
+ console.error("Rip: invalid data-state JSON:", e.message);
8900
+ }
8901
+ }
8902
+ const app = stashFn({ data: initial });
8903
+ globalThis.__ripApp = app;
8904
+ if (typeof window !== "undefined")
8905
+ window.app = app;
8906
+ const persistAttr = runtimeTag.getAttribute("data-persist");
8907
+ if (persistAttr != null && globalThis.persistStash) {
8908
+ globalThis.persistStash(app, { local: persistAttr === "local" });
8909
+ }
8910
+ }
8911
+ }
8912
+ if (compiled.length > 0) {
8913
+ let js = compiled.map((c) => c.js).join(`
8880
8914
  `);
8881
- const mount = runtimeTag?.getAttribute("data-mount");
8882
- if (mount) {
8883
- const target = runtimeTag.getAttribute("data-target") || "body";
8884
- js += `
8915
+ const mount = runtimeTag?.getAttribute("data-mount");
8916
+ if (mount) {
8917
+ const target = runtimeTag.getAttribute("data-target") || "body";
8918
+ js += `
8885
8919
  ${mount}.mount(${JSON.stringify(target)});`;
8886
- }
8887
- try {
8888
- await (0, eval)(`(async()=>{
8920
+ }
8921
+ try {
8922
+ await (0, eval)(`(async()=>{
8889
8923
  ${js}
8890
8924
  })()`);
8891
- document.body.classList.add("ready");
8892
- } catch (e) {
8893
- if (e instanceof SyntaxError) {
8894
- console.error(`Rip syntax error in combined output: ${e.message}`);
8895
- for (const c of compiled) {
8896
- try {
8897
- new Function(`(async()=>{
8925
+ document.body.classList.add("ready");
8926
+ } catch (e) {
8927
+ if (e instanceof SyntaxError) {
8928
+ console.error(`Rip syntax error in combined output: ${e.message}`);
8929
+ for (const c of compiled) {
8930
+ try {
8931
+ new Function(`(async()=>{
8898
8932
  ${c.js}
8899
8933
  })()`);
8900
- } catch (e2) {
8901
- console.error(` → source: ${c.url}`, e2.message);
8934
+ } catch (e2) {
8935
+ console.error(` → source: ${c.url}`, e2.message);
8936
+ }
8902
8937
  }
8938
+ } else {
8939
+ console.error("Rip runtime error:", e);
8903
8940
  }
8904
- } else {
8905
- console.error("Rip runtime error:", e);
8906
8941
  }
8907
8942
  }
8908
8943
  }
8909
8944
  }
8910
- const cfg = document.querySelector("script[data-launch]");
8911
- if (cfg && !globalThis.__ripLaunched) {
8912
- const ui = importRip.modules?.["ui.rip"];
8913
- if (ui?.launch) {
8914
- const url = cfg.getAttribute("data-launch") || "";
8915
- const hash = cfg.getAttribute("data-hash");
8916
- const persist = cfg.getAttribute("data-persist");
8917
- const opts = { hash: hash !== "false" };
8918
- if (url)
8919
- opts.bundleUrl = url;
8920
- if (persist != null)
8921
- opts.persist = persist === "local" ? "local" : true;
8922
- await ui.launch("", opts);
8923
- }
8924
- }
8925
- if (runtimeTag?.hasAttribute("data-reload")) {
8945
+ if (runtimeTag?.hasAttribute("data-reload") && !globalThis.__ripLaunched) {
8926
8946
  let ready = false;
8927
8947
  const es = new EventSource("/watch");
8928
8948
  es.addEventListener("connected", () => {