@elurjs/kit 2.5.0 → 2.6.0-beta.0

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
@@ -5,6 +5,37 @@ All notable changes to Elur Kit are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.6.0-beta.0]
9
+
10
+ Prerelease del canal beta alineada con `@elurjs/core@3.7.0-beta.0`
11
+ (motor `next-2` por defecto) y `@elurjs/vite-plugin-elur@2.2.0-beta.0`
12
+ (emit gating + writers especializados). Sin cambios funcionales en Kit:
13
+ todas las features de router next-gen y zero-JS ya shippearon en 2.5.x.
14
+
15
+ ### Changed
16
+
17
+ - **Peer ranges ampliados** — `@elurjs/core` acepta
18
+ `^3.6.2 || ^3.7.0-beta.0` y `@elurjs/vite-plugin-elur` acepta
19
+ `^2.1.0 || ^2.2.0-beta.0`, permitiendo instalar el stack beta completo
20
+ sin warnings de peer deps.
21
+ - **Lockfile migrado a `bun.lock`** — `package-lock.json` eliminado del
22
+ repo (el workspace usa bun).
23
+
24
+ ## [2.5.1]
25
+
26
+ ### Fixed
27
+
28
+ - **`elur-kit build` never generated image variants** — the CLI bundle
29
+ (`dist/lib/cli.js`) had `import("sharp")` rewritten by Vite's
30
+ optional-peer-dep transform into a stub that always throws
31
+ (`Could not resolve "sharp"`), because `sharp` was missing from the
32
+ externals in `vite.cli.config.ts`. `loadSharp()` caught the error and
33
+ permanently returned `null`, so `processImageBatch` fell back to
34
+ manifest-only entries (`variants: []`) and every `image()` emitted a
35
+ plain `<img>` instead of a `<picture>` with WebP/AVIF sources. `sharp`
36
+ is now external in the CLI build, so the optional peer resolves from
37
+ the consuming project's `node_modules` at runtime.
38
+
8
39
  ## [2.5.0]
9
40
 
