rip-lang 3.10.5 → 3.10.7

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,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.10.6] - 2026-02-20
11
+
12
+ ### CLI — Fix Multiline Argument Corruption
13
+
14
+ - **`execSync` → `spawnSync` in `bin/rip`** — The CLI runner was passing script arguments through a shell via `execSync` with string interpolation. Any argument containing a newline (JSON payloads, heredoc content, multiline strings) was silently split into separate shell commands. Replaced all three `execSync` call sites (`.rip` file execution, compiled temp file execution, and `bin/` script fallback) with `spawnSync` using argument arrays, bypassing the shell entirely. Exit codes use `?? 1` (nullish coalescing) instead of `|| 0` for correct signal-kill handling.
15
+
16
+ ### Utilities — `curl.rip` Improvements
17
+
18
+ - **Stdin TTY guard** — `curl.rip` no longer hangs when run interactively without a payload argument. Added `process.stdin.isTTY` check to only read from stdin when piped or heredoc'd.
19
+ - **Documented inline and heredoc modes** — Updated header comments to clearly show both usage patterns.
20
+
10
21
  ## [3.9.1] - 2026-02-18
11
22
 
12
23
  ### Runtime — Reactivity & Reconciliation
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.9.1-blue.svg" alt="Version"></a>
12
+ <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.10.7-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-1%2C243%2F1%2C243-brightgreen.svg" alt="Tests"></a>
15
15
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
@@ -290,8 +290,8 @@ See [@rip-lang/ui](packages/ui/) for the full framework: file-based router, reac
290
290
  | **Dependencies** | Multiple | Zero |
291
291
  | **Self-hosting** | No | Yes |
292
292
  | **Lexer** | 3,558 LOC | 2,024 LOC |
293
- | **Compiler** | 10,346 LOC | 3,289 LOC |
294
- | **Total** | 17,760 LOC | ~9,500 LOC |
293
+ | **Compiler** | 10,346 LOC | 3,293 LOC |
294
+ | **Total** | 17,760 LOC | ~11,100 LOC |
295
295
 
296
296
  Smaller codebase, modern output, built-in reactivity.
297
297
 
@@ -326,7 +326,7 @@ await rip("res = fetch! 'https://api.example.com/todos/1'; res.json!") // → {
326
326
 
327
327
  ```
328
328
  Source -> Lexer -> emitTypes -> Parser -> S-Expressions -> Codegen -> JavaScript
329
- (1,761) (types.js) (359) ["=", "x", 42] (3,291) + source map
329
+ (1,761) (types.js) (359) ["=", "x", 42] (3,293) + source map
330
330
  ```
331
331
 
332
332
  Simple arrays (with `.loc`) instead of AST node classes. The compiler is self-hosting — `bun run parser` rebuilds from source.
@@ -334,17 +334,17 @@ Simple arrays (with `.loc`) instead of AST node classes. The compiler is self-ho
334
334
  | Component | File | Lines |
335
335
  |-----------|------|-------|
336
336
  | Lexer + Rewriter | `src/lexer.js` | 1,761 |
337
- | Compiler + Codegen | `src/compiler.js` | 3,291 |
337
+ | Compiler + Codegen | `src/compiler.js` | 3,293 |
338
338
  | Type System | `src/types.js` | 1,099 |
339
- | Component System | `src/components.js` | 1,645 |
340
- | Source Maps | `src/sourcemaps.js` | 121 |
339
+ | Component System | `src/components.js` | 1,750 |
340
+ | Source Maps | `src/sourcemaps.js` | 189 |
341
341
  | Parser (generated) | `src/parser.js` | 359 |
342
342
  | Grammar | `src/grammar/grammar.rip` | 944 |
343
343
  | Parser Generator | `src/grammar/solar.rip` | 929 |
344
344
  | REPL | `src/repl.js` | 601 |
345
- | Browser Entry | `src/browser.js` | 150 |
345
+ | Browser Entry | `src/browser.js` | 151 |
346
346
  | Tags | `src/tags.js` | 62 |
347
- | **Total** | | **~10,962** |
347
+ | **Total** | | **~11,138** |
348
348
 
349
349
  ---
350
350
 
@@ -354,15 +354,15 @@ Rip includes optional packages for full-stack development:
354
354
 
355
355
  | Package | Version | Purpose |
356
356
  |---------|---------|---------|
