rip-lang 3.4.6 → 3.6.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/CHANGELOG.md +11 -0
- package/README.md +19 -11
- package/docs/RIP-GUIDE.md +16 -5
- package/docs/RIP-LANG.md +1 -1
- package/docs/dist/rip.browser.js +39 -7
- package/docs/dist/rip.browser.min.js +88 -85
- package/docs/dist/rip.browser.min.js.br +0 -0
- package/docs/index.html +7 -4
- package/package.json +3 -3
- package/src/browser.js +51 -11
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,17 @@ All notable changes to Rip will be documented in this file.
|
|
|
7
7
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
8
8
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
9
9
|
|
|
10
|
+
## [3.6.0] - 2026-02-10
|
|
11
|
+
|
|
12
|
+
### Browser Runtime — Full Async/Await Support
|
|
13
|
+
|
|
14
|
+
- **`rip()` console REPL** — Wraps user code in a Rip `do ->` block, so the compiler handles implicit return and auto-async natively. Sync code returns values directly; async code returns a Promise (use `await rip("...")` in the console). Variables persist on `globalThis` across calls.
|
|
15
|
+
- **`importRip(url)`** — Fetch, compile, and import `.rip` files as ES modules via blob URL. Registered on `globalThis` for use in `<script type="text/rip">` blocks.
|
|
16
|
+
- **Async `<script type="text/rip">`** — `processRipScripts` wraps compiled code in an async IIFE, enabling `await` (Rip's `!` operator) in inline scripts.
|
|
17
|
+
- **Playground** — Run button uses async IIFE for `await` support. Cmd+Enter shortcut registered on Monaco editor.
|
|
18
|
+
- **Eager reactive runtime** — `globalThis.__rip` is registered when `rip.browser.js` loads, making reactive primitives available to framework code.
|
|
19
|
+
- **`compileToJS` on globalThis** — The compiler function is globally accessible for framework auto-detection.
|
|
20
|
+
|
|
10
21
|
## [3.4.3] - 2026-02-09
|
|
11
22
|
|
|
12
23
|
### Source Maps & IDE Intelligence
|
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.
|
|
12
|
+
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.6.0-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-1140%2F1140-brightgreen.svg" alt="Tests"></a>
|
|
15
15
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
|
|
@@ -242,7 +242,7 @@ Counter = component
|
|
|
242
242
|
|
|
243
243
|
Two keywords — `component` and `render` — are all the language adds. Everything else (`:=` state, `~=` computed, methods, lifecycle) is standard Rip.
|
|
244
244
|
|
|
245
|
-
See [@rip-lang/ui](packages/ui/) for the full framework:
|
|
245
|
+
See [@rip-lang/ui](packages/ui/) for the full framework: file-based router, reactive stash, parts system, and component renderer.
|
|
246
246
|
|
|
247
247
|
---
|
|
248
248
|
|
|
@@ -264,17 +264,25 @@ Smaller codebase, modern output, built-in reactivity.
|
|
|
264
264
|
|
|
265
265
|
## Browser
|
|
266
266
|
|
|
267
|
-
Run Rip directly in the browser:
|
|
267
|
+
Run Rip directly in the browser — inline scripts and the console REPL both support `await` via the `!` operator:
|
|
268
268
|
|
|
269
269
|
```html
|
|
270
|
-
<script src="
|
|
270
|
+
<script type="module" src="/rip/browser.js"></script>
|
|
271
271
|
<script type="text/rip">
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
272
|
+
res = fetch! 'https://api.example.com/data'
|
|
273
|
+
data = res.json!
|
|
274
|
+
console.log data
|
|
275
275
|
</script>
|
|
276
276
|
```
|
|
277
277
|
|
|
278
|
+
The `rip()` function is available in the browser console:
|
|
279
|
+
|
|
280
|
+
```javascript
|
|
281
|
+
rip("42 * 10 + 8") // → 428
|
|
282
|
+
rip("(x * x for x in [1..5])") // → [1, 4, 9, 16, 25]
|
|
283
|
+
await rip("res = fetch! 'https://api.example.com/todos/1'; res.json!") // → {id: 1, ...}
|
|
284
|
+
```
|
|
285
|
+
|
|
278
286
|
**Try it live:** [shreeve.github.io/rip-lang](https://shreeve.github.io/rip-lang/)
|
|
279
287
|
|
|
280
288
|
---
|
|
@@ -299,9 +307,9 @@ Simple arrays (with `.loc`) instead of AST node classes. The compiler is self-ho
|
|
|
299
307
|
| Grammar | `src/grammar/grammar.rip` | 935 |
|
|
300
308
|
| Parser Generator | `src/grammar/solar.rip` | 916 |
|
|
301
309
|
| REPL | `src/repl.js` | 707 |
|
|
302
|
-
| Browser Entry | `src/browser.js` |
|
|
310
|
+
| Browser Entry | `src/browser.js` | 107 |
|
|
303
311
|
| Tags | `src/tags.js` | 63 |
|
|
304
|
-
| **Total** | |
|
|
312
|
+
| **Total** | | **~10,325** |
|
|
305
313
|
|
|
306
314
|
---
|
|
307
315
|
|
|
@@ -311,11 +319,11 @@ Rip includes optional packages for full-stack development:
|
|
|
311
319
|
|
|
312
320
|
| Package | Version | Purpose |
|
|
313
321
|
|---------|---------|---------|
|
|
314
|
-
| [rip-lang](https://www.npmjs.com/package/rip-lang) | 3.
|
|
322
|
+
| [rip-lang](https://www.npmjs.com/package/rip-lang) | 3.6.0 | Core language compiler |
|
|
315
323
|
| [@rip-lang/api](packages/api/) | 1.1.4 | HTTP framework (Sinatra-style routing, 37 validators) |
|
|
316
324
|
| [@rip-lang/server](packages/server/) | 1.1.3 | Multi-worker app server (hot reload, HTTPS, mDNS) |
|
|
317
325
|
| [@rip-lang/db](packages/db/) | 1.1.2 | DuckDB server with official UI (pure Bun FFI) |
|
|
318
|
-
| [@rip-lang/ui](packages/ui/) | 0.
|
|
326
|
+
| [@rip-lang/ui](packages/ui/) | 0.2.0 | Zero-build reactive web framework (stash, router, components) |
|
|
319
327
|
| [@rip-lang/swarm](packages/swarm/) | 1.1.1 | Parallel job runner with worker pool |
|
|
320
328
|
| [@rip-lang/csv](packages/csv/) | 1.1.1 | CSV parser + writer |
|
|
321
329
|
| [@rip-lang/schema](packages/schema/) | 0.1.0 | ORM + validation |
|
package/docs/RIP-GUIDE.md
CHANGED
|
@@ -448,22 +448,33 @@ start port: 3000
|
|
|
448
448
|
|
|
449
449
|
### @rip-lang/ui — Reactive Web Framework
|
|
450
450
|
|
|
451
|
-
Zero-build framework.
|
|
451
|
+
Zero-build framework. The browser loads the Rip compiler, compiles the UI
|
|
452
|
+
framework, fetches an app bundle, and renders. No build step, no bundler.
|
|
452
453
|
|
|
453
454
|
```coffee
|
|
454
|
-
# Server
|
|
455
|
+
# Server (index.rip)
|
|
455
456
|
import { get, use, start, notFound } from '@rip-lang/api'
|
|
456
457
|
import { ripUI } from '@rip-lang/ui/serve'
|
|
457
458
|
|
|
458
459
|
dir = import.meta.dir
|
|
459
|
-
use ripUI
|
|
460
|
+
use ripUI dir: dir, watch: true, title: 'My App'
|
|
461
|
+
get '/css/*', -> @send "#{dir}/css/#{@req.path.slice(5)}"
|
|
460
462
|
notFound -> @send "#{dir}/index.html", 'text/html; charset=UTF-8'
|
|
461
463
|
start port: 3000
|
|
462
464
|
```
|
|
463
465
|
|
|
466
|
+
```html
|
|
467
|
+
<!-- index.html -->
|
|
468
|
+
<script type="module" src="/rip/browser.js"></script>
|
|
469
|
+
<script type="text/rip">
|
|
470
|
+
{ launch } = importRip! '/rip/ui.rip'
|
|
471
|
+
launch()
|
|
472
|
+
</script>
|
|
473
|
+
```
|
|
474
|
+
|
|
464
475
|
```coffee
|
|
465
|
-
# Component (
|
|
466
|
-
Counter = component
|
|
476
|
+
# Component (parts/counter.rip)
|
|
477
|
+
export Counter = component
|
|
467
478
|
@count := 0
|
|
468
479
|
doubled ~= @count * 2
|
|
469
480
|
|
package/docs/RIP-LANG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<img src="https://raw.githubusercontent.com/shreeve/rip-lang/main/docs/rip.png" style="width:50px" /> <br>
|
|
2
2
|
|
|
3
|
-
# Rip
|
|
3
|
+
# Rip Language Reference
|
|
4
4
|
|
|
5
5
|
Rip is a modern reactive language that compiles to ES2022 JavaScript. It combines CoffeeScript's elegant syntax with built-in reactivity primitives. Zero dependencies, self-hosting, ~10,300 LOC.
|
|
6
6
|
|
package/docs/dist/rip.browser.js
CHANGED
|
@@ -7560,8 +7560,11 @@ function getComponentRuntime() {
|
|
|
7560
7560
|
return new CodeGenerator({}).getComponentRuntime();
|
|
7561
7561
|
}
|
|
7562
7562
|
// src/browser.js
|
|
7563
|
-
var VERSION = "3.
|
|
7564
|
-
var BUILD_DATE = "2026-02-
|
|
7563
|
+
var VERSION = "3.6.0";
|
|
7564
|
+
var BUILD_DATE = "2026-02-10@22:03:34GMT";
|
|
7565
|
+
if (typeof globalThis !== "undefined" && !globalThis.__rip) {
|
|
7566
|
+
new Function(getReactiveRuntime())();
|
|
7567
|
+
}
|
|
7565
7568
|
var dedent = (s) => {
|
|
7566
7569
|
const m = s.match(/^[ \t]*(?=\S)/gm);
|
|
7567
7570
|
const i = Math.min(...(m || []).map((x) => x.length));
|
|
@@ -7575,7 +7578,9 @@ async function processRipScripts() {
|
|
|
7575
7578
|
try {
|
|
7576
7579
|
const ripCode = dedent(script.textContent);
|
|
7577
7580
|
const jsCode = compileToJS(ripCode);
|
|
7578
|
-
(0, eval)(
|
|
7581
|
+
await (0, eval)(`(async()=>{
|
|
7582
|
+
${jsCode}
|
|
7583
|
+
})()`);
|
|
7579
7584
|
script.setAttribute("data-rip-processed", "true");
|
|
7580
7585
|
} catch (error) {
|
|
7581
7586
|
console.error("Error compiling Rip script:", error);
|
|
@@ -7590,12 +7595,36 @@ if (typeof document !== "undefined") {
|
|
|
7590
7595
|
processRipScripts();
|
|
7591
7596
|
}
|
|
7592
7597
|
}
|
|
7598
|
+
async function importRip(url) {
|
|
7599
|
+
const source = await fetch(url).then((r) => {
|
|
7600
|
+
if (!r.ok)
|
|
7601
|
+
throw new Error(`importRip: ${url} (${r.status})`);
|
|
7602
|
+
return r.text();
|
|
7603
|
+
});
|
|
7604
|
+
const js = compileToJS(source);
|
|
7605
|
+
const blob = new Blob([js], { type: "application/javascript" });
|
|
7606
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
7607
|
+
try {
|
|
7608
|
+
return await import(blobUrl);
|
|
7609
|
+
} finally {
|
|
7610
|
+
URL.revokeObjectURL(blobUrl);
|
|
7611
|
+
}
|
|
7612
|
+
}
|
|
7593
7613
|
function rip(code) {
|
|
7594
7614
|
try {
|
|
7595
|
-
const
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7615
|
+
const indented = code.replace(/^/gm, " ");
|
|
7616
|
+
const wrapped = compileToJS(`do ->
|
|
7617
|
+
${indented}`);
|
|
7618
|
+
let js = wrapped.replace(/^let\s+[^;]+;\s*\n\s*/m, "");
|
|
7619
|
+
js = js.replace(/^const\s+(\w+)\s*=/gm, "globalThis.$1 =");
|
|
7620
|
+
const result = (0, eval)(js);
|
|
7621
|
+
if (result && typeof result.then === "function") {
|
|
7622
|
+
return result.then((v) => {
|
|
7623
|
+
if (v !== undefined)
|
|
7624
|
+
globalThis._ = v;
|
|
7625
|
+
return v;
|
|
7626
|
+
});
|
|
7627
|
+
}
|
|
7599
7628
|
if (result !== undefined)
|
|
7600
7629
|
globalThis._ = result;
|
|
7601
7630
|
return result;
|
|
@@ -7606,11 +7635,14 @@ function rip(code) {
|
|
|
7606
7635
|
}
|
|
7607
7636
|
if (typeof globalThis !== "undefined") {
|
|
7608
7637
|
globalThis.rip = rip;
|
|
7638
|
+
globalThis.importRip = importRip;
|
|
7639
|
+
globalThis.compileToJS = compileToJS;
|
|
7609
7640
|
}
|
|
7610
7641
|
export {
|
|
7611
7642
|
rip,
|
|
7612
7643
|
processRipScripts,
|
|
7613
7644
|
parser,
|
|
7645
|
+
importRip,
|
|
7614
7646
|
getReactiveRuntime,
|
|
7615
7647
|
getComponentRuntime,
|
|
7616
7648
|
formatSExpr,
|