@daz4126/helium 1.0.0-rc.2 → 1.0.0-rc.3

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 CHANGED
@@ -18,7 +18,7 @@ It's really simple to use - just sprinkle the magic @attributes into your HTML a
18
18
 
19
19
  Helium is designed for developers who want:
20
20
 
21
- - **Lightweight** - About 3.9–10.9KB minified and gzipped, depending on the build
21
+ - **Lightweight** - About 5.5–13.3KB minified and gzipped, depending on the build
22
22
  - **Powerful** - Declarative JavaScript in your HTML
23
23
  - **Zero build step** - Works directly in the browser with no compiling
24
24
  - **Easy to learn** - If you know HTML and basic JavaScript, you're ready
@@ -31,7 +31,7 @@ Helium comes in three core versions, with SSE available as an optional add-on, s
31
31
 
32
32
  The full-featured version with everything included.
33
33
 
34
- - All directives (`@text`, `@html`, `@for`, `@bind`, `@data`, `@scope`, `@ref`, `@calculate`, `@effect`, `@init`, etc.)
34
+ - All directives (`@text`, `@html`, `@for`, `@if`, `@bind`, `@data`, `@ref`, `@calculate`, `@effect`, `@init`, etc.)
35
35
  - Event handlers with modifiers
36
36
  - HTTP requests (`@get`, `@post`, `@put`, `@patch`, `@delete`)
37
37
  - Module imports (`@import`)
@@ -51,7 +51,7 @@ A slimmed-down version with just the core reactivity features.
51
51
  - Core directives (`@text`, `@html`, `@bind`, `@data`, `@ref`, `@calculate`, `@effect`, `@init`)
52
52
  - Event handlers with modifiers
53
53
  - One global state namespace
54
- - No `@scope`, keyed `@for`, HTTP requests, imports, SSE, or Turbo integration
54
+ - No local `@data`, keyed `@for`, HTTP requests, imports, SSE, or Turbo integration
55
55
 
56
56
  **Best for:** Simple interactive pages where you only need reactivity and don't need server communication or module imports.
57
57
 
@@ -104,23 +104,25 @@ import helium from "@daz4126/helium/csp"
104
104
  | Feature | Standard | Lite | CSP |
105
105
  |---------|----------|------|-----|
106
106
  | Core directives | ✅ | ✅ | ✅ |
107
- | Element-local `@scope` | ✅ | ❌ | ✅ |
107
+ | Element-local `@data` | ✅ | ❌ | ✅ |
108
108
  | Keyed `@for` | ✅ | ❌ | ✅ |
109
+ | Conditional `@if` | ✅ | ❌ | ✅ |
109
110
  | Event handlers | ✅ | ✅ | ✅ |
110
111
  | HTTP requests | ✅ | ❌ | ✅ |
111
112
  | `@import` | ✅ | ❌ | ✅ |
112
113
  | SSE | Add-on | ❌ | Add-on |
113
114
  | Turbo integration | ✅ | ❌ | ✅ |
114
115
  | CSP safe | ❌ | ❌ | ✅ |
115
- | Approx. min+gzip size | 6.49KB | 3.93KB | 10.56KB |
116
+ | Approx. min+gzip size | 8.79KB | 5.52KB | 12.89KB |
116
117
 
117
118
  Sizes are enforced against the production Terser builds with gzip level 9. The
118
- CSP figure includes its expression parser. Adding SSE produces 6.86KB Standard
119
- and 10.94KB CSP bundles.
119
+ CSP figure includes its expression parser. Adding SSE produces 9.17KB Standard
120
+ and 13.27KB CSP bundles.
120
121
 
121
122
  Lite is generated from the same global-state reactive core as Standard. It has
122
- identical deep/shared reactivity, lifecycle, binding, and cleanup behavior, but
123
- intentionally excludes element-local scopes and Standard's other extensions.
123
+ identical deep/shared reactivity, lifecycle, binding, and cleanup behavior for
124
+ root state, but intentionally excludes element-local data and Standard's other
125
+ extensions.
124
126
 
125
127
  ## Installation
126
128
 
@@ -300,6 +302,32 @@ but keyed `@for` avoids HTML-string interpolation and lets each row use normal
300
302
 
301
303
  **Alias:** `data-he-for` (the key remains `:key`)