357
- | [rip-lang](https://www.npmjs.com/package/rip-lang) | 3.9.1 | Core language compiler |
358
- | [@rip-lang/api](packages/api/) | 1.1.6 | HTTP framework (Sinatra-style routing, 37 validators) |
359
- | [@rip-lang/server](packages/server/) | 1.1.5 | Multi-worker app server (hot reload, HTTPS, mDNS) |
360
- | [@rip-lang/db](packages/db/) | 1.1.5 | DuckDB server with official UI (pure Bun FFI) |
361
- | [@rip-lang/ui](packages/ui/) | 0.3.2 | Zero-build reactive web framework (stash, router, hash routing) |
362
- | [@rip-lang/swarm](packages/swarm/) | 1.1.3 | Parallel job runner with worker pool |
363
- | [@rip-lang/csv](packages/csv/) | 1.1.3 | CSV parser + writer |
364
- | [@rip-lang/schema](packages/schema/) | 0.2.0 | Unified schema → TypeScript types, SQL DDL, validation, ORM |
365
- | [VS Code Extension](packages/vscode/) | 0.3.2 | Syntax highlighting, type intelligence, source maps |
357
+ | [rip-lang](https://www.npmjs.com/package/rip-lang) | 3.10.6 | Core language compiler |
358
+ | [@rip-lang/api](packages/api/) | 1.1.10 | HTTP framework (Sinatra-style routing, 37 validators) |
359
+ | [@rip-lang/server](packages/server/) | 1.1.19 | Multi-worker app server (hot reload, HTTPS, mDNS) |
360
+ | [@rip-lang/db](packages/db/) | 1.2.0 | DuckDB server with official UI + ActiveRecord-style client |
361
+ | [@rip-lang/ui](packages/ui/) | 0.3.14 | Zero-build reactive web framework (stash, router, hash routing) |
362
+ | [@rip-lang/swarm](packages/swarm/) | 1.1.4 | Parallel job runner with worker pool |
363
+ | [@rip-lang/csv](packages/csv/) | 1.1.4 | CSV parser + writer |
364
+ | [@rip-lang/schema](packages/schema/) | 0.2.1 | Unified schema → TypeScript types, SQL DDL, validation, ORM |
365
+ | [VS Code Extension](packages/vscode/) | 0.5.0 | Syntax highlighting, type intelligence, source maps |
366
366
 
367
367
  ```bash
368
368
  bun add -g @rip-lang/db # Installs everything (rip-lang + api + db)
package/bin/rip CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
3
  import { readFileSync, writeFileSync, existsSync, statSync, unlinkSync } from 'fs';
4
- import { execSync, spawn } from 'child_process';
4
+ import { execSync, spawnSync, spawn } from 'child_process';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { dirname, basename, join } from 'path';
7
7
  import { Compiler } from '../src/compiler.js';
@@ -189,14 +189,10 @@ async function main() {
189
189
  const loaderPath = join(__dirname, '../rip-loader.js');
190
190
 
191
191
  if (inputFile.endsWith('.rip')) {
192
- try {
193
- execSync(`bun --preload ${loaderPath} ${inputFile} ${scriptArgs.join(' ')}`, {
194
- stdio: 'inherit'
195
- });
196
- process.exit(0);
197
- } catch (error) {
198
- process.exit(error.status || 1);
199
- }
192
+ const result = spawnSync('bun', ['--preload', loaderPath, inputFile, ...scriptArgs], {
193
+ stdio: 'inherit'
194
+ });
195
+ process.exit(result.status ?? 1);
200
196
  } else {
201
197
  // Non-.rip files (e.g. shebang scripts): compile, write temp file, execute
202
198
  const source = readFileSync(inputFile, 'utf-8');
@@ -206,7 +202,8 @@ async function main() {
206
202
  let exitCode = 0;
207
203
  try {
208
204
  writeFileSync(tmp, result.code);
209
- execSync(`bun --preload ${loaderPath} "${tmp}" ${scriptArgs.join(' ')}`, { stdio: 'inherit' });
205
+ const r = spawnSync('bun', ['--preload', loaderPath, tmp, ...scriptArgs], { stdio: 'inherit' });
206
+ exitCode = r.status ?? 1;
210
207
  } catch (error) {
211
208
  exitCode = error.status || 1;
212
209
  }
@@ -230,16 +227,8 @@ async function main() {
230
227
  const binScript = join(repoRoot, 'bin', inputFile);
231
228
 
232
229
  if (existsSync(binScript)) {
233
- // Found it! Execute with remaining args
234
- try {
235
- execSync(`"${binScript}" ${scriptArgs.join(' ')}`, {
236
- stdio: 'inherit',
237
- shell: true
238
- });
239
- process.exit(0);
240
- } catch (error) {
241
- process.exit(error.status || 1);
242
- }
230
+ const r = spawnSync(binScript, scriptArgs, { stdio: 'inherit' });
231
+ process.exit(r.status ?? 1);
243
232
  }
244
233
  } catch {
245
234
  // Not in a git repo, or git not available - fall through to normal error
@@ -45,7 +45,7 @@ class BinaryOp {
45
45
  ["+", left, right] // That's it!
46
46
  ```
47
47
 
48
- **Result:** CoffeeScript's compiler is 17,760 LOC. Rip's is ~10,800 LOC — smaller, yet includes a complete reactive runtime, type system, component system, and source maps.
48
+ **Result:** CoffeeScript's compiler is 17,760 LOC. Rip's is ~10,400 LOC — smaller, yet includes a complete reactive runtime, type system, component system, and source maps.
49
49
 
50
50
  > **Transform the IR (s-expressions), not the output (strings).**
51
51
 
@@ -77,7 +77,7 @@ console.log(code);
77
77
  | Dependencies | Multiple | **Zero** |
78
78
  | Parser generator | External (Jison) | **Built-in (Solar)** |
79
79
  | Self-hosting | No | **Yes** |
80
- | Total LOC | 17,760 | ~10,800 |
80
+ | Total LOC | 17,760 | ~10,400 |
81
81
 
82
82
  ## Design Principles
83
83
 
@@ -93,7 +93,7 @@ console.log(code);
93
93
 
94
94
  ```
95
95
  Source Code → Lexer → emitTypes → Parser → S-Expressions → Codegen → JavaScript
96
- (1,958) (types.js) (359) (arrays + .loc) (3,378) + source map
96
+ (1,761) (types.js) (359) (arrays + .loc) (3,293) + source map
97
97
 
98
98
  file.d.ts (when types: "emit")
99
99
  ```
@@ -102,15 +102,15 @@ Source Code → Lexer → emitTypes → Parser → S-Expressions → C
102
102
 
103
103
  | File | Purpose | Lines | Modify? |
104
104
  |------|---------|-------|---------|
105
- | `src/lexer.js` | Lexer + Rewriter | 1,958 | Yes |
106
- | `src/compiler.js` | Compiler + Code Generator | 3,378 | Yes |
105
+ | `src/lexer.js` | Lexer + Rewriter | 1,761 | Yes |
106
+ | `src/compiler.js` | Compiler + Code Generator | 3,293 | Yes |
107
107
  | `src/types.js` | Type System (lexer sidecar) | 1,099 | Yes |
108
- | `src/components.js` | Component System (compiler sidecar) | 1,240 | Yes |
109
- | `src/sourcemaps.js` | Source Map V3 Generator | 122 | Yes |
110
- | `src/tags.js` | HTML Tag Classification | 63 | Yes |
111
- | `src/parser.js` | Generated parser | 357 | No (auto-gen) |
112
- | `src/grammar/grammar.rip` | Grammar specification | 945 | Yes (carefully) |
113
- | `src/grammar/solar.rip` | Parser generator | 916 | No |
108
+ | `src/components.js` | Component System (compiler sidecar) | 1,750 | Yes |
109
+ | `src/sourcemaps.js` | Source Map V3 Generator | 189 | Yes |
110
+ | `src/tags.js` | HTML Tag Classification | 62 | Yes |
111
+ | `src/parser.js` | Generated parser | 359 | No (auto-gen) |
112
+ | `src/grammar/grammar.rip` | Grammar specification | 944 | Yes (carefully) |
113
+ | `src/grammar/solar.rip` | Parser generator | 929 | No |
114
114
 
115
115
  ## Example Flow
116
116
 
@@ -275,7 +275,7 @@ S-expressions are simple arrays that serve as Rip's intermediate representation
275
275
 
276
276
  # 4. Lexer & Rewriter
277
277
 
278
- The lexer (`src/lexer.js`) is a clean reimplementation that replaces the old lexer (3,260 lines) with ~1,870 lines producing the same token vocabulary the parser expects.
278
+ The lexer (`src/lexer.js`) is a clean reimplementation that replaces the old lexer (3,260 lines) with ~1,760 lines producing the same token vocabulary the parser expects.
279
279
 
280
280
  ## Architecture
281
281
 
@@ -439,7 +439,7 @@ REGEX tokens store `delimiter` and optional `heregex` flags in `token.data`.
439
439
 
440
440
  # 6. Compiler
441
441
 
442
- The compiler (`src/compiler.js`) is a clean reimplementation replacing the old compiler (6,016 lines) with ~3,290 lines producing identical JavaScript output.
442
+ The compiler (`src/compiler.js`) is a clean reimplementation replacing the old compiler (6,016 lines) with ~3,293 lines producing identical JavaScript output.
443
443
 
444
444
  ## Structure
445
445
 
@@ -577,4 +577,4 @@ rip> .js # Toggle JS display
577
577
 
578
578
  ---
579
579
 
580
- *Rip 3.8 — 1,241 tests passing — Zero dependencies — Self-hosting — ~11,000 LOC*
580
+ *Rip 3.10 — 1,243 tests — Zero dependencies — Self-hosting — ~13,500 LOC*