rip-lang 3.12.4 → 3.13.0
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/demo.html +1017 -0
- package/docs/dist/rip.js +9483 -0
- package/docs/dist/rip.min.js +116 -102
- package/docs/dist/rip.min.js.br +0 -0
- package/package.json +1 -1
- package/src/app.rip +14 -5
- package/src/compiler.js +20 -2
- package/src/components.js +3 -2
- package/src/typecheck.js +19 -0
package/docs/dist/rip.min.js.br
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/src/app.rip
CHANGED
|
@@ -661,6 +661,7 @@ export createRenderer = (opts = {}) ->
|
|
|
661
661
|
|
|
662
662
|
currentComponent = null
|
|
663
663
|
currentRoute = null
|
|
664
|
+
currentParams = null
|
|
664
665
|
currentLayouts = []
|
|
665
666
|
layoutInstances = []
|
|
666
667
|
mountPoint = container
|
|
@@ -688,7 +689,7 @@ export createRenderer = (opts = {}) ->
|
|
|
688
689
|
for inst in layoutInstances by -1
|
|
689
690
|
inst.beforeUnmount() if inst.beforeUnmount
|
|
690
691
|
inst.unmounted() if inst.unmounted
|
|
691
|
-
inst.
|
|
692
|
+
inst._target?.remove()
|
|
692
693
|
layoutInstances = []
|
|
693
694
|
mountPoint = container
|
|
694
695
|
|
|
@@ -702,7 +703,9 @@ export createRenderer = (opts = {}) ->
|
|
|
702
703
|
mountRoute = (info) ->
|
|
703
704
|
{ route, params, layouts: layoutFiles, query } = info
|
|
704
705
|
return unless route
|
|
705
|
-
|
|
706
|
+
if route.file is currentRoute and JSON.stringify(params) is JSON.stringify(currentParams)
|
|
707
|
+
return
|
|
708
|
+
currentParams = params
|
|
706
709
|
|
|
707
710
|
gen = ++generation
|
|
708
711
|
router.navigating = true
|
|
@@ -724,7 +727,7 @@ export createRenderer = (opts = {}) ->
|
|
|
724
727
|
return
|
|
725
728
|
|
|
726
729
|
layoutsChanged = not arraysEqual(layoutFiles, currentLayouts)
|
|
727
|
-
|
|
730
|
+
oldTarget = currentComponent?._target
|
|
728
731
|
|
|
729
732
|
if layoutsChanged
|
|
730
733
|
unmount()
|
|
@@ -768,7 +771,7 @@ export createRenderer = (opts = {}) ->
|
|
|
768
771
|
cached = componentCache.get(route.file)
|
|
769
772
|
if cached
|
|
770
773
|
componentCache.delete route.file
|
|
771
|
-
mp.appendChild cached.
|
|
774
|
+
mp.appendChild cached._target
|
|
772
775
|
currentComponent = cached
|
|
773
776
|
currentRoute = route.file
|
|
774
777
|
else
|
|
@@ -783,7 +786,7 @@ export createRenderer = (opts = {}) ->
|
|
|
783
786
|
currentRoute = route.file
|
|
784
787
|
|
|
785
788
|
instance.load!(params, query) if instance.load
|
|
786
|
-
|
|
789
|
+
oldTarget?.remove()
|
|
787
790
|
router.navigating = false
|
|
788
791
|
if container.style.opacity is '0'
|
|
789
792
|
document.fonts.ready.then ->
|
|
@@ -857,6 +860,12 @@ connectWatch = (url) ->
|
|
|
857
860
|
console.log '[Rip] Reloading...'
|
|
858
861
|
location.reload()
|
|
859
862
|
|
|
863
|
+
es.addEventListener 'css', ->
|
|
864
|
+
for link as document.querySelectorAll('link[rel="stylesheet"]')
|
|
865
|
+
url = new URL(link.href)
|
|
866
|
+
url.searchParams.set('_t', Date.now())
|
|
867
|
+
link.href = url.toString()
|
|
868
|
+
|
|
860
869
|
es.onerror = ->
|
|
861
870
|
es.close()
|
|
862
871
|
setTimeout connect, retryDelay
|
package/src/compiler.js
CHANGED
|
@@ -637,8 +637,26 @@ export class CodeGenerator {
|
|
|
637
637
|
let skip = this.options.skipPreamble;
|
|
638
638
|
|
|
639
639
|
if (!skip) {
|
|
640
|
-
|
|
641
|
-
|
|
640
|
+
|
|
641
|
+
// Standard library — always available, override by redeclaring
|
|
642
|
+
if (needsBlank) code += '\n';
|
|
643
|
+
code += 'globalThis.abort ??= (msg) => { if (msg) console.error(msg); process.exit(1); };\n';
|
|
644
|
+
code += 'globalThis.assert ??= (v, msg) => { if (!v) throw new Error(msg || "Assertion failed"); };\n';
|
|
645
|
+
code += 'globalThis.exit ??= (code) => process.exit(code || 0);\n';
|
|
646
|
+
code += 'globalThis.kind ??= (v) => v != null ? (v.constructor?.name || Object.prototype.toString.call(v).slice(8, -1)).toLowerCase() : String(v);\n';
|
|
647
|
+
code += 'globalThis.noop ??= () => {};\n';
|
|
648
|
+
code += 'globalThis.p ??= console.log;\n';
|
|
649
|
+
code += 'globalThis.pp ??= (v) => { console.log(JSON.stringify(v, null, 2)); return v; };\n';
|
|
650
|
+
code += 'globalThis.raise ??= (a, b) => { throw (b !== undefined ? new a(b) : new Error(a)); };\n';
|
|
651
|
+
code += 'globalThis.rand ??= (a, b) => b !== undefined ? (a > b && ([a, b] = [b, a]), Math.floor(Math.random() * (b - a + 1) + a)) : a ? Math.floor(Math.random() * a) : Math.random();\n';
|
|
652
|
+
code += 'globalThis.sleep ??= (ms) => new Promise(r => setTimeout(r, ms));\n';
|
|
653
|
+
code += 'globalThis.todo ??= (msg) => { throw new Error(msg || "Not implemented"); };\n';
|
|
654
|
+
code += 'globalThis.warn ??= console.warn;\n';
|
|
655
|
+
code += 'globalThis.zip ??= (...a) => a[0].map((_, i) => a.map(b => b[i]));\n';
|
|
656
|
+
needsBlank = true;
|
|
657
|
+
|
|
658
|
+
if (this.helpers.has('slice' )) { code += 'const slice = [].slice;\n'; needsBlank = true; }
|
|
659
|
+
if (this.helpers.has('modulo' )) { code += 'const modulo = (n, d) => { n = +n; d = +d; return (n % d + d) % d; };\n'; needsBlank = true; }
|
|
642
660
|
if (this.helpers.has('toMatchable')) {
|
|
643
661
|
code += 'const toMatchable = (v, allowNewlines) => {\n';
|
|
644
662
|
code += ' if (typeof v === "string") return !allowNewlines && /[\\n\\r]/.test(v) ? null : v;\n';
|
package/src/components.js
CHANGED
|
@@ -729,13 +729,14 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
729
729
|
// Effects
|
|
730
730
|
for (const effect of effects) {
|
|
731
731
|
const effectBody = effect[2];
|
|
732
|
+
const isAsync = this.containsAwait(effectBody) ? 'async ' : '';
|
|
732
733
|
if (this.is(effectBody, 'block') && effectBody.length > 2) {
|
|
733
734
|
const transformed = this.transformComponentMembers(effectBody);
|
|
734
735
|
const body = this.generateFunctionBody(transformed, [], true);
|
|
735
|
-
lines.push(` __effect(() => ${body});`);
|
|
736
|
+
lines.push(` __effect(${isAsync}() => ${body});`);
|
|
736
737
|
} else {
|
|
737
738
|
const effectCode = this.generateInComponent(effectBody, 'value');
|
|
738
|
-
lines.push(` __effect(() => { ${effectCode}; });`);
|
|
739
|
+
lines.push(` __effect(${isAsync}() => { ${effectCode}; });`);
|
|
739
740
|
}
|
|
740
741
|
}
|
|
741
742
|
|
package/src/typecheck.js
CHANGED
|
@@ -206,6 +206,25 @@ export function compileForCheck(filePath, source, compiler) {
|
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
+
// Interpolate gaps — if src line A maps to gen line X and src line B maps to
|
|
210
|
+
// gen line Y, fill src lines A+1..B-1 → gen lines X+1..Y-1. This gives hover
|
|
211
|
+
// and diagnostics coverage for function body lines that the compiler didn't map.
|
|
212
|
+
const mapped = [...srcToGen.entries()].sort((a, b) => a[0] - b[0]);
|
|
213
|
+
for (let i = 0; i < mapped.length - 1; i++) {
|
|
214
|
+
const [srcA, genA] = mapped[i];
|
|
215
|
+
const [srcB, genB] = mapped[i + 1];
|
|
216
|
+
const srcGap = srcB - srcA;
|
|
217
|
+
const genGap = genB - genA;
|
|
218
|
+
if (srcGap > 1 && genGap > 1 && srcGap <= genGap + 2) {
|
|
219
|
+
for (let d = 1; d < srcGap; d++) {
|
|
220
|
+
if (!srcToGen.has(srcA + d) && genA + d < genB) {
|
|
221
|
+
srcToGen.set(srcA + d, genA + d);
|
|
222
|
+
genToSrc.set(genA + d, srcA + d);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
209
228
|
return { tsContent, headerLines, hasTypes, srcToGen, genToSrc, source };
|
|
210
229
|
}
|
|
211
230
|
|