@hyperfixi/vite-plugin 2.7.1 → 2.8.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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @lokascript/vite-plugin
1
+ # @hyperfixi/vite-plugin
2
2
 
3
3
  Zero-config Vite plugin that automatically generates minimal LokaScript bundles based on detected hyperscript usage.
4
4
 
@@ -13,23 +13,23 @@ Zero-config Vite plugin that automatically generates minimal LokaScript bundles
13
13
  ## Installation
14
14
 
15
15
  ```bash
16
- npm install @lokascript/vite-plugin @lokascript/core
16
+ npm install @hyperfixi/vite-plugin @hyperfixi/core
17
17
  ```
18
18
 
19
19
  ## Quick Start
20
20
 
21
21
  ```javascript
22
22
  // vite.config.js
23
- import { lokascript } from '@lokascript/vite-plugin';
23
+ import { hyperfixi } from '@hyperfixi/vite-plugin';
24
24
 
25
25
  export default {
26
- plugins: [lokascript()],
26
+ plugins: [hyperfixi()],
27
27
  };
28
28
  ```
29
29
 
30
30
  ```javascript
31
31
  // main.js
32
- import 'lokascript'; // Auto-generated minimal bundle
32
+ import 'hyperfixi'; // Auto-generated minimal bundle
33
33
  ```
34
34
 
35
35
  ```html
@@ -49,7 +49,7 @@ import 'lokascript'; // Auto-generated minimal bundle
49
49
  When bundle size is the priority, use **compile mode** to pre-compile hyperscript to JavaScript at build time:
50
50
 
51
51
  ```javascript
