@hyperfixi/engine 7.3.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.
package/dist/index.js CHANGED
@@ -36,13 +36,22 @@ var host = {
36
36
  enter(_elt) {
37
37
  }
38
38
  };
39
- var store = /* @__PURE__ */ new WeakMap();
40
- var peekData = (elt) => store.get(elt);
41
- var dropData = (elt) => store.delete(elt);
39
+ var windowHolders = /* @__PURE__ */ new WeakMap();
40
+ function holder(elt) {
41
+ if (elt.window !== elt) return elt;
42
+ let h = windowHolders.get(elt);
43
+ if (!h) windowHolders.set(elt, h = {});
44
+ return h;
45
+ }
46
+ var peekData = (elt) => holder(elt)._hyperscript;
47
+ function dropData(elt) {
48
+ const h = holder(elt);
49
+ const had = h._hyperscript !== void 0;
50
+ delete h._hyperscript;
51
+ return had;
52
+ }
42
53
  function dataOf(elt) {
43
- let d = store.get(elt);
44
- if (!d) store.set(elt, d = {});
45
- return d;
54
+ return holder(elt)._hyperscript ??= {};
46
55
  }
47
56
  var rx = {
48
57
  /** True while an effect is evaluating: reads are then recorded as its dependencies. */
@@ -1607,6 +1616,108 @@ function arrayIndex(p, root) {
1607
1616
  return indirect(p, node);
1608
1617
  }
1609
1618
 
1619
+ // src/htmx-compat.ts
1620
+ var installed = /* @__PURE__ */ new WeakSet();
1621
+ function installHtmxCompat(hs) {
1622
+ if (installed.has(hs)) return;
1623
+ installed.add(hs);
1624
+ let fromHtmx = false;
1625
+ const asHtmx = (f) => {
1626
+ const was = fromHtmx;
1627
+ fromHtmx = true;
1628
+ try {
1629
+ f();
1630
+ } finally {
1631
+ fromHtmx = was;
1632
+ }
1633
+ };
1634
+ document.addEventListener(
1635
+ "htmx:load",
1636
+ (evt) => asHtmx(() => hs.process(evt.detail?.elt))
1637
+ );
1638
+ document.addEventListener("htmx:after:process", (evt) => asHtmx(() => hs.process(evt.target)));
1639
+ document.addEventListener("fx:swapped", (evt) => {
1640
+ const target = evt.detail?.cfg?.target;
1641
+ hs.process(
1642
+ target instanceof Element && target.isConnected ? target.parentElement ?? target : document.body
1643
+ );
1644
+ });
1645
+ const htmx = Reflect.get(globalThis, "htmx");
1646
+ if (typeof htmx?.process !== "function") return;
1647
+ hs.addAfterProcessHook((elt) => {
1648
+ if (!fromHtmx) asHtmx(() => htmx.process(elt));
1649
+ });
1650
+ if (htmx.version?.startsWith("4")) {
1651
+ htmx.registerExtension?.("hs-include", {
1652
+ htmx_config_request(elt, detail) {
1653
+ const ctx = detail?.ctx;
1654
+ if (!ctx) return;
1655
+ const found = findHsInclude(ctx.sourceElement || elt);
1656
+ if (!found) return;
1657
+ const vars = resolveSpecifiers(found.value, found.scopeElt);
1658
+ const body = ctx.request?.body;
1659
+ if (body instanceof FormData) for (const k in vars) body.set(k, vars[k]);
1660
+ }
1661
+ });
1662
+ }
1663
+ }
1664
+ function findHsInclude(sourceElt) {
1665
+ const attr = sourceElt.getAttribute("hs-include");
1666
+ if (attr !== null) return { value: attr, scopeElt: sourceElt };
1667
+ for (let elt = sourceElt.parentElement; elt; elt = elt.parentElement) {
1668
+ const inherited2 = elt.getAttribute("hs-include:inherited");
1669
+ if (inherited2 !== null) return { value: inherited2, scopeElt: elt };
1670
+ }
1671
+ return null;
1672
+ }
1673
+ var readScope = (elt) => elt && peekData(elt)?.scopes?.elementScope || {};
1674
+ function serialize(value) {
1675
+ if (value == null) return "";
1676
+ if (typeof value === "object") {
1677
+ try {
1678
+ return JSON.stringify(value);
1679
+ } catch {
1680
+ return "";
1681
+ }
1682
+ }
1683
+ return String(value);
1684
+ }
1685
+ function resolveInherited(scopeKey, startElt) {
1686
+ for (let elt = startElt; elt; elt = elt.parentElement) {
1687
+ const scope = readScope(elt);
1688
+ if (scopeKey in scope) return scope[scopeKey];
1689
+ }
1690
+ return void 0;
1691
+ }
1692
+ function resolveSpecifiers(attrValue, scopeElt) {
1693
+ const result = {};
1694
+ const raw = attrValue.trim();
1695
+ if (raw === "*") {
1696
+ const scope = readScope(scopeElt);
1697
+ for (const k of Object.keys(scope)) result[k[0] === ":" ? k.slice(1) : k] = serialize(scope[k]);
1698
+ return result;
1699
+ }
1700
+ for (let part of raw.split(",")) {
1701
+ part = part.trim();
1702
+ if (!part) continue;
1703
+ if (part[0] === ":") {
1704
+ const scope = readScope(scopeElt);
1705
+ if (part in scope) result[part.slice(1)] = serialize(scope[part]);
1706
+ } else if (part[0] === "^") {
1707
+ const value = resolveInherited(":" + part.slice(1), scopeElt);
1708
+ if (value !== void 0) result[part.slice(1)] = serialize(value);
1709
+ } else if (part[0] === "#") {
1710
+ const colon = part.lastIndexOf(":");
1711
+ if (colon > 0) {
1712
+ const scope = readScope(document.querySelector(part.slice(0, colon)));
1713
+ const name = part.slice(colon + 1);
1714
+ if (":" + name in scope) result[name] = serialize(scope[":" + name]);
1715
+ }
1716
+ }
1717
+ }
1718
+ return result;
1719
+ }
1720
+
1610
1721
  // src/parser.ts
1611
1722
  var ParseError = class extends Error {
1612
1723
  constructor(message, token, source, expected) {
@@ -1972,14 +2083,21 @@ function initElement(elt) {
1972
2083
  }
1973
2084
  var beforeProcess = [];
1974
2085
  var afterProcess = [];
2086
+ var processing = /* @__PURE__ */ new Set();
1975
2087
  function processNode(node) {
1976
2088
  if (!(node instanceof Element || node instanceof Document || node instanceof DocumentFragment))
1977
2089
  return;
1978
- for (const hook of beforeProcess) hook(node);
1979
- const selector = attributes().map((a) => `[${a}]`).join(", ") + ", [type='text/hyperscript']";
1980
- if (node instanceof Element && node.matches(selector)) initElement(node);
1981
- node.querySelectorAll(selector).forEach(initElement);
1982
- for (const hook of afterProcess) hook(node);
2090
+ if (processing.has(node)) return;
2091
+ processing.add(node);
2092
+ try {
2093
+ for (const hook of beforeProcess) hook(node);
2094
+ const selector = attributes().map((a) => `[${a}]`).join(", ") + ", [type='text/hyperscript']";
2095
+ if (node instanceof Element && node.matches(selector)) initElement(node);
2096
+ node.querySelectorAll(selector).forEach(initElement);
2097
+ for (const hook of afterProcess) hook(node);
2098
+ } finally {
2099
+ processing.delete(node);
2100
+ }
1983
2101
  }
1984
2102
  function cleanup(elt) {
1985
2103
  const data = peekData(elt);
@@ -2025,7 +2143,7 @@ var api = Object.assign(evaluate, {
2025
2143
  cleanup,
2026
2144
  /** The part of upstream's `internals` that pages and tests reach for. */
2027
2145
  internals: { runtime: { cleanup, processNode } },
2028
- version: false ? "dev" : "7.3.0"
2146
+ version: false ? "dev" : "7.4.0"
2029
2147
  });
2030
2148
  function boot() {
2031
2149
  Object.assign(globalThis, { _hyperscript: api });
@@ -2033,6 +2151,7 @@ function boot() {
2033
2151
  const start = () => {
2034
2152
  processNode(document.documentElement);
2035
2153
  document.dispatchEvent(new Event("hyperscript:ready"));
2154
+ installHtmxCompat(api);
2036
2155
  };
2037
2156
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start);
2038
2157
  else setTimeout(start);
@@ -3869,9 +3988,9 @@ function fetchCommand(g) {
3869
3988
  };
3870
3989
  const pending2 = Reflect.apply(fetch, globalThis, [address, detail]);
3871
3990
  return Promise.resolve(pending2).then((received) => {
3872
- const holder = { response: received };
3873
- triggerEvent(me, "fetch:afterResponse", holder);
3874
- const response = holder.response;
3991
+ const holder2 = { response: received };
3992
+ triggerEvent(me, "fetch:afterResponse", holder2);
3993
+ const response = holder2.response;
3875
3994
  if (!(response instanceof Response))
3876
3995
  throw new Error("fetch did not return a Response");
3877
3996
  if (!dontThrow && kind !== "response" && config.fetchThrowsOn.some((re) => re.test(String(response.status)))) {
package/dist/minimal.js CHANGED
@@ -37,13 +37,22 @@
37
37
  enter(_elt) {
38
38
  }
39
39
  };
40
- var store = /* @__PURE__ */ new WeakMap();
41
- var peekData = (elt) => store.get(elt);
42
- var dropData = (elt) => store.delete(elt);
40
+ var windowHolders = /* @__PURE__ */ new WeakMap();
41
+ function holder(elt) {
42
+ if (elt.window !== elt) return elt;
43
+ let h = windowHolders.get(elt);
44
+ if (!h) windowHolders.set(elt, h = {});
45
+ return h;
46
+ }
47
+ var peekData = (elt) => holder(elt)._hyperscript;
48
+ function dropData(elt) {
49
+ const h = holder(elt);
50
+ const had = h._hyperscript !== void 0;
51
+ delete h._hyperscript;
52
+ return had;
53
+ }
43
54
  function dataOf(elt) {
44
- let d = store.get(elt);
45
- if (!d) store.set(elt, d = {});
46
- return d;
55
+ return holder(elt)._hyperscript ??= {};
47
56
  }
48
57
  var rx = {
49
58
  /** True while an effect is evaluating: reads are then recorded as its dependencies. */
@@ -1876,6 +1885,108 @@
1876
1885
  };
1877
1886
  }
1878
1887
 
1888
+ // src/htmx-compat.ts
1889
+ var installed = /* @__PURE__ */ new WeakSet();
1890
+ function installHtmxCompat(hs) {
1891
+ if (installed.has(hs)) return;
1892
+ installed.add(hs);
1893
+ let fromHtmx = false;
1894
+ const asHtmx = (f) => {
1895
+ const was = fromHtmx;
1896
+ fromHtmx = true;
1897
+ try {
1898
+ f();
1899
+ } finally {
1900
+ fromHtmx = was;
1901
+ }
1902
+ };
1903
+ document.addEventListener(
1904
+ "htmx:load",
1905
+ (evt) => asHtmx(() => hs.process(evt.detail?.elt))
1906
+ );
1907
+ document.addEventListener("htmx:after:process", (evt) => asHtmx(() => hs.process(evt.target)));
1908
+ document.addEventListener("fx:swapped", (evt) => {
1909
+ const target = evt.detail?.cfg?.target;
1910
+ hs.process(
1911
+ target instanceof Element && target.isConnected ? target.parentElement ?? target : document.body
1912
+ );
1913
+ });
1914
+ const htmx = Reflect.get(globalThis, "htmx");
1915
+ if (typeof htmx?.process !== "function") return;
1916
+ hs.addAfterProcessHook((elt) => {
1917
+ if (!fromHtmx) asHtmx(() => htmx.process(elt));
1918
+ });
1919
+ if (htmx.version?.startsWith("4")) {
1920
+ htmx.registerExtension?.("hs-include", {
1921
+ htmx_config_request(elt, detail) {
1922
+ const ctx = detail?.ctx;
1923
+ if (!ctx) return;
1924
+ const found = findHsInclude(ctx.sourceElement || elt);
1925
+ if (!found) return;
1926
+ const vars = resolveSpecifiers(found.value, found.scopeElt);
1927
+ const body = ctx.request?.body;
1928
+ if (body instanceof FormData) for (const k in vars) body.set(k, vars[k]);
1929
+ }
1930
+ });
1931
+ }
1932
+ }
1933
+ function findHsInclude(sourceElt) {
1934
+ const attr = sourceElt.getAttribute("hs-include");
1935
+ if (attr !== null) return { value: attr, scopeElt: sourceElt };
1936
+ for (let elt = sourceElt.parentElement; elt; elt = elt.parentElement) {
1937
+ const inherited2 = elt.getAttribute("hs-include:inherited");
1938
+ if (inherited2 !== null) return { value: inherited2, scopeElt: elt };
1939
+ }
1940
+ return null;
1941
+ }
1942
+ var readScope = (elt) => elt && peekData(elt)?.scopes?.elementScope || {};
1943
+ function serialize(value) {
1944
+ if (value == null) return "";
1945
+ if (typeof value === "object") {
1946
+ try {
1947
+ return JSON.stringify(value);
1948
+ } catch {
1949
+ return "";
1950
+ }
1951
+ }
1952
+ return String(value);
1953
+ }
1954
+ function resolveInherited(scopeKey, startElt) {
1955
+ for (let elt = startElt; elt; elt = elt.parentElement) {
1956
+ const scope = readScope(elt);
1957
+ if (scopeKey in scope) return scope[scopeKey];
1958
+ }
1959
+ return void 0;
1960
+ }
1961
+ function resolveSpecifiers(attrValue, scopeElt) {
1962
+ const result = {};
1963
+ const raw = attrValue.trim();
1964
+ if (raw === "*") {
1965
+ const scope = readScope(scopeElt);
1966
+ for (const k of Object.keys(scope)) result[k[0] === ":" ? k.slice(1) : k] = serialize(scope[k]);
1967
+ return result;
1968
+ }
1969
+ for (let part of raw.split(",")) {
1970
+ part = part.trim();
1971
+ if (!part) continue;
1972
+ if (part[0] === ":") {
1973
+ const scope = readScope(scopeElt);
1974
+ if (part in scope) result[part.slice(1)] = serialize(scope[part]);
1975
+ } else if (part[0] === "^") {
1976
+ const value = resolveInherited(":" + part.slice(1), scopeElt);
1977
+ if (value !== void 0) result[part.slice(1)] = serialize(value);
1978
+ } else if (part[0] === "#") {
1979
+ const colon = part.lastIndexOf(":");
1980
+ if (colon > 0) {
1981
+ const scope = readScope(document.querySelector(part.slice(0, colon)));
1982
+ const name = part.slice(colon + 1);
1983
+ if (":" + name in scope) result[name] = serialize(scope[":" + name]);
1984
+ }
1985
+ }
1986
+ }
1987
+ return result;
1988
+ }
1989
+
1879
1990
  // src/parser.ts
1880
1991
  var ParseError = class extends Error {
1881
1992
  constructor(message, token, source, expected) {
@@ -2241,14 +2352,21 @@
2241
2352
  }
2242
2353
  var beforeProcess = [];
2243
2354
  var afterProcess = [];
2355
+ var processing = /* @__PURE__ */ new Set();
2244
2356
  function processNode(node) {
2245
2357
  if (!(node instanceof Element || node instanceof Document || node instanceof DocumentFragment))
2246
2358
  return;
2247
- for (const hook of beforeProcess) hook(node);
2248
- const selector = attributes().map((a) => `[${a}]`).join(", ") + ", [type='text/hyperscript']";
2249
- if (node instanceof Element && node.matches(selector)) initElement(node);
2250
- node.querySelectorAll(selector).forEach(initElement);
2251
- for (const hook of afterProcess) hook(node);
2359
+ if (processing.has(node)) return;
2360
+ processing.add(node);
2361
+ try {
2362
+ for (const hook of beforeProcess) hook(node);
2363
+ const selector = attributes().map((a) => `[${a}]`).join(", ") + ", [type='text/hyperscript']";
2364
+ if (node instanceof Element && node.matches(selector)) initElement(node);
2365
+ node.querySelectorAll(selector).forEach(initElement);
2366
+ for (const hook of afterProcess) hook(node);
2367
+ } finally {
2368
+ processing.delete(node);
2369
+ }
2252
2370
  }
2253
2371
  function cleanup(elt) {
2254
2372
  const data = peekData(elt);
@@ -2294,7 +2412,7 @@
2294
2412
  cleanup,
2295
2413
  /** The part of upstream's `internals` that pages and tests reach for. */
2296
2414
  internals: { runtime: { cleanup, processNode } },
2297
- version: false ? "dev" : "7.3.0"
2415
+ version: false ? "dev" : "7.4.0"
2298
2416
  });
2299
2417
  function boot() {
2300
2418
  Object.assign(globalThis, { _hyperscript: api });
@@ -2302,6 +2420,7 @@
2302
2420
  const start = () => {
2303
2421
  processNode(document.documentElement);
2304
2422
  document.dispatchEvent(new Event("hyperscript:ready"));
2423
+ installHtmxCompat(api);
2305
2424
  };
2306
2425
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start);
2307
2426
  else setTimeout(start);