omi-router
Version: 
Router for Omi
323 lines (322 loc) • 9.8 kB
JavaScript
import { mixin as O, tag as D, Component as N, render as S, h as I } from "omi";
function $(e) {
  for (var t = [], r = 0; r < e.length; ) {
    var a = e[r];
    if (a === "*" || a === "+" || a === "?") {
      t.push({ type: "MODIFIER", index: r, value: e[r++] });
      continue;
    }
    if (a === "\\") {
      t.push({ type: "ESCAPED_CHAR", index: r++, value: e[r++] });
      continue;
    }
    if (a === "{") {
      t.push({ type: "OPEN", index: r, value: e[r++] });
      continue;
    }
    if (a === "}") {
      t.push({ type: "CLOSE", index: r, value: e[r++] });
      continue;
    }
    if (a === ":") {
      for (var c = "", n = r + 1; n < e.length; ) {
        var i = e.charCodeAt(n);
        if (
          // `0-9`
          i >= 48 && i <= 57 || // `A-Z`
          i >= 65 && i <= 90 || // `a-z`
          i >= 97 && i <= 122 || // `_`
          i === 95
        ) {
          c += e[n++];
          continue;
        }
        break;
      }
      if (!c)
        throw new TypeError("Missing parameter name at ".concat(r));
      t.push({ type: "NAME", index: r, value: c }), r = n;
      continue;
    }
    if (a === "(") {
      var h = 1, l = "", n = r + 1;
      if (e[n] === "?")
        throw new TypeError('Pattern cannot start with "?" at '.concat(n));
      for (; n < e.length; ) {
        if (e[n] === "\\") {
          l += e[n++] + e[n++];
          continue;
        }
        if (e[n] === ")") {
          if (h--, h === 0) {
            n++;
            break;
          }
        } else if (e[n] === "(" && (h++, e[n + 1] !== "?"))
          throw new TypeError("Capturing groups are not allowed at ".concat(n));
        l += e[n++];
      }
      if (h)
        throw new TypeError("Unbalanced pattern at ".concat(r));
      if (!l)
        throw new TypeError("Missing pattern at ".concat(r));
      t.push({ type: "PATTERN", index: r, value: l }), r = n;
      continue;
    }
    t.push({ type: "CHAR", index: r, value: e[r++] });
  }
  return t.push({ type: "END", index: r, value: "" }), t;
}
function q(e, t) {
  t === void 0 && (t = {});
  for (var r = $(e), a = t.prefixes, c = a === void 0 ? "./" : a, n = "[^".concat(E(t.delimiter || "/#?"), "]+?"), i = [], h = 0, l = 0, d = "", o = function(f) {
    if (l < r.length && r[l].type === f)
      return r[l++].value;
  }, R = function(f) {
    var w = o(f);
    if (w !== void 0)
      return w;
    var g = r[l], C = g.type, T = g.index;
    throw new TypeError("Unexpected ".concat(C, " at ").concat(T, ", expected ").concat(f));
  }, A = function() {
    for (var f = "", w; w = o("CHAR") || o("ESCAPED_CHAR"); )
      f += w;
    return f;
  }; l < r.length; ) {
    var x = o("CHAR"), P = o("NAME"), m = o("PATTERN");
    if (P || m) {
      var v = x || "";
      c.indexOf(v) === -1 && (d += v, v = ""), d && (i.push(d), d = ""), i.push({
        name: P || h++,
        prefix: v,
        suffix: "",
        pattern: m || n,
        modifier: o("MODIFIER") || ""
      });
      continue;
    }
    var u = x || o("ESCAPED_CHAR");
    if (u) {
      d += u;
      continue;
    }
    d && (i.push(d), d = "");
    var y = o("OPEN");
    if (y) {
      var v = A(), b = o("NAME") || "", s = o("PATTERN") || "", p = A();
      R("CLOSE"), i.push({
        name: b || (s ? h++ : ""),
        pattern: b && !s ? n : s,
        prefix: v,
        suffix: p,
        modifier: o("MODIFIER") || ""
      });
      continue;
    }
    R("END");
  }
  return i;
}
function E(e) {
  return e.replace(/([.+*?=^!:${}()[\]|/\\])/g, "\\$1");
}
function H(e) {
  return e && e.sensitive ? "" : "i";
}
function W(e, t) {
  if (!t)
    return e;
  for (var r = /\((?:\?<(.*?)>)?(?!\?)/g, a = 0, c = r.exec(e.source); c; )
    t.push({
      // Use parenthesized substring match if available, index otherwise
      name: c[1] || a++,
      prefix: "",
      suffix: "",
      modifier: "",
      pattern: ""
    }), c = r.exec(e.source);
  return e;
}
function F(e, t, r) {
  var a = e.map(function(c) {
    return _(c, t, r).source;
  });
  return new RegExp("(?:".concat(a.join("|"), ")"), H(r));
}
function L(e, t, r) {
  return U(q(e, r), t, r);
}
function U(e, t, r) {
  r === void 0 && (r = {});
  for (var a = r.strict, c = a === void 0 ? !1 : a, n = r.start, i = n === void 0 ? !0 : n, h = r.end, l = h === void 0 ? !0 : h, d = r.encode, o = d === void 0 ? function(T) {
    return T;
  } : d, R = r.delimiter, A = R === void 0 ? "/#?" : R, x = r.endsWith, P = x === void 0 ? "" : x, m = "[".concat(E(P), "]|$"), v = "[".concat(E(A), "]"), u = i ? "^" : "", y = 0, b = e; y < b.length; y++) {
    var s = b[y];
    if (typeof s == "string")
      u += E(o(s));
    else {
      var p = E(o(s.prefix)), f = E(o(s.suffix));
      if (s.pattern)
        if (t && t.push(s), p || f)
          if (s.modifier === "+" || s.modifier === "*") {
            var w = s.modifier === "*" ? "?" : "";
            u += "(?:".concat(p, "((?:").concat(s.pattern, ")(?:").concat(f).concat(p, "(?:").concat(s.pattern, "))*)").concat(f, ")").concat(w);
          } else
            u += "(?:".concat(p, "(").concat(s.pattern, ")").concat(f, ")").concat(s.modifier);
        else
          s.modifier === "+" || s.modifier === "*" ? u += "((?:".concat(s.pattern, ")").concat(s.modifier, ")") : u += "(".concat(s.pattern, ")").concat(s.modifier);
      else
        u += "(?:".concat(p).concat(f, ")").concat(s.modifier);
    }
  }
  if (l)
    c || (u += "".concat(v, "?")), u += r.endsWith ? "(?=".concat(m, ")") : "$";
  else {
    var g = e[e.length - 1], C = typeof g == "string" ? v.indexOf(g[g.length - 1]) > -1 : g === void 0;
    c || (u += "(?:".concat(v, "(?=").concat(m, "))?")), C || (u += "(?=".concat(v, "|").concat(m, ")"));
  }
  return new RegExp(u, H(r));
}
function _(e, t, r) {
  return e instanceof RegExp ? W(e, t) : Array.isArray(e) ? F(e, t, r) : L(e, t, r);
}
var j = Object.defineProperty, Q = Object.getOwnPropertyDescriptor, V = (e, t, r, a) => {
  for (var c = a > 1 ? void 0 : a ? Q(t, r) : t, n = e.length - 1, i; n >= 0; n--)
    (i = e[n]) && (c = (a ? i(t, r, c) : i(c)) || c);
  return a && c && j(t, r, c), c;
};
O({
  router: null
});
let M = class extends N {
  constructor() {
    super(...arguments), this.currentRoute = null, this.routes = [], this.isHashMode = !0, this.params = {}, this.query = {}, this.hash = "", this.base = "";
  }
  install() {
    O({
      router: this
    }), this.base = this.props.base || "", this.isHashMode = this.props.hash !== !1, this.routes = this.props.routes.map((e) => {
      const t = [];
      if (e.render && (e.render = e.render.bind(this)), e.path === "*")
        return { ...e, regex: /(.*)/ };
      const r = _(e.path, t);
      return { ...e, keys: t, regex: r };
    }), window.onpopstate = (e) => {
      this.matchAndRender(this.getRoutePath());
    }, this.matchAndRender(this.getRoutePath());
  }
  getRoutePath() {
    return this.isHashMode ? window.location.hash.split("?")[0].replace("#", "") || "/" : window.location.pathname;
  }
  getQueryPath() {
    return this.isHashMode ? window.location.hash.split("?")[1] : window.location.search;
  }
  beforeEach(e) {
    this.beforeEachCallback = e;
  }
  afterEach(e) {
    this.afterEachCallback = e;
  }
  push(e) {
    history.pushState({}, "", this.isHashMode ? `#${e}` : e), this.matchAndRender(e);
  }
  replace(e) {
    history.replaceState({}, "", e), this.matchAndRender(e);
  }
  go(e) {
    history.go(e);
  }
  back() {
    history.back();
  }
  forward() {
    history.forward();
  }
  matchAndRender(e) {
    var t, r;
    for (const a of this.routes) {
      const c = (t = a.regex) == null ? void 0 : t.exec(e);
      if (c) {
        if (a.redirect) {
          if (this.isHashMode)
            window.location.hash = a.redirect;
          else {
            const i = this.base + a.redirect;
            window.location.href = window.location.origin + i;
          }
          return;
        }
        if (this.beforeEachCallback) {
          const i = this.beforeEachCallback({ path: e }, { path: window.location.pathname });
          if (i === !1)
            return;
          if (typeof i == "string") {
            this.push(i);
            return;
          } else if (typeof i == "object") {
            this.push(i.path);
            return;
          }
        }
        if (a.beforeEnter && a.beforeEnter({ path: e }, { path: window.location.pathname }) === !1)
          return;
        this.currentRoute = a, this.params = {}, (r = a.keys) == null || r.forEach((i, h) => {
          this.params[i.name] = c[h + 1];
        });
        const n = new URLSearchParams(this.getQueryPath());
        this.query = {}, Array.from(n.entries()).forEach(([i, h]) => {
          this.query[i] = h;
        }), this.hash = window.location.hash, this.afterEachCallback && this.afterEachCallback({ path: e }, { path: window.location.pathname }), this.update();
        break;
      }
    }
  }
  render() {
    return this.currentRoute && this.currentRoute.render ? this.currentRoute.render(this) : null;
  }
};
M = V([
  D("router-view")
], M);
class B {
  constructor(t) {
    this.params = {}, this.query = {}, this.hash = "", this.currentRoute = null, this.el = S(
      /* @__PURE__ */ I(
        "router-view",
        {
          onInstall: (r) => {
            r.detail.constructor.css = t.css;
          },
          routes: t.routes,
          base: t.base,
          hash: t.hash
        }
      ),
      t.renderTo
    );
  }
  beforeEach(t) {
    this.el.beforeEach(t);
  }
  afterEach(t) {
    this.el.afterEach(t);
  }
  push(t) {
    this.el.push(t);
  }
  replace(t) {
    this.el.replace(t);
  }
  go(t) {
    this.el.go(t);
  }
  back() {
    this.el.back();
  }
  forward() {
    this.el.forward();
  }
}
export {
  B as Router
};