52
- lokascript({
52
+ hyperfixi({
53
53
  mode: 'compile', // ~500 bytes gzip vs ~8KB for interpret mode
54
54
  });
55
55
  ```
@@ -84,7 +84,7 @@ toggle, add, remove, show, hide, focus, blur, set, get, put, increment, decremen
84
84
 
85
85
  ## Multilingual & Semantic Parsing
86
86
 
87
- Enable semantic parsing for natural language hyperscript and multilingual support across 13 languages.
87
+ Enable semantic parsing for natural language hyperscript and multilingual support across 24 languages.
88
88
 
89
89
  ### Multilingual Options
90
90
 
@@ -96,29 +96,34 @@ Enable semantic parsing for natural language hyperscript and multilingual suppor
96
96
  | `grammar` | `boolean` | `false` | Enable grammar transformation (SOV/VSO) |
97
97
  | `extraLanguages` | `string[]` | `[]` | Languages to always include |
98
98
 
99
- ### Supported Languages (13)
99
+ ### Supported Languages (24)
100
100
 
101
- - **Western:** en, es, pt, fr, de
101
+ - **Western (Latin script):** en, es, pt, fr, de, it, vi
102
+ - **Slavic:** pl, ru, uk
102
103
  - **East Asian:** ja, zh, ko
103
- - **Other:** ar, tr, id, sw, qu
104
+ - **RTL:** ar, he
105
+ - **South Asian:** hi, bn
106
+ - **Southeast Asian:** th
107
+ - **Agglutinative Latin:** tr
108
+ - **Other:** id, ms, sw, qu, tl
104
109
 
105
110
  ### Usage Examples
106
111
 
107
112
  ```javascript
108
113
  // Auto-detect languages from source files
109
- lokascript({ semantic: 'auto' });
114
+ hyperfixi({ semantic: 'auto' });
110
115
 
111
116
  // English synonyms only (smallest semantic bundle)
112
- lokascript({ semantic: 'en' });
117
+ hyperfixi({ semantic: 'en' });
113
118
 
114
119
  // Explicit languages (selects optimal regional bundle)
115
- lokascript({ languages: ['en', 'es', 'ja'] });
120
+ hyperfixi({ languages: ['en', 'es', 'ja'] });
116
121
 
117
122
  // Force a specific regional bundle
118
- lokascript({ region: 'western' });
123
+ hyperfixi({ region: 'western' });
119
124
 
120
125
  // Full multilingual with grammar transformation
121
- lokascript({ semantic: true, grammar: true });
126
+ hyperfixi({ semantic: true, grammar: true });
122
127
  ```
123
128
 
124
129
  ### Language Auto-Detection
@@ -137,28 +142,35 @@ The plugin automatically selects the smallest bundle that covers all detected la
137
142
 
138
143
  ### Semantic Bundle Sizes
139
144
 
140
- | Bundle | Gzip Size | Languages |
141
- | ---------------------- | --------- | --------------------- |
142
- | `semantic: 'en'` | ~20 KB | English only |
143
- | `semantic: 'es'` | ~16 KB | Spanish only |
144
- | `region: 'es-en'` | ~25 KB | English + Spanish |
145
- | `region: 'western'` | ~30 KB | en, es, pt, fr, de |
146
- | `region: 'east-asian'` | ~24 KB | ja, zh, ko |
147
- | `region: 'priority'` | ~48 KB | 11 priority languages |
148
- | `region: 'all'` | ~61 KB | All 13 languages |
145
+ | Bundle | Languages |
146
+ | ---------------------- | --------------------- |
147
+ | `semantic: 'en'` | English only |
148
+ | `semantic: 'es'` | Spanish only |
149
+ | `region: 'es-en'` | English + Spanish |
150
+ | `region: 'western'` | en, es, pt, fr, de |
151
+ | `region: 'east-asian'` | ja, zh, ko |
152
+ | `region: 'priority'` | 11 priority languages |
153
+ | `region: 'all'` | All 24 languages |
154
+
155
+ Final size depends on Vite's tree-shaking of the selected languages; for reference,
156
+ the prebuilt standalone semantic bundles range from ~62 KB (core) to ~203 KB
157
+ (all 24 languages) gzipped — see `docs/BROWSER_BUNDLES.md` in the repo.
149
158
 
150
159
  ### Tiered Bundle Architecture
151
160
 
152
- ```
153
- Level 0: Base HybridParser (default) 4-9 KB gzip
161
+ ```text
162
+ Level 0: Base HybridParser (default)
154
163
  ↓ semantic: true
155
- Level 1: + Semantic English +20 KB
164
+ Level 1: + Semantic English
156
165
  ↓ languages detected/specified
157
- Level 2: + Regional Semantic Bundle +16-61 KB
166
+ Level 2: + Regional Semantic Bundle
158
167
  ↓ grammar: true
159
- Level 3: + Grammar Transformation +68 KB
168
+ Level 3: + Grammar Transformation
160
169
  ```
161
170
 
171
+ Each level adds bundle weight; the plugin picks the lowest level that covers the
172
+ features and languages it detects in your source.
173
+
162
174
  ## htmx v4 reactive / streaming surface
163
175
 
164
176
  The scanner detects `hx-live`, `sse-connect` / `sse-swap`, `ws-connect` / `ws-send`, and `bind <var> to <expr>.<prop>` inside `_=` bodies. When any of those is found in the project, the generated bundle is the `hyperfixi-hx-v4.js` premade bundle (full runtime + `@hyperfixi/reactivity` + htmx-compat auto-installed + SSE/WS).
@@ -176,7 +188,7 @@ The slim minimal-bundle generator can't satisfy these features (its parser/runti
176
188
  ## Options
177
189
 
178
190
  ```javascript
179
- lokascript({
191
+ hyperfixi({
180
192
  // Bundle mode: 'interpret' (default) or 'compile'
181
193
  mode: 'interpret',
182
194
 
@@ -200,8 +212,8 @@ lokascript({
200
212
  // Custom bundle name (shown in generated code comments)
201
213
  bundleName: 'MyApp',
202
214
 
203
- // Global variable name (default: 'lokascript')
204
- globalName: 'lokascript',
215
+ // Global variable name (default: 'hyperfixi')
216
+ globalName: 'hyperfixi',
205
217
 
206
218
  // Multilingual options (see "Multilingual & Semantic Parsing" section)
207
219
  semantic: false, // boolean | 'en' | 'auto'
@@ -214,7 +226,7 @@ lokascript({
214
226
 
215
227
  ## Detected Features
216
228
 
217
- ### Commands (21)
229
+ ### Commands
218
230
 
219
231
  toggle, add, remove, removeClass, show, hide, set, get, put, append, take,
220
232
  increment, decrement, log, send, trigger, wait, transition, go, call, focus, blur, return
@@ -233,9 +245,9 @@ The plugin creates a virtual module that you can import:
233
245
 
234
246
  ```javascript
235
247
  // All of these work:
236
- import 'lokascript';
237
- import 'virtual:lokascript';
238
- import '@lokascript/core'; // Redirects to virtual module
248
+ import 'hyperfixi';
249
+ import 'virtual:hyperfixi';
250
+ import '@hyperfixi/core'; // Redirects to virtual module
239
251
  ```
240
252
 
241
253
  ## HMR Support
@@ -267,7 +279,7 @@ element.setAttribute('_', `on click ${dynamicCommand} .active`);
267
279
  Use `extraCommands` to include those:
268
280
 
269
281
  ```javascript
270
- lokascript({
282
+ hyperfixi({
271
283
  extraCommands: ['toggle', 'add', 'remove'],
272
284
  });
273
285
  ```
@@ -283,18 +295,18 @@ lokascript({
283
295
 
284
296
  ## Monorepo Development
285
297
 
286
- When developing in the lokascript monorepo:
298
+ When developing in the hyperfixi monorepo:
287
299
 
288
300
  ```javascript
289
301
  // vite.config.js
290
- import { lokascript } from '../../packages/vite-plugin/src/index.ts';
302
+ import { hyperfixi } from '../../packages/vite-plugin/src/index.ts';
291
303
  import path from 'path';
292
304
 
293
305
  export default {
294
- plugins: [lokascript({ debug: true })],
306
+ plugins: [hyperfixi({ debug: true })],
295
307
  resolve: {
296
308
  alias: {
297
- '@lokascript/core/parser/hybrid': path.resolve(
309
+ '@hyperfixi/core/parser/hybrid': path.resolve(
298
310
  __dirname,
299
311
  '../../packages/core/src/parser/hybrid'
300
312
  ),
@@ -341,7 +353,7 @@ This example demonstrates language auto-detection with Japanese, Spanish, and Ko
341
353
  | `positional` | `boolean` | `false` | Always include positional expressions |
342
354
  | `htmx` | `boolean` | `false` | Enable htmx integration |
343
355
  | `bundleName` | `string` | `'ViteAutoGenerated'` | Bundle name in comments |
344
- | `globalName` | `string` | `'lokascript'` | Window global name |
356
+ | `globalName` | `string` | `'hyperfixi'` | Window global name |
345
357
  | `semantic` | `boolean \| 'en' \| 'auto'` | `false` | Enable semantic parser |
346
358
  | `languages` | `string[]` | `[]` | Explicit language codes |
347
359
  | `region` | `string` | auto | Force regional bundle |
package/dist/index.cjs CHANGED
@@ -36,6 +36,7 @@ __export(index_exports, {
36
36
  SUPPORTED_LANGUAGES: () => SUPPORTED_LANGUAGES,
37
37
  clearCustomKeywords: () => clearCustomKeywords,
38
38
  clearSemanticParser: () => clearSemanticParser,
39
+ computeUsageHash: () => computeUsageHash,
39
40
  default: () => index_default,
40
41
  descriptorToScanRule: () => descriptorToScanRule,
41
42
  detectLanguages: () => detectLanguages,
@@ -50,6 +51,9 @@ __export(index_exports, {
50
51
  });
51
52
  module.exports = __toCommonJS(index_exports);
52
53
 
54
+ // src/scanner.ts
55
+ var import_bundle_generator = require("@hyperfixi/core/bundle-generator");
56
+
53
57
  // src/language-keywords.ts
54
58
  var SUPPORTED_LANGUAGES = [
55
59
  "en",
@@ -421,6 +425,7 @@ var INDONESIAN_KEYWORDS = /* @__PURE__ */ new Set([
421
425
  "kalau",
422
426
  "bila",
423
427
  "selainnya",
428
+ "lainnya",
424
429
  "ulangi",
425
430
  "tunggu",
426
431
  "selama"
@@ -557,6 +562,7 @@ var VIETNAMESE_KEYWORDS = /* @__PURE__ */ new Set([
557
562
  "l\u1EB7p l\u1EA1i",
558
563
  "ch\u1EDD",
559
564
  "\u0111\u1EE3i",
565
+ "ch\u1EDD \u0111\u1EE3i",
560
566
  "trong khi"
561
567
  ]);
562
568
  var POLISH_KEYWORDS = /* @__PURE__ */ new Set([
@@ -963,6 +969,17 @@ var SSE_NS_PATTERN = /\bsse-[\w\-\p{L}]+\s*=\s*["']/u;
963
969
  var WS_NS_PATTERN = /\bws-[\w\-\p{L}]+\s*=\s*["']/u;
964
970
 
965
971
  // src/scanner.ts
972
+ var SCANNABLE_COMMANDS = [
973
+ .../* @__PURE__ */ new Set([...import_bundle_generator.AVAILABLE_COMMANDS, ...import_bundle_generator.FULL_RUNTIME_ONLY_COMMANDS])
974
+ ].filter(
975
+ (cmd) => /^[A-Za-z]+$/.test(cmd) && // `unless` is handled by the block detection below (it compiles to the
976
+ // lite-capable `if` block — flagging it as a full-runtime-only COMMAND
977
+ // would needlessly bump every unless-user to a full-runtime bundle).
978
+ // `bind` is handled by the dedicated reactivity detection below, which
979
+ // routes to the hx-v4 bundle (the tier that actually ships reactivity).
980
+ cmd !== "unless" && cmd !== "bind"
981
+ );
982
+ var COMMAND_PATTERN_SOURCE = `\\b(${SCANNABLE_COMMANDS.join("|")})\\b`;
966
983
  var HTMX_REQUEST_PATTERN = /\b(hx-get|hx-post|hx-put|hx-patch|hx-delete)\s*=\s*["']([^"']+)["']/gi;
967
984
  var FIXI_ACTION_PATTERN = /\bfx-action\s*=\s*["']([^"']+)["']/gi;
968
985
  var FIXI_METHOD_PATTERN = /\bfx-method\s*=\s*["'](GET|POST|PUT|PATCH|DELETE)["']/gi;
@@ -1071,7 +1088,7 @@ var Scanner = class {
1071
1088
  * Analyze a hyperscript snippet for commands, blocks, and expressions
1072
1089
  */
1073
1090
  analyzeScript(script, usage) {
1074
- const commandPattern = /\b(toggle|add|remove|removeClass|show|hide|set|get|put|append|take|increment|decrement|log|send|trigger|wait|transition|go|call|focus|blur|return)\b/g;
1091
+ const commandPattern = new RegExp(COMMAND_PATTERN_SOURCE, "g");
1075
1092
  let match;
1076
1093
  while (match = commandPattern.exec(script)) {
1077
1094
  usage.commands.add(match[1]);
@@ -1110,6 +1127,7 @@ var Scanner = class {
1110
1127
  triggerModifiers: /* @__PURE__ */ new Set(),
1111
1128
  urlManagement: /* @__PURE__ */ new Set(),
1112
1129
  usesConfirm: false,
1130
+ needsSwapTiming: false,
1113
1131
  needsHxLive: false,
1114
1132
  needsSSE: false,
1115
1133
  needsWS: false,
@@ -1135,7 +1153,14 @@ var Scanner = class {
1135
1153
  const swapPattern = new RegExp(HTMX_SWAP_PATTERN.source, "gi");
1136
1154
  while (match = swapPattern.exec(code)) {
1137
1155
  usage.hasHtmxAttributes = true;
1138
- usage.swapStrategies.add(match[2].split(/\s+/)[0]);
1156
+ const spec = match[2].trim();
1157
+ const head = spec.split(/\s+/)[0];
1158
+ if (head.startsWith("morph") || !/^\S*:/.test(spec)) {
1159
+ usage.swapStrategies.add(head);
1160
+ }
1161
+ if (/\b(swap|settle):/.test(spec)) {
1162
+ usage.needsSwapTiming = true;
1163
+ }
1139
1164
  }
1140
1165
  const triggerPattern = new RegExp(HTMX_TRIGGER_PATTERN.source, "gi");
1141
1166
  while (match = triggerPattern.exec(code)) {
@@ -1203,17 +1228,19 @@ var Scanner = class {
1203
1228
  usage.commands.add("put");
1204
1229
  }
1205
1230
  for (const swap of htmx.swapStrategies) {
1206
- switch (swap.toLowerCase()) {
1207
- case "morph":
1208
- usage.commands.add("morph");
1209
- break;
1210
- case "delete":
1211
- usage.commands.add("remove");
1212
- break;
1213
- default:
1214
- usage.commands.add("put");
1231
+ const strategy = swap.toLowerCase();
1232
+ if (strategy.startsWith("morph")) {
1233
+ usage.commands.add("morph");
1234
+ if (strategy === "morph:innerhtml") usage.commands.add("put");
1235
+ } else if (strategy === "delete") {
1236
+ usage.commands.add("remove");
1237
+ } else {
1238
+ usage.commands.add("put");
1215
1239
  }
1216
1240
  }
1241
+ if (htmx.needsSwapTiming) {
1242
+ usage.commands.add("wait");
1243
+ }
1217
1244
  if (htmx.usesConfirm) {
1218
1245
  usage.blocks.add("if");
1219
1246
  }
@@ -1308,6 +1335,7 @@ var Aggregator = class {
1308
1335
  triggerModifiers: /* @__PURE__ */ new Set(),
1309
1336
  urlManagement: /* @__PURE__ */ new Set(),
1310
1337
  usesConfirm: false,
1338
+ needsSwapTiming: false,
1311
1339
  needsHxLive: false,
1312
1340
  needsSSE: false,
1313
1341
  needsWS: false,
@@ -1332,6 +1360,7 @@ var Aggregator = class {
1332
1360
  for (const modifier of usage.htmx.triggerModifiers) htmx.triggerModifiers.add(modifier);
1333
1361
  for (const url of usage.htmx.urlManagement) htmx.urlManagement.add(url);
1334
1362
  if (usage.htmx.usesConfirm) htmx.usesConfirm = true;
1363
+ if (usage.htmx.needsSwapTiming) htmx.needsSwapTiming = true;
1335
1364
  if (usage.htmx.needsHxLive) htmx.needsHxLive = true;
1336
1365
  if (usage.htmx.needsSSE) htmx.needsSSE = true;
1337
1366
  if (usage.htmx.needsWS) htmx.needsWS = true;
@@ -1404,12 +1433,20 @@ var Aggregator = class {
1404
1433
  htmxUsageEqual(a, b) {
1405
1434
  if (!a && !b) return true;
1406
1435
  if (!a || !b) return false;
1407
- return a.hasHtmxAttributes === b.hasHtmxAttributes && a.hasFixiAttributes === b.hasFixiAttributes && this.setsEqual(a.httpMethods, b.httpMethods) && this.setsEqual(a.swapStrategies, b.swapStrategies) && this.setsEqual(a.triggerModifiers, b.triggerModifiers) && this.setsEqual(a.urlManagement, b.urlManagement) && a.usesConfirm === b.usesConfirm;
1436
+ return a.hasHtmxAttributes === b.hasHtmxAttributes && a.hasFixiAttributes === b.hasFixiAttributes && this.setsEqual(a.httpMethods, b.httpMethods) && this.setsEqual(a.swapStrategies, b.swapStrategies) && this.setsEqual(a.triggerModifiers, b.triggerModifiers) && this.setsEqual(a.urlManagement, b.urlManagement) && a.usesConfirm === b.usesConfirm && !!a.needsSwapTiming === !!b.needsSwapTiming && // htmx v4 / reactivity flags: these drive selection of the hx-v4 tier,
1437
+ // so a change must count as "usage changed" or HMR serves a stale
1438
+ // bundle. They were omitted when the v4 surface landed (#623).
1439
+ !!a.needsHxLive === !!b.needsHxLive && !!a.needsSSE === !!b.needsSSE && !!a.needsWS === !!b.needsWS && !!a.needsBindToProperty === !!b.needsBindToProperty && !!a.needsReactivity === !!b.needsReactivity && this.arraysEqual(a.onHandlers, b.onHandlers);
1440
+ }
1441
+ arraysEqual(a, b) {
1442
+ const aa = a ?? [];
1443
+ const bb = b ?? [];
1444
+ return aa.length === bb.length && aa.every((v, i) => v === bb[i]);
1408
1445
  }
1409
1446
  };
1410
1447
 
1411
1448
  // src/generator.ts
1412
- var import_bundle_generator = require("@hyperfixi/core/bundle-generator");
1449
+ var import_bundle_generator2 = require("@hyperfixi/core/bundle-generator");
1413
1450
 
1414
1451
  // src/semantic-integration.ts
1415
1452
  var MULTILINGUAL_COMMAND_ALIASES = {
@@ -1957,10 +1994,10 @@ function stripTypes(code) {
1957
1994
  }
1958
1995
  var COMMAND_IMPLEMENTATIONS = {};
1959
1996
  var BLOCK_IMPLEMENTATIONS = {};
1960
- for (const [name, code] of Object.entries(import_bundle_generator.COMMAND_IMPLEMENTATIONS)) {
1997
+ for (const [name, code] of Object.entries(import_bundle_generator2.COMMAND_IMPLEMENTATIONS)) {
1961
1998
  COMMAND_IMPLEMENTATIONS[name] = stripTypes(code);
1962
1999
  }
1963
- for (const [name, code] of Object.entries(import_bundle_generator.BLOCK_IMPLEMENTATIONS)) {
2000
+ for (const [name, code] of Object.entries(import_bundle_generator2.BLOCK_IMPLEMENTATIONS)) {
1964
2001
  BLOCK_IMPLEMENTATIONS[name] = stripTypes(code);
1965
2002
  }
1966
2003
  function generateBundleCode(config) {
@@ -1975,14 +2012,14 @@ function generateBundleCode(config) {
1975
2012
  esModule = true,
1976
2013
  parserType = "hybrid"
1977
2014
  } = config;
1978
- const needsStyleHelpers = commands.some((cmd) => import_bundle_generator.STYLE_COMMANDS.includes(cmd));
1979
- const needsElementArrayHelper = commands.some((cmd) => import_bundle_generator.ELEMENT_ARRAY_COMMANDS.includes(cmd));
1980
- const needsMorphlex = commands.some((cmd) => import_bundle_generator.MORPH_COMMANDS.includes(cmd));
2015
+ const needsStyleHelpers = commands.some((cmd) => import_bundle_generator2.STYLE_COMMANDS.includes(cmd));
2016
+ const needsElementArrayHelper = commands.some((cmd) => import_bundle_generator2.ELEMENT_ARRAY_COMMANDS.includes(cmd));
2017
+ const needsMorphlex = commands.some((cmd) => import_bundle_generator2.MORPH_COMMANDS.includes(cmd));
1981
2018
  const hasBlocks = blocks.length > 0;
1982
2019
  const hasReturn = commands.includes("return");
1983
2020
  const commandCases = commands.filter((cmd) => COMMAND_IMPLEMENTATIONS[cmd]).map((cmd) => COMMAND_IMPLEMENTATIONS[cmd]).join("\n");
1984
2021
  const blockCases = blocks.filter((block) => BLOCK_IMPLEMENTATIONS[block]).map((block) => BLOCK_IMPLEMENTATIONS[block]).join("\n");
1985
- const parserTemplate = parserType === "lite" ? import_bundle_generator.LITE_PARSER_TEMPLATE : import_bundle_generator.HYBRID_PARSER_TEMPLATE;
2022
+ const parserTemplate = parserType === "lite" ? import_bundle_generator2.LITE_PARSER_TEMPLATE : import_bundle_generator2.HYBRID_PARSER_TEMPLATE;
1986
2023
  const morphlexImport = needsMorphlex ? `import { morph as morphlexMorph, morphInner as morphlexMorphInner } from 'morphlex';
1987
2024
 
1988
2025
  ` : "";
@@ -2411,7 +2448,7 @@ var Generator = class {
2411
2448
  }
2412
2449
  return this.generateDevFallback("full");
2413
2450
  }
2414
- const parserType = (0, import_bundle_generator.canUseLiteParser)(commands, blocks, positional) ? "lite" : "hybrid";
2451
+ const parserType = (0, import_bundle_generator2.canUseLiteParser)(commands, blocks, positional) ? "lite" : "hybrid";
2415
2452
  const config = {
2416
2453
  name: options.bundleName ?? "ViteAutoGenerated",
2417
2454
  commands,
@@ -2501,9 +2538,9 @@ ${additionalApiProps}`
2501
2538
  getUnsupportedCommands(commands) {
2502
2539
  const unsupported = [];
2503
2540
  for (const cmd of commands) {
2504
- if (import_bundle_generator.FULL_RUNTIME_ONLY_COMMANDS.includes(cmd)) {
2541
+ if (import_bundle_generator2.FULL_RUNTIME_ONLY_COMMANDS.includes(cmd)) {
2505
2542
  unsupported.push(cmd);
2506
- } else if (!(0, import_bundle_generator.isAvailableCommand)(cmd) && !COMMAND_IMPLEMENTATIONS[cmd]) {
2543
+ } else if (!(0, import_bundle_generator2.isAvailableCommand)(cmd) && !COMMAND_IMPLEMENTATIONS[cmd]) {
2507
2544
  unsupported.push(cmd);
2508
2545
  }
2509
2546
  }
@@ -3792,6 +3829,22 @@ var DomainAggregator = class {
3792
3829
  var VIRTUAL_MODULE_ID = "virtual:hyperfixi";
3793
3830
  var RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
3794
3831
  var IMPORT_ALIASES = ["hyperfixi", "@hyperfixi/core", "virtual:hyperfixi"];
3832
+ function computeUsageHash(usage) {
3833
+ const commands = [...usage.commands].sort().join(",");
3834
+ const blocks = [...usage.blocks].sort().join(",");
3835
+ const languages = [...usage.detectedLanguages].sort().join(",");
3836
+ const htmx = usage.htmx ? [
3837
+ usage.htmx.hasHtmxAttributes,
3838
+ usage.htmx.hasFixiAttributes,
3839
+ usage.htmx.needsHxLive,
3840
+ usage.htmx.needsSSE,
3841
+ usage.htmx.needsWS,
3842
+ usage.htmx.needsBindToProperty,
3843
+ usage.htmx.needsReactivity
3844
+ ].map((f) => f ? "1" : "0").join("") : "none";
3845
+ const reactivity = `${usage.needsReactivity ? 1 : 0}${usage.needsBindToProperty ? 1 : 0}`;
3846
+ return `${commands}|${blocks}|${usage.positional}|${languages}|${htmx}|${reactivity}`;
3847
+ }
3795
3848
  function hyperfixi(options = {}) {
3796
3849
  const mode = options.mode ?? "interpret";
3797
3850
  const scanner = new Scanner(options);
@@ -3808,12 +3861,6 @@ function hyperfixi(options = {}) {
3808
3861
  const fallbackScripts = /* @__PURE__ */ new Set();
3809
3862
  let needsLocals = false;
3810
3863
  let needsGlobals = false;
3811
- function computeUsageHash(usage) {
3812
- const commands = [...usage.commands].sort().join(",");
3813
- const blocks = [...usage.blocks].sort().join(",");
3814
- const languages = [...usage.detectedLanguages].sort().join(",");
3815
- return `${commands}|${blocks}|${usage.positional}|${languages}`;
3816
- }
3817
3864
  function invalidateVirtualModule() {
3818
3865
  if (!server) return;
3819
3866
  const mod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_MODULE_ID);
@@ -4114,6 +4161,7 @@ var index_default = hyperfixi;
4114
4161
  SUPPORTED_LANGUAGES,
4115
4162
  clearCustomKeywords,
4116
4163
  clearSemanticParser,
4164
+ computeUsageHash,
4117
4165
  descriptorToScanRule,
4118
4166
  detectLanguages,
4119
4167
  getAllLanguageCodes,