@hyperfixi/engine 7.2.0 → 7.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38,13 +38,22 @@
38
38
  enter(_elt) {
39
39
  }
40
40
  };
41
- var store = /* @__PURE__ */ new WeakMap();
42
- var peekData = (elt) => store.get(elt);
43
- var dropData = (elt) => store.delete(elt);
41
+ var windowHolders = /* @__PURE__ */ new WeakMap();
42
+ function holder(elt) {
43
+ if (elt.window !== elt) return elt;
44
+ let h = windowHolders.get(elt);
45
+ if (!h) windowHolders.set(elt, h = {});
46
+ return h;
47
+ }
48
+ var peekData = (elt) => holder(elt)._hyperscript;
49
+ function dropData(elt) {
50
+ const h = holder(elt);
51
+ const had = h._hyperscript !== void 0;
52
+ delete h._hyperscript;
53
+ return had;
54
+ }
44
55
  function dataOf(elt) {
45
- let d = store.get(elt);
46
- if (!d) store.set(elt, d = {});
47
- return d;
56
+ return holder(elt)._hyperscript ??= {};
48
57
  }
49
58
  var rx = {
50
59
  /** True while an effect is evaluating: reads are then recorded as its dependencies. */
@@ -1609,6 +1618,108 @@
1609
1618
  return indirect(p, node);
1610
1619
  }
1611
1620
 
1621
+ // src/htmx-compat.ts
1622
+ var installed = /* @__PURE__ */ new WeakSet();
1623
+ function installHtmxCompat(hs) {
1624
+ if (installed.has(hs)) return;
1625
+ installed.add(hs);
1626
+ let fromHtmx = false;
1627
+ const asHtmx = (f) => {
1628
+ const was = fromHtmx;
1629
+ fromHtmx = true;
1630
+ try {
1631
+ f();
1632
+ } finally {
1633
+ fromHtmx = was;
1634
+ }
1635
+ };
1636
+ document.addEventListener(
1637
+ "htmx:load",
1638
+ (evt) => asHtmx(() => hs.process(evt.detail?.elt))
1639
+ );
1640
+ document.addEventListener("htmx:after:process", (evt) => asHtmx(() => hs.process(evt.target)));
1641
+ document.addEventListener("fx:swapped", (evt) => {
1642
+ const target = evt.detail?.cfg?.target;
1643
+ hs.process(
1644
+ target instanceof Element && target.isConnected ? target.parentElement ?? target : document.body
1645
+ );
1646
+ });
1647
+ const htmx = Reflect.get(globalThis, "htmx");
1648
+ if (typeof htmx?.process !== "function") return;
1649
+ hs.addAfterProcessHook((elt) => {
1650
+ if (!fromHtmx) asHtmx(() => htmx.process(elt));
1651
+ });
1652
+ if (htmx.version?.startsWith("4")) {
1653
+ htmx.registerExtension?.("hs-include", {
1654
+ htmx_config_request(elt, detail) {
1655
+ const ctx = detail?.ctx;
1656
+ if (!ctx) return;
1657
+ const found = findHsInclude(ctx.sourceElement || elt);
1658
+ if (!found) return;
1659
+ const vars = resolveSpecifiers(found.value, found.scopeElt);
1660
+ const body = ctx.request?.body;
1661
+ if (body instanceof FormData) for (const k in vars) body.set(k, vars[k]);
1662
+ }
1663
+ });
1664
+ }
1665
+ }
1666
+ function findHsInclude(sourceElt) {
1667
+ const attr = sourceElt.getAttribute("hs-include");
1668
+ if (attr !== null) return { value: attr, scopeElt: sourceElt };
1669
+ for (let elt = sourceElt.parentElement; elt; elt = elt.parentElement) {
1670
+ const inherited2 = elt.getAttribute("hs-include:inherited");
1671
+ if (inherited2 !== null) return { value: inherited2, scopeElt: elt };
1672
+ }
1673
+ return null;
1674
+ }
1675
+ var readScope = (elt) => elt && peekData(elt)?.scopes?.elementScope || {};
1676
+ function serialize(value) {
1677
+ if (value == null) return "";
1678
+ if (typeof value === "object") {
1679
+ try {
1680
+ return JSON.stringify(value);
1681
+ } catch {
1682
+ return "";
1683
+ }
1684
+ }
1685
+ return String(value);
1686
+ }
1687
+ function resolveInherited(scopeKey, startElt) {
1688
+ for (let elt = startElt; elt; elt = elt.parentElement) {
1689
+ const scope = readScope(elt);
1690
+ if (scopeKey in scope) return scope[scopeKey];
1691
+ }
1692
+ return void 0;
1693
+ }
1694
+ function resolveSpecifiers(attrValue, scopeElt) {
1695
+ const result = {};
1696
+ const raw = attrValue.trim();
1697
+ if (raw === "*") {
1698
+ const scope = readScope(scopeElt);
1699
+ for (const k of Object.keys(scope)) result[k[0] === ":" ? k.slice(1) : k] = serialize(scope[k]);
1700
+ return result;
1701
+ }
1702
+ for (let part of raw.split(",")) {
1703
+ part = part.trim();
1704
+ if (!part) continue;
1705
+ if (part[0] === ":") {
1706
+ const scope = readScope(scopeElt);
1707
+ if (part in scope) result[part.slice(1)] = serialize(scope[part]);
1708
+ } else if (part[0] === "^") {
1709
+ const value = resolveInherited(":" + part.slice(1), scopeElt);
1710
+ if (value !== void 0) result[part.slice(1)] = serialize(value);
1711
+ } else if (part[0] === "#") {
1712
+ const colon = part.lastIndexOf(":");
1713
+ if (colon > 0) {
1714
+ const scope = readScope(document.querySelector(part.slice(0, colon)));
1715
+ const name = part.slice(colon + 1);
1716
+ if (":" + name in scope) result[name] = serialize(scope[":" + name]);
1717
+ }
1718
+ }
1719
+ }
1720
+ return result;
1721
+ }
1722
+
1612
1723
  // src/parser.ts
