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 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 only)
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,048 tests passing (100%)
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.0.0-blue.svg" alt="Version"></a>
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-1048%2F1048-brightgreen.svg" alt="Tests"></a>
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 # 1048 tests
329
+ bun run test # 1073 tests
307
330
  bun run parser # Rebuild parser
308
331
  bun run browser # Build browser bundle
309
332
  ```
@@ -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.0 — 1,048 tests passing — Zero dependencies — Self-hosting — ~7,700 LOC*
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 required)
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.0 — 1,048 tests passing — Zero dependencies — Self-hosting — ~7,700 LOC*
1131
+ *Rip 3.0 — 1,073 tests passing — Zero dependencies — Self-hosting — ~7,700 LOC*