release: WRNexusJS 0.7.0
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wrnexus/csr",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.0",
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"exports": {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 }),
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user