10
41
  All changes are additive and backwards-compatible: existing projects work
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@elurjs/kit.svg)](https://www.npmjs.com/package/@elurjs/kit)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- > Full-stack framework for Elur — file-based routing, SSG, SSR, ISR, streaming, islands, actions, content collections, cache adapters, and SPA-like navigation. Zero extra runtime dependencies on the client: Elur stays at ~15 KB. Optional build-time compiler lowers `html\`\`` templates to imperative DOM code for ~25–44% faster renders.
6
+ > Full-stack framework for Elur — file-based routing, SSG, SSR, ISR, streaming, islands, actions, content collections, cache adapters, and SPA-like navigation. Zero extra runtime dependencies on the client: Elur stays at ~15 KB. Optional build-time compiler lowers ``html` `` templates to imperative DOM code for ~25–44% faster renders.
7
7
 
8
8
  ## What is Elur Kit?
9
9
 
@@ -22,7 +22,7 @@ Elur Kit is a framework built on top of [Elur](https://elur.dev/). It brings con
22
22
 
23
23
  - **Routing**: file-based with dynamic segments, optional catch-all `[[...slug]]`, route conflict detection, safe URL decoding, redirects/rewrites/route headers
24
24
  - **Rendering**: SSG, SSR, ISR with explicit cache policy (public/private/dynamic), opt-in streaming SSR with `loading.ts` boundaries (**experimental** — ver [Streaming SSR](#streaming-ssr-experimental))
25
- - **Build-time compiler** (optional, recommended): integrates [`@elurjs/core-compiler`](https://www.npmjs.com/package/@elurjs/core-compiler) via [`@elurjs/vite-plugin-elur`](https://www.npmjs.com/package/@elurjs/vite-plugin-elur) to lower `html\`\`` templates to imperative DOM code at build time — eliminates `detectContext`, `buildHTML`, and both `TreeWalker` passes in runtime
25
+ - **Build-time compiler** (optional, recommended): integrates [`@elurjs/core-compiler`](https://www.npmjs.com/package/@elurjs/core-compiler) via [`@elurjs/vite-plugin-elur`](https://www.npmjs.com/package/@elurjs/vite-plugin-elur) to lower ``html` `` templates to imperative DOM code at build time — eliminates `detectContext`, `buildHTML`, and both `TreeWalker` passes in runtime
26
26
  - **Partial attribute interpolation**: `class="btn ${size}"` works out of the box via the Vite plugin's state-machine lexer (or the kit's legacy transform as fallback)
27
27
  - **Actions**: typed `defineAction()` with input validation, AbortSignal, idempotency, concurrency modes (latest/queue/parallel)
28
28
  - **Cache**: `CacheAdapter` with filesystem, Redis, and Cloudflare KV storage, SHA-256 keys, atomic writes, single-flight, stale-while-revalidate, tag-based invalidation
@@ -48,7 +48,7 @@ npm install @elurjs/vite-plugin-elur
48
48
 
49
49
  The plugin is an optional peer dependency. When installed, it activates:
50
50
 
51
- - **Build-time compiler** — lowers `html\`\`` to imperative DOM code
51
+ - **Build-time compiler** — lowers ``html` `` to imperative DOM code
52
52
  - **Partial attribute interpolation** — state-machine lexer (replaces the kit's legacy transform)
53
53
  - **HMR with state preservation** — signals, stores, forms, routers survive hot updates
54
54
  - **Scroll/focus preservation** — restored after re-mount
@@ -266,6 +266,52 @@ routes you want cached.
266
266
  - Behind a reverse proxy, make sure buffering and gzip buffering are disabled
267
267
  for streamed routes (the `X-Accel-Buffering: no` header covers nginx).
268
268
 
269
+ ## What's new in v2.5
270
+
271
+ **0% JavaScript by default + next-generation router.**
272
+
273
+ - **Per-page JS gating** — the document shell scans the rendered body
274
+ for `data-elur-island` markers: pages without islands ship **0 KB of
275
+ JS** when `router.enabled: false`, or **only the router chunk** when
276
+ the router is on. Pages with islands get `entry-client.js` +
277
+ `router.js`, each with `<link rel="modulepreload">`. Escape hatch:
278
+ `defineConfig({ js: "legacy" })` restores the unconditional combined
279
+ entry. See [Per-page JavaScript emission](#per-page-javascript-emission).
280
+ - **Split client entries** — the generated entry is hydrate-only and
281
+ the router lives in `.elur/router.ts` → `/_elur/router.js`.
282
+ Single-input `vite.client.config.*` files keep working (router
283
+ embedded = legacy mode de facto).
284
+ - **Production head fix** — `/__elur-js/render` now returns
285
+ `{ title, body, head, data, actions, clearActionErrorCookie }` in
286
+ every runtime; head metadata updates on SPA navigations and the
287
+ action-error cookie is actually cleared.
288
+ - **Navigation lifecycle events** — `elur:navigate-start` /
289
+ `elur:navigate-end` / `elur:navigate-error` with
290
+ `{ pathname, search, fromCache, popstate }`, plus
291
+ `elur:before-render` before the swap (islands dispose while still
292
+ attached; `detail.persisted` lists survivors).
293
+ - **`data-elur-persist="key"`** — live DOM nodes are moved (not
294
+ re-rendered) across navigations via `Element.moveBefore()`
295
+ (`replaceWith` fallback); islands inside keep their state.
296
+ - **Router robustness** — bounded LRU prefetch cache (32 entries,
297
+ 30 s), `history.scrollRestoration = "manual"` with per-entry scroll,
298
+ prefetch on `pointerenter`/`focus`/`pointerdown` + opt-in viewport
299
+ (`data-prefetch="viewport"`), Save-Data/2g-aware, inline `<script>`
300
+ re-execution after navigation, `#elur-data`/`#elur-actions` refresh.
301
+ - **Optional extras** — `router.morph` (idiomorph-based DOM morphing,
302
+ experimental), `router.loadingIndicator` (top progress bar, >200 ms
303
+ delay, reduced-motion aware), `router.speculation` (Speculation
304
+ Rules API on static pages).
305
+ - **`directive: "load"` is real now** — the generated entry calls
306
+ `hydrateIslands()` immediately; the global `requestIdleCallback`
307
+ wrapper is gone. `idle`/`visible` keep their deferred scheduling.
308
+ - **`startClientRouter(options)`** accepts
309
+ `{ prefetch, morph, loadingIndicator }`; `prefetch()` gains
310
+ `{ force: true }` to bypass network guards.
311
+
312
+ All changes are backwards-compatible; existing projects keep working
313
+ unchanged.
314
+
269
315
  ## What's new in v2.4
270
316
 
271
317
  - **Fixed: image pipeline silently no-op** — the CLI bundle was
@@ -315,7 +361,7 @@ routes you want cached.
315
361
  SSR errors are never silently swallowed — they propagate wrapped with
316
362
  the island name and remediation hints.
317
363
 
318
- #### Using the `build` hook for sitemaps
364
+ ### Using the `build` hook for sitemaps
319
365
 
320
366
  When `site` is set in your config, the build **already generates
321
367
  `sitemap.xml` automatically** from the scanned routes (dynamic routes,
@@ -396,7 +442,7 @@ When both plugins are installed:
396
442
  | Feature | Kit only | Kit + Vite plugin |
397
443
  | --- | --- | --- |
398
444
  | Partial attr interpolation | Legacy transform (heuristic) | State-machine lexer (compile-time) |
399
- | Build-time compiler | No | Yes (`html\`\`` → imperative DOM) |
445
+ | Build-time compiler | No | Yes (``html` `` → imperative DOM) |
400
446
  | HMR state preservation | No | Yes (signals, stores, forms, routers) |
401
447
  | Scroll/focus preservation | No | Yes |
402
448
  | SSR | Works (kit handles it) | Works (plugin skips compiler in SSR) |
@@ -514,6 +560,7 @@ receive the full transform pipeline.
514
560
  | v2.4.2 | Integration `build` hook wired into `build()`, `BuildResult.outDir` for post-build artifacts ✅ |
515
561
  | v2.4.3 | Client-only islands (`directive: "only"`, `options: { ssr: false, fallback }`), `isSSR()` export, SSR error wrapping ✅ |
516
562
  | v2.4.4 | Fix: `"only"` directive now hydrates immediately like `"load"`. Fix: islands without SSR DOM use fresh `_render` mount instead of `hydrateTemplate` ✅ |
563
+ | v2.5 | 0% JS por defecto (gating por página + split entry/router + `js:"legacy"`), router de nueva generación (eventos de ciclo de vida, `data-elur-persist`, LRU+network-aware prefetch, morph opcional, speculation rules, loading indicator), fix head/payload del render endpoint en prod, `load` real ✅ |
517
564
 
518
565
  ## API
519
566
 
@@ -996,7 +1043,7 @@ export default defineConfig({
996
1043
 
997
1044
  The Vite plugin activates:
998
1045
 
999
- - **Build-time compiler** — lowers `html\`\`` templates to imperative DOM
1046
+ - **Build-time compiler** — lowers ``html` `` templates to imperative DOM
1000
1047
  code (`firstChild`/`nextSibling` navigation, inline `setAttribute`,
1001
1048
  grouped effects, event delegation). Eliminates `detectContext`,
1002
1049
  `buildHTML`, and both `TreeWalker` passes in runtime.
package/dist/lib/cli.cjs CHANGED
@@ -877,14 +877,6 @@ function actionNames(actions) {
877
877
  }
878
878
  var init_scan = __esmMin((() => {}));
879
879
  //#endregion
880
- //#region __vite-optional-peer-dep:sharp:@elurjs/kit
881
- var kit_exports = /* @__PURE__ */ __exportAll({ default: () => kit_default });
882
- var kit_default;
883
- var init_kit = __esmMin((() => {
884
- kit_default = {};
885
- throw new Error(`Could not resolve "sharp" imported by "@elurjs/kit". Is it installed?`);
886
- }));
887
- //#endregion
888
880
  //#region src/image/service.ts
889
881
  init_render();
890
882
  init_scan();
@@ -898,7 +890,7 @@ async function loadSharp() {
898
890
  if (sharpLoader === null) return null;
899
891
  if (sharpLoader) return sharpLoader();
900
892
  try {
901
- const sharp = (await Promise.resolve().then(() => (init_kit(), kit_exports))).default;
893
+ const sharp = (await import("sharp")).default;
902
894
  if (typeof sharp !== "function") {
903
895
  sharpLoader = null;
904
896
  return null;