1613
1724
  var ParseError = class extends Error {
1614
1725
  constructor(message, token, source, expected) {
@@ -1974,14 +2085,21 @@
1974
2085
  }
1975
2086
  var beforeProcess = [];
1976
2087
  var afterProcess = [];
2088
+ var processing = /* @__PURE__ */ new Set();
1977
2089
  function processNode(node) {
1978
2090
  if (!(node instanceof Element || node instanceof Document || node instanceof DocumentFragment))
1979
2091
  return;
1980
- for (const hook of beforeProcess) hook(node);
1981
- const selector = attributes().map((a) => `[${a}]`).join(", ") + ", [type='text/hyperscript']";
1982
- if (node instanceof Element && node.matches(selector)) initElement(node);
1983
- node.querySelectorAll(selector).forEach(initElement);
1984
- for (const hook of afterProcess) hook(node);
2092
+ if (processing.has(node)) return;
2093
+ processing.add(node);
2094
+ try {
2095
+ for (const hook of beforeProcess) hook(node);
2096
+ const selector = attributes().map((a) => `[${a}]`).join(", ") + ", [type='text/hyperscript']";
2097
+ if (node instanceof Element && node.matches(selector)) initElement(node);
2098
+ node.querySelectorAll(selector).forEach(initElement);
2099
+ for (const hook of afterProcess) hook(node);
2100
+ } finally {
2101
+ processing.delete(node);
2102
+ }
1985
2103
  }
1986
2104
  function cleanup(elt) {
1987
2105
  const data = peekData(elt);
@@ -2027,7 +2145,7 @@
2027
2145
  cleanup,
2028
2146
  /** The part of upstream's `internals` that pages and tests reach for. */
2029
2147
  internals: { runtime: { cleanup, processNode } },
2030
- version: false ? "dev" : "7.2.0"
2148
+ version: false ? "dev" : "7.4.0"
2031
2149
  });
2032
2150
  function boot() {
2033
2151
  Object.assign(globalThis, { _hyperscript: api });
@@ -2035,6 +2153,7 @@
2035
2153
  const start = () => {
2036
2154
  processNode(document.documentElement);
2037
2155
  document.dispatchEvent(new Event("hyperscript:ready"));
2156
+ installHtmxCompat(api);
2038
2157
  };
2039
2158
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start);
2040
2159
  else setTimeout(start);
@@ -3871,9 +3990,9 @@ return { ${functions.map((name) => `${name}:${name}`).join(",")} } `
3871
3990
  };
3872
3991
  const pending2 = Reflect.apply(fetch, globalThis, [address, detail]);
3873
3992
  return Promise.resolve(pending2).then((received) => {
3874
- const holder = { response: received };
3875
- triggerEvent(me, "fetch:afterResponse", holder);
3876
- const response = holder.response;
3993
+ const holder2 = { response: received };
3994
+ triggerEvent(me, "fetch:afterResponse", holder2);
3995
+ const response = holder2.response;
3877
3996
  if (!(response instanceof Response))
3878
3997
  throw new Error("fetch did not return a Response");
3879
3998
  if (!dontThrow && kind !== "response" && config.fetchThrowsOn.some((re) => re.test(String(response.status)))) {