@hyperfixi/engine 7.3.0 → 7.5.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/CHANGELOG.md +130 -0
- package/README.md +22 -4
- package/dist/common.js +131 -12
- package/dist/common.min.js +9 -9
- package/dist/core.js +131 -12
- package/dist/core.min.js +9 -9
- package/dist/full.js +134 -15
- package/dist/full.min.js +11 -11
- package/dist/htmx-compat.d.ts +6 -0
- package/dist/hyperfixi-hs.dev.js +134 -15
- package/dist/hyperfixi-hs.js +11 -11
- package/dist/index.js +134 -15
- package/dist/minimal.js +131 -12
- package/dist/minimal.min.js +9 -9
- package/dist/runtime.d.ts +2 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,136 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [7.5.0] - 2026-10-22
|
|
11
|
+
|
|
12
|
+
What a live test of 7.3.0 found users hitting. The Vite plugin loads in a CommonJS project and
|
|
13
|
+
ships types. MCP `diff_behaviors` compares whole handlers, and `npx` installs the engine.
|
|
14
|
+
Hand-written non-English hyperscript that ran wrong in silence now reads right or says so. A
|
|
15
|
+
minor: `@lokascript/htmx-adapter`'s `hx-on` change restores what its README always documented
|
|
16
|
+
(bodies are JavaScript by default), and a page that relied on the engine switching them adds
|
|
17
|
+
`<meta name="htmx-i18n-hx-on" content="hyperscript">`.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **`@lokascript/htmx-adapter`: `hx-on` bodies stay JavaScript unless the page opts in to
|
|
22
|
+
hyperscript bodies.** The adapter used to switch every `hx-on` body on the page to hyperscript
|
|
23
|
+
whenever a hyperscript engine (`window._hyperscript`) was loaded, and the documented stack (the
|
|
24
|
+
engine, htmx 4 and this adapter) always has one. So a plain-JavaScript
|
|
25
|
+
`hx-on:click="document.getElementById('o').textContent = 'ran'"` failed with a hyperscript parse
|
|
26
|
+
error, although the README says bodies are JavaScript by default. The opt-in is now explicit:
|
|
27
|
+
`<meta name="htmx-i18n-hx-on" content="hyperscript">`, or `setBodyExecutor()` as before. A page
|
|
28
|
+
that wrote hyperscript `hx-on` bodies and relied on the engine alone adds the `<meta>` tag. With
|
|
29
|
+
the tag and no engine on the page, the adapter warns and the bodies stay JavaScript.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- **`@hyperfixi/vite-plugin` loads in a CommonJS project.** `npm init -y` writes
|
|
34
|
+
`"type": "commonjs"`, and there the plugin's `require` build failed with
|
|
35
|
+
`ERR_PACKAGE_PATH_NOT_EXPORTED`: it requires `@hyperfixi/engine`, whose `exports` had only an
|
|
36
|
+
`import` condition. The engine's `exports` now name its ES module as the `default` too, which
|
|
37
|
+
Node 20.19+ and 22.12+ (what Vite 8 needs) can `require`.
|
|
38
|
+
- **`@hyperfixi/vite-plugin` ships types for the app side** (`@hyperfixi/vite-plugin/client`):
|
|
39
|
+
the virtual module and `window.hyperfixi` / `window._hyperscript`. A TypeScript 6 project
|
|
40
|
+
rejected `import 'hyperfixi'` (`TS2882`). The README has a TypeScript section, with JSX's
|
|
41
|
+
`data-script` and an augmentation for `_`.
|
|
42
|
+
- **The Vite plugin's scanner reads a `<script type="text/hyperscript">` block that contains
|
|
43
|
+
`<`** (`if n < 10`, a `<div/>` query). It skipped the whole block, so its commands were not
|
|
44
|
+
bundled and the page failed to parse. It also reads the `script` and `data-script` attributes,
|
|
45
|
+
which the engine runs as it runs `_`, and a production build scans Vite's `root` rather than the
|
|
46
|
+
working directory (`vite build app` from a parent directory bundled the siblings' modules).
|
|
47
|
+
- **MCP `diff_behaviors` no longer calls any two multi-command or `if` handlers identical.** It
|
|
48
|
+
compared the operations it could extract, and it extracted single commands only: a `then` chain
|
|
49
|
+
(a `compound` node), an `if`, a loop and every command it had no extractor for gave nothing, so
|
|
50
|
+
`remove .b then wait 2s` and `remove .c then wait 5s` were "No semantic change", and so were an
|
|
51
|
+
English handler and an unrelated Spanish one. It now compares every command of a chain, both
|
|
52
|
+
branches of an `if`, a loop's body, and any other command with all its written roles (a
|
|
53
|
+
`fetch`'s `with` options included), and `this` is no longer read as `me`. Faithful translations
|
|
54
|
+
still compare identical (checked on chains, branches, loops and `wait for` in ja, es and ar).
|
|
55
|
+
- **`npx @hyperfixi/mcp-server` installs the engine.** `@hyperfixi/engine`, `@hyperfixi/core` and
|
|
56
|
+
`@hyperfixi/server-bridge` were optional peers, which `npx` leaves out, so the documented
|
|
57
|
+
install checked nothing on the engine: every error only the engine catches came back `ok`, and
|
|
58
|
+
only stderr said so. They are dependencies now, and a validation whose engine check could not
|
|
59
|
+
run says so in the result (`ENGINE_CHECK_SKIPPED`, `info`; `get_diagnostics`:
|
|
60
|
+
`engine-check-skipped`). release-smoke installs the server alone and checks for the three.
|
|
61
|
+
- **Validation warns on `this`** (`THIS_IS_NOT_ME`): hyperscript has no `this`, so
|
|
62
|
+
`toggle .a on this` or `put this.value.length into #n` reads a variable nobody set and does
|
|
63
|
+
nothing. These validated clean (6 of 10 clean-validating snippets that did nothing, in the 7.3.0
|
|
64
|
+
live test). The inert-shape warnings also reach commands after a `then` and inside an `if`'s
|
|
65
|
+
branches; they read only a block's `body` before.
|
|
66
|
+
- **The IR `validate_and_compile` returns has the commands of a chain, a branch or a loop**: a
|
|
67
|
+
`then` chain is `compound` with each command in `body`, an `if` has `body` and `else`. A chain
|
|
68
|
+
came back as `compound` with no commands, so it could not be checked against an intent.
|
|
69
|
+
- **AGENTS.md** said `this`, `and` or a comma between commands, and `put … in` work; all four fail
|
|
70
|
+
on both engines. Its worked example showed output the server no longer gives, and it quoted a
|
|
71
|
+
fidelity figure ("~76%") from before the renderer reached 100% on the corpus. Rewritten from the
|
|
72
|
+
server's real output.
|
|
73
|
+
- **Multilingual: a native time unit after the event is a duration.** ko `클릭할 때 1초 대기`,
|
|
74
|
+
tr `tıklamada 1 saniye bekle` and ja `クリックで 1 秒 待つ` came back `on click 1 wait s`: the
|
|
75
|
+
number became a click count (the handler ran on the first click only) and the wait waited for
|
|
76
|
+
nothing, with no error. A number and the language's word for a unit after it, glued or spaced,
|
|
77
|
+
are one duration now (`wait 1s`, `wait 150ms`).
|
|
78
|
+
- **Multilingual: a bare URL with a number in it translates.** `fetch /api/items/42` and
|
|
79
|
+
`fetch /api/slow?ms=300` were refused in every language, both ways ("would lose 42"): the check
|
|
80
|
+
counted the URL's numbers alone, and the translation writes the URL quoted. A bare URL is one
|
|
81
|
+
value now, the same as quoted.
|
|
82
|
+
- **Multilingual: es and pt `esperar a <event>` waits for the event.** es `esperar a continue`
|
|
83
|
+
came back `wait continue`, a timed wait on a variable, which waits for nothing. `esperar a`
|
|
84
|
+
(es, pt) and `esperar por` (pt) read as `wait for`, as `esperar evento` already did.
|
|
85
|
+
- **Multilingual: a hover word is `mouseenter`.** Eighteen languages' hover word (es `sobrevolar`,
|
|
86
|
+
fr `survol`, ko `호버`, …) read as `on hover`, which is not a DOM event, so the handler never ran.
|
|
87
|
+
They read as `on mouseenter` now; what `on mouseenter` is written as does not change.
|
|
88
|
+
- **Multilingual: a dropped word with content of its own is refused, not dropped.** es
|
|
89
|
+
`al hacer clic fuera quitar .open de mí` came back `on click remove .open from me` (the dropdown
|
|
90
|
+
closed on every click): a particle the language maps to a word with meaning (`fuera`, `out`) was
|
|
91
|
+
skipped like a role marker. Such a translation is refused now (`LossyTranslationError`).
|
|
92
|
+
- **`@lokascript/hyperscript-adapter` warns when a handler listens for a word nothing fires.**
|
|
93
|
+
A word the language does not know as an event (es `al pulsar …`, de `beim Tippen …`) runs as a
|
|
94
|
+
custom event of that name, and the handler never ran, silently. The adapter now warns once per
|
|
95
|
+
language and word. A name written as code (`miEvento`, `draggable:start`) stays quiet. No event
|
|
96
|
+
words were added: loka-js and our dictionaries ship the noun (`clic`), not the verbs. MCP
|
|
97
|
+
`validate_and_compile` reports the same, as an `UNKNOWN_EVENT_WORD` warning on non-English
|
|
98
|
+
input (`get_code_fixes` has its fix).
|
|
99
|
+
|
|
100
|
+
## [7.4.0] - 2026-10-21
|
|
101
|
+
|
|
102
|
+
Content htmx or fixi swaps in runs its hyperscript, as it does on upstream `_hyperscript`: the
|
|
103
|
+
engine has upstream's htmx integration in every bundle, and loading the engine twice no longer
|
|
104
|
+
binds every handler twice. A minor: new behavior and a deprecated option, nothing removed.
|
|
105
|
+
|
|
106
|
+
### Fixed
|
|
107
|
+
|
|
108
|
+
- **`@hyperfixi/engine`: content htmx or fixi swaps in runs its hyperscript, and htmx content a
|
|
109
|
+
script puts in issues its requests.** Upstream `_hyperscript` has this integration in its core
|
|
110
|
+
runtime and the engine had none: a `_="on click …"` that htmx swapped in did nothing, and an
|
|
111
|
+
`hx-get` that a script `put` into the page was never wired. The engine now has upstream's
|
|
112
|
+
integration (0.9.93's `htmx-compat.js`), installed by `boot()` in every bundle, the Vite
|
|
113
|
+
plugin's included: `htmx:load` (htmx 2) and `htmx:after:process` (htmx 4) process the content,
|
|
114
|
+
an after-process hook hands what a script inserts to `htmx.process`, and on htmx 4 it
|
|
115
|
+
registers upstream's `hs-include` extension (`hs-include=":id"` sends element-scoped variables
|
|
116
|
+
with the request; `htmx.config.extensions = "hs-include"` enables it). Two additions upstream
|
|
117
|
+
lacks: fixi (`fx:swapped` processes the swapped content), and pages with their own hooks
|
|
118
|
+
between the two (`htmx.onLoad(el => _hyperscript.process(el))`,
|
|
119
|
+
`_hyperscript.addAfterProcessHook(el => htmx.process(el))`, the workarounds until now) no longer
|
|
120
|
+
recurse, where upstream recurses until the stack runs out. The workarounds can be removed. The
|
|
121
|
+
first vendoring of upstream's suite left out its htmx tests (`integration/htmx.js`,
|
|
122
|
+
`ext/hs-include.js`), which is how the gap shipped; the gate now runs them and passes all 19
|
|
123
|
+
(1422/1486). `hyperfixi-hs.js` grows 0.7 KB gzipped, to 34.9 KB.
|
|
124
|
+
- **`@hyperfixi/engine`: loading the engine twice no longer binds every handler twice.** Element
|
|
125
|
+
state was private to each copy of the engine, so the second copy initialised every element
|
|
126
|
+
again and one click ran its handler twice. htmx 4's boosted swaps run body scripts again, so
|
|
127
|
+
boost, then back, did it on a page that loads the engine at the end of its body. The state is
|
|
128
|
+
now `elt._hyperscript`, where upstream keeps it and a second copy finds it (two more of
|
|
129
|
+
upstream's tests pass).
|
|
130
|
+
- **Examples: sortable-list's Add Task added a blank task and threw.** Its script read the input
|
|
131
|
+
with `first #new-item-input`, which is null (`first` of one element), and now reads the element
|
|
132
|
+
itself. tell-command's code sample shows its `on click`.
|
|
133
|
+
|
|
134
|
+
### Deprecated
|
|
135
|
+
|
|
136
|
+
- **`@hyperfixi/vite-plugin`'s `htmx` option does nothing.** It added a listener for htmx 2's
|
|
137
|
+
event names, which htmx 4 does not fire; the engine's integration covers every bundle. The
|
|
138
|
+
option is still accepted, so existing configs build.
|
|
139
|
+
|
|
10
140
|
## [7.3.0] - 2026-10-21
|
|
11
141
|
|
|
12
142
|
`@hyperfixi/mcp-server` lists its 14 core tools by default and keeps the other 70 in toolsets
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ core's `dist/hyperfixi.js` is this package's `hyperfixi-hs.js`. It is also publi
|
|
|
11
11
|
|
|
12
12
|
## Install
|
|
13
13
|
|
|
14
|
-
The script-tag bundle, hyperscript and nothing else (34.
|
|
14
|
+
The script-tag bundle, hyperscript and nothing else (34.9 KB gzipped). It installs as
|
|
15
15
|
`window._hyperscript` and `window.hyperfixi`, and reads the document when it is ready:
|
|
16
16
|
|
|
17
17
|
```html
|
|
@@ -57,6 +57,20 @@ A script is rewritten as it is read. The element keeps the text its author wrote
|
|
|
57
57
|
error in the rewritten script carries that text (`error.written`). `@lokascript/hyperscript-adapter`
|
|
58
58
|
uses the hook when the host has it.
|
|
59
59
|
|
|
60
|
+
### htmx and fixi
|
|
61
|
+
|
|
62
|
+
Load htmx (2 or 4) or fixi beside any bundle and nothing else is needed: once the engine has
|
|
63
|
+
processed the document it processes content they swap in, and hands htmx the content a script
|
|
64
|
+
puts in, so its `hx-*` attributes work. On htmx 4 it registers upstream's `hs-include`
|
|
65
|
+
extension (`hs-include=":userId"` sends an element-scoped variable with the request; enable it
|
|
66
|
+
with `htmx.config.extensions = "hs-include"`). This is upstream's integration
|
|
67
|
+
(`src/htmx-compat.ts`), with two additions: fixi (on `fx:swapped`), and a hand-off to htmx that
|
|
68
|
+
does not recurse when a page also hands htmx's content to the engine itself
|
|
69
|
+
(`htmx.onLoad(el => _hyperscript.process(el))`), as it does on upstream. As on upstream, the
|
|
70
|
+
engine looks for htmx once, when it has processed the document: load htmx with a script tag
|
|
71
|
+
(plain or `defer`, not `async`) for the hand-off and `hs-include`; swapped-in content is processed
|
|
72
|
+
whenever htmx loads.
|
|
73
|
+
|
|
60
74
|
## Layout
|
|
61
75
|
|
|
62
76
|
| File | What it holds |
|
|
@@ -153,7 +167,7 @@ commands) 18.4 KB, `full` 34.1 KB, `core` (no commands) 13.8 KB.
|
|
|
153
167
|
|
|
154
168
|
## The script-tag bundle: `hyperfixi-hs.js`
|
|
155
169
|
|
|
156
|
-
`dist/hyperfixi-hs.js` (minified, 34.
|
|
170
|
+
`dist/hyperfixi-hs.js` (minified, 34.9 KB gzipped; `hyperfixi-hs.dev.js` is the readable build) is the first product on this engine:
|
|
157
171
|
hyperscript and nothing else, every module, no htmx attributes, English only. It installs
|
|
158
172
|
`window._hyperscript`, as upstream does, and the same object as `window.hyperfixi`. The name
|
|
159
173
|
paired with core's `hyperfixi-hx.js` (hyperscript plus htmx, retired in Phase C3). Since C-R4b
|
|
@@ -185,8 +199,12 @@ gallery for `packages/core/test-pages/`. One behavior of core's is not in this e
|
|
|
185
199
|
engine want `increment #count's textContent`. The examples write the second, which every
|
|
186
200
|
bundle runs to the same count (the bundle matrix's Counter row).
|
|
187
201
|
|
|
188
|
-
|
|
189
|
-
`
|
|
202
|
+
Since 2026-10-21 the gate also runs upstream's htmx tests (`integration/htmx.js` and
|
|
203
|
+
`ext/hs-include.js`, 19), which the first vendoring left out, so the whole suite is 1,486. The
|
|
204
|
+
engine failed 10 of them until it had upstream's htmx integration; it passes all 19.
|
|
205
|
+
|
|
206
|
+
The 64 known failures: upstream's internal-API surface (`internals.tokenizer`,
|
|
207
|
+
`evalStatically`, source info, error collection: 45), sockets and workers (17, upstream
|
|
190
208
|
extensions that are not built), and two collection-expression tests that need upstream's
|
|
191
209
|
component extension. Upstream's one failure is a test that expects its worker extension to be
|
|
192
210
|
absent.
|
package/dist/common.js
CHANGED
|
@@ -37,13 +37,22 @@
|
|
|
37
37
|
enter(_elt) {
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
|
-
var
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
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. */
|
|
@@ -2400,6 +2409,108 @@
|
|
|
2400
2409
|
};
|
|
2401
2410
|
}
|
|
2402
2411
|
|
|
2412
|
+
// src/htmx-compat.ts
|
|
2413
|
+
var installed = /* @__PURE__ */ new WeakSet();
|
|
2414
|
+
function installHtmxCompat(hs) {
|
|
2415
|
+
if (installed.has(hs)) return;
|
|
2416
|
+
installed.add(hs);
|
|
2417
|
+
let fromHtmx = false;
|
|
2418
|
+
const asHtmx = (f) => {
|
|
2419
|
+
const was = fromHtmx;
|
|
2420
|
+
fromHtmx = true;
|
|
2421
|
+
try {
|
|
2422
|
+
f();
|
|
2423
|
+
} finally {
|
|
2424
|
+
fromHtmx = was;
|
|
2425
|
+
}
|
|
2426
|
+
};
|
|
2427
|
+
document.addEventListener(
|
|
2428
|
+
"htmx:load",
|
|
2429
|
+
(evt) => asHtmx(() => hs.process(evt.detail?.elt))
|
|
2430
|
+
);
|
|
2431
|
+
document.addEventListener("htmx:after:process", (evt) => asHtmx(() => hs.process(evt.target)));
|
|
2432
|
+
document.addEventListener("fx:swapped", (evt) => {
|
|
2433
|
+
const target = evt.detail?.cfg?.target;
|
|
2434
|
+
hs.process(
|
|
2435
|
+
target instanceof Element && target.isConnected ? target.parentElement ?? target : document.body
|
|
2436
|
+
);
|
|
2437
|
+
});
|
|
2438
|
+
const htmx = Reflect.get(globalThis, "htmx");
|
|
2439
|
+
if (typeof htmx?.process !== "function") return;
|
|
2440
|
+
hs.addAfterProcessHook((elt) => {
|
|
2441
|
+
if (!fromHtmx) asHtmx(() => htmx.process(elt));
|
|
2442
|
+
});
|
|
2443
|
+
if (htmx.version?.startsWith("4")) {
|
|
2444
|
+
htmx.registerExtension?.("hs-include", {
|
|
2445
|
+
htmx_config_request(elt, detail) {
|
|
2446
|
+
const ctx = detail?.ctx;
|
|
2447
|
+
if (!ctx) return;
|
|
2448
|
+
const found = findHsInclude(ctx.sourceElement || elt);
|
|
2449
|
+
if (!found) return;
|
|
2450
|
+
const vars = resolveSpecifiers(found.value, found.scopeElt);
|
|
2451
|
+
const body = ctx.request?.body;
|
|
2452
|
+
if (body instanceof FormData) for (const k in vars) body.set(k, vars[k]);
|
|
2453
|
+
}
|
|
2454
|
+
});
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
function findHsInclude(sourceElt) {
|
|
2458
|
+
const attr = sourceElt.getAttribute("hs-include");
|
|
2459
|
+
if (attr !== null) return { value: attr, scopeElt: sourceElt };
|
|
2460
|
+
for (let elt = sourceElt.parentElement; elt; elt = elt.parentElement) {
|
|
2461
|
+
const inherited2 = elt.getAttribute("hs-include:inherited");
|
|
2462
|
+
if (inherited2 !== null) return { value: inherited2, scopeElt: elt };
|
|
2463
|
+
}
|
|
2464
|
+
return null;
|
|
2465
|
+
}
|
|
2466
|
+
var readScope = (elt) => elt && peekData(elt)?.scopes?.elementScope || {};
|
|
2467
|
+
function serialize(value) {
|
|
2468
|
+
if (value == null) return "";
|
|
2469
|
+
if (typeof value === "object") {
|
|
2470
|
+
try {
|
|
2471
|
+
return JSON.stringify(value);
|
|
2472
|
+
} catch {
|
|
2473
|
+
return "";
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
return String(value);
|
|
2477
|
+
}
|
|
2478
|
+
function resolveInherited(scopeKey, startElt) {
|
|
2479
|
+
for (let elt = startElt; elt; elt = elt.parentElement) {
|
|
2480
|
+
const scope = readScope(elt);
|
|
2481
|
+
if (scopeKey in scope) return scope[scopeKey];
|
|
2482
|
+
}
|
|
2483
|
+
return void 0;
|
|
2484
|
+
}
|
|
2485
|
+
function resolveSpecifiers(attrValue, scopeElt) {
|
|
2486
|
+
const result = {};
|
|
2487
|
+
const raw = attrValue.trim();
|
|
2488
|
+
if (raw === "*") {
|
|
2489
|
+
const scope = readScope(scopeElt);
|
|
2490
|
+
for (const k of Object.keys(scope)) result[k[0] === ":" ? k.slice(1) : k] = serialize(scope[k]);
|
|
2491
|
+
return result;
|
|
2492
|
+
}
|
|
2493
|
+
for (let part of raw.split(",")) {
|
|
2494
|
+
part = part.trim();
|
|
2495
|
+
if (!part) continue;
|
|
2496
|
+
if (part[0] === ":") {
|
|
2497
|
+
const scope = readScope(scopeElt);
|
|
2498
|
+
if (part in scope) result[part.slice(1)] = serialize(scope[part]);
|
|
2499
|
+
} else if (part[0] === "^") {
|
|
2500
|
+
const value = resolveInherited(":" + part.slice(1), scopeElt);
|
|
2501
|
+
if (value !== void 0) result[part.slice(1)] = serialize(value);
|
|
2502
|
+
} else if (part[0] === "#") {
|
|
2503
|
+
const colon = part.lastIndexOf(":");
|
|
2504
|
+
if (colon > 0) {
|
|
2505
|
+
const scope = readScope(document.querySelector(part.slice(0, colon)));
|
|
2506
|
+
const name = part.slice(colon + 1);
|
|
2507
|
+
if (":" + name in scope) result[name] = serialize(scope[":" + name]);
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
return result;
|
|
2512
|
+
}
|
|
2513
|
+
|
|
2403
2514
|
// src/parser.ts
|
|
2404
2515
|
var ParseError = class extends Error {
|
|
2405
2516
|
constructor(message, token, source, expected) {
|
|
@@ -2681,14 +2792,21 @@
|
|
|
2681
2792
|
}
|
|
2682
2793
|
var beforeProcess = [];
|
|
2683
2794
|
var afterProcess = [];
|
|
2795
|
+
var processing = /* @__PURE__ */ new Set();
|
|
2684
2796
|
function processNode(node) {
|
|
2685
2797
|
if (!(node instanceof Element || node instanceof Document || node instanceof DocumentFragment))
|
|
2686
2798
|
return;
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2799
|
+
if (processing.has(node)) return;
|
|
2800
|
+
processing.add(node);
|
|
2801
|
+
try {
|
|
2802
|
+
for (const hook of beforeProcess) hook(node);
|
|
2803
|
+
const selector = attributes().map((a) => `[${a}]`).join(", ") + ", [type='text/hyperscript']";
|
|
2804
|
+
if (node instanceof Element && node.matches(selector)) initElement(node);
|
|
2805
|
+
node.querySelectorAll(selector).forEach(initElement);
|
|
2806
|
+
for (const hook of afterProcess) hook(node);
|
|
2807
|
+
} finally {
|
|
2808
|
+
processing.delete(node);
|
|
2809
|
+
}
|
|
2692
2810
|
}
|
|
2693
2811
|
function cleanup(elt) {
|
|
2694
2812
|
const data = peekData(elt);
|
|
@@ -2734,7 +2852,7 @@
|
|
|
2734
2852
|
cleanup,
|
|
2735
2853
|
/** The part of upstream's `internals` that pages and tests reach for. */
|
|
2736
2854
|
internals: { runtime: { cleanup, processNode } },
|
|
2737
|
-
version: false ? "dev" : "7.
|
|
2855
|
+
version: false ? "dev" : "7.5.0"
|
|
2738
2856
|
});
|
|
2739
2857
|
function boot() {
|
|
2740
2858
|
Object.assign(globalThis, { _hyperscript: api });
|
|
@@ -2742,6 +2860,7 @@
|
|
|
2742
2860
|
const start = () => {
|
|
2743
2861
|
processNode(document.documentElement);
|
|
2744
2862
|
document.dispatchEvent(new Event("hyperscript:ready"));
|
|
2863
|
+
installHtmxCompat(api);
|
|
2745
2864
|
};
|
|
2746
2865
|
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start);
|
|
2747
2866
|
else setTimeout(start);
|