@hyperfixi/vite-plugin 2.7.2 → 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 +54 -42
- package/dist/index.cjs +76 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +67 -20
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -209,6 +209,11 @@ interface HtmxUsage {
|
|
|
209
209
|
urlManagement: Set<string>;
|
|
210
210
|
/** Whether hx-confirm is used */
|
|
211
211
|
usesConfirm: boolean;
|
|
212
|
+
/**
|
|
213
|
+
* `hx-swap` carries a `swap:`/`settle:` timing modifier, which the translator
|
|
214
|
+
* emits as `wait <n>ms`. Optional so older fixture literals stay valid.
|
|
215
|
+
*/
|
|
216
|
+
needsSwapTiming?: boolean;
|
|
212
217
|
/**
|
|
213
218
|
* htmx v4 reactive/streaming surface detected. Each flag pulls in the
|
|
214
219
|
* corresponding bundle module; collectively they're what makes
|
|
@@ -625,6 +630,16 @@ declare function getOptimalRegion(languages: Set<SupportedLanguage>): 'western'
|
|
|
625
630
|
* ```
|
|
626
631
|
*/
|
|
627
632
|
|
|
633
|
+
/**
|
|
634
|
+
* Compute a hash of the current usage for dev-server cache invalidation.
|
|
635
|
+
*
|
|
636
|
+
* Every input that influences bundle SELECTION must be part of this hash.
|
|
637
|
+
* The htmx/reactivity flags route to the hybrid-hx / hx-v4 tiers; before they
|
|
638
|
+
* were hashed, adding or removing an hx-live/sse-connect/ws-send attribute —
|
|
639
|
+
* without touching any command/block/language — left the cached dev bundle at
|
|
640
|
+
* the wrong tier. Exported for tests.
|
|
641
|
+
*/
|
|
642
|
+
declare function computeUsageHash(usage: AggregatedUsage): string;
|
|
628
643
|
/**
|
|
629
644
|
* Create the HyperFixi Vite plugin
|
|
630
645
|
*
|
|
@@ -633,4 +648,4 @@ declare function getOptimalRegion(languages: Set<SupportedLanguage>): 'western'
|
|
|
633
648
|
*/
|
|
634
649
|
declare function hyperfixi(options?: HyperfixiPluginOptions): Plugin;
|
|
635
650
|
|
|
636
|
-
export { type AggregatedUsage, type CompileOptions, type CompiledHandler, type CustomLanguageKeywords, type DomainAggregatedUsage, DomainAggregator, type DomainFileUsage, type DomainScanRule, DomainScanner, type FileUsage, type HyperfixiPluginOptions, REGIONS, SUPPORTED_LANGUAGES, type ServerBridgeOptions, type SupportedLanguage, clearCustomKeywords, clearSemanticParser, hyperfixi as default, descriptorToScanRule, detectLanguages, getAllLanguageCodes, getKeywordsForLanguage, getOptimalRegion, hasSemanticParser, hyperfixi, isNonLatinLanguage, registerCustomKeywords, setSemanticParser };
|
|
651
|
+
export { type AggregatedUsage, type CompileOptions, type CompiledHandler, type CustomLanguageKeywords, type DomainAggregatedUsage, DomainAggregator, type DomainFileUsage, type DomainScanRule, DomainScanner, type FileUsage, type HyperfixiPluginOptions, REGIONS, SUPPORTED_LANGUAGES, type ServerBridgeOptions, type SupportedLanguage, clearCustomKeywords, clearSemanticParser, computeUsageHash, hyperfixi as default, descriptorToScanRule, detectLanguages, getAllLanguageCodes, getKeywordsForLanguage, getOptimalRegion, hasSemanticParser, hyperfixi, isNonLatinLanguage, registerCustomKeywords, setSemanticParser };
|
package/dist/index.d.ts
CHANGED
|
@@ -209,6 +209,11 @@ interface HtmxUsage {
|
|
|
209
209
|
urlManagement: Set<string>;
|
|
210
210
|
/** Whether hx-confirm is used */
|
|
211
211
|
usesConfirm: boolean;
|
|
212
|
+
/**
|
|
213
|
+
* `hx-swap` carries a `swap:`/`settle:` timing modifier, which the translator
|
|
214
|
+
* emits as `wait <n>ms`. Optional so older fixture literals stay valid.
|
|
215
|
+
*/
|
|
216
|
+
needsSwapTiming?: boolean;
|
|
212
217
|
/**
|
|
213
218
|
* htmx v4 reactive/streaming surface detected. Each flag pulls in the
|
|
214
219
|
* corresponding bundle module; collectively they're what makes
|
|
@@ -625,6 +630,16 @@ declare function getOptimalRegion(languages: Set<SupportedLanguage>): 'western'
|
|
|
625
630
|
* ```
|
|
626
631
|
*/
|
|
627
632
|
|
|
633
|
+
/**
|
|
634
|
+
* Compute a hash of the current usage for dev-server cache invalidation.
|
|
635
|
+
*
|
|
636
|
+
* Every input that influences bundle SELECTION must be part of this hash.
|
|
637
|
+
* The htmx/reactivity flags route to the hybrid-hx / hx-v4 tiers; before they
|
|
638
|
+
* were hashed, adding or removing an hx-live/sse-connect/ws-send attribute —
|
|
639
|
+
* without touching any command/block/language — left the cached dev bundle at
|
|
640
|
+
* the wrong tier. Exported for tests.
|
|
641
|
+
*/
|
|
642
|
+
declare function computeUsageHash(usage: AggregatedUsage): string;
|
|
628
643
|
/**
|
|
629
644
|
* Create the HyperFixi Vite plugin
|
|
630
645
|
*
|
|
@@ -633,4 +648,4 @@ declare function getOptimalRegion(languages: Set<SupportedLanguage>): 'western'
|
|
|
633
648
|
*/
|
|
634
649
|
declare function hyperfixi(options?: HyperfixiPluginOptions): Plugin;
|
|
635
650
|
|
|
636
|
-
export { type AggregatedUsage, type CompileOptions, type CompiledHandler, type CustomLanguageKeywords, type DomainAggregatedUsage, DomainAggregator, type DomainFileUsage, type DomainScanRule, DomainScanner, type FileUsage, type HyperfixiPluginOptions, REGIONS, SUPPORTED_LANGUAGES, type ServerBridgeOptions, type SupportedLanguage, clearCustomKeywords, clearSemanticParser, hyperfixi as default, descriptorToScanRule, detectLanguages, getAllLanguageCodes, getKeywordsForLanguage, getOptimalRegion, hasSemanticParser, hyperfixi, isNonLatinLanguage, registerCustomKeywords, setSemanticParser };
|
|
651
|
+
export { type AggregatedUsage, type CompileOptions, type CompiledHandler, type CustomLanguageKeywords, type DomainAggregatedUsage, DomainAggregator, type DomainFileUsage, type DomainScanRule, DomainScanner, type FileUsage, type HyperfixiPluginOptions, REGIONS, SUPPORTED_LANGUAGES, type ServerBridgeOptions, type SupportedLanguage, clearCustomKeywords, clearSemanticParser, computeUsageHash, hyperfixi as default, descriptorToScanRule, detectLanguages, getAllLanguageCodes, getKeywordsForLanguage, getOptimalRegion, hasSemanticParser, hyperfixi, isNonLatinLanguage, registerCustomKeywords, setSemanticParser };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/scanner.ts
|
|
2
|
+
import { AVAILABLE_COMMANDS, FULL_RUNTIME_ONLY_COMMANDS } from "@hyperfixi/core/bundle-generator";
|
|
3
|
+
|
|
1
4
|
// src/language-keywords.ts
|
|
2
5
|
var SUPPORTED_LANGUAGES = [
|
|
3
6
|
"en",
|
|
@@ -369,6 +372,7 @@ var INDONESIAN_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
369
372
|
"kalau",
|
|
370
373
|
"bila",
|
|
371
374
|
"selainnya",
|
|
375
|
+
"lainnya",
|
|
372
376
|
"ulangi",
|
|
373
377
|
"tunggu",
|
|
374
378
|
"selama"
|
|
@@ -505,6 +509,7 @@ var VIETNAMESE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
505
509
|
"l\u1EB7p l\u1EA1i",
|
|
506
510
|
"ch\u1EDD",
|
|
507
511
|
"\u0111\u1EE3i",
|
|
512
|
+
"ch\u1EDD \u0111\u1EE3i",
|
|
508
513
|
"trong khi"
|
|
509
514
|
]);
|
|
510
515
|
var POLISH_KEYWORDS = /* @__PURE__ */ new Set([
|
|
@@ -911,6 +916,17 @@ var SSE_NS_PATTERN = /\bsse-[\w\-\p{L}]+\s*=\s*["']/u;
|
|
|
911
916
|
var WS_NS_PATTERN = /\bws-[\w\-\p{L}]+\s*=\s*["']/u;
|
|
912
917
|
|
|
913
918
|
// src/scanner.ts
|
|
919
|
+
var SCANNABLE_COMMANDS = [
|
|
920
|
+
.../* @__PURE__ */ new Set([...AVAILABLE_COMMANDS, ...FULL_RUNTIME_ONLY_COMMANDS])
|
|
921
|
+
].filter(
|
|
922
|
+
(cmd) => /^[A-Za-z]+$/.test(cmd) && // `unless` is handled by the block detection below (it compiles to the
|
|
923
|
+
// lite-capable `if` block — flagging it as a full-runtime-only COMMAND
|
|
924
|
+
// would needlessly bump every unless-user to a full-runtime bundle).
|
|
925
|
+
// `bind` is handled by the dedicated reactivity detection below, which
|
|
926
|
+
// routes to the hx-v4 bundle (the tier that actually ships reactivity).
|
|
927
|
+
cmd !== "unless" && cmd !== "bind"
|
|
928
|
+
);
|
|
929
|
+
var COMMAND_PATTERN_SOURCE = `\\b(${SCANNABLE_COMMANDS.join("|")})\\b`;
|
|
914
930
|
var HTMX_REQUEST_PATTERN = /\b(hx-get|hx-post|hx-put|hx-patch|hx-delete)\s*=\s*["']([^"']+)["']/gi;
|
|
915
931
|
var FIXI_ACTION_PATTERN = /\bfx-action\s*=\s*["']([^"']+)["']/gi;
|
|
916
932
|
var FIXI_METHOD_PATTERN = /\bfx-method\s*=\s*["'](GET|POST|PUT|PATCH|DELETE)["']/gi;
|
|
@@ -1019,7 +1035,7 @@ var Scanner = class {
|
|
|
1019
1035
|
* Analyze a hyperscript snippet for commands, blocks, and expressions
|
|
1020
1036
|
*/
|
|
1021
1037
|
analyzeScript(script, usage) {
|
|
1022
|
-
const commandPattern =
|
|
1038
|
+
const commandPattern = new RegExp(COMMAND_PATTERN_SOURCE, "g");
|
|
1023
1039
|
let match;
|
|
1024
1040
|
while (match = commandPattern.exec(script)) {
|
|
1025
1041
|
usage.commands.add(match[1]);
|
|
@@ -1058,6 +1074,7 @@ var Scanner = class {
|
|
|
1058
1074
|
triggerModifiers: /* @__PURE__ */ new Set(),
|
|
1059
1075
|
urlManagement: /* @__PURE__ */ new Set(),
|
|
1060
1076
|
usesConfirm: false,
|
|
1077
|
+
needsSwapTiming: false,
|
|
1061
1078
|
needsHxLive: false,
|
|
1062
1079
|
needsSSE: false,
|
|
1063
1080
|
needsWS: false,
|
|
@@ -1083,7 +1100,14 @@ var Scanner = class {
|
|
|
1083
1100
|
const swapPattern = new RegExp(HTMX_SWAP_PATTERN.source, "gi");
|
|
1084
1101
|
while (match = swapPattern.exec(code)) {
|
|
1085
1102
|
usage.hasHtmxAttributes = true;
|
|
1086
|
-
|
|
1103
|
+
const spec = match[2].trim();
|
|
1104
|
+
const head = spec.split(/\s+/)[0];
|
|
1105
|
+
if (head.startsWith("morph") || !/^\S*:/.test(spec)) {
|
|
1106
|
+
usage.swapStrategies.add(head);
|
|
1107
|
+
}
|
|
1108
|
+
if (/\b(swap|settle):/.test(spec)) {
|
|
1109
|
+
usage.needsSwapTiming = true;
|
|
1110
|
+
}
|
|
1087
1111
|
}
|
|
1088
1112
|
const triggerPattern = new RegExp(HTMX_TRIGGER_PATTERN.source, "gi");
|
|
1089
1113
|
while (match = triggerPattern.exec(code)) {
|
|
@@ -1151,17 +1175,19 @@ var Scanner = class {
|
|
|
1151
1175
|
usage.commands.add("put");
|
|
1152
1176
|
}
|
|
1153
1177
|
for (const swap of htmx.swapStrategies) {
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
usage.commands.add("put");
|
|
1178
|
+
const strategy = swap.toLowerCase();
|
|
1179
|
+
if (strategy.startsWith("morph")) {
|
|
1180
|
+
usage.commands.add("morph");
|
|
1181
|
+
if (strategy === "morph:innerhtml") usage.commands.add("put");
|
|
1182
|
+
} else if (strategy === "delete") {
|
|
1183
|
+
usage.commands.add("remove");
|
|
1184
|
+
} else {
|
|
1185
|
+
usage.commands.add("put");
|
|
1163
1186
|
}
|
|
1164
1187
|
}
|
|
1188
|
+
if (htmx.needsSwapTiming) {
|
|
1189
|
+
usage.commands.add("wait");
|
|
1190
|
+
}
|
|
1165
1191
|
if (htmx.usesConfirm) {
|
|
1166
1192
|
usage.blocks.add("if");
|
|
1167
1193
|
}
|
|
@@ -1256,6 +1282,7 @@ var Aggregator = class {
|
|
|
1256
1282
|
triggerModifiers: /* @__PURE__ */ new Set(),
|
|
1257
1283
|
urlManagement: /* @__PURE__ */ new Set(),
|
|
1258
1284
|
usesConfirm: false,
|
|
1285
|
+
needsSwapTiming: false,
|
|
1259
1286
|
needsHxLive: false,
|
|
1260
1287
|
needsSSE: false,
|
|
1261
1288
|
needsWS: false,
|
|
@@ -1280,6 +1307,7 @@ var Aggregator = class {
|
|
|
1280
1307
|
for (const modifier of usage.htmx.triggerModifiers) htmx.triggerModifiers.add(modifier);
|
|
1281
1308
|
for (const url of usage.htmx.urlManagement) htmx.urlManagement.add(url);
|
|
1282
1309
|
if (usage.htmx.usesConfirm) htmx.usesConfirm = true;
|
|
1310
|
+
if (usage.htmx.needsSwapTiming) htmx.needsSwapTiming = true;
|
|
1283
1311
|
if (usage.htmx.needsHxLive) htmx.needsHxLive = true;
|
|
1284
1312
|
if (usage.htmx.needsSSE) htmx.needsSSE = true;
|
|
1285
1313
|
if (usage.htmx.needsWS) htmx.needsWS = true;
|
|
@@ -1352,7 +1380,15 @@ var Aggregator = class {
|
|
|
1352
1380
|
htmxUsageEqual(a, b) {
|
|
1353
1381
|
if (!a && !b) return true;
|
|
1354
1382
|
if (!a || !b) return false;
|
|
1355
|
-
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
|
|
1383
|
+
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,
|
|
1384
|
+
// so a change must count as "usage changed" or HMR serves a stale
|
|
1385
|
+
// bundle. They were omitted when the v4 surface landed (#623).
|
|
1386
|
+
!!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);
|
|
1387
|
+
}
|
|
1388
|
+
arraysEqual(a, b) {
|
|
1389
|
+
const aa = a ?? [];
|
|
1390
|
+
const bb = b ?? [];
|
|
1391
|
+
return aa.length === bb.length && aa.every((v, i) => v === bb[i]);
|
|
1356
1392
|
}
|
|
1357
1393
|
};
|
|
1358
1394
|
|
|
@@ -1366,7 +1402,7 @@ import {
|
|
|
1366
1402
|
LITE_PARSER_TEMPLATE,
|
|
1367
1403
|
HYBRID_PARSER_TEMPLATE,
|
|
1368
1404
|
canUseLiteParser,
|
|
1369
|
-
FULL_RUNTIME_ONLY_COMMANDS,
|
|
1405
|
+
FULL_RUNTIME_ONLY_COMMANDS as FULL_RUNTIME_ONLY_COMMANDS2,
|
|
1370
1406
|
isAvailableCommand
|
|
1371
1407
|
} from "@hyperfixi/core/bundle-generator";
|
|
1372
1408
|
|
|
@@ -2460,7 +2496,7 @@ ${additionalApiProps}`
|
|
|
2460
2496
|
getUnsupportedCommands(commands) {
|
|
2461
2497
|
const unsupported = [];
|
|
2462
2498
|
for (const cmd of commands) {
|
|
2463
|
-
if (
|
|
2499
|
+
if (FULL_RUNTIME_ONLY_COMMANDS2.includes(cmd)) {
|
|
2464
2500
|
unsupported.push(cmd);
|
|
2465
2501
|
} else if (!isAvailableCommand(cmd) && !COMMAND_IMPLEMENTATIONS[cmd]) {
|
|
2466
2502
|
unsupported.push(cmd);
|
|
@@ -3751,6 +3787,22 @@ var DomainAggregator = class {
|
|
|
3751
3787
|
var VIRTUAL_MODULE_ID = "virtual:hyperfixi";
|
|
3752
3788
|
var RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
|
|
3753
3789
|
var IMPORT_ALIASES = ["hyperfixi", "@hyperfixi/core", "virtual:hyperfixi"];
|
|
3790
|
+
function computeUsageHash(usage) {
|
|
3791
|
+
const commands = [...usage.commands].sort().join(",");
|
|
3792
|
+
const blocks = [...usage.blocks].sort().join(",");
|
|
3793
|
+
const languages = [...usage.detectedLanguages].sort().join(",");
|
|
3794
|
+
const htmx = usage.htmx ? [
|
|
3795
|
+
usage.htmx.hasHtmxAttributes,
|
|
3796
|
+
usage.htmx.hasFixiAttributes,
|
|
3797
|
+
usage.htmx.needsHxLive,
|
|
3798
|
+
usage.htmx.needsSSE,
|
|
3799
|
+
usage.htmx.needsWS,
|
|
3800
|
+
usage.htmx.needsBindToProperty,
|
|
3801
|
+
usage.htmx.needsReactivity
|
|
3802
|
+
].map((f) => f ? "1" : "0").join("") : "none";
|
|
3803
|
+
const reactivity = `${usage.needsReactivity ? 1 : 0}${usage.needsBindToProperty ? 1 : 0}`;
|
|
3804
|
+
return `${commands}|${blocks}|${usage.positional}|${languages}|${htmx}|${reactivity}`;
|
|
3805
|
+
}
|
|
3754
3806
|
function hyperfixi(options = {}) {
|
|
3755
3807
|
const mode = options.mode ?? "interpret";
|
|
3756
3808
|
const scanner = new Scanner(options);
|
|
@@ -3767,12 +3819,6 @@ function hyperfixi(options = {}) {
|
|
|
3767
3819
|
const fallbackScripts = /* @__PURE__ */ new Set();
|
|
3768
3820
|
let needsLocals = false;
|
|
3769
3821
|
let needsGlobals = false;
|
|
3770
|
-
function computeUsageHash(usage) {
|
|
3771
|
-
const commands = [...usage.commands].sort().join(",");
|
|
3772
|
-
const blocks = [...usage.blocks].sort().join(",");
|
|
3773
|
-
const languages = [...usage.detectedLanguages].sort().join(",");
|
|
3774
|
-
return `${commands}|${blocks}|${usage.positional}|${languages}`;
|
|
3775
|
-
}
|
|
3776
3822
|
function invalidateVirtualModule() {
|
|
3777
3823
|
if (!server) return;
|
|
3778
3824
|
const mod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_MODULE_ID);
|
|
@@ -4072,6 +4118,7 @@ export {
|
|
|
4072
4118
|
SUPPORTED_LANGUAGES,
|
|
4073
4119
|
clearCustomKeywords,
|
|
4074
4120
|
clearSemanticParser,
|
|
4121
|
+
computeUsageHash,
|
|
4075
4122
|
index_default as default,
|
|
4076
4123
|
descriptorToScanRule,
|
|
4077
4124
|
detectLanguages,
|