rip-lang 3.0.2 → 3.1.1
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 +47 -5
- package/README.md +26 -3
- package/docs/RIP-INTERNALS.md +5 -7
- package/docs/RIP-LANG.md +7 -2
- package/docs/dist/rip.browser.js +1670 -333
- package/docs/dist/rip.browser.min.js +298 -224
- package/docs/dist/rip.browser.min.js.br +0 -0
- package/package.json +6 -2
- package/src/browser.js +1 -1
- package/src/compiler.js +46 -5
- package/src/components.js +1239 -0
- package/src/grammar/grammar.rip +37 -1
- package/src/grammar/solar.rip +11 -11
- package/src/lexer.js +286 -2
- package/src/parser.js +216 -214
- package/src/repl.js +53 -1
- package/src/tags.js +62 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,49 @@ 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.1.0] - 2026-02-08
|
|
11
|
+
|
|
12
|
+
### Rip UI — Zero-Build Reactive Web Framework
|
|
13
|
+
|
|
14
|
+
Rip UI inverts the traditional web development model. Instead of building and
|
|
15
|
+
bundling on the server, the 40KB Rip compiler ships to the browser. Components
|
|
16
|
+
are delivered as `.rip` source files, stored in a browser-local Virtual File
|
|
17
|
+
System, compiled on demand, and rendered with fine-grained DOM updates.
|
|
18
|
+
|
|
19
|
+
**Component model** — Two keywords added to the language:
|
|
20
|
+
|
|
21
|
+
- `component` — Declares an anonymous ES6 class with reactive props, computed
|
|
22
|
+
values, effects, methods, and lifecycle hooks. `@` properties become props
|
|
23
|
+
the parent can set. `:=` creates signals, `~=` creates computed values.
|
|
24
|
+
- `render` — Defines a Pug/Jade-like template DSL inside a component. Tags are
|
|
25
|
+
bare identifiers, classes use dot notation (`div.card.active`), dynamic
|
|
26
|
+
classes use dot-parens (`div.("active" if @selected)`), and events use
|
|
27
|
+
`@click: handler`. No virtual DOM — each reactive binding creates a direct
|
|
28
|
+
effect that updates exactly the DOM nodes it touches.
|
|
29
|
+
|
|
30
|
+
**Framework modules** (all in `packages/ui/`):
|
|
31
|
+
|
|
32
|
+
| Module | Role |
|
|
33
|
+
|--------|------|
|
|
34
|
+
| `stash.js` | Deep reactive state tree with path-based navigation |
|
|
35
|
+
| `vfs.js` | Browser-local Virtual File System with file watchers |
|
|
36
|
+
| `router.js` | File-based router (URL ↔ VFS paths, History API) |
|
|
37
|
+
| `renderer.js` | Component lifecycle, layout nesting, route transitions |
|
|
38
|
+
| `ui.js` | `createApp` entry point, re-exports everything |
|
|
39
|
+
|
|
40
|
+
**Compiler changes** (`src/components.js`, 1,193 lines):
|
|
41
|
+
|
|
42
|
+
- 22 methods installed on `CodeGenerator.prototype` via `installComponentSupport()`
|
|
43
|
+
- Categorizes component body into state, computed, readonly, methods, effects, render
|
|
44
|
+
- Emits fine-grained DOM creation (`_create()`) and reactive setup (`_setup()`)
|
|
45
|
+
- Block factories for conditionals and loops with disposable effects
|
|
46
|
+
- Keyed reconciliation for list rendering
|
|
47
|
+
- Component runtime emitted only when `component` keyword is used
|
|
48
|
+
|
|
49
|
+
**No build step. No bundler. No configuration files.**
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
10
53
|
## [3.0.0] - 2026-02-07
|
|
11
54
|
|
|
12
55
|
### Complete Rewrite
|
|
@@ -27,8 +70,6 @@ Rip 3.0 is a ground-up rewrite of the entire compiler pipeline. Every component
|
|
|
27
70
|
#### Removed
|
|
28
71
|
- Postfix spread/rest (`x...`) — use prefix `...x` (ES6)
|
|
29
72
|
- Prototype access (`x::y`, `x?::y`) — use `.prototype` or class syntax
|
|
30
|
-
- Soak call sugar (`fn?(arg)`) — use `fn?.(arg)` (ES6 optional call)
|
|
31
|
-
- Soak index sugar (`arr?[i]`) — use `arr?.[i]` (ES6 optional index)
|
|
32
73
|
- `is not` contraction — use `isnt`
|
|
33
74
|
|
|
34
75
|
#### Added
|
|
@@ -37,15 +78,16 @@ Rip 3.0 is a ground-up rewrite of the entire compiler pipeline. Every component
|
|
|
37
78
|
- `as!` async shorthand: `for x as! iterable` (shorthand for `for await x as iterable`)
|
|
38
79
|
|
|
39
80
|
#### Kept
|
|
40
|
-
- Existence check: `x?` compiles to `(x != null)`
|
|
81
|
+
- Existence check: `x?` compiles to `(x != null)` — works after any expression
|
|
41
82
|
- All reactive operators: `:=`, `~=`, `~>`, `=!`
|
|
42
83
|
- Dammit operator: `x!` compiles to `await x()`
|
|
43
|
-
- Optional chaining: `?.`, `?.[]`, `?.()` (ES6 dot-form
|
|
84
|
+
- Optional chaining: `?.`, `?.[]`, `?.()` (ES6 dot-form)
|
|
85
|
+
- Optional chaining shorthand: `?[]`, `?()` (compiles to `?.[]`, `?.()`)
|
|
44
86
|
- Nullish coalescing: `??`
|
|
45
87
|
- All other CoffeeScript-compatible syntax
|
|
46
88
|
|
|
47
89
|
### Tests
|
|
48
|
-
- 1,
|
|
90
|
+
- 1,073 tests passing (100%)
|
|
49
91
|
- 25 test files across all language features
|
|
50
92
|
|
|
51
93
|
---
|
package/README.md
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
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.1.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
|
-
<a href="#"><img src="https://img.shields.io/badge/tests-
|
|
14
|
+
<a href="#"><img src="https://img.shields.io/badge/tests-1073%2F1073-brightgreen.svg" alt="Tests"></a>
|
|
15
15
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
|
|
16
16
|
</p>
|
|
17
17
|
|
|
@@ -147,6 +147,7 @@ State, computed values, and effects as language operators:
|
|
|
147
147
|
| `?` (existence) | `x?` | True if `x != null` |
|
|
148
148
|
| `?:` (ternary) | `x > 0 ? 'yes' : 'no'` | JS-style ternary expression |
|
|
149
149
|
| `?.` `?.[]` `?.()` | `a?.b` `a?.[0]` `a?.()` | Optional chaining (ES6) |
|
|
150
|
+
| `?[]` `?()` | `a?[0]` `a?(x)` | Optional chaining shorthand |
|
|
150
151
|
| `??` | `a ?? b` | Nullish coalescing |
|
|
151
152
|
| `...` (spread) | `[...items, last]` | Prefix spread (ES6) |
|
|
152
153
|
| `//` | `7 // 2` | Floor division |
|
|
@@ -202,6 +203,27 @@ Rip's reactivity is framework-agnostic — use it with React, Vue, Svelte, or va
|
|
|
202
203
|
|
|
203
204
|
---
|
|
204
205
|
|
|
206
|
+
## Rip UI
|
|
207
|
+
|
|
208
|
+
Ship the 40KB Rip compiler to the browser. Components are `.rip` source files, compiled on demand, rendered with fine-grained reactivity. No build step. No bundler.
|
|
209
|
+
|
|
210
|
+
```coffee
|
|
211
|
+
Counter = component
|
|
212
|
+
@count := 0
|
|
213
|
+
|
|
214
|
+
render
|
|
215
|
+
div.counter
|
|
216
|
+
h1 "Count: #{@count}"
|
|
217
|
+
button @click: (-> @count++), "+"
|
|
218
|
+
button @click: (-> @count--), "-"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Two keywords — `component` and `render` — are all the language adds. Everything else (`:=` state, `~=` computed, methods, lifecycle) is standard Rip.
|
|
222
|
+
|
|
223
|
+
See [@rip-lang/ui](packages/ui/) for the full framework: Virtual File System, file-based router, reactive stash, and component renderer.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
205
227
|
## vs CoffeeScript
|
|
206
228
|
|
|
207
229
|
| Feature | CoffeeScript | Rip |
|
|
@@ -263,6 +285,7 @@ Rip includes optional packages for full-stack development:
|
|
|
263
285
|
|
|
264
286
|
| Package | Purpose | Lines |
|
|
265
287
|
|---------|---------|-------|
|
|
288
|
+
| [@rip-lang/ui](packages/ui/) | Zero-build reactive web framework (VFS, router, components) | ~1,300 |
|
|
266
289
|
| [@rip-lang/api](packages/api/) | HTTP framework (Sinatra-style routing, 37 validators) | ~1,050 |
|
|
267
290
|
| [@rip-lang/server](packages/server/) | Multi-worker app server (hot reload, HTTPS, mDNS) | ~1,210 |
|
|
268
291
|
| [@rip-lang/db](packages/db/) | DuckDB server with official UI (pure Bun FFI) | ~1,740 |
|
|
@@ -303,7 +326,7 @@ rip file.rip # Run
|
|
|
303
326
|
rip -c file.rip # Compile
|
|
304
327
|
rip -t file.rip # Tokens
|
|
305
328
|
rip -s file.rip # S-expressions
|
|
306
|
-
bun run test #
|
|
329
|
+
bun run test # 1073 tests
|
|
307
330
|
bun run parser # Rebuild parser
|
|
308
331
|
bun run browser # Build browser bundle
|
|
309
332
|
```
|
package/docs/RIP-INTERNALS.md
CHANGED
|
@@ -63,7 +63,7 @@ console.log(code);
|
|
|
63
63
|
|
|
64
64
|
| Feature | CoffeeScript | Rip |
|
|
65
65
|
|---------|-------------|------|
|
|
66
|
-
| Optional chaining | 4 soak operators | ES6 `?.` / `?.[]` / `?.()` |
|
|
66
|
+
| Optional chaining | 4 soak operators | ES6 `?.` / `?.[]` / `?.()` + shorthand `?[]` / `?()` |
|
|
67
67
|
| Ternary | No | `x ? a : b` |
|
|
68
68
|
| Regex features | Basic | Ruby-style (`=~`, indexing, captures in `_`) |
|
|
69
69
|
| Async shorthand | No | Dammit operator (`!`) |
|
|
@@ -298,8 +298,6 @@ The `!` suffix on `as` in for-loops (`as!`) emits `FORASAWAIT` instead of `FORAS
|
|
|
298
298
|
|---------|-----------|-------------|
|
|
299
299
|
| Postfix spread/rest | `x...` | `...x` (ES6 prefix only) |
|
|
300
300
|
| Prototype access | `x::y`, `x?::y` | Direct `.prototype` or class syntax; `::` reserved for type annotations |
|
|
301
|
-
| Soak call sugar | `x?(args)` | `x?.(args)` (ES6 optional call) |
|
|
302
|
-
| Soak index sugar | `x?[i]` | `x?.[i]` (ES6 optional index) |
|
|
303
301
|
| `is not` contraction | `x is not y` | `x isnt y` |
|
|
304
302
|
|
|
305
303
|
### Added
|
|
@@ -395,13 +393,15 @@ counter = ->
|
|
|
395
393
|
| `x ?? y` | `x ?? y` |
|
|
396
394
|
| `x ??= 10` | `x ??= 10` |
|
|
397
395
|
|
|
398
|
-
Optional chaining uses ES6 syntax:
|
|
396
|
+
Optional chaining uses ES6 syntax (both forms supported):
|
|
399
397
|
|
|
400
398
|
| Syntax | Compiles To |
|
|
401
399
|
|--------|-------------|
|
|
402
400
|
| `obj?.prop` | `obj?.prop` |
|
|
403
401
|
| `arr?.[0]` | `arr?.[0]` |
|
|
404
402
|
| `fn?.(x)` | `fn?.(x)` |
|
|
403
|
+
| `arr?[0]` | `arr?.[0]` |
|
|
404
|
+
| `fn?(x)` | `fn?.(x)` |
|
|
405
405
|
|
|
406
406
|
## Range Optimization
|
|
407
407
|
|
|
@@ -458,8 +458,6 @@ The `Compiler` class's lexer adapter reconstructs `new String()` wrapping from t
|
|
|
458
458
|
|-----------|--------|--------|
|
|
459
459
|
| `generatePrototype` | `::` | Feature removed from lexer |
|
|
460
460
|
| `generateOptionalPrototype` | `?::` | Feature removed from lexer |
|
|
461
|
-
| `generateSoakIndex` | `?[]` | Replaced by `optindex` / `?.[]` |
|
|
462
|
-
| `generateSoakCall` | `?call` | Replaced by `optcall` / `?.()` |
|
|
463
461
|
|
|
464
462
|
## Renamed: `for-from` → `for-as`
|
|
465
463
|
|
|
@@ -573,4 +571,4 @@ bun src/compare-compilers.js
|
|
|
573
571
|
|
|
574
572
|
---
|
|
575
573
|
|
|
576
|
-
*Rip 3.0
|
|
574
|
+
*Rip 3.0 — 1,073 tests passing — Zero dependencies — Self-hosting — ~7,700 LOC*
|
package/docs/RIP-LANG.md
CHANGED
|
@@ -273,6 +273,7 @@ Multiple lines
|
|
|
273
273
|
| `?` (postfix) | `a?` | Existence check (`a != null`) |
|
|
274
274
|
| `?` (ternary) | `a ? b : c` | Ternary conditional |
|
|
275
275
|
| `?.` `?.[]` `?.()` | `a?.b` `a?.[0]` `a?.()` | Optional chaining (ES6) |
|
|
276
|
+
| `?[]` `?()` | `a?[0]` `a?(x)` | Optional chaining shorthand |
|
|
276
277
|
| `??` | `a ?? b` | Nullish coalescing |
|
|
277
278
|
|
|
278
279
|
## Rip-Specific Operators
|
|
@@ -311,10 +312,14 @@ x ||= val # x = x || val
|
|
|
311
312
|
## Optional Chaining
|
|
312
313
|
|
|
313
314
|
```coffee
|
|
314
|
-
# ES6 optional chaining (dot
|
|
315
|
+
# ES6 optional chaining (with dot)
|
|
315
316
|
user?.profile?.name
|
|
316
317
|
arr?.[0]
|
|
317
318
|
fn?.(arg)
|
|
319
|
+
|
|
320
|
+
# Shorthand (without dot — same behavior)
|
|
321
|
+
arr?[0] # Compiles to arr?.[0]
|
|
322
|
+
fn?(arg) # Compiles to fn?.(arg)
|
|
318
323
|
```
|
|
319
324
|
|
|
320
325
|
## Ternary Operator
|
|
@@ -1123,4 +1128,4 @@ count = 10 # Logs: "Count: 10, Doubled: 20"
|
|
|
1123
1128
|
|
|
1124
1129
|
---
|
|
1125
1130
|
|
|
1126
|
-
*Rip 3.0
|
|
1131
|
+
*Rip 3.0 — 1,073 tests passing — Zero dependencies — Self-hosting — ~7,700 LOC*
|