rip-lang 3.13.55 → 3.13.57
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/README.md +4 -2
- package/bin/rip +26 -15
- package/docs/RIP-LANG.md +38 -10
- package/docs/dist/rip.js +413 -375
- package/docs/dist/rip.min.js +116 -116
- package/docs/dist/rip.min.js.br +0 -0
- package/package.json +1 -1
- package/src/app.rip +1 -1
- package/src/browser.js +13 -4
- package/src/compiler.js +29 -14
- package/src/components.js +25 -15
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.13.
|
|
12
|
+
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.13.57-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%2C300%2F1%2C300-brightgreen.svg" alt="Tests"></a>
|
|
15
15
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
|
|
@@ -105,6 +105,7 @@ def loadUser(id)
|
|
|
105
105
|
await response.json()
|
|
106
106
|
|
|
107
107
|
user?.profile?.name # Optional chaining
|
|
108
|
+
el?.scrollTop = 0 # Optional chain assignment
|
|
108
109
|
data = fetchData! # Await shorthand
|
|
109
110
|
```
|
|
110
111
|
|
|
@@ -211,6 +212,7 @@ All use `globalThis` with `??=` — override any by redeclaring locally.
|
|
|
211
212
|
| `if...else` (postfix) | `"yes" if cond else "no"` | Python-style ternary expression |
|
|
212
213
|
| `?.` `?.[]` `?.()` | `a?.b` `a?.[0]` `a?.()` | Optional chaining (ES6) |
|
|
213
214
|
| `?[]` `?()` | `a?[0]` `a?(x)` | Optional chaining shorthand |
|
|
215
|
+
| `?.` `=` | `el?.scrollTop = 0` | Optional chain assignment — guarded write |
|
|
214
216
|
| `??` | `a ?? b` | Nullish coalescing |
|
|
215
217
|
| `...` (spread) | `[...items, last]` | Prefix spread (ES6) |
|
|
216
218
|
| `//` | `7 // 2` | Floor division |
|
|
@@ -421,7 +423,7 @@ Rip includes optional packages for full-stack development:
|
|
|
421
423
|
| [rip-lang](https://www.npmjs.com/package/rip-lang) | 3.13.27 | Core language compiler |
|
|
422
424
|
| [@rip-lang/server](packages/server/) | 1.3.12 | Multi-worker app server (web framework, hot reload, HTTPS, mDNS) |
|
|
423
425
|
| [@rip-lang/db](packages/db/) | 1.3.15 | DuckDB server with official UI + ActiveRecord-style client |
|
|
424
|
-
| [
|
|
426
|
+
| [ui](packages/ui/) | — | Rip UI — 38 headless components (Grid, Select, Dialog, Tabs, etc.) |
|
|
425
427
|
| [@rip-lang/swarm](packages/swarm/) | 1.2.18 | Parallel job runner with worker pool |
|
|
426
428
|
| [@rip-lang/csv](packages/csv/) | 1.3.6 | CSV parser + writer |
|
|
427
429
|
| [@rip-lang/schema](packages/schema/) | 0.3.8 | Unified schema → TypeScript types, SQL DDL, validation, ORM |
|
package/bin/rip
CHANGED
|
@@ -173,19 +173,32 @@ async function main() {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
// Stdin
|
|
176
|
+
// Stdin handling — read into memory; only write temp file for the execute path
|
|
177
177
|
const hasCompileFlag = showCompiled || showTokens || showSExpr || generateDts || generateMap || outputFile;
|
|
178
|
-
let
|
|
178
|
+
let source;
|
|
179
|
+
|
|
179
180
|
if (!inputFile) {
|
|
180
|
-
const tmp = join(process.cwd(), '.__rip_stdin__.rip');
|
|
181
181
|
try {
|
|
182
|
-
|
|
183
|
-
inputFile = tmp;
|
|
184
|
-
isStdin = true;
|
|
182
|
+
source = readFileSync(0, 'utf-8');
|
|
185
183
|
} catch (error) {
|
|
186
184
|
console.error('Error reading stdin:', error.message);
|
|
187
185
|
process.exit(1);
|
|
188
186
|
}
|
|
187
|
+
|
|
188
|
+
if (!hasCompileFlag) {
|
|
189
|
+
const tmp = join(process.cwd(), '.__rip_stdin__.rip');
|
|
190
|
+
try {
|
|
191
|
+
writeFileSync(tmp, source);
|
|
192
|
+
const result = spawnSync('bun', ['--preload', loaderPath, tmp, ...scriptArgs], {
|
|
193
|
+
stdio: 'inherit', env: process.env
|
|
194
|
+
});
|
|
195
|
+
try { unlinkSync(tmp); } catch {}
|
|
196
|
+
process.exit(result.status ?? 1);
|
|
197
|
+
} catch {
|
|
198
|
+
try { unlinkSync(tmp); } catch {}
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
189
202
|
}
|
|
190
203
|
|
|
191
204
|
// Execute script directly (no compile flags)
|
|
@@ -195,7 +208,6 @@ async function main() {
|
|
|
195
208
|
stdio: 'inherit',
|
|
196
209
|
env: process.env
|
|
197
210
|
});
|
|
198
|
-
if (isStdin) try { unlinkSync(inputFile); } catch {}
|
|
199
211
|
process.exit(result.status ?? 1);
|
|
200
212
|
}
|
|
201
213
|
|
|
@@ -217,7 +229,7 @@ async function main() {
|
|
|
217
229
|
|
|
218
230
|
// Fallback: look for bin/{command} in git repo root
|
|
219
231
|
// Allows `rip migrate --status` to find and run {repo}/bin/migrate
|
|
220
|
-
if (
|
|
232
|
+
if (inputFile && !inputFile.startsWith('-') && !isFile(inputFile)) {
|
|
221
233
|
try {
|
|
222
234
|
const repoRoot = execSync('git rev-parse --show-toplevel', {
|
|
223
235
|
encoding: 'utf-8',
|
|
@@ -233,13 +245,14 @@ async function main() {
|
|
|
233
245
|
|
|
234
246
|
// --- Compile (with flags) ---
|
|
235
247
|
|
|
236
|
-
if (
|
|
237
|
-
|
|
238
|
-
|
|
248
|
+
if (source === undefined) {
|
|
249
|
+
if (!isFile(inputFile)) {
|
|
250
|
+
console.error(`Error: File not found: ${inputFile}`);
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
253
|
+
source = readFileSync(inputFile, 'utf-8');
|
|
239
254
|
}
|
|
240
255
|
|
|
241
|
-
let source = readFileSync(inputFile, 'utf-8');
|
|
242
|
-
|
|
243
256
|
try {
|
|
244
257
|
const compiler = new Compiler({ showTokens, showSExpr, quiet,
|
|
245
258
|
types: generateDts ? 'emit' : undefined,
|
|
@@ -263,8 +276,6 @@ async function main() {
|
|
|
263
276
|
console.error('Compilation Error:', error.message);
|
|
264
277
|
if (error.stack) console.error(error.stack);
|
|
265
278
|
process.exit(1);
|
|
266
|
-
} finally {
|
|
267
|
-
if (isStdin) try { unlinkSync(inputFile); } catch {}
|
|
268
279
|
}
|
|
269
280
|
}
|
|
270
281
|
|
package/docs/RIP-LANG.md
CHANGED
|
@@ -360,6 +360,34 @@ arr?[0] # Compiles to arr?.[0]
|
|
|
360
360
|
fn?(arg) # Compiles to fn?.(arg)
|
|
361
361
|
```
|
|
362
362
|
|
|
363
|
+
### Optional Chain Assignment
|
|
364
|
+
|
|
365
|
+
Rip extends optional chaining to the left side of assignments. If the
|
|
366
|
+
target is null or undefined, the assignment is silently skipped. This
|
|
367
|
+
eliminates the common `x.prop = val if x` guard pattern.
|
|
368
|
+
|
|
369
|
+
```coffee
|
|
370
|
+
# Simple property
|
|
371
|
+
el?.scrollTop = 0 # if (el != null) el.scrollTop = 0
|
|
372
|
+
|
|
373
|
+
# Deep chain
|
|
374
|
+
el?.style.display = 'none' # if (el != null) el.style.display = 'none'
|
|
375
|
+
|
|
376
|
+
# Inner chain
|
|
377
|
+
obj.inner?.value = 42 # if (obj.inner != null) obj.inner.value = 42
|
|
378
|
+
|
|
379
|
+
# Bracket access
|
|
380
|
+
arr?[0] = 99 # if (arr != null) arr[0] = 99
|
|
381
|
+
|
|
382
|
+
# Compound operators work too
|
|
383
|
+
counter?.value += 1 # if (counter != null) counter.value += 1
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
JavaScript does not allow optional chaining on the left side of assignments
|
|
387
|
+
(`x?.prop = val` is a SyntaxError). Rip compiles it to a guarded assignment
|
|
388
|
+
automatically. This is particularly useful for DOM element references that
|
|
389
|
+
may not exist yet (before mount, inside conditionals, etc.).
|
|
390
|
+
|
|
363
391
|
## Ternary Operator
|
|
364
392
|
|
|
365
393
|
```coffee
|
|
@@ -420,25 +448,25 @@ or `undefined` if it's falsy. Now you see it… now you don't.
|
|
|
420
448
|
(idx is active)?! # ((idx === active) ? true : undefined)
|
|
421
449
|
```
|
|
422
450
|
|
|
423
|
-
Designed for
|
|
451
|
+
Designed for `$` attributes (data-* sigil) in headless UI components, where falsy values
|
|
424
452
|
need to *remove* the attribute rather than set it to `"false"`:
|
|
425
453
|
|
|
426
454
|
```coffee
|
|
427
455
|
# Before — verbose and repetitive
|
|
428
|
-
|
|
429
|
-
|
|
456
|
+
$checked: (@checked or undefined),
|
|
457
|
+
$disabled: (@disabled or undefined),
|
|
430
458
|
|
|
431
459
|
# After — clean and expressive
|
|
432
|
-
|
|
433
|
-
|
|
460
|
+
$checked: @checked?!,
|
|
461
|
+
$disabled: @disabled?!,
|
|
434
462
|
```
|
|
435
463
|
|
|
436
464
|
Works with any expression, not just identifiers:
|
|
437
465
|
|
|
438
466
|
```coffee
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
467
|
+
$highlighted: (idx is highlightedIndex)?!,
|
|
468
|
+
$selected: (opt.value is String(@value))?!,
|
|
469
|
+
$active: (tab is @active)?!,
|
|
442
470
|
```
|
|
443
471
|
|
|
444
472
|
## Method Assignment (`.=`)
|
|
@@ -1269,11 +1297,11 @@ Rip includes optional packages for full-stack development. All are written in Ri
|
|
|
1269
1297
|
|
|
1270
1298
|
```bash
|
|
1271
1299
|
bun add @rip-lang/server # Web framework + production server
|
|
1272
|
-
bun add @rip-lang/grid # Reactive data grid
|
|
1273
1300
|
bun add @rip-lang/db # DuckDB server + client
|
|
1274
1301
|
bun add @rip-lang/schema # ORM + validation
|
|
1275
1302
|
bun add @rip-lang/swarm # Parallel job runner
|
|
1276
1303
|
bun add @rip-lang/csv # CSV parser + writer
|
|
1304
|
+
# Widgets are included in packages/ui/ (not a separate npm package)
|
|
1277
1305
|
```
|
|
1278
1306
|
|
|
1279
1307
|
## @rip-lang/server — Web Framework & Production Server
|
|
@@ -1592,7 +1620,7 @@ App = component
|
|
|
1592
1620
|
**Hyphenated Attributes:**
|
|
1593
1621
|
|
|
1594
1622
|
```coffee
|
|
1595
|
-
div
|
|
1623
|
+
div $testid: "main", aria-label: "content"
|
|
1596
1624
|
```
|
|
1597
1625
|
|
|
1598
1626
|
**DOM Properties:**
|