@moku-labs/web 1.13.1 → 1.14.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/browser.d.mts +31 -13
- package/dist/browser.mjs +135 -22
- package/dist/index.cjs +160 -40
- package/dist/index.d.cts +31 -13
- package/dist/index.d.mts +31 -13
- package/dist/index.mjs +160 -40
- package/package.json +1 -1
package/dist/browser.d.mts
CHANGED
|
@@ -287,7 +287,10 @@ interface RouteState<P extends string = string, D = unknown> {
|
|
|
287
287
|
/** Loaded data type produced by `.load()` (widened only by `.load()`). */
|
|
288
288
|
readonly data: D;
|
|
289
289
|
}
|
|
290
|
-
/**
|
|
290
|
+
/**
|
|
291
|
+
* Render-time context handed to `.render()` / `.head()`; `data` is `.load()`'s return,
|
|
292
|
+
* `meta` the route's `.meta()` bag.
|
|
293
|
+
*/
|
|
291
294
|
interface RouteContext<S extends RouteState> {
|
|
292
295
|
/** Resolved path params. */
|
|
293
296
|
readonly params: S["params"];
|
|
@@ -295,6 +298,13 @@ interface RouteContext<S extends RouteState> {
|
|
|
295
298
|
readonly data: S["data"];
|
|
296
299
|
/** Active locale for this render. */
|
|
297
300
|
readonly locale: string;
|
|
301
|
+
/**
|
|
302
|
+
* The route's `.meta()` bag (e.g. `{ activeTab: "home" }`). Available in `.render()` and
|
|
303
|
+
* `.head()`, identically at build and on the client — `meta` is compiled into the route and
|
|
304
|
+
* shipped in the client manifest, so a client-only route (dynamic, no `.generate()`, whose
|
|
305
|
+
* `.load()` data is `{}` on the client) can feed static per-route config into its render.
|
|
306
|
+
*/
|
|
307
|
+
readonly meta: Record<string, unknown>;
|
|
298
308
|
/**
|
|
299
309
|
* Build a link to a named route by pattern substitution — the framework delivers
|
|
300
310
|
* this on the context (same output as `app.router.toUrl`), so render/head build
|
|
@@ -375,21 +385,16 @@ interface GenerateContext {
|
|
|
375
385
|
readonly has: (name: string) => boolean;
|
|
376
386
|
}
|
|
377
387
|
/**
|
|
378
|
-
* Context handed to a route's `.layout()` wrapper
|
|
379
|
-
*
|
|
380
|
-
*
|
|
381
|
-
* `RouteContext` because the layout is the only handler that needs `meta`; keeping
|
|
382
|
-
* it on its own type leaves `.render()`/`.head()` contexts unchanged.
|
|
388
|
+
* Context handed to a route's `.layout()` wrapper — identical to {@link RouteContext}
|
|
389
|
+
* (which now carries `meta` for every handler). Retained as a named alias so existing
|
|
390
|
+
* `.layout((ctx, children) => …)` typings keep compiling.
|
|
383
391
|
*
|
|
384
392
|
* @remarks
|
|
385
393
|
* The layout is applied in the SSG render path ONLY. On client (SPA) navigation the
|
|
386
|
-
* chrome is persistent and the layout is intentionally NOT re-applied — only the
|
|
387
|
-
*
|
|
394
|
+
* chrome is persistent and the layout is intentionally NOT re-applied — only the inner
|
|
395
|
+
* swap region is replaced. See `build`'s pages phase and `spa`'s kernel.
|
|
388
396
|
*/
|
|
389
|
-
|
|
390
|
-
/** The route's `.meta()` bag (e.g. `{ activeTab: "home" }`). */
|
|
391
|
-
readonly meta: Record<string, unknown>;
|
|
392
|
-
}
|
|
397
|
+
type LayoutContext<S extends RouteState> = RouteContext<S>;
|
|
393
398
|
/** Head metadata produced by a route's `.head()` handler. */
|
|
394
399
|
interface HeadConfig$1 {
|
|
395
400
|
/** Document title. */
|
|
@@ -944,12 +949,25 @@ interface ResolvedSpaConfig {
|
|
|
944
949
|
/** Pre-registered components. */
|
|
945
950
|
components: ComponentDef[];
|
|
946
951
|
}
|
|
947
|
-
/**
|
|
952
|
+
/**
|
|
953
|
+
* Context handed to every component lifecycle hook — the bound element + page data,
|
|
954
|
+
* plus the matched route's `params`/`meta`/`locale` and a link builder, so an island
|
|
955
|
+
* can read its route context (e.g. a `card` route's `ctx.meta.focus` + `ctx.params.id`)
|
|
956
|
+
* directly, without the page bridging it through `data-*` attributes.
|
|
957
|
+
*/
|
|
948
958
|
interface ComponentContext {
|
|
949
959
|
/** The element the component instance is bound to. */
|
|
950
960
|
el: Element;
|
|
951
961
|
/** Page data extracted from the `script#__DATA__` payload. */
|
|
952
962
|
data: PageData;
|
|
963
|
+
/** Resolved path params of the route matched for the current URL (empty if unmatched). */
|
|
964
|
+
readonly params: Record<string, string | undefined>;
|
|
965
|
+
/** The matched route's `.meta()` bag (empty if unmatched). */
|
|
966
|
+
readonly meta: Record<string, unknown>;
|
|
967
|
+
/** Active locale for the current route (empty string if unknown). */
|
|
968
|
+
readonly locale: string;
|
|
969
|
+
/** Build a link to a named route by pattern substitution (same output as `app.router.toUrl`). */
|
|
970
|
+
readonly url: (name: string, params?: Record<string, string>) => string;
|
|
953
971
|
}
|
|
954
972
|
/** Lifecycle hooks a component may implement. */
|
|
955
973
|
interface ComponentHooks {
|
package/dist/browser.mjs
CHANGED
|
@@ -471,6 +471,38 @@ function dynamicSegmentCount(pattern) {
|
|
|
471
471
|
return count;
|
|
472
472
|
}
|
|
473
473
|
/**
|
|
474
|
+
* Whether a route is rendered ENTIRELY on the client in `spa` mode: a dynamic route
|
|
475
|
+
* (≥1 non-lang param) that declares no build-time `.generate()` enumerator, so its
|
|
476
|
+
* concrete param paths are unknown until runtime.
|
|
477
|
+
*
|
|
478
|
+
* The build SKIPS such a route — emitting a static page for it would write one
|
|
479
|
+
* param-less shell whose path (`/b/{id}`) matches no file (a 404) and carries no
|
|
480
|
+
* param for the islands to read. Instead the SPA client-renders it from the URL on
|
|
481
|
+
* boot and on navigation. Build and client share this ONE predicate (the same way
|
|
482
|
+
* `dynamicSegmentCount`/`bySpecificity` are shared) so the two sides can never
|
|
483
|
+
* disagree about which routes are pre-rendered vs. client-only.
|
|
484
|
+
*
|
|
485
|
+
* Static routes (`/`) and dynamic routes WITH `.generate()` are pre-rendered as
|
|
486
|
+
* usual and so are NOT client-only. In `ssg`/`hybrid` mode nothing is client-only
|
|
487
|
+
* (the build pre-renders every route), so this is always `false` outside `spa`.
|
|
488
|
+
*
|
|
489
|
+
* @param mode - The global render mode (`router.mode()`).
|
|
490
|
+
* @param route - The route to test (only its `pattern` + `.generate()` presence are read).
|
|
491
|
+
* @param route.pattern - The route's URL pattern string.
|
|
492
|
+
* @param route._handlers - The route's handler bag.
|
|
493
|
+
* @param route._handlers.generate - The build-only static-paths enumerator, if any (presence only).
|
|
494
|
+
* @returns `true` when the route is client-only (spa mode, dynamic, no `.generate()`).
|
|
495
|
+
* @example
|
|
496
|
+
* ```ts
|
|
497
|
+
* isClientOnlyRoute("spa", { pattern: "/b/{id}", _handlers: {} }); // true
|
|
498
|
+
* isClientOnlyRoute("spa", { pattern: "/", _handlers: {} }); // false (static)
|
|
499
|
+
* isClientOnlyRoute("hybrid", { pattern: "/b/{id}", _handlers: {} }); // false (not spa)
|
|
500
|
+
* ```
|
|
501
|
+
*/
|
|
502
|
+
function isClientOnlyRoute(mode, route) {
|
|
503
|
+
return mode === "spa" && route._handlers.generate === void 0 && dynamicSegmentCount(route.pattern) > 0;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
474
506
|
* Comparator that orders two routes most-specific-first (fewest dynamic segments
|
|
475
507
|
* first). Equal specificity yields `0` so a stable sort preserves declaration
|
|
476
508
|
* order — the exact ordering the compiled matcher table uses, guaranteeing
|
|
@@ -2441,6 +2473,23 @@ const ERROR_PREFIX$2 = "[web]";
|
|
|
2441
2473
|
/** The set of legal hook names, frozen for O(1) membership checks. */
|
|
2442
2474
|
const HOOK_NAME_SET = new Set(COMPONENT_HOOK_NAMES);
|
|
2443
2475
|
/**
|
|
2476
|
+
* No-op link builder for the {@link EMPTY_ROUTE} slice (used when no route matched).
|
|
2477
|
+
*
|
|
2478
|
+
* @returns An empty string.
|
|
2479
|
+
* @example
|
|
2480
|
+
* const href = noUrl();
|
|
2481
|
+
*/
|
|
2482
|
+
function noUrl() {
|
|
2483
|
+
return "";
|
|
2484
|
+
}
|
|
2485
|
+
/** Empty route slice — used for mounts with no matched route (headless, tests, public `scan()`). */
|
|
2486
|
+
const EMPTY_ROUTE = {
|
|
2487
|
+
params: {},
|
|
2488
|
+
meta: {},
|
|
2489
|
+
locale: "",
|
|
2490
|
+
url: noUrl
|
|
2491
|
+
};
|
|
2492
|
+
/**
|
|
2444
2493
|
* Validate a single hook entry: its key must be a known hook name and its value
|
|
2445
2494
|
* must be a function. Throws fail-fast on the first violation.
|
|
2446
2495
|
*
|
|
@@ -2528,18 +2577,25 @@ function runHook(instance, hook, ctx) {
|
|
|
2528
2577
|
instance.def.hooks[hook]?.(ctx);
|
|
2529
2578
|
}
|
|
2530
2579
|
/**
|
|
2531
|
-
* Builds the component context handed to a hook
|
|
2580
|
+
* Builds the component context handed to a hook: the bound element + page data, merged
|
|
2581
|
+
* with the matched route's slice (params/meta/locale/url). Defaults to {@link EMPTY_ROUTE}
|
|
2582
|
+
* when no route is supplied (headless, tests, public `scan()`).
|
|
2532
2583
|
*
|
|
2533
2584
|
* @param element - The element the instance is bound to.
|
|
2534
2585
|
* @param data - The current page data payload.
|
|
2586
|
+
* @param route - The matched-route slice for the current URL.
|
|
2535
2587
|
* @returns The hook context.
|
|
2536
2588
|
* @example
|
|
2537
|
-
* const ctx = makeContext(element, data);
|
|
2589
|
+
* const ctx = makeContext(element, data, route);
|
|
2538
2590
|
*/
|
|
2539
|
-
function makeContext(element, data) {
|
|
2591
|
+
function makeContext(element, data, route = EMPTY_ROUTE) {
|
|
2540
2592
|
return {
|
|
2541
2593
|
el: element,
|
|
2542
|
-
data
|
|
2594
|
+
data,
|
|
2595
|
+
params: route.params,
|
|
2596
|
+
meta: route.meta,
|
|
2597
|
+
locale: route.locale,
|
|
2598
|
+
url: route.url
|
|
2543
2599
|
};
|
|
2544
2600
|
}
|
|
2545
2601
|
/**
|
|
@@ -2553,17 +2609,18 @@ function makeContext(element, data) {
|
|
|
2553
2609
|
* @param swapArea - The swap-region element, or null when none was found.
|
|
2554
2610
|
* @param data - The current page data payload.
|
|
2555
2611
|
* @param element - The candidate element carrying a `data-component` attribute.
|
|
2612
|
+
* @param route - The matched-route slice for the current URL (params/meta/locale/url).
|
|
2556
2613
|
* @example
|
|
2557
|
-
* mountElement(state, emit, swapArea, data, element);
|
|
2614
|
+
* mountElement(state, emit, swapArea, data, element, route);
|
|
2558
2615
|
*/
|
|
2559
|
-
function mountElement(state, emit, swapArea, data, element) {
|
|
2616
|
+
function mountElement(state, emit, swapArea, data, element, route = EMPTY_ROUTE) {
|
|
2560
2617
|
if (state.instances.has(element)) return;
|
|
2561
2618
|
const name = element.dataset.component;
|
|
2562
2619
|
if (!name) return;
|
|
2563
2620
|
const definition = state.registeredComponents.get(name);
|
|
2564
2621
|
if (!definition) return;
|
|
2565
2622
|
const instance = createInstance(definition, element, swapArea ? !swapArea.contains(element) : true);
|
|
2566
|
-
const ctx = makeContext(element, data);
|
|
2623
|
+
const ctx = makeContext(element, data, route);
|
|
2567
2624
|
runHook(instance, "onCreate", ctx);
|
|
2568
2625
|
runHook(instance, "onMount", ctx);
|
|
2569
2626
|
state.instances.set(element, instance);
|
|
@@ -2581,14 +2638,15 @@ function mountElement(state, emit, swapArea, data, element) {
|
|
|
2581
2638
|
* @param state - The plugin state (registeredComponents + instances).
|
|
2582
2639
|
* @param emit - The event emitter for spa:component-mount.
|
|
2583
2640
|
* @param swapSelector - CSS selector bounding page-specific components.
|
|
2641
|
+
* @param route - The matched-route slice for the current URL (params/meta/locale/url).
|
|
2584
2642
|
* @example
|
|
2585
|
-
* scanAndMount(state, emit, "main > section");
|
|
2643
|
+
* scanAndMount(state, emit, "main > section", route);
|
|
2586
2644
|
*/
|
|
2587
|
-
function scanAndMount(state, emit, swapSelector) {
|
|
2645
|
+
function scanAndMount(state, emit, swapSelector, route = EMPTY_ROUTE) {
|
|
2588
2646
|
if (typeof document === "undefined") return;
|
|
2589
2647
|
const swapArea = document.querySelector(swapSelector);
|
|
2590
2648
|
const data = extractPageData(document);
|
|
2591
|
-
for (const element of document.querySelectorAll("[data-component]")) mountElement(state, emit, swapArea, data, element);
|
|
2649
|
+
for (const element of document.querySelectorAll("[data-component]")) mountElement(state, emit, swapArea, data, element, route);
|
|
2592
2650
|
}
|
|
2593
2651
|
/**
|
|
2594
2652
|
* Unmounts page-specific instances inside the swap region (runs `onUnMount`
|
|
@@ -2654,12 +2712,13 @@ function notifyNavStart(state) {
|
|
|
2654
2712
|
* instances were already destroyed and re-created by the swap).
|
|
2655
2713
|
*
|
|
2656
2714
|
* @param state - The plugin state holding live instances.
|
|
2715
|
+
* @param route - The matched-route slice for the destination URL (params/meta/locale/url).
|
|
2657
2716
|
* @example
|
|
2658
|
-
* notifyNavEnd(state);
|
|
2717
|
+
* notifyNavEnd(state, route);
|
|
2659
2718
|
*/
|
|
2660
|
-
function notifyNavEnd(state) {
|
|
2719
|
+
function notifyNavEnd(state, route = EMPTY_ROUTE) {
|
|
2661
2720
|
const data = typeof document === "undefined" ? {} : extractPageData(document);
|
|
2662
|
-
for (const [element, instance] of state.instances) if (instance.persistent) runHook(instance, "onNavEnd", makeContext(element, data));
|
|
2721
|
+
for (const [element, instance] of state.instances) if (instance.persistent) runHook(instance, "onNavEnd", makeContext(element, data, route));
|
|
2663
2722
|
}
|
|
2664
2723
|
//#endregion
|
|
2665
2724
|
//#region src/plugins/spa/head.ts
|
|
@@ -3302,6 +3361,26 @@ function createSpaKernel(state, config, emit, deps) {
|
|
|
3302
3361
|
});
|
|
3303
3362
|
};
|
|
3304
3363
|
/**
|
|
3364
|
+
* Build the matched-route slice (params/meta/locale/url) for the component context at `path`,
|
|
3365
|
+
* so islands read their route's params/meta directly. An unmatched path yields an empty slice.
|
|
3366
|
+
*
|
|
3367
|
+
* @param path - The URL (pathname + search) to match.
|
|
3368
|
+
* @returns The route slice for the matched route.
|
|
3369
|
+
* @example
|
|
3370
|
+
* scanAndMount(state, emit, resolved.swapSelector, componentRouteContext(pathname));
|
|
3371
|
+
*/
|
|
3372
|
+
const componentRouteContext = (path) => {
|
|
3373
|
+
const matchPath = path.split("?")[0] ?? path;
|
|
3374
|
+
const hit = deps.router.match(matchPath);
|
|
3375
|
+
const locale = hit?.params.lang ?? (typeof document === "undefined" ? "" : document.documentElement.lang) ?? "";
|
|
3376
|
+
return {
|
|
3377
|
+
params: hit?.params ?? {},
|
|
3378
|
+
meta: hit?.route._meta ?? {},
|
|
3379
|
+
locale,
|
|
3380
|
+
url: (name, params = {}) => deps.router.toUrl(name, params)
|
|
3381
|
+
};
|
|
3382
|
+
};
|
|
3383
|
+
/**
|
|
3305
3384
|
* Process one navigation: head-sync, unmount, swap, re-mount, emit navigated.
|
|
3306
3385
|
* When the region cannot be swapped (either document lacks the swap selector)
|
|
3307
3386
|
* the SPA nav cannot complete — the head is already synced and the islands torn
|
|
@@ -3319,8 +3398,9 @@ function createSpaKernel(state, config, emit, deps) {
|
|
|
3319
3398
|
syncHead(deps.head, doc);
|
|
3320
3399
|
unmountPageSpecific(state, emit);
|
|
3321
3400
|
if (!swapRegion(doc, resolved.swapSelector, resolved.viewTransitions, () => {
|
|
3322
|
-
|
|
3323
|
-
|
|
3401
|
+
const routeSlice = componentRouteContext(pathname);
|
|
3402
|
+
scanAndMount(state, emit, resolved.swapSelector, routeSlice);
|
|
3403
|
+
notifyNavEnd(state, routeSlice);
|
|
3324
3404
|
}, applyPendingScroll)) {
|
|
3325
3405
|
handleError();
|
|
3326
3406
|
location.href = pathname;
|
|
@@ -3374,17 +3454,22 @@ function createSpaKernel(state, config, emit, deps) {
|
|
|
3374
3454
|
* const resolved = await resolveDataRender("/en/world/");
|
|
3375
3455
|
*/
|
|
3376
3456
|
const resolveDataRender = async (pathname) => {
|
|
3377
|
-
if (!deps.dataAt) return false;
|
|
3378
3457
|
const matchPath = pathname.split("?")[0] ?? pathname;
|
|
3379
3458
|
const hit = deps.router.match(matchPath);
|
|
3380
3459
|
if (!hit?.route._handlers.render) return false;
|
|
3381
|
-
|
|
3382
|
-
if (
|
|
3460
|
+
let data = {};
|
|
3461
|
+
if (!isClientOnlyRoute(deps.router.mode(), hit.route)) {
|
|
3462
|
+
if (!deps.dataAt) return false;
|
|
3463
|
+
const persisted = await deps.dataAt(pathname);
|
|
3464
|
+
if (persisted === null) return false;
|
|
3465
|
+
data = persisted;
|
|
3466
|
+
}
|
|
3383
3467
|
const locale = hit.params.lang ?? document.documentElement.lang ?? "";
|
|
3384
3468
|
const routeContext = {
|
|
3385
3469
|
params: hit.params,
|
|
3386
3470
|
data,
|
|
3387
3471
|
locale,
|
|
3472
|
+
meta: hit.route._meta,
|
|
3388
3473
|
url: (routeName, routeParams = {}) => deps.router.toUrl(routeName, routeParams)
|
|
3389
3474
|
};
|
|
3390
3475
|
const vnode = hit.route._handlers.render(routeContext);
|
|
@@ -3416,6 +3501,7 @@ function createSpaKernel(state, config, emit, deps) {
|
|
|
3416
3501
|
if (signal?.aborted) return;
|
|
3417
3502
|
syncDataHead(deps.head, route, routeContext);
|
|
3418
3503
|
unmountPageSpecific(state, emit);
|
|
3504
|
+
const routeSlice = componentRouteContext(pathname);
|
|
3419
3505
|
/**
|
|
3420
3506
|
* Render the VNode into the region and re-mount its islands in one paint — the
|
|
3421
3507
|
* swap body handed to `runSwap` (optionally wrapped in a View Transition).
|
|
@@ -3427,8 +3513,8 @@ function createSpaKernel(state, config, emit, deps) {
|
|
|
3427
3513
|
*/
|
|
3428
3514
|
const renderAndMount = () => {
|
|
3429
3515
|
renderVNode(vnode, region);
|
|
3430
|
-
scanAndMount(state, emit, resolved.swapSelector);
|
|
3431
|
-
notifyNavEnd(state);
|
|
3516
|
+
scanAndMount(state, emit, resolved.swapSelector, routeSlice);
|
|
3517
|
+
notifyNavEnd(state, routeSlice);
|
|
3432
3518
|
};
|
|
3433
3519
|
runSwap(renderAndMount, resolved.viewTransitions, applyPendingScroll);
|
|
3434
3520
|
state.currentUrl = pathname;
|
|
@@ -3461,6 +3547,30 @@ function createSpaKernel(state, config, emit, deps) {
|
|
|
3461
3547
|
}
|
|
3462
3548
|
};
|
|
3463
3549
|
/**
|
|
3550
|
+
* Initial-load render for a spa client-only route (dynamic, no `.generate()`): the build emitted
|
|
3551
|
+
* no static HTML for it, so the host served a fallback shell. Client-render the matched route into
|
|
3552
|
+
* the swap region from the URL, then mount its islands — the deep-link / refresh paint. Unlike a
|
|
3553
|
+
* navigation there is nothing to unmount and no `spa:navigated` to emit. If the route cannot be
|
|
3554
|
+
* resolved (defensive — a matched client-only route always resolves), fall back to mounting the
|
|
3555
|
+
* served body so boot still wires up whatever islands the shell does carry.
|
|
3556
|
+
*
|
|
3557
|
+
* @param pathname - The current document path (pathname + search).
|
|
3558
|
+
* @example
|
|
3559
|
+
* await bootRender("/b/abc123");
|
|
3560
|
+
*/
|
|
3561
|
+
const bootRender = async (pathname) => {
|
|
3562
|
+
const routeSlice = componentRouteContext(pathname);
|
|
3563
|
+
const resolvedRender = await resolveDataRender(pathname);
|
|
3564
|
+
if (resolvedRender === false) {
|
|
3565
|
+
scanAndMount(state, emit, resolved.swapSelector, routeSlice);
|
|
3566
|
+
return;
|
|
3567
|
+
}
|
|
3568
|
+
const { vnode, region } = resolvedRender;
|
|
3569
|
+
const { renderVNode } = await import("./render-BNe0s7fr.mjs");
|
|
3570
|
+
renderVNode(vnode, region);
|
|
3571
|
+
scanAndMount(state, emit, resolved.swapSelector, routeSlice);
|
|
3572
|
+
};
|
|
3573
|
+
/**
|
|
3464
3574
|
* Unified navigation: try the client DATA path first (only when the `data`
|
|
3465
3575
|
* plugin is composed), then fall back to HTML-over-fetch (which itself falls
|
|
3466
3576
|
* back to a full `location.href` reload). Injected into the router so every
|
|
@@ -3505,7 +3615,10 @@ function createSpaKernel(state, config, emit, deps) {
|
|
|
3505
3615
|
progress = createProgressBar(resolved.progressBar);
|
|
3506
3616
|
state.currentUrl = currentLocationUrl();
|
|
3507
3617
|
state.destroyRouter = attachRouter(handlers, navigate);
|
|
3508
|
-
|
|
3618
|
+
const matchPath = state.currentUrl.split("?")[0] ?? state.currentUrl;
|
|
3619
|
+
const hit = deps.router.match(matchPath);
|
|
3620
|
+
if (hit?.route._handlers.render && isClientOnlyRoute(deps.router.mode(), hit.route)) bootRender(state.currentUrl);
|
|
3621
|
+
else scanAndMount(state, emit, resolved.swapSelector, componentRouteContext(state.currentUrl));
|
|
3509
3622
|
state.started = true;
|
|
3510
3623
|
},
|
|
3511
3624
|
/**
|
|
@@ -3536,7 +3649,7 @@ function createSpaKernel(state, config, emit, deps) {
|
|
|
3536
3649
|
* kernel.scan();
|
|
3537
3650
|
*/
|
|
3538
3651
|
scan() {
|
|
3539
|
-
scanAndMount(state, emit, resolved.swapSelector);
|
|
3652
|
+
scanAndMount(state, emit, resolved.swapSelector, componentRouteContext(state.currentUrl));
|
|
3540
3653
|
},
|
|
3541
3654
|
/**
|
|
3542
3655
|
* Tear down router listeners, dispose all instances, reset boot state.
|