rip-lang 3.4.4 → 3.4.6

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
@@ -641,7 +641,7 @@ All 962 tests passing (100%) ✅
641
641
  - Zero performance impact, much more maintainable
642
642
 
643
643
  - **Added inline SVG favicon to HTML files**
644
- - repl.html, index.html, example.html now have embedded favicon
644
+ - index.html now has embedded favicon
645
645
  - No HTTP request needed for favicon
646
646
  - Works in all contexts (local, GitHub Pages, offline)
647
647
 
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.4.3-blue.svg" alt="Version"></a>
12
+ <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.4.6-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>
@@ -309,16 +309,17 @@ Simple arrays (with `.loc`) instead of AST node classes. The compiler is self-ho
309
309
 
310
310
  Rip includes optional packages for full-stack development:
311
311
 
312
- | Package | Purpose |
313
- |---------|---------|
314
- | [@rip-lang/ui](packages/ui/) | Zero-build reactive web framework (VFS, router, components) |
315
- | [@rip-lang/api](packages/api/) | HTTP framework (Sinatra-style routing, 37 validators) |
316
- | [@rip-lang/server](packages/server/) | Multi-worker app server (hot reload, HTTPS, mDNS) |
317
- | [@rip-lang/db](packages/db/) | DuckDB server with official UI (pure Bun FFI) |
318
- | [@rip-lang/swarm](packages/swarm/) | Parallel job runner with worker pool |
319
- | [@rip-lang/csv](packages/csv/) | CSV parser + writer |
320
- | [@rip-lang/schema](packages/schema/) | ORM + validation |
321
- | [VS Code Extension](packages/vscode/) | Syntax highlighting, type intelligence, source maps |
312
+ | Package | Version | Purpose |
313
+ |---------|---------|---------|
314
+ | [rip-lang](https://www.npmjs.com/package/rip-lang) | 3.4.4 | Core language compiler |
315
+ | [@rip-lang/api](packages/api/) | 1.1.4 | HTTP framework (Sinatra-style routing, 37 validators) |
316
+ | [@rip-lang/server](packages/server/) | 1.1.3 | Multi-worker app server (hot reload, HTTPS, mDNS) |
317
+ | [@rip-lang/db](packages/db/) | 1.1.2 | DuckDB server with official UI (pure Bun FFI) |
318
+ | [@rip-lang/ui](packages/ui/) | 0.1.2 | Zero-build reactive web framework (VFS, router, components) |
319
+ | [@rip-lang/swarm](packages/swarm/) | 1.1.1 | Parallel job runner with worker pool |
320
+ | [@rip-lang/csv](packages/csv/) | 1.1.1 | CSV parser + writer |
321
+ | [@rip-lang/schema](packages/schema/) | 0.1.0 | ORM + validation |
322
+ | [VS Code Extension](packages/vscode/) | 0.3.1 | Syntax highlighting, type intelligence, source maps |
322
323
 
323
324
  ```bash
324
325
  bun add -g @rip-lang/db # Installs everything (rip-lang + api + db)
@@ -367,11 +368,12 @@ bun run browser # Build browser bundle
367
368
 
368
369
  | Guide | Description |
369
370
  |-------|-------------|
370
- | [docs/RIP-LANG.md](docs/RIP-LANG.md) | Language reference |
371
- | [docs/RIP-REACTIVITY.md](docs/RIP-REACTIVITY.md) | Reactivity deep dive |
372
- | [docs/RIP-INTERNALS.md](docs/RIP-INTERNALS.md) | Compiler internals |
373
- | [packages/](packages/README.md) | Full-stack packages |
374
- | [CONTRIBUTING.md](CONTRIBUTING.md) | How to contribute |
371
+ | [docs/RIP-GUIDE.md](docs/RIP-GUIDE.md) | Users / AI — practical guide for using Rip in projects |
372
+ | [AGENT.md](AGENT.md) | AI agents get up to speed for working on the compiler |
373
+ | [docs/RIP-LANG.md](docs/RIP-LANG.md) | Users full language reference |
374
+ | [docs/RIP-TYPES.md](docs/RIP-TYPES.md) | Contributors type system specification |
375
+ | [docs/RIP-REACTIVITY.md](docs/RIP-REACTIVITY.md) | Users reactivity deep dive |
376
+ | [docs/RIP-INTERNALS.md](docs/RIP-INTERNALS.md) | Contributors — compiler architecture |
375
377
 
376
378
  ---
377
379
 
@@ -0,0 +1,598 @@
1
+ <img src="https://raw.githubusercontent.com/shreeve/rip-lang/main/docs/rip.png" style="width:50px" /> <br>
2
+
3
+ # Rip Guide
4
+
5
+ A practical guide for using Rip in your projects. Rip is a modern language that compiles to ES2022 JavaScript. It runs on [Bun](https://bun.sh) and has zero dependencies.
6
+
7
+ ---
8
+
9
+ ## Getting Started
10
+
11
+ ```bash
12
+ # Install Bun (if needed)
13
+ curl -fsSL https://bun.sh/install | bash
14
+
15
+ # Install Rip
16
+ bun add -g rip-lang
17
+
18
+ # Run a file
19
+ rip app.rip
20
+
21
+ # Interactive REPL
22
+ rip
23
+
24
+ # Compile to JavaScript
25
+ rip -c app.rip
26
+
27
+ # Compile with source map
28
+ rip -cm app.rip
29
+
30
+ # Generate .d.ts type declarations
31
+ rip -d app.rip
32
+ ```
33
+
34
+ Rip files use the `.rip` extension. Bun runs them directly via `bun app.rip` or `rip app.rip`.
35
+
36
+ ---
37
+
38
+ ## Language Basics
39
+
40
+ Rip uses **significant whitespace** (indentation, not braces) and **implicit returns** (the last expression is the return value). Semicolons and parentheses are optional in most contexts.
41
+
42
+ ### Variables
43
+
44
+ ```coffee
45
+ # Assignment (compiles to let)
46
+ name = "Alice"
47
+ count = 0
48
+
49
+ # Constant ("equals, dammit!")
50
+ MAX =! 100
51
+
52
+ # Destructuring
53
+ {name, age} = person
54
+ [first, ...rest] = items
55
+ ```
56
+
57
+ ### Strings
58
+
59
+ ```coffee
60
+ # Interpolation (both styles work)
61
+ greeting = "Hello, #{name}!"
62
+ greeting = "Hello, ${name}!"
63
+
64
+ # Heredocs (closing delimiter sets left margin)
65
+ html = """
66
+ <div>
67
+ <p>Hello</p>
68
+ </div>
69
+ """
70
+ ```
71
+
72
+ ### Functions
73
+
74
+ ```coffee
75
+ # Named function
76
+ def greet(name)
77
+ "Hello, #{name}!"
78
+
79
+ # Arrow function
80
+ add = (a, b) -> a + b
81
+
82
+ # Fat arrow (preserves this)
83
+ handler = (e) => @process(e)
84
+
85
+ # Default parameters
86
+ def greet(name = "World")
87
+ "Hello, #{name}!"
88
+
89
+ # Void function (suppresses return)
90
+ def log!(message)
91
+ console.log message
92
+ ```
93
+
94
+ ### Classes
95
+
96
+ ```coffee
97
+ class Animal
98
+ constructor: (@name) ->
99
+
100
+ speak: -> "#{@name} makes a sound"
101
+
102
+ class Dog extends Animal
103
+ speak: -> "#{@name} barks!"
104
+
105
+ # Ruby-style instantiation
106
+ dog = Dog.new "Buddy"
107
+ ```
108
+
109
+ ### Control Flow
110
+
111
+ ```coffee
112
+ # If/else
113
+ if user.admin
114
+ showAdmin()
115
+ else
116
+ showUser()
117
+
118
+ # Ternary
119
+ status = active ? "on" : "off"
120
+
121
+ # Postfix
122
+ console.log "hi" if ready
123
+ return unless valid
124
+
125
+ # Switch
126
+ result = switch status
127
+ when "active" then "Running"
128
+ when "done" then "Complete"
129
+ else "Unknown"
130
+ ```
131
+
132
+ ### Loops
133
+
134
+ ```coffee
135
+ # Arrays
136
+ for item in items
137
+ console.log item
138
+
139
+ for item, i in items # with index
140
+ console.log "#{i}: #{item}"
141
+
142
+ # Objects
143
+ for key, value of object
144
+ console.log "#{key} = #{value}"
145
+
146
+ # Ranges
147
+ for i in [1..10] # inclusive (1 to 10)
148
+ for i in [1...10] # exclusive (1 to 9)
149
+
150
+ # Comprehensions
151
+ squares = (x * x for x in [1..10])
152
+ evens = (x for x in items when x % 2 is 0)
153
+ ```
154
+
155
+ ---
156
+
157
+ ## Operators
158
+
159
+ Rip extends JavaScript with powerful operators:
160
+
161
+ | Operator | Name | Example | Result |
162
+ |----------|------|---------|--------|
163
+ | `!` | Dammit | `fetchData!` | `await fetchData()` |
164
+ | `!` | Void | `def log!` | Function returns `undefined` |
165
+ | `=!` | Readonly | `MAX =! 100` | `const MAX = 100` |
166
+ | `!?` | Otherwise | `val !? 5` | Default if undefined/throws |
167
+ | `?` | Existence | `x?` | `x != null` |
168
+ | `?.` | Optional chain | `a?.b?.c` | ES6 optional chaining |
169
+ | `?[]` | Optional index | `arr?[0]` | `arr?.[0]` |
170
+ | `??` | Nullish | `a ?? b` | ES6 nullish coalescing |
171
+ | `//` | Floor div | `7 // 2` | `3` |
172
+ | `%%` | True modulo | `-1 %% 3` | `2` (always positive) |
173
+ | `=~` | Regex match | `str =~ /pat/` | Match, captures in `_` |
174
+ | `:=` | State | `count := 0` | Reactive signal |
175
+ | `~=` | Computed | `doubled ~= x * 2` | Reactive computed |
176
+ | `~>` | Effect | `~> console.log x` | Reactive side effect |
177
+ | `**` | Power | `2 ** 10` | `1024` |
178
+ | `..` | Range | `[1..5]` | Inclusive range |
179
+ | `...` | Spread/rest | `[...a, ...b]` | ES6 spread |
180
+
181
+ ### Dammit Operator (`!`)
182
+
183
+ The most distinctive Rip operator. Appended to a function call, it both calls AND awaits:
184
+
185
+ ```coffee
186
+ # These are equivalent:
187
+ data = fetchUsers!
188
+ data = await fetchUsers()
189
+
190
+ # With arguments:
191
+ user = getUser!(id)
192
+ user = await getUser(id)
193
+
194
+ # Functions are auto-async when they contain !
195
+ def loadData(id)
196
+ user = getUser!(id)
197
+ posts = getPosts!(user.id)
198
+ {user, posts}
199
+ # Compiles to: async function loadData(id) { ... }
200
+ ```
201
+
202
+ ### Regex Match (`=~`)
203
+
204
+ Ruby-style pattern matching with captures stored in `_`:
205
+
206
+ ```coffee
207
+ if text =~ /Hello, (\w+)/
208
+ console.log "Found: #{_[1]}"
209
+
210
+ # Direct extraction via regex indexing
211
+ domain = "user@example.com"[/@(.+)$/, 1] # "example.com"
212
+ ```
213
+
214
+ ### Guard Clauses
215
+
216
+ ```coffee
217
+ def loadUser(id)
218
+ data = fetchUser!(id) or return {error: "Not found"}
219
+ token = headers.auth or throw new Error "No auth"
220
+ port = config.port ?? return 3000
221
+ ```
222
+
223
+ ### Implicit Commas
224
+
225
+ When a literal value is followed by an arrow function, Rip inserts a comma automatically:
226
+
227
+ ```coffee
228
+ # Clean route handlers
229
+ get '/users' -> User.all!
230
+ get '/users/:id' -> User.find params.id
231
+ post '/users' -> User.create body
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Reactivity
237
+
238
+ Rip provides fine-grained reactivity as language-level operators, not library imports:
239
+
240
+ ```coffee
241
+ # State — reactive container
242
+ count := 0
243
+
244
+ # Computed — derived value (lazy, cached)
245
+ doubled ~= count * 2
246
+ message ~= "Count is #{count}"
247
+
248
+ # Effect — side effect, re-runs when dependencies change
249
+ ~> console.log "Count changed to #{count}"
250
+
251
+ # Update state (triggers dependents)
252
+ count = 5
253
+ # doubled is now 10
254
+ # effect logs: "Count changed to 5"
255
+ ```
256
+
257
+ ### Reactive Methods
258
+
259
+ ```coffee
260
+ count := 0
261
+ count.read() # Get value without tracking
262
+ count.lock() # Make readonly
263
+ count.free() # Unsubscribe from dependencies
264
+ count.kill() # Clean up, return final value
265
+ ```
266
+
267
+ ---
268
+
269
+ ## Type Annotations
270
+
271
+ Rip's optional type system adds annotations that are **erased** from JavaScript output and **emitted** as `.d.ts` files for TypeScript interoperability.
272
+
273
+ ```coffee
274
+ # Annotate parameters and return types
275
+ def greet(name:: string):: string
276
+ "Hello, #{name}!"
277
+
278
+ # Type aliases
279
+ User ::= type
280
+ id: number
281
+ name: string
282
+ email?: string # optional property
283
+
284
+ # Interfaces
285
+ interface Animal
286
+ name: string
287
+ speak: => void
288
+
289
+ # Enums (emit runtime JS + .d.ts)
290
+ enum Status
291
+ Active
292
+ Inactive
293
+ Pending
294
+
295
+ # Generate .d.ts
296
+ # rip -d myfile.rip
297
+ ```
298
+
299
+ ---
300
+
301
+ ## Modules
302
+
303
+ Standard ES6 module syntax:
304
+
305
+ ```coffee
306
+ # Import
307
+ import express from 'express'
308
+ import { readFile } from 'fs'
309
+ import * as path from 'path'
310
+
311
+ # Export
312
+ export def processData(data)
313
+ data.map (x) -> x * 2
314
+
315
+ export default { process: processData }
316
+
317
+ # Re-export
318
+ export { foo, bar } from './utils'
319
+ ```
320
+
321
+ ---
322
+
323
+ ## Async Patterns
324
+
325
+ ```coffee
326
+ # Traditional await
327
+ user = await getUser(id)
328
+
329
+ # Dammit operator (call + await)
330
+ user = getUser!(id)
331
+ posts = getPosts!(user.id)
332
+
333
+ # Error handling
334
+ try
335
+ data = fetchData!
336
+ catch error
337
+ console.error error
338
+
339
+ # Async iteration
340
+ for item as! asyncIterable
341
+ console.log item
342
+ ```
343
+
344
+ ---
345
+
346
+ ## Packages
347
+
348
+ Rip includes optional packages for full-stack development. All are written in Rip, have zero dependencies, and run on Bun.
349
+
350
+ ```bash
351
+ bun add @rip-lang/api # Web framework
352
+ bun add @rip-lang/server # Production server
353
+ bun add @rip-lang/db # DuckDB server
354
+ bun add @rip-lang/ui # Reactive web UI
355
+ bun add @rip-lang/schema # ORM + validation
356
+ bun add @rip-lang/swarm # Parallel job runner
357
+ bun add @rip-lang/csv # CSV parser + writer
358
+ ```
359
+
360
+ ### @rip-lang/api — Web Framework
361
+
362
+ Sinatra-style routing with `@` context magic and 37 built-in validators.
363
+
364
+ ```coffee
365
+ import { get, post, use, read, start, notFound } from '@rip-lang/api'
366
+
367
+ # Routes — return data directly
368
+ get '/' -> { message: 'Hello!' }
369
+ get '/users/:id' -> User.find!(read 'id', 'id!')
370
+
371
+ # Form validation with read()
372
+ post '/signup' ->
373
+ email = read 'email', 'email!' # required email
374
+ age = read 'age', 'int', [18, 120] # integer between 18-120
375
+ role = read 'role', ['admin', 'user'] # enum
376
+ { success: true, email, age, role }
377
+
378
+ # File serving
379
+ get '/css/*' -> @send "public/#{@req.path.slice(5)}"
380
+ notFound -> @send 'index.html', 'text/html; charset=UTF-8'
381
+
382
+ # Middleware
383
+ import { cors, logger, sessions } from '@rip-lang/api/middleware'
384
+
385
+ use logger()
386
+ use cors origin: '*'
387
+ use sessions secret: process.env.SECRET
388
+
389
+ # Lifecycle hooks
390
+ before -> @start = Date.now()
391
+ after -> console.log "#{@req.method} #{@req.path} - #{Date.now() - @start}ms"
392
+
393
+ start port: 3000
394
+ ```
395
+
396
+ #### read() Validators
397
+
398
+ ```coffee
399
+ id = read 'id', 'id!' # positive integer (required)
400
+ count = read 'count', 'whole' # non-negative integer
401
+ price = read 'price', 'money' # cents (multiplies by 100)
402
+ name = read 'name', 'string' # collapses whitespace
403
+ email = read 'email', 'email' # valid email format
404
+ phone = read 'phone', 'phone' # US phone → (555) 123-4567
405
+ state = read 'state', 'state' # two-letter → uppercase
406
+ zip = read 'zip', 'zip' # 5-digit zip
407
+ url = read 'url', 'url' # valid URL
408
+ uuid = read 'id', 'uuid' # UUID format
409
+ date = read 'date', 'date' # YYYY-MM-DD
410
+ time = read 'time', 'time' # HH:MM or HH:MM:SS
411
+ flag = read 'flag', 'bool' # boolean
412
+ tags = read 'tags', 'array' # must be array
413
+ ids = read 'ids', 'ids' # "1,2,3" → [1, 2, 3]
414
+ slug = read 'slug', 'slug' # URL-safe slug
415
+ ```
416
+
417
+ ### @rip-lang/server — Production Server
418
+
419
+ Multi-worker process manager with hot reload, HTTPS, and mDNS.
420
+
421
+ ```bash
422
+ rip-server # Start (uses ./index.rip)
423
+ rip-server -w # With file watching + hot-reload
424
+ rip-server myapp # Named (accessible at myapp.local)
425
+ rip-server http:3000 # HTTP on specific port
426
+ ```
427
+
428
+ ### @rip-lang/db — DuckDB Server
429
+
430
+ HTTP server for DuckDB with JSONCompact responses.
431
+
432
+ ```bash
433
+ rip-db mydata.duckdb --port=4000
434
+ ```
435
+
436
+ ```coffee
437
+ # Query from Rip
438
+ import { get, start } from '@rip-lang/api'
439
+ import { DB } from '@rip-lang/db'
440
+
441
+ db = DB.new 'data.duckdb'
442
+
443
+ get '/users' -> db.query! "SELECT * FROM users"
444
+ get '/users/:id' -> db.query! "SELECT * FROM users WHERE id = ?", [read 'id', 'id!']
445
+
446
+ start port: 3000
447
+ ```
448
+
449
+ ### @rip-lang/ui — Reactive Web Framework
450
+
451
+ Zero-build framework. Ships the 40KB compiler to the browser and compiles `.rip` components on demand.
452
+
453
+ ```coffee
454
+ # Server setup (index.rip)
455
+ import { get, use, start, notFound } from '@rip-lang/api'
456
+ import { ripUI } from '@rip-lang/ui/serve'
457
+
458
+ dir = import.meta.dir
459
+ use ripUI pages: "#{dir}/pages", watch: true
460
+ notFound -> @send "#{dir}/index.html", 'text/html; charset=UTF-8'
461
+ start port: 3000
462
+ ```
463
+
464
+ ```coffee
465
+ # Component (pages/counter.rip)
466
+ Counter = component
467
+ @count := 0
468
+ doubled ~= @count * 2
469
+
470
+ increment: -> @count += 1
471
+
472
+ render
473
+ div.counter
474
+ h1 "Count: #{@count}"
475
+ p "Doubled: #{doubled}"
476
+ button @click: @increment, "+"
477
+ ```
478
+
479
+ ### @rip-lang/swarm — Parallel Job Runner
480
+
481
+ ```coffee
482
+ import { swarm, init, retry, todo } from '@rip-lang/swarm'
483
+
484
+ setup = ->
485
+ unless retry()
486
+ init()
487
+ for i in [1..100] then todo(i)
488
+
489
+ perform = (task, ctx) ->
490
+ await Bun.sleep(Math.random() * 1000)
491
+
492
+ swarm { setup, perform }
493
+ ```
494
+
495
+ ### @rip-lang/csv — CSV Parser + Writer
496
+
497
+ ```coffee
498
+ import { CSV } from '@rip-lang/csv'
499
+
500
+ # Parse
501
+ rows = CSV.read "name,age\nAlice,30\nBob,25\n", headers: true
502
+ # [{name: 'Alice', age: '30'}, {name: 'Bob', age: '25'}]
503
+
504
+ # Write
505
+ CSV.save! 'output.csv', rows
506
+ ```
507
+
508
+ ### @rip-lang/schema — ORM + Validation
509
+
510
+ ```coffee
511
+ import { Model } from '@rip-lang/schema'
512
+
513
+ class User extends Model
514
+ @table = 'users'
515
+ @schema
516
+ name: { type: 'string', required: true }
517
+ email: { type: 'email', unique: true }
518
+
519
+ user = User.find!(25)
520
+ user.name = 'Alice'
521
+ user.save!()
522
+ ```
523
+
524
+ ---
525
+
526
+ ## Full-Stack Example
527
+
528
+ A complete API server in Rip:
529
+
530
+ ```coffee
531
+ import { get, post, use, read, start, notFound } from '@rip-lang/api'
532
+ import { cors, logger } from '@rip-lang/api/middleware'
533
+
534
+ use logger()
535
+ use cors origin: '*'
536
+
537
+ # In-memory store
538
+ users = []
539
+ nextId = 1
540
+
541
+ get '/api/users' -> users
542
+
543
+ get '/api/users/:id' ->
544
+ id = read 'id', 'id!'
545
+ user = users.find (u) -> u.id is id
546
+ user or throw { status: 404, message: 'Not found' }
547
+
548
+ post '/api/users' ->
549
+ name = read 'name', 'string!'
550
+ email = read 'email', 'email!'
551
+ user = { id: nextId++, name, email }
552
+ users.push user
553
+ user
554
+
555
+ notFound -> { error: 'Not found' }
556
+
557
+ start port: 3000
558
+ ```
559
+
560
+ ---
561
+
562
+ ## CLI Reference
563
+
564
+ ```bash
565
+ rip # REPL
566
+ rip file.rip # Run
567
+ rip -c file.rip # Compile to JS (stdout)
568
+ rip -o out.js file.rip # Compile to file
569
+ rip -m file.rip # Compile with inline source map
570
+ rip -d file.rip # Generate .d.ts
571
+ rip -t file.rip # Show tokens
572
+ rip -s file.rip # Show S-expressions
573
+ rip -q -c file.rip # Quiet (no headers)
574
+ bun run test # Run test suite (1,140 tests)
575
+ ```
576
+
577
+ ---
578
+
579
+ ## Documentation
580
+
581
+ | Document | Audience | Purpose |
582
+ |----------|----------|---------|
583
+ | **[RIP-GUIDE.md](RIP-GUIDE.md)** | Users / AI | Practical guide for using Rip in projects |
584
+ | **[AGENT.md](../AGENT.md)** | AI agents | Get up to speed for working on the compiler |
585
+ | **[RIP-LANG.md](RIP-LANG.md)** | Users | Full language reference |
586
+ | **[RIP-TYPES.md](RIP-TYPES.md)** | Contributors | Type system specification |
587
+ | **[RIP-REACTIVITY.md](RIP-REACTIVITY.md)** | Users | Reactivity deep dive |
588
+ | **[RIP-INTERNALS.md](RIP-INTERNALS.md)** | Contributors | Compiler architecture |
589
+
590
+ ## Resources
591
+
592
+ - [Rip Playground](https://shreeve.github.io/rip-lang/) — Try Rip in the browser
593
+ - [VS Code Extension](https://marketplace.visualstudio.com/items?itemName=rip-lang.rip) — IDE support
594
+ - [GitHub](https://github.com/shreeve/rip-lang) — Source code
595
+
596
+ ---
597
+
598
+ *Rip — Start simple. Build incrementally. Ship elegantly.*
@@ -1,4 +1,6 @@
1
- # Rip Compiler Internals
1
+ <img src="https://raw.githubusercontent.com/shreeve/rip-lang/main/docs/rip.png" style="width:50px" /> <br>
2
+
3
+ # Rip Internals
2
4
 
3
5
  > Architecture, design decisions, and technical reference for the Rip compiler.
4
6
 
@@ -570,6 +572,7 @@ rip> .js # Toggle JS display
570
572
  ---
571
573
 
572
574
  **See Also:**
575
+ - [RIP-GUIDE.md](RIP-GUIDE.md) — Practical guide for using Rip
573
576
  - [RIP-LANG.md](RIP-LANG.md) — Language reference
574
577
  - [RIP-TYPES.md](RIP-TYPES.md) — Type system specification
575
578
  - [RIP-REACTIVITY.md](RIP-REACTIVITY.md) — Reactivity deep dive
package/docs/RIP-LANG.md CHANGED
@@ -1,3 +1,5 @@
1
+ <img src="https://raw.githubusercontent.com/shreeve/rip-lang/main/docs/rip.png" style="width:50px" /> <br>
2
+
1
3
  # Rip 3.0 Language Reference
2
4
 
3
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.
@@ -1,4 +1,6 @@
1
- # Rip Reactivity System
1
+ <img src="https://raw.githubusercontent.com/shreeve/rip-lang/main/docs/rip.png" style="width:50px" /> <br>
2
+
3
+ # Rip Reactivity
2
4
 
3
5
  Rip implements a **fine-grained reactive system** that rivals and often exceeds the capabilities of major frameworks like Vue, Svelte, Solid, and React — in just ~200 lines of runtime code.
4
6
 
package/docs/RIP-TYPES.md CHANGED
@@ -1,3 +1,5 @@
1
+ <img src="https://raw.githubusercontent.com/shreeve/rip-lang/main/docs/rip.png" style="width:50px" /> <br>
2
+
1
3
  # Rip Types
2
4
 
3
5
  > **Types describe what you mean. Code does what you say.**