GitFOSS
fe04f67 (parent 5c6496d)5/9/2026, 8:25:56 AM
.js
JavaScript
(text/javascript)
/* InstantRouter */ 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());
  });
}; // node_modules/@ethicdevs/fastify-stream-react-views/src/instant-router/InstantRouterEvents.ts

var InstantRouterEvents = {
  LOADING: `instantroute_loading`,
  LOADED: `instantroute_loaded`,
  LOAD_ERROR: `instantroute_load_error`,
  NAVIGATING: `instantroute_navigating`,
  NAVIGATED: `instantroute_navigated`,
  NAVIGATION_ERROR: `instantroute_navigation_error`,
}; // node_modules/@ethicdevs/fastify-stream-react-views/src/instant-router/InstantRouter.ts

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 = /* @__PURE__ */ __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 = /* @__PURE__ */ __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 = /* @__PURE__ */ __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 = /* @__PURE__ */ __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 = /* @__PURE__ */ __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 = /* @__PURE__ */ __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",
}; // node_modules/@ethicdevs/fastify-stream-react-views/src/instant-router/index.ts

// if (typeof window !== "undefined") {
//   window.InstantRouter = new InstantRouter({
//     fetchAnchorsOn: "mousedown"
//   });
//   window.InstantRouter.init();
// }

export { InstantRouter, InstantRouterEvents };

GitFOSS • v0.2.0 (#421408f) • MIT License