@xingwangzhe/stalux 1.54.0 → 1.54.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xingwangzhe/stalux",
3
- "version": "1.54.0",
3
+ "version": "1.54.1",
4
4
  "description": "A powerful, modern Astro blog theme — use as template or install as plugin",
5
5
  "keywords": [
6
6
  "astro",
@@ -1,4 +1,6 @@
1
+ import { readFileSync } from "node:fs";
1
2
  import { createRequire } from "node:module";
3
+ import { dirname, resolve } from "node:path";
2
4
  import type { Plugin } from "vite";
3
5
 
4
6
  /** Keep a source-only devDependency optional in published consumer projects. */
@@ -7,7 +9,18 @@ export function swupDebugPlugin(development: boolean): Plugin {
7
9
  let entry: string | undefined;
8
10
  if (development) {
9
11
  try {
10
- entry = createRequire(import.meta.url).resolve("@swup/debug-plugin");
12
+ // require.resolve honours the "require" condition and returns the CJS
13
+ // build. Re-exporting that from a virtual ESM module makes the browser
14
+ // fail with "does not provide an export named 'default'". Pick the
15
+ // package's ESM entry from its manifest instead.
16
+ const cjs = createRequire(import.meta.url).resolve("@swup/debug-plugin");
17
+ const manifest = resolve(dirname(cjs), "../package.json");
18
+ const pkg = JSON.parse(readFileSync(manifest, "utf8")) as {
19
+ exports?: { "."?: { import?: string } };
20
+ module?: string;
21
+ };
22
+ const esm = pkg.exports?.["."]?.import ?? pkg.module;
23
+ if (esm) entry = resolve(dirname(manifest), esm);
11
24
  } catch {
12
25
  // Consumers can install @swup/debug-plugin as their own devDependency.
13
26
  }
@@ -36,6 +36,7 @@ interface NavigationContext {
36
36
  incomingDocument?: Document;
37
37
  removeOutgoing?: () => void;
38
38
  obsoleteStyles: Element[];
39
+ pruneObsoleteStyles?: () => void;
39
40
  glide?: PageGlide;
40
41
  releaseOutgoing?: () => void;
41
42
  }
@@ -405,7 +406,17 @@ export function installSwupRouter(): Swup {
405
406
  // motion.start, in the same synchronous block as the entry cue: releasing
406
407
  // it here would paint the new document fully visible for one frame.
407
408
  if (context.controller.signal.aborted) return;
408
- for (const element of context.obsoleteStyles) element.remove();
409
+ // ParallelPlugin keeps the outgoing container visible while it fades out
410
+ // and only removes it at visit:end / content:remove. Its page-scoped CSS
411
+ // must outlive that DOM: pruning here paints the outgoing (and already
412
+ // overlapping) content unstyled for the whole overlap. `awaitAssets`
413
+ // only covers the incoming stylesheets, not the outgoing ones.
414
+ const pruneObsoleteStyles = once(() => {
415
+ for (const element of context.obsoleteStyles) element.remove();
416
+ });
417
+ context.pruneObsoleteStyles = pruneObsoleteStyles;
418
+ if (context.outgoingReady) void context.outgoingReady.then(pruneObsoleteStyles);
419
+ else pruneObsoleteStyles();
409
420
  const incomingStyles = [...next.head.querySelectorAll("style,link[rel=stylesheet]")];
410
421
  authoredStyles = [...document.head.querySelectorAll("style,link[rel=stylesheet]")].filter(
411
422
  (el) => incomingStyles.some((other) => el.isEqualNode(other)),
@@ -513,6 +524,9 @@ export function installSwupRouter(): Swup {
513
524
  const context = contexts.get(visit);
514
525
  context?.controller.abort();
515
526
  context?.removeOutgoing?.();
527
+ // An aborted visit never reaches visit:end, so its outgoing CSS has to
528
+ // be released here or it would linger in head forever.
529
+ context?.pruneObsoleteStyles?.();
516
530
  context?.glide?.cancel();
517
531
  // An aborted visit keeps no exit fill: without this the stage would stay
518
532
  // transparent until the next successful navigation.
@@ -528,6 +542,9 @@ export function installSwupRouter(): Swup {
528
542
  swup.hooks.on("visit:fail", cancel);
529
543
  swup.hooks.on("visit:end", (visit) => {
530
544
  const context = contexts.get(visit);
545
+ // Safety net for paths where the exit animation never settles. The prune
546
+ // is idempotent, so a completed outgoingReady does not remove twice.
547
+ context?.pruneObsoleteStyles?.();
531
548
  context?.glide?.cancel();
532
549
  context?.releaseOutgoing?.();
533
550
  context?.motion?.start(null, { skip: true });