302
304
 
305
+ ### @if
306
+
307
+ Standard and CSP can conditionally render a `<template>`'s content. Unlike
308
+ `@hidden`/`@visible`, which only toggle visibility, `@if` adds the content to
309
+ the DOM when the expression is truthy and fully removes it — bindings,
310
+ listeners, and `@init` cleanup included — when it becomes falsy:
311
+
312
+ ```html
313
+ <template @if="loggedIn">
314
+ <p>Welcome back, <span @text="user.name"></span>!</p>
315
+ <button @click="logout($data)">Log out</button>
316
+ </template>
317
+ ```
318
+
319
+ Content that is switched off costs nothing: its expressions never evaluate and
320
+ its listeners don't exist. Use `@if` for anything conditional-but-expensive
321
+ (modals, tab panels, admin-only markup) and `@hidden`/`@visible` for cheap
322
+ show/hide toggles where you want to preserve element state such as form input.
323
+
324
+ `@if` requires a `<template>` element (like `@for`, and like Alpine's `x-if`)
325
+ because template content is inert until inserted — that's what makes the "off"
326
+ state free. It cannot be combined with `@for` on the same template; nest one
327
+ template inside the other instead. Lite excludes this feature.
328
+
329
+ **Alias:** `data-he-if`
330
+
303
331
  ### @bind
304
332
 
305
333
  Creates a 2-way binding between an input element's value and a variable. Whatever is entered in the following input field will be stored as a variable called name:
@@ -389,31 +417,23 @@ Makes the element hidden or visible depending on the result of a JavaScript expr
389
417
 
390
418
  ### @data
391
419
 
392
- Initializes variables that can be used in JavaScript expressions. This is useful for setting up initial state.
420
+ Initializes variables that can be used in JavaScript expressions. In Standard
421
+ and CSP, `@data` behaves like Alpine's `x-data`: root-level `@data` initializes
422
+ the mounted root state, while nested `@data` creates local state for that
423
+ element and its descendants. Lite always uses one global state namespace, so
424
+ every `@data` merges into root state.
393
425
 
394
426
  ```html
395
- <div @data="{ count: 0, open: false, name: 'Helium' }"></div>
396
- ```
397
-
398
- You can then use these variables in other Helium attributes:
399
-
400
- ```html
401
- <div @data="{ count: 0 }">
402
- <button @click="count++">Increment</button>
403
- <p @text="count"></p>
404
- </div>
427
+ <main @helium @data="{ count: 100, name: 'Helium' }">
428
+ <p @text="name + ': ' + count"></p>
429
+ </main>
405
430
  ```
406
431
 
407
- **Alias:** `data-he-data`
408
-
409
- ### @scope (Standard/CSP)
410
-
411
- Creates reactive state owned by an element and its descendants. Scoped names
412
- shadow root state without changing the object returned by `helium()`:
432
+ Nested `@data` is local in Standard/CSP:
413
433
 
414
434
  ```html
415
- <main @data="{ count: 100 }">
416
- <section @scope="{ count: 0, open: false }">
435
+ <main @helium @data="{ count: 100 }">
436
+ <section @data="{ count: 0, open: false }">
417
437
  <button @click="count++">Increment local count</button>
418
438
  <button @click="open = !open">Toggle</button>
419
439
  <p @text="count"></p>
@@ -424,41 +444,49 @@ shadow root state without changing the object returned by `helium()`:
424
444
  </main>
425
445
  ```
426
446
 
427
- The scope expression runs once in its parent context, so defaults can use outer
428
- values. Nested scopes inherit outer names, and assignment updates the nearest
429
- scope that declares that name:
447
+ The object is evaluated once in its parent context, so local defaults can use
448
+ outer values. Nested data objects inherit outer names, and assignment updates
449
+ the nearest data object that declares that name:
430
450
 
431
451
  ```html
432
- <div @scope="{ count: startingCount, label: 'outer' }">
433
- <div @scope="{ label: 'inner' }">
452
+ <div @data="{ count: startingCount, label: 'outer' }">
453
+ <div @data="{ label: 'inner' }">
434
454
  <button @click="count++">Updates the outer local count</button>
435
455
  <span @text="label"></span> <!-- inner -->
436
456
  </div>
437
457
  </div>
438
458
  ```
439
459
 
440
- Declare every name that should remain local. Assigning an undeclared name keeps
441
- the existing Helium behavior and writes to root state. The same applies to
442
- `@bind` and `@calculate` targets: declare their target names in `@scope` when
443
- they should be local. Inside the subtree, `$data` is the scoped state view.
444
- Local values are not included in root `@local-storage` persistence.
460
+ Declare every name that should remain local. Assigning an undeclared name writes
461
+ to root state. The same applies to `@bind` and `@calculate` targets: declare
462
+ their target names in local `@data` when they should be local. Inside the
463
+ subtree, `$data` is the scoped state view. Local values are not returned from
464
+ `helium()` and are not included in root `@local-storage` persistence.
445
465
 
446
- `@data` continues to merge into root state; it has not changed semantics.
447
-
448
- **Alias:** `data-he-scope`
449
-
450
- `@scope` is intentionally excluded from Lite, which always uses one global
451
- state namespace per mounted root.
466
+ **Alias:** `data-he-data` (the legacy bare `data-he` alias is also accepted)
452
467
 
453
468
  ### @ref
454
469
 
455
- Creates a reference to the element that can be used in JavaScript expressions. References are prefixed with `$` when accessed.
470
+ Creates a scoped reference to an element. The first matching element is
471
+ available through `$name`, and every matching element is available as the
472
+ always-array `$refs.name` in current DOM order:
456
473
 
457
474
  ```html
458
- <ul @ref="list"></ul>
475
+ <section @data="{ items: [] }">
476
+ <ul @ref="list"></ul>
477
+ <div @ref="row"></div>
478
+ <div @ref="row"></div>
479
+ <button @click="console.log($list, $refs.row)">Inspect refs</button>
480
+ </section>
459
481
  ```
460
482
 
461
- This element can then be accessed in other JavaScript expressions as `$list`:
483
+ Ref lookup starts in the nearest explicit `@data` scope and falls back through
484
+ parent scopes. A ref with the same name in a nested scope shadows the outer
485
+ name. Lite has one root scope, so all of its refs belong to the mounted root.
486
+ When refs are removed or reordered, singular and plural lookup follows the
487
+ current DOM.
488
+
489
+ This element can be accessed in other JavaScript expressions as `$list`:
462
490
 
463
491
  ```html
464
492
  <button @click="$list.appendChild($html('<li>New item</li>'))">Add Task</button>
@@ -648,11 +676,22 @@ You can add modifiers by appending them with a dot (`.`) after the event name:
648
676
  - **once** - Only runs the event handler once, then removes the listener
649
677
  - **outside** - Only fires when the event happens outside the element
650
678
  - **document** - Attaches the listener to the document instead of the element
679
+ - **window** - Attaches the listener to `window` instead of the element
680
+ - **self** - Only fires when the element itself is the event target
681
+ - **capture** - Handles the event during the capture phase
682
+ - **passive** - Registers a native passive listener
651
683
  - **debounce** - Debounces the event handler (default 300ms)
652
684
  - **debounce:500** - Debounces with custom delay in milliseconds
685
+ - **throttle** - Runs immediately, then at most once per interval (default 300ms)
686
+ - **throttle:500** - Throttles with a custom interval in milliseconds
653
687
  - **shift, ctrl, alt, meta** - Only fires if the modifier key is pressed
654
688
  - **Key names** - For keyboard events, specify which key (e.g., `enter`, `esc`, `space`)
655
689
 
690
+ Throttle uses leading and trailing calls: the first matching event runs
691
+ immediately, and events received during the interval are coalesced into one
692
+ final call using the latest event. `.passive.prevent` is invalid because a
693
+ passive listener cannot cancel an event; Helium warns and does not register it.
694
+
656
695
  **Examples:**
657
696
 
658
697
  ```html
@@ -682,6 +721,12 @@ You can add modifiers by appending them with a dot (`.`) after the event name:
682
721
 
683
722
  <!-- Listen on document level -->
684
723
  <div @keydown.document.esc="closeModal()">Press ESC anywhere</div>
724
+
725
+ <!-- Window listener with throttled updates -->
726
+ <div @resize.window.throttle:100="measureLayout()"></div>
727
+
728
+ <!-- Ignore clicks that originated in descendants -->
729
+ <button @click.self="select()"><span>Select</span></button>
685
730
  ```
686
731
 
687
732
  **Alias:** Prepend the event name with `data-he-`, for example `data-he-click="count++"`
@@ -1000,13 +1045,26 @@ You can also use a string:
1000
1045
  These special variables are available in all JavaScript expressions:
1001
1046
 
1002
1047
  ### $
1003
- Alias for `document.querySelector` - quickly select elements:
1048
+ The `$` query helper preserves `document.querySelector` as its default and adds
1049
+ array-returning plural and scoped forms:
1004
1050
 
1005
1051
  ```html
1006
1052
  <div @click="$('#header').classList.add('active')">Activate Header!</div>
1007
1053
  <button @click="$('.sidebar').style.display = 'none'">Hide Sidebar</button>
1008
1054
  ```
1009
1055
 
1056
+ ```js
1057
+ $(selector) // first match in document
1058
+ $.all(selector) // all matches in document
1059
+ $.root(selector) // first descendant match in $root
1060
+ $.root.all(selector) // all descendant matches in $root
1061
+ $.scope(selector) // first descendant match in $scope
1062
+ $.scope.all(selector) // all descendant matches in $scope
1063
+ ```
1064
+
1065
+ The plural forms return normal arrays. Like `querySelector`, the root and scope
1066
+ forms search descendants and do not include `$root` or `$scope` themselves.
1067
+
1010
1068
  ### $el
1011
1069
  Reference to the current element:
1012
1070
 
@@ -1016,6 +1074,17 @@ Reference to the current element:
1016
1074
  <input @input="console.log($el.value)">
1017
1075
  ```
1018
1076
 
1077
+ ### $root
1078
+
1079
+ The actual root element owned by the current Helium instance. This is the
1080
+ element selected by `@helium`/`data-helium`, the element passed to
1081
+ `helium.mount()`, or `document.body` for the default fallback root.
1082
+
1083
+ ### $scope
1084
+
1085
+ The nearest element that declares local `@data` state, falling back to `$root`.
1086
+ Lite has no local data scopes, so `$scope` and `$root` are always the same.
1087
+
1019
1088
  ### $event
1020
1089
  The event object (available in event handlers):
1021
1090
 
@@ -1025,6 +1094,21 @@ The event object (available in event handlers):
1025
1094
  <form @submit="$event.preventDefault(); handleSubmit()">
1026
1095
  ```
1027
1096
 
1097
+ ### $dispatch
1098
+
1099
+ Dispatch a bubbling, cancelable `CustomEvent` from the current element. The
1100
+ event is returned, so callers can inspect `defaultPrevented`:
1101
+
1102
+ ```html
1103
+ <section @cart:add="total += $event.detail.price">
1104
+ <button @click="$dispatch('cart:add', { price: 12 })">Add</button>
1105
+ </section>
1106
+ ```
1107
+
1108
+ The signature is `$dispatch(name, detail = {}, options = {})`. Options can set
1109
+ `target` (default `$el`), `bubbles` (default `true`), and `cancelable` (default
1110
+ `true`).
1111
+
1028
1112
  ### $data
1029
1113
  The reactive data object containing all Helium variables:
1030
1114
 
@@ -1060,12 +1144,17 @@ The arguments are `url`,`params` (not for `$get`) and `options`. `options` is an
1060
1144
 
1061
1145
  ### Named refs
1062
1146
 
1063
- Each element marked with `@ref="name"` is available as `$name`. There is no
1064
- separate `$refs` object:
1147
+ The first element marked with `@ref="name"` in the nearest defining scope is
1148
+ available as `$name`. `$refs.name` is an array of every matching ref in that
1149
+ scope, in current DOM order:
1065
1150
 
1066
1151
  ```html
1067
1152
  <input @ref="username">
1068
1153
  <button @click="console.log($username.value)">Log Username</button>
1154
+
1155
+ <div @ref="item"></div>
1156
+ <div @ref="item"></div>
1157
+ <button @click="console.log($refs.item.length)">Log item count</button>
1069
1158
  ```
1070
1159
 
1071
1160
  ## Functions
@@ -1164,6 +1253,29 @@ This is the recommended approach when you need to update variables:
1164
1253
 
1165
1254
  ## Advanced Features
1166
1255
 
1256
+ ### Batched Updates
1257
+
1258
+ State changes are batched: a burst of synchronous mutations triggers a single
1259
+ DOM update on the next microtask, and each affected binding runs once no matter
1260
+ how many mutations fed it. This keeps loops over state cheap — updating 100
1261
+ items in a keyed list re-renders the list once, not 100 times:
1262
+
1263
+ ```javascript
1264
+ // One DOM update, not 100
1265
+ for (let i = 0; i < 100; i++) state.items[i].done = true;
1266
+ ```
1267
+
1268
+ Two practical consequences:
1269
+
1270
+ - **Reading the DOM right after a mutation shows the old value.** Await a
1271
+ microtask first: `state.count = 5; await Promise.resolve();` (in tests, a
1272
+ `setTimeout(0)` tick also covers content inserted by `@if`/`@for`, which is
1273
+ processed asynchronously by the MutationObserver).
1274
+ - **Assigning a value that is already current is a no-op** — it doesn't
1275
+ re-trigger bindings, so effects that write unchanged state settle instead of
1276
+ looping. A binding cascade that *never* stops writing new values (e.g.
1277
+ `@effect:*="count++"`) is detected and reported after 100 passes.
1278
+
1167
1279
  ### DOM Morphing with Idiomorph
1168
1280
 
1169
1281
  By default, when you update innerHTML with `@html`, Helium replaces the entire content. This can cause issues like losing focus, resetting scroll positions, or interrupting animations.
@@ -1306,6 +1418,18 @@ import helium from "@daz4126/helium/csp"
1306
1418
  <div @effect:page="analytics.track('page_view', { page })"></div>
1307
1419
  ```
1308
1420
 
1421
+ **Benchmarking:**
1422
+
1423
+ The repo includes a head-to-head runtime benchmark against Alpine.js, React,
1424
+ and Datastar (keyed list create/update/swap/clear plus rapid counter updates,
1425
+ run in real Chromium; Datastar only runs the counter test since it renders
1426
+ lists server-side). Run it with:
1427
+
1428
+ ```bash
1429
+ npm run bench # defaults: 1000 rows, 7 runs
1430
+ node scripts/benchmark.mjs --rows 5000 --runs 5
1431
+ ```
1432
+
1309
1433
  ### Structuring Larger Apps
1310
1434
 
1311
1435
  **Organize state at the root:**
@@ -1411,7 +1535,11 @@ helium({
1411
1535
 
1412
1536
  ### JavaScript Expression Errors
1413
1537
 
1414
- If a binding expression throws at runtime, Helium logs the error and continues without updating that binding. Standard and lite retain malformed expressions as literal text for compatibility; quote intentional string constants, for example `@text="'Ready'"`.
1538
+ If a binding expression throws at runtime, Helium logs the error and continues
1539
+ without updating that binding. Failed compilation keeps Helium's literal-string
1540
+ ergonomics: plain text such as `@text="Loading..."` stays quiet, while
1541
+ expression-looking failures such as `@text="user.name."` or
1542
+ `@click="count +"` emit a `console.warn` with the attribute and expression.
1415
1543
 
1416
1544
  ```html
1417
1545
  <!-- If items is undefined, this won't crash the page -->
@@ -1434,8 +1562,10 @@ promises, so you can handle failures explicitly:
1434
1562
 
1435
1563
  ### Invalid Attribute Syntax
1436
1564
 
1437
- Standard and Lite retain expressions that cannot be compiled as literal values.
1438
- The CSP build logs the parser error and leaves the binding undefined.
1565
+ Helium keeps plain malformed value expressions as literal values. If a failed
1566
+ expression looks like broken JavaScript, Helium emits a warning with directive
1567
+ context. Event handlers, HTTP options, `@data`, `@for`, `@if`, `@calculate`,
1568
+ `@effect`, and `@init` are treated strictly and warn on compile failure.
1439
1569
 
1440
1570
 
1441
1571
  ## Roadmap & Known Limitations
@@ -1445,42 +1575,36 @@ intentionally absent (or still on the roadmap). Current gaps:
1445
1575
 
1446
1576
  ### Not yet supported
1447
1577
 
1448
- - **No DOM-removing `@if`** — only `@hidden`/`@visible`, which toggle visibility
1449
- but keep elements in the DOM.
1450
1578
  - **No `$watch`/`$nextTick`, and no cross-root shared store** — each mounted
1451
1579
  instance has its own isolated state namespace.
1580
+ - **No transition helper** — use CSS transitions/classes directly with
1581
+ `@hidden`, `@visible`, or `@if`.
1452
1582
 
1453
1583
  ### Roadmap
1454
1584
 
1455
1585
  Ordered by recommended implementation sequence:
1456
1586
 
1457
- 1. **Improve expression-compilation diagnostics** — emit a useful `console.warn`
1458
- containing the expression and build/engine context instead of silently
1459
- treating every compile failure as a literal value.
1460
- 2. **Add real-browser CI** covering CSP, Turbo, SSE, focus preservation, late
1461
- imports, generated Lite output, and package exports before adding more DOM
1462
- lifecycle behavior.
1463
- 3. **Document function and `this` context limitations** alongside the existing
1587
+ 1. **Document function and `this` context limitations** alongside the existing
1464
1588
  magic-variable guidance, with correct patterns for passing `$data`, `$el`,
1465
1589
  and other context explicitly.
1466
- 4. **Add opt-in required-CSRF validation for POST/PUT/PATCH** — fail before the
1590
+ 2. **Add opt-in required-CSRF validation for POST/PUT/PATCH** — fail before the
1467
1591
  request when an application declares that a token is mandatory, without
1468
1592
  breaking tokenless APIs and cross-origin requests.
1469
- 5. **Add request cancellation and explicit success/error hooks** using
1593
+ 3. **Add request cancellation and explicit success/error hooks** using
1470
1594
  `AbortController`; define the request lifecycle before expanding loading and
1471
1595
  error-state APIs.
1472
- 6. **Document a form-validation pattern first**, using native constraint
1596
+ 4. **Document a form-validation pattern first**, using native constraint
1473
1597
  validation and Helium state; add helpers only if examples reveal recurring
1474
1598
  boilerplate.
1475
- 7. **Create a complete error-state example** covering validation, HTTP failure,
1599
+ 5. **Create a complete error-state example** covering validation, HTTP failure,
1476
1600
  retry, accessible messaging, and clearing stale errors.
1477
- 8. **Complete HTTP loading-state lifecycle behavior** — `@loading` already
1601
+ 6. **Complete HTTP loading-state lifecycle behavior** — `@loading` already
1478
1602
  exists, so define consistent success, error, cancellation, and restoration
1479
1603
  behavior rather than adding a second loading mechanism.
1480
- 9. **Add debounced two-way binding updates if needed** after reproducing a real
1604
+ 7. **Add debounced two-way binding updates if needed** after reproducing a real
1481
1605
  feedback/caret loop; event-handler debouncing already covers ordinary input
1482
1606
  throttling.
1483
- 10. **Add a minimal watch/middleware system** together with a clear size budget;
1607
+ 8. **Add a minimal watch/middleware system** together with a clear size budget;
1484
1608
  avoid adopting Alpine-scale surface area without demonstrated use cases.
1485
1609
 
1486
1610
  ## Contributing
@@ -1491,9 +1615,12 @@ Helium is open source! Contributions, issues, and feature requests are welcome.
1491
1615
  - Report issues: Create an issue on GitHub
1492
1616
  - Suggest features: Open a discussion on GitHub
1493
1617
 
1494
- Before submitting a change, run `npm run check`. It executes the full test
1495
- suite, creates the production bundles, and fails if any gzip size budget is
1496
- exceeded. `npm run size` also reports raw, gzip, and Brotli sizes.
1618
+ Before submitting a change, run `npm run check`. It executes the full jsdom test
1619
+ suite, creates the production bundles, smoke-tests them, and fails if any gzip
1620
+ size budget is exceeded. `npm run test:browser` runs the Chromium smoke suite
1621
+ used by CI for CSP, Turbo, SSE, keyed focus preservation, late imports, Lite
1622
+ generation, and browser entry imports. `npm run check:ci` runs both paths.
1623
+ `npm run size` also reports raw, gzip, and Brotli sizes.
1497
1624
 
1498
1625
  `helium.js` contains the shared runtime plus sections marked Standard-only.
1499
1626
  `npm run generate` derives `helium-lite.js`; do not edit the generated Lite file