@lokascript/vite-plugin 1.0.0 → 1.1.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.cjs CHANGED
@@ -840,6 +840,15 @@ function getOptimalRegion(languages) {
840
840
  }
841
841
 
842
842
  // src/scanner.ts
843
+ var HTMX_REQUEST_PATTERN = /\b(hx-get|hx-post|hx-put|hx-patch|hx-delete)\s*=\s*["']([^"']+)["']/gi;
844
+ var FIXI_ACTION_PATTERN = /\bfx-action\s*=\s*["']([^"']+)["']/gi;
845
+ var FIXI_METHOD_PATTERN = /\bfx-method\s*=\s*["'](GET|POST|PUT|PATCH|DELETE)["']/gi;
846
+ var HTMX_SWAP_PATTERN = /\b(hx-swap|fx-swap)\s*=\s*["']([^"']+)["']/gi;
847
+ var HTMX_TARGET_PATTERN = /\b(hx-target|fx-target)\s*=\s*["']([^"']+)["']/gi;
848
+ var HTMX_TRIGGER_PATTERN = /\b(hx-trigger|fx-trigger)\s*=\s*["']([^"']+)["']/gi;
849
+ var HTMX_URL_PATTERN = /\b(hx-push-url|hx-replace-url)\s*=\s*["'][^"']+["']/gi;
850
+ var HTMX_CONFIRM_PATTERN = /\bhx-confirm\s*=\s*["']/gi;
851
+ var HTMX_ON_PATTERN = /\bhx-on:(\w+)\s*=\s*["']([^"']+)["']/g;
843
852
  function toRegex(pattern, defaultPattern) {
844
853
  if (!pattern) return defaultPattern;
845
854
  if (pattern instanceof RegExp) return pattern;
@@ -897,12 +906,29 @@ var Scanner = class {
897
906
  while (match = scriptPattern.exec(code)) {
898
907
  this.analyzeScript(match[1], usage);
899
908
  }
900
- if (this.debug && (usage.commands.size > 0 || usage.blocks.size > 0 || usage.detectedLanguages.size > 0)) {
909
+ const htmxUsage = this.scanHtmxAttributes(code);
910
+ if (htmxUsage.hasHtmxAttributes) {
911
+ usage.htmx = htmxUsage;
912
+ this.inferCommandsFromHtmx(htmxUsage, usage);
913
+ for (const handlerCode of htmxUsage.onHandlers) {
914
+ this.analyzeScript(handlerCode, usage);
915
+ }
916
+ if (/hx-target\s*=\s*["'](closest|next|previous|find)\s/i.test(code)) {
917
+ usage.positional = true;
918
+ }
919
+ }
920
+ if (this.debug && (usage.commands.size > 0 || usage.blocks.size > 0 || usage.detectedLanguages.size > 0 || usage.htmx?.hasHtmxAttributes)) {
901
921
  console.log(`[hyperfixi] Scanned ${id}:`, {
902
922
  commands: [...usage.commands],
903
923
  blocks: [...usage.blocks],
904
924
  positional: usage.positional,
905
- languages: [...usage.detectedLanguages]
925
+ languages: [...usage.detectedLanguages],
926
+ htmx: usage.htmx ? {
927
+ hasHtmxAttributes: usage.htmx.hasHtmxAttributes,
928
+ hasFixiAttributes: usage.htmx.hasFixiAttributes,
929
+ httpMethods: [...usage.htmx.httpMethods],
930
+ swapStrategies: [...usage.htmx.swapStrategies]
931
+ } : void 0
906
932
  });
907
933
  }
908
934
  return usage;
@@ -930,6 +956,93 @@ var Scanner = class {
930
956
  usage.detectedLanguages.add(lang);
931
957
  }
932
958
  }
959
+ /**
960
+ * Scan for htmx/fixi attributes
961
+ */
962
+ scanHtmxAttributes(code) {
963
+ const usage = {
964
+ hasHtmxAttributes: false,
965
+ hasFixiAttributes: false,
966
+ httpMethods: /* @__PURE__ */ new Set(),
967
+ swapStrategies: /* @__PURE__ */ new Set(),
968
+ onHandlers: [],
969
+ triggerModifiers: /* @__PURE__ */ new Set(),
970
+ urlManagement: /* @__PURE__ */ new Set(),
971
+ usesConfirm: false
972
+ };
973
+ let match;
974
+ const requestPattern = new RegExp(HTMX_REQUEST_PATTERN.source, "gi");
975
+ while (match = requestPattern.exec(code)) {
976
+ usage.hasHtmxAttributes = true;
977
+ usage.httpMethods.add(match[1].replace("hx-", "").toUpperCase());
978
+ }
979
+ if (new RegExp(FIXI_ACTION_PATTERN.source, "gi").test(code)) {
980
+ usage.hasHtmxAttributes = true;
981
+ usage.hasFixiAttributes = true;
982
+ }
983
+ const fixiMethodPattern = new RegExp(FIXI_METHOD_PATTERN.source, "gi");
984
+ while (match = fixiMethodPattern.exec(code)) {
985
+ usage.hasHtmxAttributes = true;
986
+ usage.hasFixiAttributes = true;
987
+ usage.httpMethods.add(match[1].toUpperCase());
988
+ }
989
+ const swapPattern = new RegExp(HTMX_SWAP_PATTERN.source, "gi");
990
+ while (match = swapPattern.exec(code)) {
991
+ usage.hasHtmxAttributes = true;
992
+ usage.swapStrategies.add(match[2].split(/\s+/)[0]);
993
+ }
994
+ const triggerPattern = new RegExp(HTMX_TRIGGER_PATTERN.source, "gi");
995
+ while (match = triggerPattern.exec(code)) {
996
+ usage.hasHtmxAttributes = true;
997
+ const trigger = match[2];
998
+ if (/delay:/i.test(trigger)) usage.triggerModifiers.add("debounce");
999
+ if (/throttle:/i.test(trigger)) usage.triggerModifiers.add("throttle");
1000
+ if (/\bonce\b/i.test(trigger)) usage.triggerModifiers.add("once");
1001
+ }
1002
+ if (new RegExp(HTMX_URL_PATTERN.source, "gi").test(code)) {
1003
+ usage.hasHtmxAttributes = true;
1004
+ if (/hx-push-url/i.test(code)) usage.urlManagement.add("push-url");
1005
+ if (/hx-replace-url/i.test(code)) usage.urlManagement.add("replace-url");
1006
+ }
1007
+ if (new RegExp(HTMX_CONFIRM_PATTERN.source, "gi").test(code)) {
1008
+ usage.hasHtmxAttributes = true;
1009
+ usage.usesConfirm = true;
1010
+ }
1011
+ const onPattern = new RegExp(HTMX_ON_PATTERN.source, "g");
1012
+ while (match = onPattern.exec(code)) {
1013
+ usage.hasHtmxAttributes = true;
1014
+ usage.onHandlers.push(match[2]);
1015
+ }
1016
+ const targetPattern = new RegExp(HTMX_TARGET_PATTERN.source, "gi");
1017
+ while (match = targetPattern.exec(code)) {
1018
+ usage.hasHtmxAttributes = true;
1019
+ }
1020
+ return usage;
1021
+ }
1022
+ /**
1023
+ * Infer commands from htmx usage
1024
+ */
1025
+ inferCommandsFromHtmx(htmx, usage) {
1026
+ if (htmx.httpMethods.size > 0) {
1027
+ usage.blocks.add("fetch");
1028
+ usage.commands.add("put");
1029
+ }
1030
+ for (const swap of htmx.swapStrategies) {
1031
+ switch (swap.toLowerCase()) {
1032
+ case "morph":
1033
+ usage.commands.add("morph");
1034
+ break;
1035
+ case "delete":
1036
+ usage.commands.add("remove");
1037
+ break;
1038
+ default:
1039
+ usage.commands.add("put");
1040
+ }
1041
+ }
1042
+ if (htmx.usesConfirm) {
1043
+ usage.blocks.add("if");
1044
+ }
1045
+ }
933
1046
  /**
934
1047
  * Scan all files in a project directory
935
1048
  * Used during production build to scan the entire codebase
@@ -980,7 +1093,8 @@ var Aggregator = class {
980
1093
  const blocksEqual = this.setsEqual(existing.blocks, usage.blocks);
981
1094
  const positionalEqual = existing.positional === usage.positional;
982
1095
  const languagesEqual = this.setsEqual(existing.detectedLanguages, usage.detectedLanguages);
983
- if (commandsEqual && blocksEqual && positionalEqual && languagesEqual) {
1096
+ const htmxEqual = this.htmxUsageEqual(existing.htmx, usage.htmx);
1097
+ if (commandsEqual && blocksEqual && positionalEqual && languagesEqual && htmxEqual) {
984
1098
  return false;
985
1099
  }
986
1100
  }
@@ -1010,17 +1124,38 @@ var Aggregator = class {
1010
1124
  const blocks = /* @__PURE__ */ new Set();
1011
1125
  const detectedLanguages = /* @__PURE__ */ new Set();
1012
1126
  let positional = false;
1127
+ const htmx = {
1128
+ hasHtmxAttributes: false,
1129
+ hasFixiAttributes: false,
1130
+ httpMethods: /* @__PURE__ */ new Set(),
1131
+ swapStrategies: /* @__PURE__ */ new Set(),
1132
+ onHandlers: [],
1133
+ triggerModifiers: /* @__PURE__ */ new Set(),
1134
+ urlManagement: /* @__PURE__ */ new Set(),
1135
+ usesConfirm: false
1136
+ };
1013
1137
  for (const usage of this.fileUsage.values()) {
1014
1138
  for (const cmd of usage.commands) commands.add(cmd);
1015
1139
  for (const block of usage.blocks) blocks.add(block);
1016
1140
  for (const lang of usage.detectedLanguages) detectedLanguages.add(lang);
1017
1141
  if (usage.positional) positional = true;
1142
+ if (usage.htmx) {
1143
+ if (usage.htmx.hasHtmxAttributes) htmx.hasHtmxAttributes = true;
1144
+ if (usage.htmx.hasFixiAttributes) htmx.hasFixiAttributes = true;
1145
+ for (const method of usage.htmx.httpMethods) htmx.httpMethods.add(method);
1146
+ for (const swap of usage.htmx.swapStrategies) htmx.swapStrategies.add(swap);
1147
+ htmx.onHandlers.push(...usage.htmx.onHandlers);
1148
+ for (const modifier of usage.htmx.triggerModifiers) htmx.triggerModifiers.add(modifier);
1149
+ for (const url of usage.htmx.urlManagement) htmx.urlManagement.add(url);
1150
+ if (usage.htmx.usesConfirm) htmx.usesConfirm = true;
1151
+ }
1018
1152
  }
1019
1153
  this.cachedUsage = {
1020
1154
  commands,
1021
1155
  blocks,
1022
1156
  positional,
1023
1157
  detectedLanguages,
1158
+ htmx,
1024
1159
  fileUsage: new Map(this.fileUsage)
1025
1160
  };
1026
1161
  return this.cachedUsage;
@@ -1069,6 +1204,14 @@ var Aggregator = class {
1069
1204
  }
1070
1205
  return true;
1071
1206
  }
1207
+ /**
1208
+ * Compare two HtmxUsage objects for equality
1209
+ */
1210
+ htmxUsageEqual(a, b) {
1211
+ if (!a && !b) return true;
1212
+ if (!a || !b) return false;
1213
+ 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;
1214
+ }
1072
1215
  };
1073
1216
 
1074
1217
  // src/generator.ts
@@ -1938,7 +2081,7 @@ var Generator = class {
1938
2081
  commands,
1939
2082
  blocks,
1940
2083
  positionalExpressions: positional,
1941
- htmxIntegration: options.htmx ?? false,
2084
+ htmxIntegration: options.htmx ?? usage.htmx?.hasHtmxAttributes ?? false,
1942
2085
  globalName: options.globalName ?? "hyperfixi",
1943
2086
  // Use @lokascript/core package path for virtual module
1944
2087
  parserImportPath: "@lokascript/core/parser/hybrid",