fix(runtime): stabilize navigation and custom errors
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wrnexus/csr",
|
||||
"version": "0.8.19",
|
||||
"version": "0.8.20",
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"exports": {
|
||||
|
||||
@@ -367,6 +367,27 @@ export const NAV_RUNTIME = String.raw`
|
||||
});
|
||||
}
|
||||
|
||||
function syncI18n(nextDocument) {
|
||||
var script = Array.prototype.find.call(
|
||||
nextDocument.querySelectorAll("script:not([src])"),
|
||||
function (node) { return /^window\.__wrnI18n=/.test(String(node.textContent || "").trim()); },
|
||||
);
|
||||
if (!script) return;
|
||||
var match = /^window\.__wrnI18n=([\s\S]*);\s*$/.exec(String(script.textContent || "").trim());
|
||||
if (!match) return;
|
||||
try {
|
||||
var incoming = JSON.parse(match[1]);
|
||||
var current = window.__wrnI18n || {};
|
||||
var translator = current.t;
|
||||
var setter = current.set;
|
||||
window.__wrnI18n = incoming;
|
||||
if (translator) window.__wrnI18n.t = translator;
|
||||
if (setter) window.__wrnI18n.set = setter;
|
||||
} catch (error) {
|
||||
console.error("[wrnexus] failed to synchronize i18n data", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run explicit component cleanup before removing the existing page.
|
||||
*
|
||||
@@ -516,6 +537,8 @@ export const NAV_RUNTIME = String.raw`
|
||||
|
||||
syncPreservationPolicy(doc);
|
||||
|
||||
syncI18n(doc);
|
||||
|
||||
syncWrnStyles(doc);
|
||||
|
||||
var importedNodes = [];
|
||||
@@ -568,6 +591,10 @@ export const NAV_RUNTIME = String.raw`
|
||||
*/
|
||||
rehydrate(currentApp);
|
||||
|
||||
if (window.__wrnLang && typeof window.__wrnLang.bind === "function") {
|
||||
window.__wrnLang.bind(currentApp);
|
||||
}
|
||||
|
||||
if (!isPop) {
|
||||
history.pushState(
|
||||
{
|
||||
|
||||
@@ -139,6 +139,28 @@ test("rebinds theme controls after swapping the page", async () => {
|
||||
expect(win.document.querySelector("[data-wrn-theme-toggle]")).not.toBeNull();
|
||||
});
|
||||
|
||||
test("synchronizes and rebinds i18n data during client navigation", async () => {
|
||||
install(`<div id="app"><a href="/about" id="lnk">About</a></div>`);
|
||||
let boundRoot: unknown;
|
||||
const translate = () => "translated";
|
||||
const setLanguage = () => true;
|
||||
win.__wrnI18n = { lang: "en", messages: { old: "Old" }, t: translate, set: setLanguage };
|
||||
win.__wrnLang = { bind: (root: unknown) => (boundRoot = root) };
|
||||
nextHtml =
|
||||
`<html lang="mr"><body><div id="app"><p data-t="home.title">नवीन</p></div>` +
|
||||
`<script>window.__wrnI18n={"lang":"mr","messages":{"home":{"title":"नवीन"}},"fallbackMessages":{}};</script>` +
|
||||
`</body></html>`;
|
||||
|
||||
win.document.getElementById("lnk").click();
|
||||
await flush();
|
||||
|
||||
expect(win.__wrnI18n.lang).toBe("mr");
|
||||
expect(win.__wrnI18n.messages.home.title).toBe("नवीन");
|
||||
expect(win.__wrnI18n.t).toBe(translate);
|
||||
expect(win.__wrnI18n.set).toBe(setLanguage);
|
||||
expect(boundRoot).toBe(win.document.getElementById("app"));
|
||||
});
|
||||
|
||||
test("unmounts and remounts package runtimes during client navigation", async () => {
|
||||
install(
|
||||
`<div id="app"><div data-wrnexus-runtime="captcha">Old</div><a href="/next" id="lnk">Next</a></div>`,
|
||||
|
||||
Reference in New Issue
Block a user