release: WRNexusJS 0.7.0

This commit is contained in:
2026-08-01 10:04:42 +05:30
parent c54144f2e4
commit 87507edf59
207 changed files with 12607 additions and 679 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/csr",
"version": "0.6.0",
"version": "0.7.0",
"type": "module",
"main": "src/index.ts",
"exports": {
+34 -7
View File
@@ -352,8 +352,22 @@ export const REACTIVE_RUNTIME = String.raw`
},
};
}
function sanitizeReactiveUrl(value) {
var raw = String(value == null ? "" : value);
var compact = raw.trim().replace(/[\u0000-\u0020]+/g, "").toLowerCase();
if (/^(?:javascript|vbscript|file):/.test(compact)) return "about:blank";
if (/^data:(?!image\/(?:png|gif|jpeg|webp|avif);)/.test(compact)) return "about:blank";
return raw;
}
function applyReactiveAttribute(node, name, value) {
var lowerName = String(name || "").toLowerCase();
if (
value != null &&
["href", "src", "action", "formaction", "poster", "cite", "background", "xlink:href"].indexOf(lowerName) !== -1
) {
value = sanitizeReactiveUrl(value);
}
if (
lowerName === "value" &&
@@ -2030,16 +2044,29 @@ export const REACTIVE_RUNTIME = String.raw`
function hydrate() {
if (element.__wrnexusScope || !element.isConnected) return;
var started = performance.now ? performance.now() : Date.now();
function complete(module) {
if (element.__wrnexusScope || !element.isConnected) return;
if (module) element.__wrnexusClientModule = module;
setupScope(element);
var ended = performance.now ? performance.now() : Date.now();
try {
element.dispatchEvent(new CustomEvent("wrnexus:hydrated", {
bubbles: true,
detail: {
id: element.getAttribute("data-wrn-hydration") || null,
strategy: strategy,
durationMs: Math.max(0, ended - started),
},
}));
} catch (_) {}
}
var moduleUrl = element.getAttribute("data-wrn-client-module");
if (!moduleUrl || moduleUrl === "__WRNEXUS_CLIENT_MODULE__") {
setupScope(element);
complete(null);
return;
}
loadClientModule(element).then(function (module) {
if (element.__wrnexusScope || !element.isConnected) return;
element.__wrnexusClientModule = module;
setupScope(element);
});
loadClientModule(element).then(complete);
}
if (strategy === "load") {
@@ -2744,7 +2771,7 @@ export const REACTIVE_RUNTIME = String.raw`
credentials: "same-origin",
headers: {
"content-type": "application/json",
"x-wrnexus-csrf": csrf ? csrf.getAttribute("content") || "" : "",
"x-csrf-token": csrf ? csrf.getAttribute("content") || "" : "",
},
body: JSON.stringify({ component: component, function: functionName, args: args || [] }),
}).then(function (response) {
+2 -2
View File
@@ -17,7 +17,7 @@ export class WrnServerCallError extends Error {
function csrfFromCookie(): string | undefined {
if (typeof document === "undefined") return undefined;
const raw = /(?:^|;\s*)wrnexus_csrf=([^;]+)/.exec(document.cookie)?.[1];
const raw = /(?:^|;\s*)wire-csrf=([^;]+)/.exec(document.cookie)?.[1];
return raw ? decodeURIComponent(raw) : undefined;
}
@@ -34,7 +34,7 @@ export async function callServerFunction<TInput extends unknown[], TOutput>(
signal: options.signal,
headers: {
"content-type": "application/json",
...(csrfToken ? { "x-wrnexus-csrf": csrfToken } : {}),
...(csrfToken ? { "x-csrf-token": csrfToken } : {}),
...options.headers,
},
body: JSON.stringify({ component, function: functionName, args }),
+9 -5
View File
@@ -73,11 +73,15 @@ test("ignores cross-origin links (full navigation)", async () => {
test("ignores modified clicks so new-tab still works", async () => {
install(`<div id="app"><a href="/about" id="lnk">x</a></div>`);
win.document
.getElementById("lnk")
.dispatchEvent(
new win.MouseEvent("click", { bubbles: true, cancelable: true, button: 0, metaKey: true }),
);
const MouseEventConstructor = (win as unknown as { MouseEvent: typeof MouseEvent }).MouseEvent;
win.document.getElementById("lnk").dispatchEvent(
new MouseEventConstructor("click", {
bubbles: true,
cancelable: true,
button: 0,
metaKey: true,
}),
);
await flush();
expect(fetchCalls.length).toBe(0);
});
+4 -1
View File
@@ -73,7 +73,10 @@ test("component functions support formatted multiline assignments and ternaries"
increment.click();
expect(increment.textContent).toBe("1");
increment.dispatchEvent(new win.MouseEvent("click", { shiftKey: true }) as unknown as Event);
const MouseEventConstructor = (win as unknown as { MouseEvent: typeof MouseEvent }).MouseEvent;
increment.dispatchEvent(
new MouseEventConstructor("click", { shiftKey: true }) as unknown as Event,
);
expect(increment.textContent).toBe("11");
(win.document.getElementById("normalize") as unknown as HTMLElement).click();