rip-lang 1.5.7 β†’ 2.5.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
@@ -1,3 +1,5 @@
1
+ <p><img src="docs/rip.svg" alt="Rip Logo" width="100"></p>
2
+
1
3
  # Changelog
2
4
 
3
5
  All notable changes to Rip will be documented in this file.
@@ -5,6 +7,340 @@ All notable changes to Rip will be documented in this file.
5
7
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
8
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
9
 
10
+ ## [2.5.1] - 2026-01-16
11
+
12
+ ### Template Enhancement
13
+
14
+ **Hyphenated Attributes Work Directly**:
15
+ ```coffee
16
+ render
17
+ # Before: needed quoted keys or spread syntax
18
+ i {"data-lucide": "search"}
19
+
20
+ # Now: just works!
21
+ i data-lucide: "search", aria-hidden: "true"
22
+ div data-testid: "container", aria-label: "Menu"
23
+ span data-foo-bar-baz: "multiple-hyphens-work"
24
+ ```
25
+
26
+ The lexer now automatically converts hyphenated attribute names (like `data-*`, `aria-*`) into quoted strings, making HTML-style data attributes intuitive and clean.
27
+
28
+ ---
29
+
30
+ ## [2.5.0] - 2026-01-16
31
+
32
+ ### Major Release - Parser Optimization + Complete Framework
33
+
34
+ This release consolidates all improvements since 2.2.1 into a polished, well-documented package. Rip is now a complete language AND reactive framework in just 51KB (Brotli compressed).
35
+
36
+ ---
37
+
38
+ ### πŸš€ Parser Optimization
39
+
40
+ **Interleaved Delta-Encoded Parse Table** - Major size reduction for the generated parser:
41
+ - New format in `solar.rip`: `[count, Ξ”key₁, Ξ”keyβ‚‚..., val₁, valβ‚‚...]` per state
42
+ - **31% smaller Brotli** for parser alone (19.2KB β†’ 13.2KB)
43
+ - **17% faster module load** time
44
+ - Identical runtime performance (same data structure after decode)
45
+ - Solar parser generator now **250Γ— faster** than Jison
46
+
47
+ ---
48
+
49
+ ### ✨ New Language Features
50
+
51
+ **Ruby-Style Constructor Syntax**:
52
+ ```coffee
53
+ # Both are equivalent
54
+ counter = new Counter()
55
+ counter = Counter.new() # Ruby-style - elegant!
56
+
57
+ # Works with arguments
58
+ user = User.new("Alice", 30)
59
+
60
+ # Chainable
61
+ Counter.new().mount("#app")
62
+ ```
63
+
64
+ **"Equal, Dammit!" Operator (`=!`)**:
65
+ ```coffee
66
+ # Regular assignment β†’ let (can reassign)
67
+ host = "localhost"
68
+ host = "example.com" # OK
69
+
70
+ # Equal, dammit! β†’ const (can't reassign)
71
+ API_URL =! "https://api.example.com"
72
+ API_URL = "other" # Error! const cannot be reassigned
73
+ ```
74
+ Note: `=!` compiles to plain `const` - does NOT pull in the reactive runtime.
75
+
76
+ **Smart Two-Way Binding**:
77
+ ```coffee
78
+ # Automatically uses valueAsNumber for number/range inputs
79
+ input type: "number", value <=> count # No .valueAsNumber needed!
80
+ input type: "range", value <=> volume # Just works!
81
+ ```
82
+
83
+ ---
84
+
85
+ ### 🎨 Template & Component Improvements
86
+
87
+ **Pug-Style Shorthand**:
88
+ ```coffee
89
+ # Implicit div for class-only selectors
90
+ .card # β†’ <div class="card">
91
+ .btn.primary # β†’ <div class="btn primary">
92
+
93
+ # Nested shorthand works correctly
94
+ .container
95
+ .row
96
+ .col "Content"
97
+ ```
98
+
99
+ **Dynamic Class Syntax**:
100
+ ```coffee
101
+ div.("bg-white rounded-lg shadow-md") # Static Tailwind classes
102
+ button.(active && "bg-blue-500") # Conditional classes
103
+ ```
104
+
105
+ **Component Mount with Selectors**:
106
+ ```coffee
107
+ # Both work
108
+ Counter.new().mount(document.body)
109
+ Counter.new().mount("#app") # Selector string support
110
+ ```
111
+
112
+ ---
113
+
114
+ ### πŸ–₯️ Browser REPL Enhancements
115
+
116
+ **Live Demo Tab** (now default):
117
+ - Interactive component demos
118
+ - Temperature converter, counter examples
119
+ - Real-time reactive updates
120
+
121
+ **UI Improvements**:
122
+ - Tab state persists in URL hash
123
+ - No flash of wrong tab on page load
124
+ - Consistent pane header heights
125
+ - GitHub icon link in header
126
+
127
+ **Demo Improvements**:
128
+ - Shows `@prop` syntax for component props
129
+ - Uses Ruby-style `.new()` syntax
130
+ - Fat arrows for proper `this` binding
131
+
132
+ ---
133
+
134
+ ### πŸ“š Documentation Overhaul
135
+
136
+ **Consolidated Documentation** - 13 files merged into 4 main docs:
137
+ - `docs/GUIDE.md` - Language features, reactivity, templates, components
138
+ - `docs/INTERNALS.md` - Compiler architecture, S-expressions, Solar
139
+ - `docs/PHILOSOPHY.md` - Design principles, CoffeeScript comparison
140
+ - `docs/BROWSER.md` - Browser usage, REPL, deployment
141
+
142
+ **Kept Separate** (referenced from PHILOSOPHY.md):
143
+ - `docs/WHY-NOT-COFFEESCRIPT.md` - The case against CoffeeScript
144
+ - `docs/WHY-YES-RIP.md` - The case for Rip
145
+
146
+ **Updated Statistics**:
147
+ - ~14,000 LOC total (smaller than CoffeeScript's 17,760, yet includes full reactive framework)
148
+ - 51KB browser bundle (compiler + reactive runtime + templates + components)
149
+ - 1046 tests passing
150
+ - Solar: ~1,000 LOC, 250Γ— faster than Jison
151
+
152
+ ---
153
+
154
+ ### πŸ”§ Internal Improvements
155
+
156
+ **Compiler Consolidation**:
157
+ - Merged `codegen.js` into `compiler.js` (single file for all code generation)
158
+ - Renamed `docs/CODEGEN.md` to `docs/COMPILER.md`
159
+
160
+ **Project Cleanup**:
161
+ - Deleted unused `src/runtime.js` (runtime now embedded in compiler output)
162
+ - Deleted redundant `docs/demo.html`
163
+ - Overhauled `AGENT.md` for accuracy
164
+ - Added `notes.txt` to `.gitignore`
165
+
166
+ **Bug Fixes**:
167
+ - Fixed `<=>` two-way binding in components
168
+ - Fixed reactive variable shadowing in function bodies
169
+ - Fixed nested Pug-style shorthand in render blocks
170
+ - Fixed `generateParam` bug
171
+ - Consistent name handling in `generateReadonly`
172
+
173
+ ---
174
+
175
+ ### πŸ“Š Updated Scores
176
+
177
+ | Category | Score | Notes |
178
+ |----------|-------|-------|
179
+ | **Reactivity** | A+ | Fine-grained, signals, effects |
180
+ | **Templates** | A | S-expressions, Pug shorthand |
181
+ | **Components** | A | Props, lifecycle, context API |
182
+ | **Performance** | A | 250Γ— faster parser gen, 51KB bundle |
183
+
184
+ ---
185
+
186
+ ### Summary
187
+
188
+ **What's in 51KB?**
189
+ - Complete compiler (lexer, parser, code generator)
190
+ - Reactive runtime (signals, derived values, effects)
191
+ - Template engine (S-expression syntax, dynamic classes)
192
+ - Component system (props, lifecycle, fine-grained updates)
193
+ - Zero dependencies
194
+
195
+ **Comparison**:
196
+ - React (min+gzip): ~42KB (just the library, no compiler)
197
+ - Vue (min+gzip): ~34KB (just the library, no compiler)
198
+ - **Rip: 51KB (complete language + framework, runs anywhere!)**
199
+
200
+ ---
201
+
202
+ ## [2.2.1] - 2026-01-15
203
+
204
+ ### Added - Context API & Error Primitives
205
+
206
+ **Context API** - Pass data through component trees without prop drilling:
207
+ - `setContext(key, value)` - Set context in current component
208
+ - `getContext(key)` - Get context from nearest ancestor
209
+ - `hasContext(key)` - Check if context exists
210
+
211
+ **Error Primitives** - Low-level building blocks for error handling:
212
+ - `__catchErrors(fn)` - Wrap function to route errors to handler
213
+ - `__handleError(error)` - Route error to handler or rethrow
214
+ - `__setErrorHandler(fn)` - Set current error handler
215
+
216
+ **Dynamic Class Syntax** - Cleaner Tailwind support:
217
+ ```coffee
218
+ div.("bg-white rounded-lg shadow-md") # Static classes
219
+ button.(active && "bg-blue-500") # Conditional classes
220
+ ```
221
+
222
+ **Other Improvements**:
223
+ - Components now track parent via `_parent` pointer
224
+ - Batching optimization with `__batch()` for grouped updates
225
+ - Improved reactive runtime documentation (~330 lines total)
226
+
227
+ **Updated Scores**:
228
+ - Components: B+ β†’ A- (Context API implemented)
229
+ - Tests: 1017 β†’ 1033
230
+
231
+ ---
232
+
233
+ ## [2.2.0] - 2026-01-15
234
+
235
+ ### Added - Keyed Reconciliation & Per-Item Effects
236
+
237
+ **The Final Boss: True Svelte-Class Performance**
238
+
239
+ Lists now have O(1) performance for ALL operations:
240
+ - **Add item**: Create 1 node (not rebuild all)
241
+ - **Remove item**: Remove 1 node (not rebuild all)
242
+ - **Reorder**: Move existing nodes (not recreate)
243
+ - **Selection change**: Per-item effects update independently
244
+
245
+ **Key Features**:
246
+ - Keyed reconciliation via `key:` attribute
247
+ - Per-item effects with proper cleanup
248
+ - Conditional effect cleanup (no memory leaks)
249
+ - Effect disposal on item removal
250
+
251
+ **Example**:
252
+ ```coffee
253
+ for item, i in items
254
+ li key: item.id, class: (i == selected && "selected"), item.name
255
+ ```
256
+
257
+ Each item gets its own effect. Changing `selected` updates ONLY the affected classes, not the whole list.
258
+
259
+ ---
260
+
261
+ ## [2.1.0] - 2026-01-15
262
+
263
+ ### Added - Fine-Grained Reactivity
264
+
265
+ **MAJOR PERFORMANCE IMPROVEMENT**: Components now update only specific DOM nodes that changed, not the entire tree. This brings Rip to Svelte-class performance.
266
+
267
+ **Architecture Change**:
268
+ - Before: `render()` recreates all DOM on every state change
269
+ - After: `_create()` builds DOM once, `_setup()` wires minimal effects
270
+
271
+ **Performance**:
272
+ - Text binding: O(1) instead of O(n)
273
+ - Attribute binding: O(1) instead of O(n)
274
+ - **30-40x faster** for typical reactive updates
275
+
276
+ **New Features**:
277
+ - Fine-grained text bindings: `span count` β†’ effect updates just that text node
278
+ - Fine-grained attribute bindings: `div class: active` β†’ effect updates just that attribute
279
+ - Fine-grained conditionals: `if show` β†’ anchor-based content swapping
280
+ - Fine-grained loops: `for item in items` β†’ tracked node list
281
+ - Named slots: Props can be DOM nodes (`@header`, `@footer`, etc.)
282
+
283
+ **Updated Scores**:
284
+ - Reactivity: A β†’ A+
285
+ - Templates: A- β†’ A
286
+ - Components: A- β†’ A
287
+
288
+ ---
289
+
290
+ ## [2.0.0] - 2026-01-14
291
+
292
+ ### Added - Reactive UI Framework
293
+
294
+ **Phase 1: Reactivity** (previously released)
295
+ - Signal-based reactivity: `count = 0` creates reactive state
296
+ - Derived values: `doubled ~= count * 2` auto-tracks dependencies
297
+ - Effects: `effect -> console.log count` runs on changes
298
+ - Runtime: `__signal()`, `__computed()`, `__effect()`, `__batch()`, `__readonly()`
299
+
300
+ **Phase 2: Templates**
301
+ - Indentation-based template syntax in `render` blocks
302
+ - CSS-style selectors: `div#main.card.active`
303
+ - Event handlers: `@click: handler`
304
+ - Event modifiers: `@click.prevent.stop: handler`
305
+ - Two-way binding: `input value <=> username`
306
+ - Spread attributes: `div ...props`
307
+ - Dynamic classes: `div.('btn', isActive && 'active')` (clsx-style)
308
+ - Control flow: `if`/`else`, `for` loops in templates
309
+ - Special attributes: `key:`, `ref:`
310
+ - Multiple roots via `DocumentFragment`
311
+ - Runtime helpers: `h()`, `frag()`, `txt()`, `cx()`
312
+
313
+ **Phase 3: Components**
314
+ - `component` keyword for defining UI components
315
+ - Props system:
316
+ - Required: `@label`
317
+ - Optional: `@label?`
318
+ - Default: `@label = "default"`
319
+ - Rest: `@...rest`
320
+ - Reactive state within components (auto-signals)
321
+ - Derived values within components (auto-computed)
322
+ - Component composition: `Button label: "Click"` inside render
323
+ - Children/slots: `@children` prop for nested content
324
+ - Lifecycle hooks: `mounted:`, `unmounted:`
325
+ - Reactive re-rendering via effect-based mount
326
+
327
+ ### Changed
328
+ - Grammar extended with `component`, `render`, `style` keywords
329
+ - Lexer handles template contexts (ID selectors, arrow injection)
330
+ - Codegen generates ES6 classes for components
331
+
332
+ ### Technical Details
333
+ - Components compile to ES6 classes with constructor, render, mount, unmount
334
+ - Props validated at construction (required props throw if missing)
335
+ - State variables become `__signal()` calls
336
+ - Derived values become `__computed()` calls
337
+ - `mount()` wraps render in `__effect()` for reactive updates
338
+ - PascalCase names in templates trigger component instantiation
339
+
340
+ All 1033 tests passing (100%) βœ…
341
+
342
+ ---
343
+
8
344
  ## [1.5.7] - 2025-11-16
9
345
 
10
346
  ### Changed
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Steve Shreeve
3
+ Copyright (c) 2026 Steve Shreeve
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal