@moku-labs/web 1.13.2 → 1.15.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/dist/index.d.cts CHANGED
@@ -231,6 +231,28 @@ type Api$6 = {
231
231
  t(locale: string, key: string): string;
232
232
  };
233
233
  //#endregion
234
+ //#region src/plugins/i18n/index.d.ts
235
+ /**
236
+ * Internationalization plugin — locale registry plus a flat translation helper
237
+ * with default-locale fallback. Pure config-as-data (no state or events);
238
+ * consumed read-only by content, router, head, and build.
239
+ *
240
+ * @example Register locales and translations
241
+ * ```ts
242
+ * const app = createApp({
243
+ * pluginConfigs: {
244
+ * i18n: {
245
+ * locales: ["en", "uk"],
246
+ * defaultLocale: "en",
247
+ * localeNames: { en: "English", uk: "Українська" },
248
+ * translations: { uk: { "nav.home": "Головна" } }
249
+ * }
250
+ * }
251
+ * });
252
+ * ```
253
+ */
254
+ declare const i18nPlugin: import("@moku-labs/core").PluginInstance<"i18n", Config$6, Record<string, never>, Api$6, {}> & Record<never, never>;
255
+ //#endregion
234
256
  //#region src/plugins/router/iso-match.d.ts
235
257
  /**
236
258
  * A compiled, engine-agnostic path matcher: the same `.exec({ pathname })` shape the
@@ -288,7 +310,10 @@ interface RouteState<P extends string = string, D = unknown> {
288
310
  /** Loaded data type produced by `.load()` (widened only by `.load()`). */
289
311
  readonly data: D;
290
312
  }
291
- /** Render-time context handed to `.render()` / `.head()`; `data` is `.load()`'s return. */
313
+ /**
314
+ * Render-time context handed to `.render()` / `.head()`; `data` is `.load()`'s return,
315
+ * `meta` the route's `.meta()` bag.
316
+ */
292
317
  interface RouteContext<S extends RouteState> {
293
318
  /** Resolved path params. */
294
319
  readonly params: S["params"];
@@ -296,6 +321,13 @@ interface RouteContext<S extends RouteState> {
296
321
  readonly data: S["data"];
297
322
  /** Active locale for this render. */
298
323
  readonly locale: string;
324
+ /**
325
+ * The route's `.meta()` bag (e.g. `{ activeTab: "home" }`). Available in `.render()` and
326
+ * `.head()`, identically at build and on the client — `meta` is compiled into the route and
327
+ * shipped in the client manifest, so a client-only route (dynamic, no `.generate()`, whose
328
+ * `.load()` data is `{}` on the client) can feed static per-route config into its render.
329
+ */
330
+ readonly meta: Record<string, unknown>;
299
331
  /**
300
332
  * Build a link to a named route by pattern substitution — the framework delivers
301
333
  * this on the context (same output as `app.router.toUrl`), so render/head build
@@ -376,21 +408,16 @@ interface GenerateContext {
376
408
  readonly has: (name: string) => boolean;
377
409
  }
378
410
  /**
379
- * Context handed to a route's `.layout()` wrapper: the render-time
380
- * {@link RouteContext} plus the route's `.meta()` bag, so persistent chrome (e.g. a
381
- * TopBar/TabNav) can read `locale` and `meta.activeTab`. Distinct from
382
- * `RouteContext` because the layout is the only handler that needs `meta`; keeping
383
- * it on its own type leaves `.render()`/`.head()` contexts unchanged.
411
+ * Context handed to a route's `.layout()` wrapper identical to {@link RouteContext}
412
+ * (which now carries `meta` for every handler). Retained as a named alias so existing
413
+ * `.layout((ctx, children) => …)` typings keep compiling.
384
414
  *
385
415
  * @remarks
386
416
  * The layout is applied in the SSG render path ONLY. On client (SPA) navigation the
387
- * chrome is persistent and the layout is intentionally NOT re-applied — only the
388
- * inner swap region is replaced. See `build`'s pages phase and `spa`'s kernel.
417
+ * chrome is persistent and the layout is intentionally NOT re-applied — only the inner
418
+ * swap region is replaced. See `build`'s pages phase and `spa`'s kernel.
389
419
  */
390
- interface LayoutContext<S extends RouteState> extends RouteContext<S> {
391
- /** The route's `.meta()` bag (e.g. `{ activeTab: "home" }`). */
392
- readonly meta: Record<string, unknown>;
393
- }
420
+ type LayoutContext<S extends RouteState> = RouteContext<S>;
394
421
  /** Head metadata produced by a route's `.head()` handler. */
395
422
  interface HeadConfig$1 {
396
423
  /** Document title. */
@@ -945,12 +972,25 @@ interface ResolvedSpaConfig {
945
972
  /** Pre-registered components. */
946
973
  components: ComponentDef[];
947
974
  }
948
- /** Context handed to every component lifecycle hook. */
975
+ /**
976
+ * Context handed to every component lifecycle hook — the bound element + page data,
977
+ * plus the matched route's `params`/`meta`/`locale` and a link builder, so an island
978
+ * can read its route context (e.g. a `card` route's `ctx.meta.focus` + `ctx.params.id`)
979
+ * directly, without the page bridging it through `data-*` attributes.
980
+ */
949
981
  interface ComponentContext {
950
982
  /** The element the component instance is bound to. */
951
983
  el: Element;
952
984
  /** Page data extracted from the `script#__DATA__` payload. */
953
985
  data: PageData;
986
+ /** Resolved path params of the route matched for the current URL (empty if unmatched). */
987
+ readonly params: Record<string, string | undefined>;
988
+ /** The matched route's `.meta()` bag (empty if unmatched). */
989
+ readonly meta: Record<string, unknown>;
990
+ /** Active locale for the current route (empty string if unknown). */
991
+ readonly locale: string;
992
+ /** Build a link to a named route by pattern substitution (same output as `app.router.toUrl`). */
993
+ readonly url: (name: string, params?: Record<string, string>) => string;
954
994
  }
955
995
  /** Lifecycle hooks a component may implement. */
956
996
  interface ComponentHooks {
@@ -1234,7 +1274,7 @@ type PhaseContext = {
1234
1274
  readonly global: Readonly<{
1235
1275
  stage: Stage;
1236
1276
  }>; /** Resolve a depended-upon plugin instance to its public API. */
1237
- require: PhaseRequire; /** Whether a plugin is registered (by name) — used to detect the OPTIONAL `data` plugin. */
1277
+ require: PhaseRequire; /** Whether a plugin is registered (by name) — used to detect OPTIONAL plugins (`data`, `content`, `i18n`, `head`). */
1238
1278
  has: (name: string) => boolean; /** Emit a build event (notification-only). */
1239
1279
  emit: PhaseEmit; /** Structured logger (core `log` API). */
1240
1280
  readonly log: PhaseLog;
@@ -1567,7 +1607,8 @@ type Api$3 = {
1567
1607
  /**
1568
1608
  * Build plugin — the static-site-generation orchestrator. Renders every route to
1569
1609
  * `outDir`, and optionally emits feeds, a sitemap, optimized images, and OG
1570
- * images. Depends on site, i18n, content, router, and head; emits `build:phase`.
1610
+ * images. Hard-depends only on site, router, and head; `content` and `i18n` are
1611
+ * OPTIONAL (a content-less or single-locale site builds without them). Emits `build:phase`.
1571
1612
  *
1572
1613
  * @example Configure the production build
1573
1614
  * ```ts
@@ -2817,7 +2858,8 @@ type Api = {
2817
2858
  * (locale fallback, draft filtering, sort, caching, events) lives here; source I/O +
2818
2859
  * the Markdown pipeline live in a {@link ContentProvider} you compose (like `env`
2819
2860
  * providers). The shell imports zero node code, so `contentPlugin` is browser-safe.
2820
- * Depends on i18n; emits `content:ready` and `content:invalidated`.
2861
+ * i18n is OPTIONAL (single default-locale fallback when absent); emits `content:ready`
2862
+ * and `content:invalidated`.
2821
2863
  *
2822
2864
  * @example Compose the node filesystem provider with a content dir + Shiki theme
2823
2865
  * ```ts
@@ -3109,7 +3151,7 @@ declare function buildArticleHead(articleMeta: ArticleMeta, canonicalUrl: string
3109
3151
  * Head plugin — composes per-route `<head>` metadata (title template, Open Graph,
3110
3152
  * Twitter cards, canonical, hreflang). Use the re-exported SEO primitives
3111
3153
  * ({@link meta}, {@link og}, {@link twitter}, …) inside a route's `.head()`.
3112
- * Depends on site, i18n, and router.
3154
+ * Depends on site and router; i18n is OPTIONAL (single default-locale fallback when absent).
3113
3155
  *
3114
3156
  * @example Set global head defaults
3115
3157
  * ```ts
@@ -3135,28 +3177,6 @@ declare const headPlugin: import("@moku-labs/core").PluginInstance<"head", Confi
3135
3177
  buildArticleHead: typeof buildArticleHead;
3136
3178
  };
3137
3179
  //#endregion
3138
- //#region src/plugins/i18n/index.d.ts
3139
- /**
3140
- * Internationalization plugin — locale registry plus a flat translation helper
3141
- * with default-locale fallback. Pure config-as-data (no state or events);
3142
- * consumed read-only by content, router, head, and build.
3143
- *
3144
- * @example Register locales and translations
3145
- * ```ts
3146
- * const app = createApp({
3147
- * pluginConfigs: {
3148
- * i18n: {
3149
- * locales: ["en", "uk"],
3150
- * defaultLocale: "en",
3151
- * localeNames: { en: "English", uk: "Українська" },
3152
- * translations: { uk: { "nav.home": "Головна" } }
3153
- * }
3154
- * }
3155
- * });
3156
- * ```
3157
- */
3158
- declare const i18nPlugin: import("@moku-labs/core").PluginInstance<"i18n", Config$6, Record<string, never>, Api$6, {}> & Record<never, never>;
3159
- //#endregion
3160
3180
  //#region src/plugins/router/builders/route-builder.d.ts
3161
3181
  /**
3162
3182
  * Create a fluent route builder from a URL pattern string. Captures the pattern
@@ -3220,8 +3240,8 @@ declare function createUrls<T extends RouteMap>(routes: T, defaultLocale?: strin
3220
3240
  /**
3221
3241
  * Router plugin — typed, named route definitions with locale-aware URL generation
3222
3242
  * and matching. Author routes with {@link route}, then register them the normal config
3223
- * way via `pluginConfigs.router.routes` (compiled at init). Depends on site (base URL)
3224
- * and i18n (locales).
3243
+ * way via `pluginConfigs.router.routes` (compiled at init). Depends on site (base URL);
3244
+ * i18n (locales) is OPTIONAL — falls back to a single default locale ("en") when absent.
3225
3245
  *
3226
3246
  * @example Register routes via config, then start/build
3227
3247
  * ```ts
package/dist/index.d.mts CHANGED
@@ -229,6 +229,28 @@ type Api$6 = {
229
229
  t(locale: string, key: string): string;
230
230
  };
231
231
  //#endregion
232
+ //#region src/plugins/i18n/index.d.ts
233
+ /**
234
+ * Internationalization plugin — locale registry plus a flat translation helper
235
+ * with default-locale fallback. Pure config-as-data (no state or events);
236
+ * consumed read-only by content, router, head, and build.
237
+ *
238
+ * @example Register locales and translations
239
+ * ```ts
240
+ * const app = createApp({
241
+ * pluginConfigs: {
242
+ * i18n: {
243
+ * locales: ["en", "uk"],
244
+ * defaultLocale: "en",
245
+ * localeNames: { en: "English", uk: "Українська" },
246
+ * translations: { uk: { "nav.home": "Головна" } }
247
+ * }
248
+ * }
249
+ * });
250
+ * ```
251
+ */
252
+ declare const i18nPlugin: import("@moku-labs/core").PluginInstance<"i18n", Config$6, Record<string, never>, Api$6, {}> & Record<never, never>;
253
+ //#endregion
232
254
  //#region src/plugins/router/iso-match.d.ts
233
255
  /**
234
256
  * A compiled, engine-agnostic path matcher: the same `.exec({ pathname })` shape the
@@ -286,7 +308,10 @@ interface RouteState<P extends string = string, D = unknown> {
286
308
  /** Loaded data type produced by `.load()` (widened only by `.load()`). */
287
309
  readonly data: D;
288
310
  }
289
- /** Render-time context handed to `.render()` / `.head()`; `data` is `.load()`'s return. */
311
+ /**
312
+ * Render-time context handed to `.render()` / `.head()`; `data` is `.load()`'s return,
313
+ * `meta` the route's `.meta()` bag.
314
+ */
290
315
  interface RouteContext<S extends RouteState> {
291
316
  /** Resolved path params. */
292
317
  readonly params: S["params"];
@@ -294,6 +319,13 @@ interface RouteContext<S extends RouteState> {
294
319
  readonly data: S["data"];
295
320
  /** Active locale for this render. */
296
321
  readonly locale: string;
322
+ /**
323
+ * The route's `.meta()` bag (e.g. `{ activeTab: "home" }`). Available in `.render()` and
324
+ * `.head()`, identically at build and on the client — `meta` is compiled into the route and
325
+ * shipped in the client manifest, so a client-only route (dynamic, no `.generate()`, whose
326
+ * `.load()` data is `{}` on the client) can feed static per-route config into its render.
327
+ */
328
+ readonly meta: Record<string, unknown>;
297
329
  /**
298
330
  * Build a link to a named route by pattern substitution — the framework delivers
299
331
  * this on the context (same output as `app.router.toUrl`), so render/head build
@@ -374,21 +406,16 @@ interface GenerateContext {
374
406
  readonly has: (name: string) => boolean;
375
407
  }
376
408
  /**
377
- * Context handed to a route's `.layout()` wrapper: the render-time
378
- * {@link RouteContext} plus the route's `.meta()` bag, so persistent chrome (e.g. a
379
- * TopBar/TabNav) can read `locale` and `meta.activeTab`. Distinct from
380
- * `RouteContext` because the layout is the only handler that needs `meta`; keeping
381
- * it on its own type leaves `.render()`/`.head()` contexts unchanged.
409
+ * Context handed to a route's `.layout()` wrapper identical to {@link RouteContext}
410
+ * (which now carries `meta` for every handler). Retained as a named alias so existing
411
+ * `.layout((ctx, children) => …)` typings keep compiling.
382
412
  *
383
413
  * @remarks
384
414
  * The layout is applied in the SSG render path ONLY. On client (SPA) navigation the
385
- * chrome is persistent and the layout is intentionally NOT re-applied — only the
386
- * inner swap region is replaced. See `build`'s pages phase and `spa`'s kernel.
415
+ * chrome is persistent and the layout is intentionally NOT re-applied — only the inner
416
+ * swap region is replaced. See `build`'s pages phase and `spa`'s kernel.
387
417
  */
388
- interface LayoutContext<S extends RouteState> extends RouteContext<S> {
389
- /** The route's `.meta()` bag (e.g. `{ activeTab: "home" }`). */
390
- readonly meta: Record<string, unknown>;
391
- }
418
+ type LayoutContext<S extends RouteState> = RouteContext<S>;
392
419
  /** Head metadata produced by a route's `.head()` handler. */
393
420
  interface HeadConfig$1 {
394
421
  /** Document title. */
@@ -943,12 +970,25 @@ interface ResolvedSpaConfig {
943
970
  /** Pre-registered components. */
944
971
  components: ComponentDef[];
945
972
  }
946
- /** Context handed to every component lifecycle hook. */
973
+ /**
974
+ * Context handed to every component lifecycle hook — the bound element + page data,
975
+ * plus the matched route's `params`/`meta`/`locale` and a link builder, so an island
976
+ * can read its route context (e.g. a `card` route's `ctx.meta.focus` + `ctx.params.id`)
977
+ * directly, without the page bridging it through `data-*` attributes.
978
+ */
947
979
  interface ComponentContext {
948
980
  /** The element the component instance is bound to. */
949
981
  el: Element;
950
982
  /** Page data extracted from the `script#__DATA__` payload. */
951
983
  data: PageData;
984
+ /** Resolved path params of the route matched for the current URL (empty if unmatched). */
985
+ readonly params: Record<string, string | undefined>;
986
+ /** The matched route's `.meta()` bag (empty if unmatched). */
987
+ readonly meta: Record<string, unknown>;
988
+ /** Active locale for the current route (empty string if unknown). */
989
+ readonly locale: string;
990
+ /** Build a link to a named route by pattern substitution (same output as `app.router.toUrl`). */
991
+ readonly url: (name: string, params?: Record<string, string>) => string;
952
992
  }
953
993
  /** Lifecycle hooks a component may implement. */
954
994
  interface ComponentHooks {
@@ -1232,7 +1272,7 @@ type PhaseContext = {
1232
1272
  readonly global: Readonly<{
1233
1273
  stage: Stage;
1234
1274
  }>; /** Resolve a depended-upon plugin instance to its public API. */
1235
- require: PhaseRequire; /** Whether a plugin is registered (by name) — used to detect the OPTIONAL `data` plugin. */
1275
+ require: PhaseRequire; /** Whether a plugin is registered (by name) — used to detect OPTIONAL plugins (`data`, `content`, `i18n`, `head`). */
1236
1276
  has: (name: string) => boolean; /** Emit a build event (notification-only). */
1237
1277
  emit: PhaseEmit; /** Structured logger (core `log` API). */
1238
1278
  readonly log: PhaseLog;
@@ -1565,7 +1605,8 @@ type Api$3 = {
1565
1605
  /**
1566
1606
  * Build plugin — the static-site-generation orchestrator. Renders every route to
1567
1607
  * `outDir`, and optionally emits feeds, a sitemap, optimized images, and OG
1568
- * images. Depends on site, i18n, content, router, and head; emits `build:phase`.
1608
+ * images. Hard-depends only on site, router, and head; `content` and `i18n` are
1609
+ * OPTIONAL (a content-less or single-locale site builds without them). Emits `build:phase`.
1569
1610
  *
1570
1611
  * @example Configure the production build
1571
1612
  * ```ts
@@ -2815,7 +2856,8 @@ type Api = {
2815
2856
  * (locale fallback, draft filtering, sort, caching, events) lives here; source I/O +
2816
2857
  * the Markdown pipeline live in a {@link ContentProvider} you compose (like `env`
2817
2858
  * providers). The shell imports zero node code, so `contentPlugin` is browser-safe.
2818
- * Depends on i18n; emits `content:ready` and `content:invalidated`.
2859
+ * i18n is OPTIONAL (single default-locale fallback when absent); emits `content:ready`
2860
+ * and `content:invalidated`.
2819
2861
  *
2820
2862
  * @example Compose the node filesystem provider with a content dir + Shiki theme
2821
2863
  * ```ts
@@ -3107,7 +3149,7 @@ declare function buildArticleHead(articleMeta: ArticleMeta, canonicalUrl: string
3107
3149
  * Head plugin — composes per-route `<head>` metadata (title template, Open Graph,
3108
3150
  * Twitter cards, canonical, hreflang). Use the re-exported SEO primitives
3109
3151
  * ({@link meta}, {@link og}, {@link twitter}, …) inside a route's `.head()`.
3110
- * Depends on site, i18n, and router.
3152
+ * Depends on site and router; i18n is OPTIONAL (single default-locale fallback when absent).
3111
3153
  *
3112
3154
  * @example Set global head defaults
3113
3155
  * ```ts
@@ -3133,28 +3175,6 @@ declare const headPlugin: import("@moku-labs/core").PluginInstance<"head", Confi
3133
3175
  buildArticleHead: typeof buildArticleHead;
3134
3176
  };
3135
3177
  //#endregion
3136
- //#region src/plugins/i18n/index.d.ts
3137
- /**
3138
- * Internationalization plugin — locale registry plus a flat translation helper
3139
- * with default-locale fallback. Pure config-as-data (no state or events);
3140
- * consumed read-only by content, router, head, and build.
3141
- *
3142
- * @example Register locales and translations
3143
- * ```ts
3144
- * const app = createApp({
3145
- * pluginConfigs: {
3146
- * i18n: {
3147
- * locales: ["en", "uk"],
3148
- * defaultLocale: "en",
3149
- * localeNames: { en: "English", uk: "Українська" },
3150
- * translations: { uk: { "nav.home": "Головна" } }
3151
- * }
3152
- * }
3153
- * });
3154
- * ```
3155
- */
3156
- declare const i18nPlugin: import("@moku-labs/core").PluginInstance<"i18n", Config$6, Record<string, never>, Api$6, {}> & Record<never, never>;
3157
- //#endregion
3158
3178
  //#region src/plugins/router/builders/route-builder.d.ts
3159
3179
  /**
3160
3180
  * Create a fluent route builder from a URL pattern string. Captures the pattern
@@ -3218,8 +3238,8 @@ declare function createUrls<T extends RouteMap>(routes: T, defaultLocale?: strin
3218
3238
  /**
3219
3239
  * Router plugin — typed, named route definitions with locale-aware URL generation
3220
3240
  * and matching. Author routes with {@link route}, then register them the normal config
3221
- * way via `pluginConfigs.router.routes` (compiled at init). Depends on site (base URL)
3222
- * and i18n (locales).
3241
+ * way via `pluginConfigs.router.routes` (compiled at init). Depends on site (base URL);
3242
+ * i18n (locales) is OPTIONAL — falls back to a single default locale ("en") when absent.
3223
3243
  *
3224
3244
  * @example Register routes via config, then start/build
3225
3245
  * ```ts