var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) =>
key in obj
? __defProp(obj, key, {
enumerable: true,
configurable: true,
writable: true,
value,
})
: (obj[key] = value);
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __name = (target, value) =>
__defProp(target, "name", {
value,
configurable: true,
});
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) =>
x.done
? resolve(x.value)
: Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
var InstantRouterEvents = {
LOADING: `instantroute_loading`,
LOADED: `instantroute_loaded`,
LOAD_ERROR: `instantroute_load_error`,
NAVIGATING: `instantroute_navigating`,
NAVIGATED: `instantroute_navigated`,
NAVIGATION_ERROR: `instantroute_navigation_error`,
};
var _InstantRouter = class {
constructor(opts) {
this.pageHref = window.location.href;
this.domParser = new DOMParser();
this.opts = __spreadValues(
__spreadValues({}, _InstantRouter.defaultOpts),
opts || {},
);
}
init() {
this.monkeyPatchLocationReplace();
document.addEventListener(
this.opts.fetchAnchorsOn,
this.onClientSideRouterMouseDown,
false,
);
document.addEventListener("submit", this.onClientSideRouterSubmit);
window.addEventListener("popstate", this.onClientSideRouterPopstate);
console.log(
`[${Date.now()}][InstantRouter] Ready to handle clicks & form submissions!`,
);
}
onClientSideRouterMouseDown(ev) {
console.log("mouse click:", ev);
let targetEl = ev.target;
if (ev == null || ev.button !== 0) {
return false;
}
if (targetEl == null) {
return false;
}
if (
targetEl.tagName.toLowerCase() !== "a" &&
targetEl.parentElement != null
) {
const parentAnchor = targetEl.parentElement.closest("a");
if (parentAnchor != null) {
targetEl = parentAnchor;
}
}
if (
"href" in targetEl === false ||
targetEl.href == null ||
targetEl.href.trim() === ""
) {
return false;
}
console.log("click on a link has been catched... processing...");
const targetDataset = targetEl.dataset;
const baseUrl = new URL(document.baseURI);
const targetUrl = new URL(targetEl.href, document.baseURI);
const isExternalUrl = baseUrl.origin !== targetUrl.origin;
if (isExternalUrl || targetDataset["externalLink"] === "true") {
return false;
}
const targetHash = targetUrl.hash;
const isHashChange = !!(
targetHash != null &&
targetHash.trim() !== "" &&
targetHash.startsWith("#")
);
if (isHashChange) {
const hashEl = document.querySelector(targetHash);
if (hashEl != null) {
ev.preventDefault();
if (targetDataset["smoothScroll"] !== "disabled") {
hashEl.scrollIntoView({
behavior: "smooth",
});
}
window.location.hash = targetHash;
return true;
}
return false;
}
console.log("not a hash, need navigation to new page");
ev.preventDefault();
ev.stopPropagation();
return __async(this, null, function* () {
let doNavigate = null;
let pollWaitFetchDoneIntervalId = null;
const navigateOrWait = __name(() => {
if (doNavigate != null) {
doNavigate();
if (pollWaitFetchDoneIntervalId != null) {
clearTimeout(pollWaitFetchDoneIntervalId);
pollWaitFetchDoneIntervalId = null;
}
if (targetEl != null && onClickHandler != null) {
targetEl.removeEventListener("click", onClickHandler);
onClickHandler = null;
}
} else {
pollWaitFetchDoneIntervalId = setTimeout(() => {
if (pollWaitFetchDoneIntervalId != null) {
clearTimeout(pollWaitFetchDoneIntervalId);
pollWaitFetchDoneIntervalId = null;
}
navigateOrWait();
}, 10);
}
}, "navigateOrWait");
let onClickHandler = __name((subEv) => {
subEv.preventDefault();
navigateOrWait();
return true;
}, "onClickHandler");
try {
targetEl.addEventListener("click", onClickHandler);
doNavigate = yield this.fetchAndPushState(
targetEl.href,
this.pageHref,
void 0,
void 0,
void 0,
targetDataset["smoothScroll"] !== "disabled",
);
} catch (_) {
targetEl.removeEventListener("click", onClickHandler);
onClickHandler = null;
doNavigate = __name(() => {
window.location.href = targetEl.href;
}, "doNavigate");
}
return true;
});
}
onClientSideRouterSubmit(ev) {
return __async(this, null, function* () {
const targetEl = ev.target;
if (targetEl == null || targetEl.tagName.toLowerCase() !== "form") {
return false;
}
const targetAction = targetEl.action;
const targetMethod = targetEl.method;
if (
targetAction == null ||
targetAction.trim() === "" ||
targetMethod == null ||
["get", "post"].includes(targetMethod.toLowerCase()) === false
) {
return false;
}
ev.preventDefault();
const headers = {
"content-type": "application/x-www-form-urlencoded",
};
const targetFormData = new FormData(targetEl);
let targetFormDataEntries = {};
targetFormData.forEach((v, k) => {
targetFormDataEntries = __spreadProps(
__spreadValues({}, targetFormDataEntries),
{
[k]: v,
},
);
});
const bodyFormEncoded = Object.entries(targetFormDataEntries)
.map(([k, v]) => `${k}=${v}`)
.join("&");
let doNavigate = __name(() => {
window.location.href = targetAction;
}, "doNavigate");
try {
doNavigate = yield this.fetchAndPushState(
targetAction,
this.pageHref,
targetMethod,
bodyFormEncoded,
headers,
);
} catch (_) {}
doNavigate();
return true;
});
}
onClientSideRouterPopstate(event) {
return __async(this, null, function* () {
setTimeout(
() =>
__async(this, null, function* () {
if (event.state) {
if (event.state.targetHref != null) {
let doNavigate = __name(() => {
window.location.href = event.state.targetHref;
}, "doNavigate");
try {
doNavigate = yield this.fetchAndPushState(
event.state.targetHref,
this.pageHref,
void 0,
void 0,
void 0,
false,
);
} catch (_) {}
doNavigate();
return true;
}
return false;
} else {
return false;
}
}),
0,
);
});
}
monkeyPatchLocationReplace() {
window.location["hardReplace"] = window.location.replace;
const replace = __name((url) => {
this.pageHref = window.location.href;
this.fetchAndPushState(url.toString(), this.pageHref)
.then((doNavigate) => doNavigate())
.catch(() => window.location["hardReplace"](url.toString()));
}, "replace");
try {
window.location.replace = replace;
Object.defineProperty(window.location, "replace", {
writable: true,
value: {
assign: replace,
},
});
} catch (_) {}
}
fetchAnchorHref(
anchorHref,
currentLocationHref,
method = "get",
body = void 0,
headers = void 0,
) {
return __async(this, null, function* () {
const url =
method.toLowerCase() === "get" && body != null
? `${anchorHref}?${body}`
: anchorHref;
const res = yield fetch(url, {
method,
body: method.toLowerCase() !== "get" ? body : void 0,
headers: __spreadProps(
__spreadValues(
__spreadValues({}, headers || {}),
anchorHref !== currentLocationHref
? {
referer: currentLocationHref,
}
: {},
),
{
accept: "text/html",
"accept-charset": "utf-8",
"x-requested-with": "XMLHttpRequest",
},
),
});
return res;
});
}
fetchAndPushState(
targetHref,
refererHref,
method = "get",
body = void 0,
headers = void 0,
withAutoScroll = true,
) {
return __async(this, null, function* () {
let targetHtml = null;
try {
document.dispatchEvent(
new CustomEvent(InstantRouterEvents.LOADING, {
detail: {
request: {
method,
url: targetHref,
body,
headers,
referer: refererHref,
},
},
}),
);
let res = yield this.fetchAnchorHref(
targetHref,
refererHref,
method,
body,
headers,
);
if (res.status >= 301 && res.status <= 308) {
const locationHeaderHref = res.headers.get("location");
if (locationHeaderHref != null) {
targetHref = locationHeaderHref;
res = yield this.fetchAnchorHref(
targetHref,
refererHref,
method,
body,
headers,
);
}
} else {
targetHtml = yield res.text();
targetHref = res.url;
}
document.dispatchEvent(
new CustomEvent(InstantRouterEvents.LOADED, {
detail: {
request: {
method,
url: targetHref,
body,
headers,
referer: refererHref,
},
response: {
html: targetHtml,
},
},
}),
);
} catch (err) {
const error = err;
document.dispatchEvent(
new CustomEvent(InstantRouterEvents.LOAD_ERROR, {
detail: {
request: {
method,
url: targetHref,
body,
headers,
referer: refererHref,
},
response: {
error,
},
},
}),
);
}
if (targetHtml == null) {
document.dispatchEvent(
new CustomEvent(InstantRouterEvents.LOAD_ERROR, {
detail: {
request: {
method,
url: targetHref,
body,
headers,
referer: refererHref,
},
response: {
error: new Error(
"Could not retrieve HTML to display, it was null.",
),
},
},
}),
);
return () => void 0;
}
const targetDoc = this.domParser.parseFromString(targetHtml, "text/html");
const {
body: targetBody,
head: targetHead,
title: targetTitle,
} = targetDoc;
const targetStyles = [];
targetHead.childNodes.forEach((node) => {
if (node.nodeType === 1 && node.nodeName.toLowerCase() === "style") {
targetStyles.push(node);
}
});
return () => {
var _a;
try {
document.dispatchEvent(
new CustomEvent(InstantRouterEvents.NAVIGATING, {
detail: {
request: {
url: targetHref,
referer: refererHref,
body: targetBody,
head: targetHead,
title: targetTitle,
},
},
}),
);
document.title = targetTitle;
document.body.innerHTML =
targetBody.innerHTML || document.body.innerHTML;
if (document.scrollingElement != null && withAutoScroll === true) {
document.scrollingElement.scrollTo({
behavior: "smooth",
top: 0,
});
}
if (
typeof window.history !== "undefined" &&
targetHref !==
((_a = history.state) == null ? void 0 : _a.targetHref) &&
targetHref !== refererHref
) {
const targetUrl = new URL(targetHref);
window.history.pushState(
{
targetHref,
},
"",
method.toLowerCase() === "get" && body != null
? [
targetUrl.pathname,
targetUrl.search.trim() === ""
? `?${body}`
: `${targetUrl.search}`,
].join("")
: [targetUrl.pathname, targetUrl.search].join(""),
);
}
document.body.childNodes.forEach((childNode) => {
if (
childNode.nodeName.toLowerCase() === "script" &&
childNode.type === "module"
) {
const islandsScriptTxt = childNode.textContent;
if (
islandsScriptTxt != null &&
islandsScriptTxt.includes("IslandsRuntime")
) {
const nextScriptEl = document.createElement("script");
nextScriptEl.textContent = islandsScriptTxt;
nextScriptEl.type = "module";
childNode.remove();
document.body.appendChild(nextScriptEl);
}
}
});
this.pageHref = targetHref;
document.dispatchEvent(
new CustomEvent(InstantRouterEvents.NAVIGATED, {
detail: {
request: {
url: targetHref,
referer: refererHref,
body: targetBody,
head: targetHead,
title: targetTitle,
},
response: true,
},
}),
);
} catch (err) {
const error = err;
document.dispatchEvent(
new CustomEvent(InstantRouterEvents.NAVIGATION_ERROR, {
detail: {
request: {
url: targetHref,
referer: refererHref,
body: targetBody,
head: targetHead,
title: targetTitle,
},
response: {
error,
},
},
}),
);
}
};
});
}
};
var InstantRouter = _InstantRouter;
__name(InstantRouter, "InstantRouter");
InstantRouter.defaultOpts = {
fetchAnchorsOn: "mousedown",
};
export { InstantRouter, InstantRouterEvents };