@lokascript/vite-plugin 1.0.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 +345 -0
- package/dist/index.cjs +3272 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +379 -0
- package/dist/index.d.ts +379 -0
- package/dist/index.js +3228 -0
- package/dist/index.js.map +1 -0
- package/package.json +67 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,3272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
REGIONS: () => REGIONS,
|
|
34
|
+
SUPPORTED_LANGUAGES: () => SUPPORTED_LANGUAGES,
|
|
35
|
+
clearCustomKeywords: () => clearCustomKeywords,
|
|
36
|
+
clearSemanticParser: () => clearSemanticParser,
|
|
37
|
+
default: () => index_default,
|
|
38
|
+
detectLanguages: () => detectLanguages,
|
|
39
|
+
getAllLanguageCodes: () => getAllLanguageCodes,
|
|
40
|
+
getKeywordsForLanguage: () => getKeywordsForLanguage,
|
|
41
|
+
getOptimalRegion: () => getOptimalRegion,
|
|
42
|
+
hasSemanticParser: () => hasSemanticParser,
|
|
43
|
+
hyperfixi: () => hyperfixi,
|
|
44
|
+
isNonLatinLanguage: () => isNonLatinLanguage,
|
|
45
|
+
registerCustomKeywords: () => registerCustomKeywords,
|
|
46
|
+
setSemanticParser: () => setSemanticParser
|
|
47
|
+
});
|
|
48
|
+
module.exports = __toCommonJS(index_exports);
|
|
49
|
+
|
|
50
|
+
// src/language-keywords.ts
|
|
51
|
+
var SUPPORTED_LANGUAGES = [
|
|
52
|
+
"en",
|
|
53
|
+
"es",
|
|
54
|
+
"pt",
|
|
55
|
+
"fr",
|
|
56
|
+
"de",
|
|
57
|
+
"it",
|
|
58
|
+
"vi",
|
|
59
|
+
// Western (Latin script)
|
|
60
|
+
"pl",
|
|
61
|
+
"ru",
|
|
62
|
+
"uk",
|
|
63
|
+
// Slavic (Latin/Cyrillic)
|
|
64
|
+
"ja",
|
|
65
|
+
"zh",
|
|
66
|
+
"ko",
|
|
67
|
+
// East Asian
|
|
68
|
+
"ar",
|
|
69
|
+
// RTL (Arabic script)
|
|
70
|
+
"hi",
|
|
71
|
+
"bn",
|
|
72
|
+
// South Asian (Indic scripts)
|
|
73
|
+
"th",
|
|
74
|
+
// Southeast Asian (Thai script)
|
|
75
|
+
"tr",
|
|
76
|
+
// Agglutinative Latin
|
|
77
|
+
"id",
|
|
78
|
+
"sw",
|
|
79
|
+
"qu",
|
|
80
|
+
// Other
|
|
81
|
+
"tl"
|
|
82
|
+
// Tagalog (auto-added)
|
|
83
|
+
];
|
|
84
|
+
var REGIONS = {
|
|
85
|
+
western: ["en", "es", "pt", "fr", "de", "it"],
|
|
86
|
+
"east-asian": ["ja", "zh", "ko"],
|
|
87
|
+
slavic: ["pl", "ru", "uk"],
|
|
88
|
+
"south-asian": ["hi", "bn"],
|
|
89
|
+
priority: [
|
|
90
|
+
"en",
|
|
91
|
+
"es",
|
|
92
|
+
"pt",
|
|
93
|
+
"fr",
|
|
94
|
+
"de",
|
|
95
|
+
"it",
|
|
96
|
+
"ja",
|
|
97
|
+
"zh",
|
|
98
|
+
"ko",
|
|
99
|
+
"ar",
|
|
100
|
+
"tr",
|
|
101
|
+
"ru",
|
|
102
|
+
"hi"
|
|
103
|
+
],
|
|
104
|
+
all: SUPPORTED_LANGUAGES
|
|
105
|
+
};
|
|
106
|
+
var JAPANESE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
107
|
+
"\u5207\u308A\u66FF\u3048",
|
|
108
|
+
"\u5207\u308A\u66FF\u3048\u308B",
|
|
109
|
+
"\u30C8\u30B0\u30EB",
|
|
110
|
+
"\u30C8\u30B0\u30EB\u3059\u308B",
|
|
111
|
+
"\u8FFD\u52A0",
|
|
112
|
+
"\u8FFD\u52A0\u3059\u308B",
|
|
113
|
+
"\u52A0\u3048\u308B",
|
|
114
|
+
"\u524A\u9664",
|
|
115
|
+
"\u524A\u9664\u3059\u308B",
|
|
116
|
+
"\u53D6\u308A\u9664\u304F",
|
|
117
|
+
"\u8868\u793A",
|
|
118
|
+
"\u8868\u793A\u3059\u308B",
|
|
119
|
+
"\u898B\u305B\u308B",
|
|
120
|
+
"\u96A0\u3059",
|
|
121
|
+
"\u975E\u8868\u793A",
|
|
122
|
+
"\u975E\u8868\u793A\u306B\u3059\u308B",
|
|
123
|
+
"\u8A2D\u5B9A",
|
|
124
|
+
"\u8A2D\u5B9A\u3059\u308B",
|
|
125
|
+
"\u30BB\u30C3\u30C8",
|
|
126
|
+
"\u5897\u52A0",
|
|
127
|
+
"\u5897\u3084\u3059",
|
|
128
|
+
"\u30A4\u30F3\u30AF\u30EA\u30E1\u30F3\u30C8",
|
|
129
|
+
"\u6E1B\u5C11",
|
|
130
|
+
"\u6E1B\u3089\u3059",
|
|
131
|
+
"\u30C7\u30AF\u30EA\u30E1\u30F3\u30C8",
|
|
132
|
+
"\u5F15\u304D\u91D1",
|
|
133
|
+
"\u767A\u706B",
|
|
134
|
+
"\u30C8\u30EA\u30AC\u30FC",
|
|
135
|
+
"\u9001\u308B",
|
|
136
|
+
"\u9001\u4FE1",
|
|
137
|
+
"\u3082\u3057",
|
|
138
|
+
"\u6761\u4EF6",
|
|
139
|
+
"\u305D\u3046\u3067\u306A\u3051\u308C\u3070",
|
|
140
|
+
"\u305D\u308C\u4EE5\u5916",
|
|
141
|
+
"\u7E70\u308A\u8FD4\u3057",
|
|
142
|
+
"\u7E70\u308A\u8FD4\u3059",
|
|
143
|
+
"\u30EA\u30D4\u30FC\u30C8",
|
|
144
|
+
"\u5F85\u3064",
|
|
145
|
+
"\u5F85\u6A5F",
|
|
146
|
+
"\u306E\u9593",
|
|
147
|
+
"\u9593"
|
|
148
|
+
]);
|
|
149
|
+
var KOREAN_KEYWORDS = /* @__PURE__ */ new Set([
|
|
150
|
+
"\uD1A0\uAE00",
|
|
151
|
+
"\uC804\uD658",
|
|
152
|
+
"\uCD94\uAC00",
|
|
153
|
+
"\uC81C\uAC70",
|
|
154
|
+
"\uC0AD\uC81C",
|
|
155
|
+
"\uBCF4\uC774\uB2E4",
|
|
156
|
+
"\uD45C\uC2DC",
|
|
157
|
+
"\uBCF4\uC774\uAE30",
|
|
158
|
+
"\uC228\uAE30\uB2E4",
|
|
159
|
+
"\uC228\uAE30\uAE30",
|
|
160
|
+
"\uC124\uC815",
|
|
161
|
+
"\uC99D\uAC00",
|
|
162
|
+
"\uAC10\uC18C",
|
|
163
|
+
"\uD2B8\uB9AC\uAC70",
|
|
164
|
+
"\uBCF4\uB0B4\uB2E4",
|
|
165
|
+
"\uB9CC\uC57D",
|
|
166
|
+
"\uC544\uB2C8\uBA74",
|
|
167
|
+
"\uBC18\uBCF5",
|
|
168
|
+
"\uB300\uAE30",
|
|
169
|
+
"\uB3D9\uC548"
|
|
170
|
+
]);
|
|
171
|
+
var CHINESE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
172
|
+
"\u5207\u6362",
|
|
173
|
+
"\u6DFB\u52A0",
|
|
174
|
+
"\u52A0",
|
|
175
|
+
"\u79FB\u9664",
|
|
176
|
+
"\u5220\u9664",
|
|
177
|
+
"\u53BB\u6389",
|
|
178
|
+
"\u663E\u793A",
|
|
179
|
+
"\u5C55\u793A",
|
|
180
|
+
"\u9690\u85CF",
|
|
181
|
+
"\u8BBE\u7F6E",
|
|
182
|
+
"\u8BBE\u5B9A",
|
|
183
|
+
"\u589E\u52A0",
|
|
184
|
+
"\u51CF\u5C11",
|
|
185
|
+
"\u89E6\u53D1",
|
|
186
|
+
"\u53D1\u9001",
|
|
187
|
+
"\u5982\u679C",
|
|
188
|
+
"\u5426\u5219",
|
|
189
|
+
"\u91CD\u590D",
|
|
190
|
+
"\u7B49\u5F85",
|
|
191
|
+
"\u5F53"
|
|
192
|
+
]);
|
|
193
|
+
var ARABIC_KEYWORDS = /* @__PURE__ */ new Set([
|
|
194
|
+
"\u0628\u062F\u0644",
|
|
195
|
+
"\u0628\u062F\u0651\u0644",
|
|
196
|
+
"\u063A\u064A\u0651\u0631",
|
|
197
|
+
"\u063A\u064A\u0631",
|
|
198
|
+
"\u0623\u0636\u0641",
|
|
199
|
+
"\u0627\u0636\u0641",
|
|
200
|
+
"\u0632\u0650\u062F",
|
|
201
|
+
"\u0627\u062D\u0630\u0641",
|
|
202
|
+
"\u0623\u0632\u0644",
|
|
203
|
+
"\u0627\u0645\u0633\u062D",
|
|
204
|
+
"\u0627\u0638\u0647\u0631",
|
|
205
|
+
"\u0623\u0638\u0647\u0631",
|
|
206
|
+
"\u0627\u0639\u0631\u0636",
|
|
207
|
+
"\u0627\u062E\u0641",
|
|
208
|
+
"\u0623\u062E\u0641\u0650",
|
|
209
|
+
"\u0627\u062E\u0641\u064A",
|
|
210
|
+
"\u0627\u0636\u0628\u0637",
|
|
211
|
+
"\u0639\u064A\u0651\u0646",
|
|
212
|
+
"\u062D\u062F\u062F",
|
|
213
|
+
"\u0627\u0631\u0641\u0639",
|
|
214
|
+
"\u0623\u0646\u0642\u0635",
|
|
215
|
+
"\u0642\u0644\u0644",
|
|
216
|
+
"\u062A\u0634\u063A\u064A\u0644",
|
|
217
|
+
"\u0623\u0637\u0644\u0642",
|
|
218
|
+
"\u0641\u0639\u0651\u0644",
|
|
219
|
+
"\u0623\u0631\u0633\u0644",
|
|
220
|
+
"\u0625\u0630\u0627",
|
|
221
|
+
"\u0648\u0625\u0644\u0627",
|
|
222
|
+
"\u062E\u0644\u0627\u0641 \u0630\u0644\u0643",
|
|
223
|
+
"\u0643\u0631\u0631",
|
|
224
|
+
"\u0627\u0646\u062A\u0638\u0631",
|
|
225
|
+
"\u0628\u064A\u0646\u0645\u0627"
|
|
226
|
+
]);
|
|
227
|
+
var SPANISH_KEYWORDS = /* @__PURE__ */ new Set([
|
|
228
|
+
"alternar",
|
|
229
|
+
"cambiar",
|
|
230
|
+
"conmutar",
|
|
231
|
+
"agregar",
|
|
232
|
+
"a\xF1adir",
|
|
233
|
+
"quitar",
|
|
234
|
+
"eliminar",
|
|
235
|
+
"remover",
|
|
236
|
+
"sacar",
|
|
237
|
+
"mostrar",
|
|
238
|
+
"ense\xF1ar",
|
|
239
|
+
"ocultar",
|
|
240
|
+
"esconder",
|
|
241
|
+
"establecer",
|
|
242
|
+
"fijar",
|
|
243
|
+
"definir",
|
|
244
|
+
"incrementar",
|
|
245
|
+
"aumentar",
|
|
246
|
+
"decrementar",
|
|
247
|
+
"disminuir",
|
|
248
|
+
"disparar",
|
|
249
|
+
"activar",
|
|
250
|
+
"enviar",
|
|
251
|
+
"si",
|
|
252
|
+
"sino",
|
|
253
|
+
"de lo contrario",
|
|
254
|
+
"repetir",
|
|
255
|
+
"esperar",
|
|
256
|
+
"mientras"
|
|
257
|
+
]);
|
|
258
|
+
var PORTUGUESE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
259
|
+
"alternar",
|
|
260
|
+
"trocar",
|
|
261
|
+
"adicionar",
|
|
262
|
+
"acrescentar",
|
|
263
|
+
"remover",
|
|
264
|
+
"eliminar",
|
|
265
|
+
"apagar",
|
|
266
|
+
"mostrar",
|
|
267
|
+
"exibir",
|
|
268
|
+
"ocultar",
|
|
269
|
+
"esconder",
|
|
270
|
+
"definir",
|
|
271
|
+
"configurar",
|
|
272
|
+
"incrementar",
|
|
273
|
+
"aumentar",
|
|
274
|
+
"decrementar",
|
|
275
|
+
"diminuir",
|
|
276
|
+
"disparar",
|
|
277
|
+
"ativar",
|
|
278
|
+
"enviar",
|
|
279
|
+
"se",
|
|
280
|
+
"sen\xE3o",
|
|
281
|
+
"repetir",
|
|
282
|
+
"esperar",
|
|
283
|
+
"aguardar",
|
|
284
|
+
"enquanto"
|
|
285
|
+
]);
|
|
286
|
+
var FRENCH_KEYWORDS = /* @__PURE__ */ new Set([
|
|
287
|
+
"basculer",
|
|
288
|
+
"permuter",
|
|
289
|
+
"alterner",
|
|
290
|
+
"ajouter",
|
|
291
|
+
"supprimer",
|
|
292
|
+
"enlever",
|
|
293
|
+
"retirer",
|
|
294
|
+
"montrer",
|
|
295
|
+
"afficher",
|
|
296
|
+
"cacher",
|
|
297
|
+
"masquer",
|
|
298
|
+
"d\xE9finir",
|
|
299
|
+
"\xE9tablir",
|
|
300
|
+
"incr\xE9menter",
|
|
301
|
+
"augmenter",
|
|
302
|
+
"d\xE9cr\xE9menter",
|
|
303
|
+
"diminuer",
|
|
304
|
+
"d\xE9clencher",
|
|
305
|
+
"envoyer",
|
|
306
|
+
"si",
|
|
307
|
+
"sinon",
|
|
308
|
+
"r\xE9p\xE9ter",
|
|
309
|
+
"attendre",
|
|
310
|
+
"pendant"
|
|
311
|
+
]);
|
|
312
|
+
var GERMAN_KEYWORDS = /* @__PURE__ */ new Set([
|
|
313
|
+
"umschalten",
|
|
314
|
+
"wechseln",
|
|
315
|
+
"hinzuf\xFCgen",
|
|
316
|
+
"entfernen",
|
|
317
|
+
"l\xF6schen",
|
|
318
|
+
"zeigen",
|
|
319
|
+
"anzeigen",
|
|
320
|
+
"verbergen",
|
|
321
|
+
"verstecken",
|
|
322
|
+
"festlegen",
|
|
323
|
+
"definieren",
|
|
324
|
+
"erh\xF6hen",
|
|
325
|
+
"verringern",
|
|
326
|
+
"vermindern",
|
|
327
|
+
"ausl\xF6sen",
|
|
328
|
+
"senden",
|
|
329
|
+
"schicken",
|
|
330
|
+
"wenn",
|
|
331
|
+
"falls",
|
|
332
|
+
"sonst",
|
|
333
|
+
"ansonsten",
|
|
334
|
+
"wiederholen",
|
|
335
|
+
"warten",
|
|
336
|
+
"solange",
|
|
337
|
+
"w\xE4hrend"
|
|
338
|
+
]);
|
|
339
|
+
var TURKISH_KEYWORDS = /* @__PURE__ */ new Set([
|
|
340
|
+
"de\u011Fi\u015Ftir",
|
|
341
|
+
"a\xE7/kapat",
|
|
342
|
+
"ekle",
|
|
343
|
+
"kald\u0131r",
|
|
344
|
+
"sil",
|
|
345
|
+
"g\xF6ster",
|
|
346
|
+
"gizle",
|
|
347
|
+
"ayarla",
|
|
348
|
+
"yap",
|
|
349
|
+
"belirle",
|
|
350
|
+
"art\u0131r",
|
|
351
|
+
"azalt",
|
|
352
|
+
"tetikle",
|
|
353
|
+
"g\xF6nder",
|
|
354
|
+
"e\u011Fer",
|
|
355
|
+
"yoksa",
|
|
356
|
+
"tekrarla",
|
|
357
|
+
"bekle",
|
|
358
|
+
"iken"
|
|
359
|
+
]);
|
|
360
|
+
var INDONESIAN_KEYWORDS = /* @__PURE__ */ new Set([
|
|
361
|
+
"alihkan",
|
|
362
|
+
"ganti",
|
|
363
|
+
"tukar",
|
|
364
|
+
"tambah",
|
|
365
|
+
"tambahkan",
|
|
366
|
+
"hapus",
|
|
367
|
+
"buang",
|
|
368
|
+
"hilangkan",
|
|
369
|
+
"tampilkan",
|
|
370
|
+
"perlihatkan",
|
|
371
|
+
"sembunyikan",
|
|
372
|
+
"tutup",
|
|
373
|
+
"atur",
|
|
374
|
+
"tetapkan",
|
|
375
|
+
"tingkatkan",
|
|
376
|
+
"naikkan",
|
|
377
|
+
"turunkan",
|
|
378
|
+
"kurangi",
|
|
379
|
+
"picu",
|
|
380
|
+
"jalankan",
|
|
381
|
+
"kirim",
|
|
382
|
+
"kirimkan",
|
|
383
|
+
"jika",
|
|
384
|
+
"kalau",
|
|
385
|
+
"bila",
|
|
386
|
+
"selainnya",
|
|
387
|
+
"ulangi",
|
|
388
|
+
"tunggu",
|
|
389
|
+
"selama"
|
|
390
|
+
]);
|
|
391
|
+
var SWAHILI_KEYWORDS = /* @__PURE__ */ new Set([
|
|
392
|
+
"badilisha",
|
|
393
|
+
"geuza",
|
|
394
|
+
"ongeza",
|
|
395
|
+
"weka",
|
|
396
|
+
"ondoa",
|
|
397
|
+
"futa",
|
|
398
|
+
"toa",
|
|
399
|
+
"onyesha",
|
|
400
|
+
"ficha",
|
|
401
|
+
"mficho",
|
|
402
|
+
"seti",
|
|
403
|
+
"punguza",
|
|
404
|
+
"chochea",
|
|
405
|
+
"anzisha",
|
|
406
|
+
"tuma",
|
|
407
|
+
"peleka",
|
|
408
|
+
"kama",
|
|
409
|
+
"ikiwa",
|
|
410
|
+
"vinginevyo",
|
|
411
|
+
"sivyo",
|
|
412
|
+
"rudia",
|
|
413
|
+
"subiri",
|
|
414
|
+
"ngoja",
|
|
415
|
+
"wakati"
|
|
416
|
+
]);
|
|
417
|
+
var QUECHUA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
418
|
+
"t",
|
|
419
|
+
"tikray",
|
|
420
|
+
"kutichiy",
|
|
421
|
+
"yapay",
|
|
422
|
+
"yapaykuy",
|
|
423
|
+
"qichuy",
|
|
424
|
+
"hurquy",
|
|
425
|
+
"anchuchiy",
|
|
426
|
+
"rikuchiy",
|
|
427
|
+
"qawachiy",
|
|
428
|
+
"pakay",
|
|
429
|
+
"pakakuy",
|
|
430
|
+
"churay",
|
|
431
|
+
"kamaykuy",
|
|
432
|
+
"yapachiy",
|
|
433
|
+
"pisiyachiy",
|
|
434
|
+
"qallarichiy",
|
|
435
|
+
"kachay",
|
|
436
|
+
"apachiy",
|
|
437
|
+
"sichus",
|
|
438
|
+
"manachus",
|
|
439
|
+
"hukniraq",
|
|
440
|
+
"kutipay",
|
|
441
|
+
"muyu",
|
|
442
|
+
"suyay",
|
|
443
|
+
"kaykamaqa"
|
|
444
|
+
]);
|
|
445
|
+
var ITALIAN_KEYWORDS = /* @__PURE__ */ new Set([
|
|
446
|
+
"commutare",
|
|
447
|
+
"alternare",
|
|
448
|
+
"cambiare",
|
|
449
|
+
"aggiungere",
|
|
450
|
+
"aggiungi",
|
|
451
|
+
"rimuovere",
|
|
452
|
+
"eliminare",
|
|
453
|
+
"togliere",
|
|
454
|
+
"mostrare",
|
|
455
|
+
"visualizzare",
|
|
456
|
+
"nascondere",
|
|
457
|
+
"impostare",
|
|
458
|
+
"definire",
|
|
459
|
+
"incrementare",
|
|
460
|
+
"aumentare",
|
|
461
|
+
"decrementare",
|
|
462
|
+
"diminuire",
|
|
463
|
+
"scatenare",
|
|
464
|
+
"attivare",
|
|
465
|
+
"inviare",
|
|
466
|
+
"se",
|
|
467
|
+
"altrimenti",
|
|
468
|
+
"ripetere",
|
|
469
|
+
"aspettare",
|
|
470
|
+
"attendere",
|
|
471
|
+
"mentre"
|
|
472
|
+
]);
|
|
473
|
+
var VIETNAMESE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
474
|
+
"chuy\u1EC3n \u0111\u1ED5i",
|
|
475
|
+
"b\u1EADt t\u1EAFt",
|
|
476
|
+
"chuy\u1EC3n",
|
|
477
|
+
"th\xEAm",
|
|
478
|
+
"b\u1ED5 sung",
|
|
479
|
+
"x\xF3a",
|
|
480
|
+
"g\u1EE1 b\u1ECF",
|
|
481
|
+
"lo\u1EA1i b\u1ECF",
|
|
482
|
+
"b\u1ECF",
|
|
483
|
+
"hi\u1EC3n th\u1ECB",
|
|
484
|
+
"hi\u1EC7n",
|
|
485
|
+
"\u1EA9n",
|
|
486
|
+
"che",
|
|
487
|
+
"gi\u1EA5u",
|
|
488
|
+
"g\xE1n",
|
|
489
|
+
"thi\u1EBFt l\u1EADp",
|
|
490
|
+
"\u0111\u1EB7t",
|
|
491
|
+
"t\u0103ng",
|
|
492
|
+
"t\u0103ng l\xEAn",
|
|
493
|
+
"gi\u1EA3m",
|
|
494
|
+
"gi\u1EA3m \u0111i",
|
|
495
|
+
"k\xEDch ho\u1EA1t",
|
|
496
|
+
"g\u1EEDi",
|
|
497
|
+
"n\u1EBFu",
|
|
498
|
+
"kh\xF4ng th\xEC",
|
|
499
|
+
"n\u1EBFu kh\xF4ng",
|
|
500
|
+
"l\u1EB7p l\u1EA1i",
|
|
501
|
+
"ch\u1EDD",
|
|
502
|
+
"\u0111\u1EE3i",
|
|
503
|
+
"trong khi"
|
|
504
|
+
]);
|
|
505
|
+
var POLISH_KEYWORDS = /* @__PURE__ */ new Set([
|
|
506
|
+
"prze\u0142\u0105cz",
|
|
507
|
+
"przelacz",
|
|
508
|
+
"dodaj",
|
|
509
|
+
"usu\u0144",
|
|
510
|
+
"usun",
|
|
511
|
+
"wyczy\u015B\u0107",
|
|
512
|
+
"wyczysc",
|
|
513
|
+
"poka\u017C",
|
|
514
|
+
"pokaz",
|
|
515
|
+
"wy\u015Bwietl",
|
|
516
|
+
"wyswietl",
|
|
517
|
+
"ukryj",
|
|
518
|
+
"schowaj",
|
|
519
|
+
"ustaw",
|
|
520
|
+
"okre\u015Bl",
|
|
521
|
+
"okresl",
|
|
522
|
+
"zwi\u0119ksz",
|
|
523
|
+
"zwieksz",
|
|
524
|
+
"zmniejsz",
|
|
525
|
+
"wywo\u0142aj",
|
|
526
|
+
"wywolaj",
|
|
527
|
+
"wyzw\xF3l",
|
|
528
|
+
"wyzwol",
|
|
529
|
+
"wy\u015Blij",
|
|
530
|
+
"wyslij",
|
|
531
|
+
"je\u015Bli",
|
|
532
|
+
"jesli",
|
|
533
|
+
"je\u017Celi",
|
|
534
|
+
"jezeli",
|
|
535
|
+
"inaczej",
|
|
536
|
+
"wpp",
|
|
537
|
+
"powt\xF3rz",
|
|
538
|
+
"powtorz",
|
|
539
|
+
"czekaj",
|
|
540
|
+
"poczekaj",
|
|
541
|
+
"dop\xF3ki",
|
|
542
|
+
"dopoki",
|
|
543
|
+
"podczas"
|
|
544
|
+
]);
|
|
545
|
+
var RUSSIAN_KEYWORDS = /* @__PURE__ */ new Set([
|
|
546
|
+
"\u043F\u0435\u0440\u0435\u043A\u043B\u044E\u0447\u0438\u0442\u044C",
|
|
547
|
+
"\u043F\u0435\u0440\u0435\u043A\u043B\u044E\u0447\u0438",
|
|
548
|
+
"\u0434\u043E\u0431\u0430\u0432\u0438\u0442\u044C",
|
|
549
|
+
"\u0434\u043E\u0431\u0430\u0432\u044C",
|
|
550
|
+
"\u0443\u0434\u0430\u043B\u0438\u0442\u044C",
|
|
551
|
+
"\u0443\u0434\u0430\u043B\u0438",
|
|
552
|
+
"\u0443\u0431\u0440\u0430\u0442\u044C",
|
|
553
|
+
"\u0443\u0431\u0435\u0440\u0438",
|
|
554
|
+
"\u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C",
|
|
555
|
+
"\u043F\u043E\u043A\u0430\u0436\u0438",
|
|
556
|
+
"\u0441\u043A\u0440\u044B\u0442\u044C",
|
|
557
|
+
"\u0441\u043A\u0440\u043E\u0439",
|
|
558
|
+
"\u0441\u043F\u0440\u044F\u0442\u0430\u0442\u044C",
|
|
559
|
+
"\u0441\u043F\u0440\u044F\u0447\u044C",
|
|
560
|
+
"\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C",
|
|
561
|
+
"\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438",
|
|
562
|
+
"\u0437\u0430\u0434\u0430\u0442\u044C",
|
|
563
|
+
"\u0437\u0430\u0434\u0430\u0439",
|
|
564
|
+
"\u0443\u0432\u0435\u043B\u0438\u0447\u0438\u0442\u044C",
|
|
565
|
+
"\u0443\u0432\u0435\u043B\u0438\u0447\u044C",
|
|
566
|
+
"\u0443\u043C\u0435\u043D\u044C\u0448\u0438\u0442\u044C",
|
|
567
|
+
"\u0443\u043C\u0435\u043D\u044C\u0448\u0438",
|
|
568
|
+
"\u0432\u044B\u0437\u0432\u0430\u0442\u044C",
|
|
569
|
+
"\u0432\u044B\u0437\u043E\u0432\u0438",
|
|
570
|
+
"\u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C",
|
|
571
|
+
"\u043E\u0442\u043F\u0440\u0430\u0432\u044C",
|
|
572
|
+
"\u0435\u0441\u043B\u0438",
|
|
573
|
+
"\u0438\u043D\u0430\u0447\u0435",
|
|
574
|
+
"\u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C",
|
|
575
|
+
"\u043F\u043E\u0432\u0442\u043E\u0440\u0438",
|
|
576
|
+
"\u0436\u0434\u0430\u0442\u044C",
|
|
577
|
+
"\u0436\u0434\u0438",
|
|
578
|
+
"\u043F\u043E\u0434\u043E\u0436\u0434\u0438",
|
|
579
|
+
"\u043F\u043E\u043A\u0430"
|
|
580
|
+
]);
|
|
581
|
+
var UKRAINIAN_KEYWORDS = /* @__PURE__ */ new Set([
|
|
582
|
+
"\u043F\u0435\u0440\u0435\u043C\u043A\u043D\u0443\u0442\u0438",
|
|
583
|
+
"\u043F\u0435\u0440\u0435\u043C\u043A\u043D\u0438",
|
|
584
|
+
"\u0434\u043E\u0434\u0430\u0442\u0438",
|
|
585
|
+
"\u0434\u043E\u0434\u0430\u0439",
|
|
586
|
+
"\u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438",
|
|
587
|
+
"\u0432\u0438\u0434\u0430\u043B\u0438",
|
|
588
|
+
"\u043F\u0440\u0438\u0431\u0440\u0430\u0442\u0438",
|
|
589
|
+
"\u043F\u0440\u0438\u0431\u0435\u0440\u0438",
|
|
590
|
+
"\u043F\u043E\u043A\u0430\u0437\u0430\u0442\u0438",
|
|
591
|
+
"\u043F\u043E\u043A\u0430\u0436\u0438",
|
|
592
|
+
"\u0441\u0445\u043E\u0432\u0430\u0442\u0438",
|
|
593
|
+
"\u0441\u0445\u043E\u0432\u0430\u0439",
|
|
594
|
+
"\u043F\u0440\u0438\u0445\u043E\u0432\u0430\u0442\u0438",
|
|
595
|
+
"\u043F\u0440\u0438\u0445\u043E\u0432\u0430\u0439",
|
|
596
|
+
"\u0432\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438",
|
|
597
|
+
"\u0432\u0441\u0442\u0430\u043D\u043E\u0432\u0438",
|
|
598
|
+
"\u0437\u0430\u0434\u0430\u0442\u0438",
|
|
599
|
+
"\u0437\u0430\u0434\u0430\u0439",
|
|
600
|
+
"\u0437\u0431\u0456\u043B\u044C\u0448\u0438\u0442\u0438",
|
|
601
|
+
"\u0437\u0431\u0456\u043B\u044C\u0448",
|
|
602
|
+
"\u0437\u043C\u0435\u043D\u0448\u0438\u0442\u0438",
|
|
603
|
+
"\u0437\u043C\u0435\u043D\u0448",
|
|
604
|
+
"\u0432\u0438\u043A\u043B\u0438\u043A\u0430\u0442\u0438",
|
|
605
|
+
"\u0432\u0438\u043A\u043B\u0438\u0447",
|
|
606
|
+
"\u043D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438",
|
|
607
|
+
"\u043D\u0430\u0434\u0456\u0448\u043B\u0438",
|
|
608
|
+
"\u044F\u043A\u0449\u043E",
|
|
609
|
+
"\u0456\u043D\u0430\u043A\u0448\u0435",
|
|
610
|
+
"\u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0438",
|
|
611
|
+
"\u043F\u043E\u0432\u0442\u043E\u0440\u0438",
|
|
612
|
+
"\u0447\u0435\u043A\u0430\u0442\u0438",
|
|
613
|
+
"\u0447\u0435\u043A\u0430\u0439",
|
|
614
|
+
"\u0437\u0430\u0447\u0435\u043A\u0430\u0439",
|
|
615
|
+
"\u043F\u043E\u043A\u0438"
|
|
616
|
+
]);
|
|
617
|
+
var HINDI_KEYWORDS = /* @__PURE__ */ new Set([
|
|
618
|
+
"\u091F\u0949\u0917\u0932",
|
|
619
|
+
"\u092C\u0926\u0932\u0947\u0902",
|
|
620
|
+
"\u092C\u0926\u0932",
|
|
621
|
+
"\u091C\u094B\u0921\u093C\u0947\u0902",
|
|
622
|
+
"\u091C\u094B\u0921\u093C",
|
|
623
|
+
"\u0939\u091F\u093E\u090F\u0902",
|
|
624
|
+
"\u0939\u091F\u093E",
|
|
625
|
+
"\u092E\u093F\u091F\u093E\u090F\u0902",
|
|
626
|
+
"\u0926\u093F\u0916\u093E\u090F\u0902",
|
|
627
|
+
"\u0926\u093F\u0916\u093E",
|
|
628
|
+
"\u091B\u093F\u092A\u093E\u090F\u0902",
|
|
629
|
+
"\u091B\u093F\u092A\u093E",
|
|
630
|
+
"\u0938\u0947\u091F",
|
|
631
|
+
"\u0928\u093F\u0930\u094D\u0927\u093E\u0930\u093F\u0924",
|
|
632
|
+
"\u092C\u0922\u093C\u093E\u090F\u0902",
|
|
633
|
+
"\u092C\u0922\u093C\u093E",
|
|
634
|
+
"\u0918\u091F\u093E\u090F\u0902",
|
|
635
|
+
"\u0918\u091F\u093E",
|
|
636
|
+
"\u091F\u094D\u0930\u093F\u0917\u0930",
|
|
637
|
+
"\u092D\u0947\u091C\u0947\u0902",
|
|
638
|
+
"\u092D\u0947\u091C",
|
|
639
|
+
"\u0905\u0917\u0930",
|
|
640
|
+
"\u092F\u0926\u093F",
|
|
641
|
+
"\u0935\u0930\u0928\u093E",
|
|
642
|
+
"\u0928\u0939\u0940\u0902 \u0924\u094B",
|
|
643
|
+
"\u0926\u094B\u0939\u0930\u093E\u090F\u0902",
|
|
644
|
+
"\u0926\u094B\u0939\u0930\u093E",
|
|
645
|
+
"\u092A\u094D\u0930\u0924\u0940\u0915\u094D\u0937\u093E",
|
|
646
|
+
"\u0930\u0941\u0915\u0947\u0902",
|
|
647
|
+
"\u091C\u092C \u0924\u0915"
|
|
648
|
+
]);
|
|
649
|
+
var BENGALI_KEYWORDS = /* @__PURE__ */ new Set([
|
|
650
|
+
"\u099F\u0997\u09B2",
|
|
651
|
+
"\u09AA\u09B0\u09BF\u09AC\u09B0\u09CD\u09A4\u09A8",
|
|
652
|
+
"\u09AF\u09CB\u0997",
|
|
653
|
+
"\u09AF\u09CB\u0997 \u0995\u09B0\u09C1\u09A8",
|
|
654
|
+
"\u09B8\u09B0\u09BE\u09A8",
|
|
655
|
+
"\u09B8\u09B0\u09BF\u09AF\u09BC\u09C7 \u09AB\u09C7\u09B2\u09C1\u09A8",
|
|
656
|
+
"\u09AE\u09C1\u099B\u09C1\u09A8",
|
|
657
|
+
"\u09A6\u09C7\u0996\u09BE\u09A8",
|
|
658
|
+
"\u09A6\u09C7\u0996\u09BE\u0993",
|
|
659
|
+
"\u09B2\u09C1\u0995\u09BE\u09A8",
|
|
660
|
+
"\u09B2\u09C1\u0995\u09BE\u0993",
|
|
661
|
+
"\u09B8\u09C7\u099F",
|
|
662
|
+
"\u09A8\u09BF\u09B0\u09CD\u09A7\u09BE\u09B0\u09A3",
|
|
663
|
+
"\u09AC\u09C3\u09A6\u09CD\u09A7\u09BF",
|
|
664
|
+
"\u09AC\u09BE\u09A1\u09BC\u09BE\u09A8",
|
|
665
|
+
"\u09B9\u09CD\u09B0\u09BE\u09B8",
|
|
666
|
+
"\u0995\u09AE\u09BE\u09A8",
|
|
667
|
+
"\u099F\u09CD\u09B0\u09BF\u0997\u09BE\u09B0",
|
|
668
|
+
"\u09AA\u09BE\u09A0\u09BE\u09A8",
|
|
669
|
+
"\u09AA\u09BE\u09A0\u09BE\u0993",
|
|
670
|
+
"\u09AF\u09A6\u09BF",
|
|
671
|
+
"\u09A8\u09A4\u09C1\u09AC\u09BE",
|
|
672
|
+
"\u09A8\u09BE \u09B9\u09B2\u09C7",
|
|
673
|
+
"\u09AA\u09C1\u09A8\u09B0\u09BE\u09AC\u09C3\u09A4\u09CD\u09A4\u09BF",
|
|
674
|
+
"\u09AC\u09BE\u09B0 \u09AC\u09BE\u09B0",
|
|
675
|
+
"\u0985\u09AA\u09C7\u0995\u09CD\u09B7\u09BE",
|
|
676
|
+
"\u09A5\u09BE\u09AE\u09C1\u09A8",
|
|
677
|
+
"\u09AF\u09A4\u0995\u09CD\u09B7\u09A3"
|
|
678
|
+
]);
|
|
679
|
+
var THAI_KEYWORDS = /* @__PURE__ */ new Set([
|
|
680
|
+
"\u0E2A\u0E25\u0E31\u0E1A",
|
|
681
|
+
"\u0E40\u0E1E\u0E34\u0E48\u0E21",
|
|
682
|
+
"\u0E25\u0E1A",
|
|
683
|
+
"\u0E25\u0E1A\u0E2D\u0E2D\u0E01",
|
|
684
|
+
"\u0E41\u0E2A\u0E14\u0E07",
|
|
685
|
+
"\u0E0B\u0E48\u0E2D\u0E19",
|
|
686
|
+
"\u0E15\u0E31\u0E49\u0E07",
|
|
687
|
+
"\u0E01\u0E33\u0E2B\u0E19\u0E14",
|
|
688
|
+
"\u0E40\u0E1E\u0E34\u0E48\u0E21\u0E04\u0E48\u0E32",
|
|
689
|
+
"\u0E25\u0E14\u0E04\u0E48\u0E32",
|
|
690
|
+
"\u0E17\u0E23\u0E34\u0E01\u0E40\u0E01\u0E2D\u0E23\u0E4C",
|
|
691
|
+
"\u0E2A\u0E48\u0E07",
|
|
692
|
+
"\u0E16\u0E49\u0E32",
|
|
693
|
+
"\u0E2B\u0E32\u0E01",
|
|
694
|
+
"\u0E44\u0E21\u0E48\u0E07\u0E31\u0E49\u0E19",
|
|
695
|
+
"\u0E44\u0E21\u0E48\u0E40\u0E0A\u0E48\u0E19\u0E19\u0E31\u0E49\u0E19",
|
|
696
|
+
"\u0E17\u0E33\u0E0B\u0E49\u0E33",
|
|
697
|
+
"\u0E23\u0E2D",
|
|
698
|
+
"\u0E43\u0E19\u0E02\u0E13\u0E30\u0E17\u0E35\u0E48"
|
|
699
|
+
]);
|
|
700
|
+
var TL_KEYWORDS = /* @__PURE__ */ new Set([
|
|
701
|
+
"palitan",
|
|
702
|
+
"itoggle",
|
|
703
|
+
"idagdag",
|
|
704
|
+
"magdagdag",
|
|
705
|
+
"alisin",
|
|
706
|
+
"tanggalin",
|
|
707
|
+
"ipakita",
|
|
708
|
+
"magpakita",
|
|
709
|
+
"itago",
|
|
710
|
+
"magtago",
|
|
711
|
+
"itakda",
|
|
712
|
+
"magtakda",
|
|
713
|
+
"dagdagan",
|
|
714
|
+
"taasan",
|
|
715
|
+
"bawasan",
|
|
716
|
+
"ibaba",
|
|
717
|
+
"magpatugtog",
|
|
718
|
+
"ipadala",
|
|
719
|
+
"magpadala",
|
|
720
|
+
"kung",
|
|
721
|
+
"kapag",
|
|
722
|
+
"kung_hindi",
|
|
723
|
+
"kundi",
|
|
724
|
+
"ulitin",
|
|
725
|
+
"paulit-ulit",
|
|
726
|
+
"maghintay",
|
|
727
|
+
"hintay",
|
|
728
|
+
"habang"
|
|
729
|
+
]);
|
|
730
|
+
var LANGUAGE_KEYWORDS = {
|
|
731
|
+
en: /* @__PURE__ */ new Set(),
|
|
732
|
+
// English is the default, no detection needed
|
|
733
|
+
ja: JAPANESE_KEYWORDS,
|
|
734
|
+
ko: KOREAN_KEYWORDS,
|
|
735
|
+
zh: CHINESE_KEYWORDS,
|
|
736
|
+
ar: ARABIC_KEYWORDS,
|
|
737
|
+
es: SPANISH_KEYWORDS,
|
|
738
|
+
pt: PORTUGUESE_KEYWORDS,
|
|
739
|
+
fr: FRENCH_KEYWORDS,
|
|
740
|
+
de: GERMAN_KEYWORDS,
|
|
741
|
+
it: ITALIAN_KEYWORDS,
|
|
742
|
+
vi: VIETNAMESE_KEYWORDS,
|
|
743
|
+
pl: POLISH_KEYWORDS,
|
|
744
|
+
ru: RUSSIAN_KEYWORDS,
|
|
745
|
+
uk: UKRAINIAN_KEYWORDS,
|
|
746
|
+
hi: HINDI_KEYWORDS,
|
|
747
|
+
bn: BENGALI_KEYWORDS,
|
|
748
|
+
th: THAI_KEYWORDS,
|
|
749
|
+
tr: TURKISH_KEYWORDS,
|
|
750
|
+
id: INDONESIAN_KEYWORDS,
|
|
751
|
+
sw: SWAHILI_KEYWORDS,
|
|
752
|
+
qu: QUECHUA_KEYWORDS,
|
|
753
|
+
tl: TL_KEYWORDS
|
|
754
|
+
};
|
|
755
|
+
function containsLanguageKeywords(script, language) {
|
|
756
|
+
const keywords = LANGUAGE_KEYWORDS[language];
|
|
757
|
+
if (!keywords || keywords.size === 0) return false;
|
|
758
|
+
const nonLatinLangs = ["ja", "ko", "zh", "ar", "ru", "uk", "hi", "bn", "th"];
|
|
759
|
+
if (nonLatinLangs.includes(language)) {
|
|
760
|
+
for (const keyword of keywords) {
|
|
761
|
+
if (script.includes(keyword)) {
|
|
762
|
+
return true;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
return false;
|
|
766
|
+
}
|
|
767
|
+
const lowerScript = script.toLowerCase();
|
|
768
|
+
for (const keyword of keywords) {
|
|
769
|
+
if (keyword.length <= 2) continue;
|
|
770
|
+
const pattern = new RegExp(`\\b${escapeRegExp(keyword.toLowerCase())}\\b`);
|
|
771
|
+
if (pattern.test(lowerScript)) {
|
|
772
|
+
return true;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
return false;
|
|
776
|
+
}
|
|
777
|
+
function escapeRegExp(str) {
|
|
778
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
779
|
+
}
|
|
780
|
+
function detectLanguages(script) {
|
|
781
|
+
const detected = /* @__PURE__ */ new Set();
|
|
782
|
+
for (const lang of SUPPORTED_LANGUAGES) {
|
|
783
|
+
if (lang === "en") continue;
|
|
784
|
+
if (containsLanguageKeywords(script, lang)) {
|
|
785
|
+
detected.add(lang);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
return detected;
|
|
789
|
+
}
|
|
790
|
+
var customKeywordRegistry = /* @__PURE__ */ new Map();
|
|
791
|
+
function registerCustomKeywords(code, config) {
|
|
792
|
+
const existing = LANGUAGE_KEYWORDS[code];
|
|
793
|
+
const nonLatinLangs = ["ja", "ko", "zh", "ar", "ru", "uk", "hi", "bn", "th"];
|
|
794
|
+
const isNonLatin = config.isNonLatin ?? nonLatinLangs.includes(code);
|
|
795
|
+
if (config.extend && existing) {
|
|
796
|
+
const merged = /* @__PURE__ */ new Set([...existing, ...config.keywords]);
|
|
797
|
+
customKeywordRegistry.set(code, { keywords: merged, isNonLatin });
|
|
798
|
+
} else {
|
|
799
|
+
customKeywordRegistry.set(code, { keywords: config.keywords, isNonLatin });
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
function getKeywordsForLanguage(code) {
|
|
803
|
+
const custom = customKeywordRegistry.get(code);
|
|
804
|
+
if (custom) return custom.keywords;
|
|
805
|
+
return LANGUAGE_KEYWORDS[code];
|
|
806
|
+
}
|
|
807
|
+
function isNonLatinLanguage(code) {
|
|
808
|
+
const custom = customKeywordRegistry.get(code);
|
|
809
|
+
if (custom) return custom.isNonLatin;
|
|
810
|
+
const nonLatinLangs = ["ja", "ko", "zh", "ar", "ru", "uk", "hi", "bn", "th"];
|
|
811
|
+
return nonLatinLangs.includes(code);
|
|
812
|
+
}
|
|
813
|
+
function getAllLanguageCodes() {
|
|
814
|
+
const builtin = [...SUPPORTED_LANGUAGES];
|
|
815
|
+
const custom = [...customKeywordRegistry.keys()];
|
|
816
|
+
return [.../* @__PURE__ */ new Set([...builtin, ...custom])];
|
|
817
|
+
}
|
|
818
|
+
function clearCustomKeywords() {
|
|
819
|
+
customKeywordRegistry.clear();
|
|
820
|
+
}
|
|
821
|
+
function getOptimalRegion(languages) {
|
|
822
|
+
if (languages.size === 0) return null;
|
|
823
|
+
const langArray = [...languages];
|
|
824
|
+
if (langArray.every((l) => REGIONS.western.includes(l))) {
|
|
825
|
+
return "western";
|
|
826
|
+
}
|
|
827
|
+
if (langArray.every((l) => REGIONS["east-asian"].includes(l))) {
|
|
828
|
+
return "east-asian";
|
|
829
|
+
}
|
|
830
|
+
if (langArray.every((l) => REGIONS.slavic.includes(l))) {
|
|
831
|
+
return "slavic";
|
|
832
|
+
}
|
|
833
|
+
if (langArray.every((l) => REGIONS["south-asian"].includes(l))) {
|
|
834
|
+
return "south-asian";
|
|
835
|
+
}
|
|
836
|
+
if (langArray.every((l) => REGIONS.priority.includes(l))) {
|
|
837
|
+
return "priority";
|
|
838
|
+
}
|
|
839
|
+
return "all";
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// src/scanner.ts
|
|
843
|
+
function toRegex(pattern, defaultPattern) {
|
|
844
|
+
if (!pattern) return defaultPattern;
|
|
845
|
+
if (pattern instanceof RegExp) return pattern;
|
|
846
|
+
if (Array.isArray(pattern)) {
|
|
847
|
+
const escaped = pattern.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
848
|
+
return new RegExp(`(${escaped.join("|")})`);
|
|
849
|
+
}
|
|
850
|
+
return defaultPattern;
|
|
851
|
+
}
|
|
852
|
+
var Scanner = class {
|
|
853
|
+
constructor(options) {
|
|
854
|
+
this.include = toRegex(
|
|
855
|
+
options.include,
|
|
856
|
+
/\.(html?|vue|svelte|jsx?|tsx?|astro|php|erb|ejs|hbs|handlebars)$/
|
|
857
|
+
);
|
|
858
|
+
this.exclude = toRegex(options.exclude, /node_modules|\.git/);
|
|
859
|
+
this.debug = options.debug ?? false;
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Check if a file should be scanned
|
|
863
|
+
*/
|
|
864
|
+
shouldScan(id) {
|
|
865
|
+
return this.include.test(id) && !this.exclude.test(id);
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* Scan code for hyperscript usage
|
|
869
|
+
*/
|
|
870
|
+
scan(code, id) {
|
|
871
|
+
const usage = {
|
|
872
|
+
commands: /* @__PURE__ */ new Set(),
|
|
873
|
+
blocks: /* @__PURE__ */ new Set(),
|
|
874
|
+
positional: false,
|
|
875
|
+
detectedLanguages: /* @__PURE__ */ new Set()
|
|
876
|
+
};
|
|
877
|
+
const attrPatterns = [
|
|
878
|
+
/_\s*=\s*"([^"]+)"/g,
|
|
879
|
+
// _="..."
|
|
880
|
+
/_\s*=\s*'([^']+)'/g,
|
|
881
|
+
// _='...'
|
|
882
|
+
/_\s*=\s*`([^`]+)`/g,
|
|
883
|
+
// _=`...`
|
|
884
|
+
/_=\{`([^`]+)`\}/g,
|
|
885
|
+
// _={`...`} (JSX)
|
|
886
|
+
/_=\{['"]([^'"]+)['"]\}/g
|
|
887
|
+
// _={"..."} or _={'...'} (JSX)
|
|
888
|
+
];
|
|
889
|
+
for (const pattern of attrPatterns) {
|
|
890
|
+
let match2;
|
|
891
|
+
while (match2 = pattern.exec(code)) {
|
|
892
|
+
this.analyzeScript(match2[1], usage);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
const scriptPattern = /<script[^>]*type=["']?text\/hyperscript["']?[^>]*>([^<]+)<\/script>/gi;
|
|
896
|
+
let match;
|
|
897
|
+
while (match = scriptPattern.exec(code)) {
|
|
898
|
+
this.analyzeScript(match[1], usage);
|
|
899
|
+
}
|
|
900
|
+
if (this.debug && (usage.commands.size > 0 || usage.blocks.size > 0 || usage.detectedLanguages.size > 0)) {
|
|
901
|
+
console.log(`[hyperfixi] Scanned ${id}:`, {
|
|
902
|
+
commands: [...usage.commands],
|
|
903
|
+
blocks: [...usage.blocks],
|
|
904
|
+
positional: usage.positional,
|
|
905
|
+
languages: [...usage.detectedLanguages]
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
return usage;
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* Analyze a hyperscript snippet for commands, blocks, and expressions
|
|
912
|
+
*/
|
|
913
|
+
analyzeScript(script, usage) {
|
|
914
|
+
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;
|
|
915
|
+
let match;
|
|
916
|
+
while (match = commandPattern.exec(script)) {
|
|
917
|
+
usage.commands.add(match[1]);
|
|
918
|
+
}
|
|
919
|
+
if (/\bif\b/.test(script)) usage.blocks.add("if");
|
|
920
|
+
if (/\bunless\b/.test(script)) usage.blocks.add("if");
|
|
921
|
+
if (/\brepeat\s+(\d+|:\w+|\$\w+|[\w.]+)\s+times?\b/i.test(script)) usage.blocks.add("repeat");
|
|
922
|
+
if (/\bfor\s+(each|every)\b/i.test(script)) usage.blocks.add("for");
|
|
923
|
+
if (/\bwhile\b/.test(script)) usage.blocks.add("while");
|
|
924
|
+
if (/\bfetch\b/.test(script)) usage.blocks.add("fetch");
|
|
925
|
+
if (/\b(first|last|next|previous|closest|parent)\b/.test(script)) {
|
|
926
|
+
usage.positional = true;
|
|
927
|
+
}
|
|
928
|
+
const languages = detectLanguages(script);
|
|
929
|
+
for (const lang of languages) {
|
|
930
|
+
usage.detectedLanguages.add(lang);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Scan all files in a project directory
|
|
935
|
+
* Used during production build to scan the entire codebase
|
|
936
|
+
*/
|
|
937
|
+
async scanProject(dir) {
|
|
938
|
+
const results = /* @__PURE__ */ new Map();
|
|
939
|
+
try {
|
|
940
|
+
const { glob } = await import("glob");
|
|
941
|
+
const fs = await import("fs");
|
|
942
|
+
const files = await glob("**/*.{html,htm,vue,svelte,js,jsx,ts,tsx,astro,php,erb,ejs,hbs}", {
|
|
943
|
+
cwd: dir,
|
|
944
|
+
ignore: ["node_modules/**", "dist/**", ".git/**"],
|
|
945
|
+
absolute: true
|
|
946
|
+
});
|
|
947
|
+
for (const file of files) {
|
|
948
|
+
if (this.shouldScan(file)) {
|
|
949
|
+
try {
|
|
950
|
+
const code = fs.readFileSync(file, "utf-8");
|
|
951
|
+
const usage = this.scan(code, file);
|
|
952
|
+
if (usage.commands.size > 0 || usage.blocks.size > 0 || usage.positional || usage.detectedLanguages.size > 0) {
|
|
953
|
+
results.set(file, usage);
|
|
954
|
+
}
|
|
955
|
+
} catch {
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
} catch (error) {
|
|
960
|
+
console.warn("[hyperfixi] Error scanning project:", error);
|
|
961
|
+
}
|
|
962
|
+
return results;
|
|
963
|
+
}
|
|
964
|
+
};
|
|
965
|
+
|
|
966
|
+
// src/aggregator.ts
|
|
967
|
+
var Aggregator = class {
|
|
968
|
+
constructor() {
|
|
969
|
+
this.fileUsage = /* @__PURE__ */ new Map();
|
|
970
|
+
this.cachedUsage = null;
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Add or update usage for a file
|
|
974
|
+
* @returns true if the overall usage changed
|
|
975
|
+
*/
|
|
976
|
+
add(filePath, usage) {
|
|
977
|
+
const existing = this.fileUsage.get(filePath);
|
|
978
|
+
if (existing) {
|
|
979
|
+
const commandsEqual = this.setsEqual(existing.commands, usage.commands);
|
|
980
|
+
const blocksEqual = this.setsEqual(existing.blocks, usage.blocks);
|
|
981
|
+
const positionalEqual = existing.positional === usage.positional;
|
|
982
|
+
const languagesEqual = this.setsEqual(existing.detectedLanguages, usage.detectedLanguages);
|
|
983
|
+
if (commandsEqual && blocksEqual && positionalEqual && languagesEqual) {
|
|
984
|
+
return false;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
this.fileUsage.set(filePath, usage);
|
|
988
|
+
this.cachedUsage = null;
|
|
989
|
+
return true;
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Remove a file from tracking (e.g., when deleted)
|
|
993
|
+
* @returns true if the overall usage changed
|
|
994
|
+
*/
|
|
995
|
+
remove(filePath) {
|
|
996
|
+
const existed = this.fileUsage.delete(filePath);
|
|
997
|
+
if (existed) {
|
|
998
|
+
this.cachedUsage = null;
|
|
999
|
+
}
|
|
1000
|
+
return existed;
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Get aggregated usage across all files
|
|
1004
|
+
*/
|
|
1005
|
+
getUsage() {
|
|
1006
|
+
if (this.cachedUsage) {
|
|
1007
|
+
return this.cachedUsage;
|
|
1008
|
+
}
|
|
1009
|
+
const commands = /* @__PURE__ */ new Set();
|
|
1010
|
+
const blocks = /* @__PURE__ */ new Set();
|
|
1011
|
+
const detectedLanguages = /* @__PURE__ */ new Set();
|
|
1012
|
+
let positional = false;
|
|
1013
|
+
for (const usage of this.fileUsage.values()) {
|
|
1014
|
+
for (const cmd of usage.commands) commands.add(cmd);
|
|
1015
|
+
for (const block of usage.blocks) blocks.add(block);
|
|
1016
|
+
for (const lang of usage.detectedLanguages) detectedLanguages.add(lang);
|
|
1017
|
+
if (usage.positional) positional = true;
|
|
1018
|
+
}
|
|
1019
|
+
this.cachedUsage = {
|
|
1020
|
+
commands,
|
|
1021
|
+
blocks,
|
|
1022
|
+
positional,
|
|
1023
|
+
detectedLanguages,
|
|
1024
|
+
fileUsage: new Map(this.fileUsage)
|
|
1025
|
+
};
|
|
1026
|
+
return this.cachedUsage;
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Load usage from a project scan
|
|
1030
|
+
*/
|
|
1031
|
+
loadFromScan(scannedFiles) {
|
|
1032
|
+
this.fileUsage = new Map(scannedFiles);
|
|
1033
|
+
this.cachedUsage = null;
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Check if any hyperscript usage has been detected
|
|
1037
|
+
*/
|
|
1038
|
+
hasUsage() {
|
|
1039
|
+
const usage = this.getUsage();
|
|
1040
|
+
return usage.commands.size > 0 || usage.blocks.size > 0 || usage.positional || usage.detectedLanguages.size > 0;
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Get summary for logging
|
|
1044
|
+
*/
|
|
1045
|
+
getSummary() {
|
|
1046
|
+
const usage = this.getUsage();
|
|
1047
|
+
return {
|
|
1048
|
+
commands: [...usage.commands].sort(),
|
|
1049
|
+
blocks: [...usage.blocks].sort(),
|
|
1050
|
+
positional: usage.positional,
|
|
1051
|
+
languages: [...usage.detectedLanguages].sort(),
|
|
1052
|
+
fileCount: this.fileUsage.size
|
|
1053
|
+
};
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
1056
|
+
* Clear all tracked usage
|
|
1057
|
+
*/
|
|
1058
|
+
clear() {
|
|
1059
|
+
this.fileUsage.clear();
|
|
1060
|
+
this.cachedUsage = null;
|
|
1061
|
+
}
|
|
1062
|
+
/**
|
|
1063
|
+
* Compare two sets for equality
|
|
1064
|
+
*/
|
|
1065
|
+
setsEqual(a, b) {
|
|
1066
|
+
if (a.size !== b.size) return false;
|
|
1067
|
+
for (const item of a) {
|
|
1068
|
+
if (!b.has(item)) return false;
|
|
1069
|
+
}
|
|
1070
|
+
return true;
|
|
1071
|
+
}
|
|
1072
|
+
};
|
|
1073
|
+
|
|
1074
|
+
// src/generator.ts
|
|
1075
|
+
var import_bundle_generator = require("@lokascript/core/bundle-generator");
|
|
1076
|
+
|
|
1077
|
+
// src/semantic-integration.ts
|
|
1078
|
+
var MULTILINGUAL_COMMAND_ALIASES = {
|
|
1079
|
+
ja: {
|
|
1080
|
+
\u30C8\u30B0\u30EB: "toggle",
|
|
1081
|
+
\u5207\u308A\u66FF\u3048: "toggle",
|
|
1082
|
+
\u8FFD\u52A0: "add",
|
|
1083
|
+
\u524A\u9664: "remove",
|
|
1084
|
+
\u8868\u793A: "show",
|
|
1085
|
+
\u96A0\u3059: "hide",
|
|
1086
|
+
\u975E\u8868\u793A: "hide",
|
|
1087
|
+
\u8A2D\u5B9A: "set",
|
|
1088
|
+
\u30BB\u30C3\u30C8: "set",
|
|
1089
|
+
\u5897\u52A0: "increment",
|
|
1090
|
+
\u6E1B\u5C11: "decrement",
|
|
1091
|
+
\u30ED\u30B0: "log",
|
|
1092
|
+
\u51FA\u529B: "log"
|
|
1093
|
+
},
|
|
1094
|
+
ko: {
|
|
1095
|
+
\uD1A0\uAE00: "toggle",
|
|
1096
|
+
\uC804\uD658: "toggle",
|
|
1097
|
+
\uCD94\uAC00: "add",
|
|
1098
|
+
\uC81C\uAC70: "remove",
|
|
1099
|
+
\uC0AD\uC81C: "remove",
|
|
1100
|
+
\uD45C\uC2DC: "show",
|
|
1101
|
+
\uC228\uAE30\uB2E4: "hide",
|
|
1102
|
+
\uC124\uC815: "set",
|
|
1103
|
+
\uC99D\uAC00: "increment",
|
|
1104
|
+
\uAC10\uC18C: "decrement",
|
|
1105
|
+
\uB85C\uADF8: "log"
|
|
1106
|
+
},
|
|
1107
|
+
zh: {
|
|
1108
|
+
\u5207\u6362: "toggle",
|
|
1109
|
+
\u6DFB\u52A0: "add",
|
|
1110
|
+
\u79FB\u9664: "remove",
|
|
1111
|
+
\u5220\u9664: "remove",
|
|
1112
|
+
\u663E\u793A: "show",
|
|
1113
|
+
\u9690\u85CF: "hide",
|
|
1114
|
+
\u8BBE\u7F6E: "set",
|
|
1115
|
+
\u8BBE\u5B9A: "set",
|
|
1116
|
+
\u589E\u52A0: "increment",
|
|
1117
|
+
\u51CF\u5C11: "decrement",
|
|
1118
|
+
\u65E5\u5FD7: "log",
|
|
1119
|
+
\u8BB0\u5F55: "log"
|
|
1120
|
+
},
|
|
1121
|
+
ar: {
|
|
1122
|
+
\u0628\u062F\u0651\u0644: "toggle",
|
|
1123
|
+
\u0628\u062F\u0644: "toggle",
|
|
1124
|
+
\u0623\u0636\u0641: "add",
|
|
1125
|
+
\u0627\u0636\u0641: "add",
|
|
1126
|
+
\u0623\u0632\u0644: "remove",
|
|
1127
|
+
\u0627\u0632\u0644: "remove",
|
|
1128
|
+
\u0627\u062D\u0630\u0641: "remove",
|
|
1129
|
+
\u0623\u0638\u0647\u0631: "show",
|
|
1130
|
+
\u0627\u0638\u0647\u0631: "show",
|
|
1131
|
+
\u0623\u062E\u0641\u0650: "hide",
|
|
1132
|
+
\u0627\u062E\u0641: "hide",
|
|
1133
|
+
\u0636\u0639: "set",
|
|
1134
|
+
\u0627\u0636\u0639: "set",
|
|
1135
|
+
\u0632\u0650\u062F: "increment",
|
|
1136
|
+
\u0623\u0646\u0642\u0635: "decrement"
|
|
1137
|
+
},
|
|
1138
|
+
es: {
|
|
1139
|
+
alternar: "toggle",
|
|
1140
|
+
a\u00F1adir: "add",
|
|
1141
|
+
agregar: "add",
|
|
1142
|
+
quitar: "remove",
|
|
1143
|
+
eliminar: "remove",
|
|
1144
|
+
mostrar: "show",
|
|
1145
|
+
ocultar: "hide",
|
|
1146
|
+
esconder: "hide",
|
|
1147
|
+
establecer: "set",
|
|
1148
|
+
fijar: "set",
|
|
1149
|
+
incrementar: "increment",
|
|
1150
|
+
decrementar: "decrement"
|
|
1151
|
+
},
|
|
1152
|
+
pt: {
|
|
1153
|
+
alternar: "toggle",
|
|
1154
|
+
adicionar: "add",
|
|
1155
|
+
remover: "remove",
|
|
1156
|
+
mostrar: "show",
|
|
1157
|
+
esconder: "hide",
|
|
1158
|
+
ocultar: "hide",
|
|
1159
|
+
definir: "set",
|
|
1160
|
+
incrementar: "increment",
|
|
1161
|
+
decrementar: "decrement"
|
|
1162
|
+
},
|
|
1163
|
+
fr: {
|
|
1164
|
+
basculer: "toggle",
|
|
1165
|
+
ajouter: "add",
|
|
1166
|
+
supprimer: "remove",
|
|
1167
|
+
retirer: "remove",
|
|
1168
|
+
afficher: "show",
|
|
1169
|
+
montrer: "show",
|
|
1170
|
+
cacher: "hide",
|
|
1171
|
+
masquer: "hide",
|
|
1172
|
+
d\u00E9finir: "set",
|
|
1173
|
+
incr\u00E9menter: "increment",
|
|
1174
|
+
d\u00E9cr\u00E9menter: "decrement"
|
|
1175
|
+
},
|
|
1176
|
+
de: {
|
|
1177
|
+
umschalten: "toggle",
|
|
1178
|
+
hinzuf\u00FCgen: "add",
|
|
1179
|
+
entfernen: "remove",
|
|
1180
|
+
l\u00F6schen: "remove",
|
|
1181
|
+
anzeigen: "show",
|
|
1182
|
+
zeigen: "show",
|
|
1183
|
+
verbergen: "hide",
|
|
1184
|
+
verstecken: "hide",
|
|
1185
|
+
setzen: "set",
|
|
1186
|
+
festlegen: "set",
|
|
1187
|
+
erh\u00F6hen: "increment",
|
|
1188
|
+
verringern: "decrement"
|
|
1189
|
+
},
|
|
1190
|
+
tr: {
|
|
1191
|
+
de\u011Fi\u015Ftir: "toggle",
|
|
1192
|
+
de\u011Fistir: "toggle",
|
|
1193
|
+
ekle: "add",
|
|
1194
|
+
kald\u0131r: "remove",
|
|
1195
|
+
kaldir: "remove",
|
|
1196
|
+
sil: "remove",
|
|
1197
|
+
g\u00F6ster: "show",
|
|
1198
|
+
gizle: "hide",
|
|
1199
|
+
sakla: "hide",
|
|
1200
|
+
ayarla: "set",
|
|
1201
|
+
belirle: "set",
|
|
1202
|
+
artt\u0131r: "increment",
|
|
1203
|
+
azalt: "decrement"
|
|
1204
|
+
},
|
|
1205
|
+
id: {
|
|
1206
|
+
alih: "toggle",
|
|
1207
|
+
beralih: "toggle",
|
|
1208
|
+
tambah: "add",
|
|
1209
|
+
hapus: "remove",
|
|
1210
|
+
buang: "remove",
|
|
1211
|
+
tampilkan: "show",
|
|
1212
|
+
sembunyikan: "hide",
|
|
1213
|
+
atur: "set",
|
|
1214
|
+
tetapkan: "set",
|
|
1215
|
+
tambahkan: "increment",
|
|
1216
|
+
kurangi: "decrement"
|
|
1217
|
+
},
|
|
1218
|
+
sw: {
|
|
1219
|
+
badilisha: "toggle",
|
|
1220
|
+
ongeza: "add",
|
|
1221
|
+
ondoa: "remove",
|
|
1222
|
+
futa: "remove",
|
|
1223
|
+
onyesha: "show",
|
|
1224
|
+
ficha: "hide",
|
|
1225
|
+
weka: "set",
|
|
1226
|
+
sanidi: "set",
|
|
1227
|
+
ongezea: "increment",
|
|
1228
|
+
punguza: "decrement"
|
|
1229
|
+
},
|
|
1230
|
+
qu: {
|
|
1231
|
+
tikray: "toggle",
|
|
1232
|
+
yapay: "add",
|
|
1233
|
+
qichuy: "remove",
|
|
1234
|
+
pichay: "remove",
|
|
1235
|
+
rikuchiy: "show",
|
|
1236
|
+
pakay: "hide",
|
|
1237
|
+
churay: "set",
|
|
1238
|
+
pisiyachiy: "decrement"
|
|
1239
|
+
}
|
|
1240
|
+
};
|
|
1241
|
+
function getMultilingualCommandAliases(languages) {
|
|
1242
|
+
const aliases = {};
|
|
1243
|
+
for (const lang of languages) {
|
|
1244
|
+
const langAliases = MULTILINGUAL_COMMAND_ALIASES[lang];
|
|
1245
|
+
if (langAliases) {
|
|
1246
|
+
Object.assign(aliases, langAliases);
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
return aliases;
|
|
1250
|
+
}
|
|
1251
|
+
function generateMultilingualAliases(languages) {
|
|
1252
|
+
const aliases = {};
|
|
1253
|
+
for (const lang of languages) {
|
|
1254
|
+
const langAliases = MULTILINGUAL_COMMAND_ALIASES[lang];
|
|
1255
|
+
if (langAliases) {
|
|
1256
|
+
Object.assign(aliases, langAliases);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
if (Object.keys(aliases).length === 0) {
|
|
1260
|
+
return `
|
|
1261
|
+
// No multilingual aliases needed - just pass through
|
|
1262
|
+
function preprocessMultilingual(code) { return code; }
|
|
1263
|
+
`;
|
|
1264
|
+
}
|
|
1265
|
+
const aliasEntries = Object.entries(aliases).map(([key, val]) => ` '${key}': '${val}'`).join(",\n");
|
|
1266
|
+
const escapedKeys = Object.keys(aliases).map((k) => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
1267
|
+
return `
|
|
1268
|
+
// Multilingual command aliases for HybridParser fallback
|
|
1269
|
+
const MULTILINGUAL_ALIASES = {
|
|
1270
|
+
${aliasEntries}
|
|
1271
|
+
};
|
|
1272
|
+
|
|
1273
|
+
// Register multilingual aliases with the parser
|
|
1274
|
+
addCommandAliases(MULTILINGUAL_ALIASES);
|
|
1275
|
+
|
|
1276
|
+
// Preprocessing regex to translate multilingual keywords to English
|
|
1277
|
+
// The HybridParser tokenizer only accepts ASCII identifiers, so we need
|
|
1278
|
+
// to translate non-ASCII keywords before parsing.
|
|
1279
|
+
const MULTILINGUAL_KEYWORD_REGEX = new RegExp('(^|\\\\s)(${escapedKeys})(?=\\\\s|\\\\.|$)', 'g');
|
|
1280
|
+
|
|
1281
|
+
/**
|
|
1282
|
+
* Preprocess multilingual code to replace non-ASCII keywords with English equivalents.
|
|
1283
|
+
* This is needed because HybridParser's tokenizer only accepts ASCII identifiers.
|
|
1284
|
+
*/
|
|
1285
|
+
function preprocessMultilingual(code) {
|
|
1286
|
+
return code.replace(MULTILINGUAL_KEYWORD_REGEX, (match, prefix, keyword) => {
|
|
1287
|
+
const english = MULTILINGUAL_ALIASES[keyword];
|
|
1288
|
+
return english ? prefix + english : match;
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
1291
|
+
`;
|
|
1292
|
+
}
|
|
1293
|
+
function resolveSemanticConfig(options, detectedLanguages) {
|
|
1294
|
+
const grammarEnabled = options.grammar ?? false;
|
|
1295
|
+
let semanticEnabled = grammarEnabled;
|
|
1296
|
+
if (options.semantic === true || options.semantic === "auto") {
|
|
1297
|
+
semanticEnabled = true;
|
|
1298
|
+
} else if (options.semantic === "en") {
|
|
1299
|
+
semanticEnabled = true;
|
|
1300
|
+
} else if (options.semantic === false) {
|
|
1301
|
+
semanticEnabled = false;
|
|
1302
|
+
}
|
|
1303
|
+
if (!semanticEnabled) {
|
|
1304
|
+
return {
|
|
1305
|
+
enabled: false,
|
|
1306
|
+
bundleType: null,
|
|
1307
|
+
languages: /* @__PURE__ */ new Set(),
|
|
1308
|
+
grammarEnabled: false
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
const languages = /* @__PURE__ */ new Set();
|
|
1312
|
+
for (const lang of detectedLanguages) {
|
|
1313
|
+
languages.add(lang);
|
|
1314
|
+
}
|
|
1315
|
+
if (options.languages) {
|
|
1316
|
+
for (const lang of options.languages) {
|
|
1317
|
+
languages.add(lang);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
if (options.extraLanguages) {
|
|
1321
|
+
for (const lang of options.extraLanguages) {
|
|
1322
|
+
languages.add(lang);
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
let bundleType = selectBundleType(options, languages);
|
|
1326
|
+
return {
|
|
1327
|
+
enabled: true,
|
|
1328
|
+
bundleType,
|
|
1329
|
+
languages,
|
|
1330
|
+
grammarEnabled
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
function selectBundleType(options, languages) {
|
|
1334
|
+
if (options.region) {
|
|
1335
|
+
return options.region;
|
|
1336
|
+
}
|
|
1337
|
+
if (options.semantic === "en") {
|
|
1338
|
+
return "en";
|
|
1339
|
+
}
|
|
1340
|
+
if (options.languages?.length) {
|
|
1341
|
+
return selectOptimalBundle(new Set(options.languages));
|
|
1342
|
+
}
|
|
1343
|
+
if (languages.size === 0) {
|
|
1344
|
+
return "en";
|
|
1345
|
+
}
|
|
1346
|
+
return selectOptimalBundle(languages);
|
|
1347
|
+
}
|
|
1348
|
+
var SINGLE_LANGUAGE_BUNDLES = [
|
|
1349
|
+
"en",
|
|
1350
|
+
"es",
|
|
1351
|
+
"ja",
|
|
1352
|
+
"ar",
|
|
1353
|
+
"ko",
|
|
1354
|
+
"zh",
|
|
1355
|
+
"tr",
|
|
1356
|
+
"pt",
|
|
1357
|
+
"fr",
|
|
1358
|
+
"de",
|
|
1359
|
+
"id",
|
|
1360
|
+
"qu",
|
|
1361
|
+
"sw"
|
|
1362
|
+
];
|
|
1363
|
+
function selectOptimalBundle(languages) {
|
|
1364
|
+
if (languages.size === 0) {
|
|
1365
|
+
return "en";
|
|
1366
|
+
}
|
|
1367
|
+
const langArray = [...languages];
|
|
1368
|
+
if (langArray.length === 1) {
|
|
1369
|
+
const lang = langArray[0];
|
|
1370
|
+
if (SINGLE_LANGUAGE_BUNDLES.includes(lang)) {
|
|
1371
|
+
return lang;
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
if (langArray.length === 2 && langArray.includes("en") && langArray.includes("es")) {
|
|
1375
|
+
return "es-en";
|
|
1376
|
+
}
|
|
1377
|
+
if (langArray.every((l) => REGIONS.western.includes(l))) {
|
|
1378
|
+
return "western";
|
|
1379
|
+
}
|
|
1380
|
+
if (langArray.every((l) => REGIONS["east-asian"].includes(l))) {
|
|
1381
|
+
return "east-asian";
|
|
1382
|
+
}
|
|
1383
|
+
if (langArray.every((l) => REGIONS.priority.includes(l))) {
|
|
1384
|
+
return "priority";
|
|
1385
|
+
}
|
|
1386
|
+
return "all";
|
|
1387
|
+
}
|
|
1388
|
+
var SEMANTIC_BUNDLE_SIZES = {
|
|
1389
|
+
// Single-language bundles (all 13 languages)
|
|
1390
|
+
en: { raw: "82 KB", gzip: "~20 KB" },
|
|
1391
|
+
es: { raw: "64 KB", gzip: "~16 KB" },
|
|
1392
|
+
ja: { raw: "67 KB", gzip: "~17 KB" },
|
|
1393
|
+
ar: { raw: "66 KB", gzip: "~17 KB" },
|
|
1394
|
+
ko: { raw: "69 KB", gzip: "~18 KB" },
|
|
1395
|
+
zh: { raw: "58 KB", gzip: "~15 KB" },
|
|
1396
|
+
tr: { raw: "73 KB", gzip: "~18 KB" },
|
|
1397
|
+
pt: { raw: "56 KB", gzip: "~14 KB" },
|
|
1398
|
+
fr: { raw: "57 KB", gzip: "~14 KB" },
|
|
1399
|
+
de: { raw: "57 KB", gzip: "~14 KB" },
|
|
1400
|
+
id: { raw: "57 KB", gzip: "~14 KB" },
|
|
1401
|
+
qu: { raw: "56 KB", gzip: "~14 KB" },
|
|
1402
|
+
sw: { raw: "56 KB", gzip: "~14 KB" },
|
|
1403
|
+
// Regional bundles
|
|
1404
|
+
"es-en": { raw: "99 KB", gzip: "~25 KB" },
|
|
1405
|
+
western: { raw: "127 KB", gzip: "~30 KB" },
|
|
1406
|
+
"east-asian": { raw: "99 KB", gzip: "~24 KB" },
|
|
1407
|
+
priority: { raw: "231 KB", gzip: "~48 KB" },
|
|
1408
|
+
all: { raw: "324 KB", gzip: "~61 KB" }
|
|
1409
|
+
};
|
|
1410
|
+
function getSemanticBundleSize(bundleType) {
|
|
1411
|
+
return SEMANTIC_BUNDLE_SIZES[bundleType] ?? SEMANTIC_BUNDLE_SIZES.all;
|
|
1412
|
+
}
|
|
1413
|
+
function getSemanticBundleImport(_bundleType) {
|
|
1414
|
+
return "@lokascript/semantic";
|
|
1415
|
+
}
|
|
1416
|
+
function generateSemanticIntegrationCode(config) {
|
|
1417
|
+
if (!config.enabled || !config.bundleType) {
|
|
1418
|
+
return "";
|
|
1419
|
+
}
|
|
1420
|
+
const bundleImport = getSemanticBundleImport(config.bundleType);
|
|
1421
|
+
const languages = [...config.languages].join("', '");
|
|
1422
|
+
let code = `
|
|
1423
|
+
// =============================================================================
|
|
1424
|
+
// SEMANTIC PARSER INTEGRATION
|
|
1425
|
+
// =============================================================================
|
|
1426
|
+
|
|
1427
|
+
import {
|
|
1428
|
+
createSemanticAnalyzer,
|
|
1429
|
+
buildAST,
|
|
1430
|
+
isLanguageSupported,
|
|
1431
|
+
} from '${bundleImport}';
|
|
1432
|
+
`;
|
|
1433
|
+
if (config.grammarEnabled) {
|
|
1434
|
+
code += `
|
|
1435
|
+
import { GrammarTransformer, translate } from '@lokascript/i18n';
|
|
1436
|
+
|
|
1437
|
+
const grammarTransformer = new GrammarTransformer();
|
|
1438
|
+
`;
|
|
1439
|
+
}
|
|
1440
|
+
const aliasesCode = generateMultilingualAliases(config.languages);
|
|
1441
|
+
code += `
|
|
1442
|
+
const semanticAnalyzer = createSemanticAnalyzer();
|
|
1443
|
+
const SUPPORTED_SEMANTIC_LANGUAGES = ['${languages}', 'en'];
|
|
1444
|
+
const SEMANTIC_CONFIDENCE_THRESHOLD = 0.7;
|
|
1445
|
+
|
|
1446
|
+
${aliasesCode}
|
|
1447
|
+
|
|
1448
|
+
/**
|
|
1449
|
+
* Parse hyperscript using semantic parser with auto-language detection.
|
|
1450
|
+
* Tries each supported language until one returns a high-confidence result.
|
|
1451
|
+
* Falls back to HybridParser if none match.
|
|
1452
|
+
*
|
|
1453
|
+
* @param code - The hyperscript code to parse
|
|
1454
|
+
* @param lang - Optional language hint. If provided, tries this language first.
|
|
1455
|
+
*/
|
|
1456
|
+
function parseWithSemantic(code, lang = null) {
|
|
1457
|
+
// Determine languages to try: specified lang first, then others
|
|
1458
|
+
let languagesToTry = [...SUPPORTED_SEMANTIC_LANGUAGES];
|
|
1459
|
+
if (lang && !languagesToTry.includes(lang)) {
|
|
1460
|
+
languagesToTry.unshift(lang);
|
|
1461
|
+
} else if (lang) {
|
|
1462
|
+
// Move specified lang to front
|
|
1463
|
+
languagesToTry = [lang, ...languagesToTry.filter(l => l !== lang)];
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
// Try each language until one succeeds
|
|
1467
|
+
for (const tryLang of languagesToTry) {
|
|
1468
|
+
if (!isLanguageSupported(tryLang)) continue;
|
|
1469
|
+
try {
|
|
1470
|
+
const result = semanticAnalyzer.analyze(code, tryLang);
|
|
1471
|
+
if (result && result.confidence >= SEMANTIC_CONFIDENCE_THRESHOLD) {
|
|
1472
|
+
// buildAST returns {ast, warnings} - extract the ast
|
|
1473
|
+
const buildResult = buildAST(result.node);
|
|
1474
|
+
const ast = buildResult.ast;
|
|
1475
|
+
|
|
1476
|
+
// Semantic parser doesn't fully handle event handlers - fallback to HybridParser
|
|
1477
|
+
// Event handlers like "on click toggle .active" produce incomplete AST
|
|
1478
|
+
if (ast && ast.type === 'command' && ast.name === 'on') {
|
|
1479
|
+
break; // Fallback to HybridParser
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
return ast;
|
|
1483
|
+
}
|
|
1484
|
+
} catch (e) {
|
|
1485
|
+
// Continue trying other languages
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
// Fallback to HybridParser for event handlers and unrecognized patterns
|
|
1490
|
+
// Preprocess to translate non-ASCII keywords to English (tokenizer only accepts ASCII)
|
|
1491
|
+
const preprocessedCode = preprocessMultilingual(code);
|
|
1492
|
+
return new HybridParser(preprocessedCode).parse();
|
|
1493
|
+
}
|
|
1494
|
+
`;
|
|
1495
|
+
if (config.grammarEnabled) {
|
|
1496
|
+
code += `
|
|
1497
|
+
/**
|
|
1498
|
+
* Translate hyperscript between languages.
|
|
1499
|
+
*/
|
|
1500
|
+
function translateHyperscript(code, fromLang, toLang) {
|
|
1501
|
+
return translate(code, fromLang, toLang);
|
|
1502
|
+
}
|
|
1503
|
+
`;
|
|
1504
|
+
}
|
|
1505
|
+
return code;
|
|
1506
|
+
}
|
|
1507
|
+
function getSemanticExports(config) {
|
|
1508
|
+
const exports2 = [];
|
|
1509
|
+
if (config.enabled) {
|
|
1510
|
+
exports2.push("parseWithSemantic");
|
|
1511
|
+
exports2.push("SUPPORTED_SEMANTIC_LANGUAGES");
|
|
1512
|
+
}
|
|
1513
|
+
if (config.grammarEnabled) {
|
|
1514
|
+
exports2.push("translateHyperscript");
|
|
1515
|
+
exports2.push("grammarTransformer");
|
|
1516
|
+
}
|
|
1517
|
+
return exports2;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
// src/generator.ts
|
|
1521
|
+
function stripTypes(code) {
|
|
1522
|
+
return code.replace(/\s+as\s+\w+(?:\[\])?/g, "").replace(/\((\w+):\s*\w+\)/g, "($1)").replace(/\((\w+):\s*any\)/g, "($1)").replace(/Promise<void>\[\]/g, "Promise[]").replace(/Promise<void>/g, "Promise").replace(/:\s*TransitionEvent/g, "");
|
|
1523
|
+
}
|
|
1524
|
+
var COMMAND_IMPLEMENTATIONS = {};
|
|
1525
|
+
var BLOCK_IMPLEMENTATIONS = {};
|
|
1526
|
+
for (const [name, code] of Object.entries(import_bundle_generator.COMMAND_IMPLEMENTATIONS)) {
|
|
1527
|
+
COMMAND_IMPLEMENTATIONS[name] = stripTypes(code);
|
|
1528
|
+
}
|
|
1529
|
+
for (const [name, code] of Object.entries(import_bundle_generator.BLOCK_IMPLEMENTATIONS)) {
|
|
1530
|
+
BLOCK_IMPLEMENTATIONS[name] = stripTypes(code);
|
|
1531
|
+
}
|
|
1532
|
+
function generateBundleCode(config) {
|
|
1533
|
+
const {
|
|
1534
|
+
name,
|
|
1535
|
+
commands,
|
|
1536
|
+
blocks = [],
|
|
1537
|
+
htmxIntegration = false,
|
|
1538
|
+
globalName = "hyperfixi",
|
|
1539
|
+
positionalExpressions = false,
|
|
1540
|
+
parserImportPath = "../parser/hybrid",
|
|
1541
|
+
autoInit = true,
|
|
1542
|
+
esModule = true
|
|
1543
|
+
} = config;
|
|
1544
|
+
const needsStyleHelpers = commands.some((cmd) => import_bundle_generator.STYLE_COMMANDS.includes(cmd));
|
|
1545
|
+
const needsElementArrayHelper = commands.some((cmd) => import_bundle_generator.ELEMENT_ARRAY_COMMANDS.includes(cmd));
|
|
1546
|
+
const hasBlocks = blocks.length > 0;
|
|
1547
|
+
const hasReturn = commands.includes("return");
|
|
1548
|
+
const commandCases = commands.filter((cmd) => COMMAND_IMPLEMENTATIONS[cmd]).map((cmd) => COMMAND_IMPLEMENTATIONS[cmd]).join("\n");
|
|
1549
|
+
const blockCases = blocks.filter((block) => BLOCK_IMPLEMENTATIONS[block]).map((block) => BLOCK_IMPLEMENTATIONS[block]).join("\n");
|
|
1550
|
+
return `/**
|
|
1551
|
+
* HyperFixi ${name} Bundle (Auto-Generated)
|
|
1552
|
+
*
|
|
1553
|
+
* Generated by: @lokascript/vite-plugin
|
|
1554
|
+
* Commands: ${commands.join(", ")}${blocks.length > 0 ? `
|
|
1555
|
+
* Blocks: ${blocks.join(", ")}` : ""}${positionalExpressions ? "\n * Positional expressions: enabled" : ""}
|
|
1556
|
+
*
|
|
1557
|
+
* DO NOT EDIT - This file is automatically regenerated.
|
|
1558
|
+
*/
|
|
1559
|
+
|
|
1560
|
+
// Parser imports
|
|
1561
|
+
import { HybridParser, addCommandAliases } from '${parserImportPath}';
|
|
1562
|
+
|
|
1563
|
+
// Runtime state
|
|
1564
|
+
const globalVars = new Map();
|
|
1565
|
+
${hasBlocks ? "const MAX_LOOP_ITERATIONS = 1000;" : ""}
|
|
1566
|
+
|
|
1567
|
+
async function evaluate(node, ctx) {
|
|
1568
|
+
switch (node.type) {
|
|
1569
|
+
case 'literal': return node.value;
|
|
1570
|
+
|
|
1571
|
+
case 'identifier':
|
|
1572
|
+
if (node.value === 'me' || node.value === 'my') return ctx.me;
|
|
1573
|
+
if (node.value === 'it') return ctx.it;
|
|
1574
|
+
if (node.value === 'you') return ctx.you;
|
|
1575
|
+
if (node.value === 'event') return ctx.event;
|
|
1576
|
+
if (node.value === 'body') return document.body;
|
|
1577
|
+
if (node.value === 'document') return document;
|
|
1578
|
+
if (node.value === 'window') return window;
|
|
1579
|
+
if (ctx.locals.has(node.value)) return ctx.locals.get(node.value);
|
|
1580
|
+
if (node.value in ctx.me) return ctx.me[node.value];
|
|
1581
|
+
return node.value;
|
|
1582
|
+
|
|
1583
|
+
case 'contextReference':
|
|
1584
|
+
// Semantic AST format for context references (me, you, it, etc.)
|
|
1585
|
+
switch (node.contextType || node.name) {
|
|
1586
|
+
case 'me': return ctx.me;
|
|
1587
|
+
case 'it': return ctx.it;
|
|
1588
|
+
case 'you': return ctx.you;
|
|
1589
|
+
case 'event': return ctx.event;
|
|
1590
|
+
case 'body': return document.body;
|
|
1591
|
+
case 'document': return document;
|
|
1592
|
+
case 'window': return window;
|
|
1593
|
+
default: return ctx.me;
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
case 'variable':
|
|
1597
|
+
if (node.scope === 'local') return ctx.locals.get(node.name.slice(1));
|
|
1598
|
+
const gName = node.name.slice(1);
|
|
1599
|
+
if (globalVars.has(gName)) return globalVars.get(gName);
|
|
1600
|
+
return window[node.name];
|
|
1601
|
+
|
|
1602
|
+
case 'selector':
|
|
1603
|
+
const elements = document.querySelectorAll(node.value);
|
|
1604
|
+
return elements.length === 1 ? elements[0] : Array.from(elements);
|
|
1605
|
+
|
|
1606
|
+
case 'binary':
|
|
1607
|
+
return evaluateBinary(node, ctx);
|
|
1608
|
+
|
|
1609
|
+
case 'possessive':
|
|
1610
|
+
case 'member':
|
|
1611
|
+
const obj = await evaluate(node.object, ctx);
|
|
1612
|
+
if (obj == null) return undefined;
|
|
1613
|
+
const prop = node.computed ? await evaluate(node.property, ctx) : node.property;
|
|
1614
|
+
return obj[prop];
|
|
1615
|
+
|
|
1616
|
+
case 'call': {
|
|
1617
|
+
let callContext = null;
|
|
1618
|
+
let callee;
|
|
1619
|
+
|
|
1620
|
+
if (node.callee.type === 'member' || node.callee.type === 'possessive') {
|
|
1621
|
+
callContext = await evaluate(node.callee.object, ctx);
|
|
1622
|
+
const p = node.callee.computed
|
|
1623
|
+
? await evaluate(node.callee.property, ctx)
|
|
1624
|
+
: node.callee.property;
|
|
1625
|
+
callee = callContext?.[p];
|
|
1626
|
+
} else {
|
|
1627
|
+
callee = await evaluate(node.callee, ctx);
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
const args = await Promise.all(node.args.map(a => evaluate(a, ctx)));
|
|
1631
|
+
if (typeof callee === 'function') return callee.apply(callContext, args);
|
|
1632
|
+
return undefined;
|
|
1633
|
+
}
|
|
1634
|
+
${positionalExpressions ? `
|
|
1635
|
+
case 'positional':
|
|
1636
|
+
return evaluatePositional(node, ctx);
|
|
1637
|
+
` : ""}
|
|
1638
|
+
default: return undefined;
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
async function evaluateBinary(node, ctx) {
|
|
1643
|
+
if (node.operator === 'has') {
|
|
1644
|
+
const left = await evaluate(node.left, ctx);
|
|
1645
|
+
if (left instanceof Element && node.right.type === 'selector' && node.right.value.startsWith('.')) {
|
|
1646
|
+
return left.classList.contains(node.right.value.slice(1));
|
|
1647
|
+
}
|
|
1648
|
+
return false;
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
const left = await evaluate(node.left, ctx);
|
|
1652
|
+
const right = await evaluate(node.right, ctx);
|
|
1653
|
+
|
|
1654
|
+
switch (node.operator) {
|
|
1655
|
+
case '+': return left + right;
|
|
1656
|
+
case '-': return left - right;
|
|
1657
|
+
case '*': return left * right;
|
|
1658
|
+
case '/': return left / right;
|
|
1659
|
+
case '%': return left % right;
|
|
1660
|
+
case '==': case 'is': return left == right;
|
|
1661
|
+
case '!=': case 'is not': return left != right;
|
|
1662
|
+
case '<': return left < right;
|
|
1663
|
+
case '>': return left > right;
|
|
1664
|
+
case '<=': return left <= right;
|
|
1665
|
+
case '>=': return left >= right;
|
|
1666
|
+
case 'and': case '&&': return left && right;
|
|
1667
|
+
case 'or': case '||': return left || right;
|
|
1668
|
+
case 'contains': case 'includes':
|
|
1669
|
+
if (typeof left === 'string') return left.includes(right);
|
|
1670
|
+
if (Array.isArray(left)) return left.includes(right);
|
|
1671
|
+
if (left instanceof Element) return left.contains(right);
|
|
1672
|
+
return false;
|
|
1673
|
+
case 'matches':
|
|
1674
|
+
if (left instanceof Element) return left.matches(right);
|
|
1675
|
+
if (typeof left === 'string') return new RegExp(right).test(left);
|
|
1676
|
+
return false;
|
|
1677
|
+
default: return undefined;
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
${positionalExpressions ? `
|
|
1681
|
+
function evaluatePositional(node, ctx) {
|
|
1682
|
+
const target = node.target;
|
|
1683
|
+
let elements = [];
|
|
1684
|
+
|
|
1685
|
+
let selector = null;
|
|
1686
|
+
if (target.type === 'selector') {
|
|
1687
|
+
selector = target.value;
|
|
1688
|
+
} else if (target.type === 'identifier') {
|
|
1689
|
+
selector = target.value;
|
|
1690
|
+
} else if (target.type === 'htmlSelector') {
|
|
1691
|
+
selector = target.value;
|
|
1692
|
+
}
|
|
1693
|
+
if (selector) {
|
|
1694
|
+
elements = Array.from(document.querySelectorAll(selector));
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
switch (node.position) {
|
|
1698
|
+
case 'first': return elements[0] || null;
|
|
1699
|
+
case 'last': return elements[elements.length - 1] || null;
|
|
1700
|
+
case 'next': return ctx.me.nextElementSibling;
|
|
1701
|
+
case 'previous': return ctx.me.previousElementSibling;
|
|
1702
|
+
case 'closest': return target.value ? ctx.me.closest(target.value) : null;
|
|
1703
|
+
case 'parent': return ctx.me.parentElement;
|
|
1704
|
+
default: return elements[0] || null;
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
` : ""}
|
|
1708
|
+
${needsStyleHelpers ? `
|
|
1709
|
+
const isStyleProp = (prop) => prop?.startsWith('*');
|
|
1710
|
+
const getStyleName = (prop) => prop.substring(1);
|
|
1711
|
+
const setStyleProp = (el, prop, value) => {
|
|
1712
|
+
if (!isStyleProp(prop)) return false;
|
|
1713
|
+
el.style.setProperty(getStyleName(prop), String(value));
|
|
1714
|
+
return true;
|
|
1715
|
+
};
|
|
1716
|
+
` : ""}
|
|
1717
|
+
|
|
1718
|
+
${needsElementArrayHelper ? `
|
|
1719
|
+
const toElementArray = (val) => {
|
|
1720
|
+
if (Array.isArray(val)) return val.filter(e => e instanceof Element);
|
|
1721
|
+
if (val instanceof Element) return [val];
|
|
1722
|
+
if (typeof val === 'string') return Array.from(document.querySelectorAll(val));
|
|
1723
|
+
return [];
|
|
1724
|
+
};
|
|
1725
|
+
` : ""}
|
|
1726
|
+
|
|
1727
|
+
async function executeCommand(cmd, ctx) {
|
|
1728
|
+
const getTarget = async () => {
|
|
1729
|
+
// Support both HybridParser (cmd.target) and semantic AST (cmd.modifiers.on) formats
|
|
1730
|
+
const target = cmd.target || cmd.modifiers?.on;
|
|
1731
|
+
if (!target) return [ctx.me];
|
|
1732
|
+
const t = await evaluate(target, ctx);
|
|
1733
|
+
if (Array.isArray(t)) return t;
|
|
1734
|
+
if (t instanceof Element) return [t];
|
|
1735
|
+
if (typeof t === 'string') return Array.from(document.querySelectorAll(t));
|
|
1736
|
+
return [ctx.me];
|
|
1737
|
+
};
|
|
1738
|
+
|
|
1739
|
+
const getClassName = (node) => {
|
|
1740
|
+
if (!node) return '';
|
|
1741
|
+
if (node.type === 'selector') return node.value.slice(1);
|
|
1742
|
+
if (node.type === 'string' || node.type === 'literal') {
|
|
1743
|
+
const val = node.value;
|
|
1744
|
+
return typeof val === 'string' && val.startsWith('.') ? val.slice(1) : String(val);
|
|
1745
|
+
}
|
|
1746
|
+
if (node.type === 'identifier') return node.value;
|
|
1747
|
+
return '';
|
|
1748
|
+
};
|
|
1749
|
+
|
|
1750
|
+
switch (cmd.name) {
|
|
1751
|
+
${commandCases}
|
|
1752
|
+
|
|
1753
|
+
default:
|
|
1754
|
+
console.warn(\`${name} bundle: Unknown command '\${cmd.name}'\`);
|
|
1755
|
+
return null;
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
${hasBlocks ? `
|
|
1759
|
+
async function executeBlock(block, ctx) {
|
|
1760
|
+
switch (block.type) {
|
|
1761
|
+
${blockCases}
|
|
1762
|
+
|
|
1763
|
+
default:
|
|
1764
|
+
console.warn(\`${name} bundle: Unknown block '\${block.type}'\`);
|
|
1765
|
+
return null;
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
` : ""}
|
|
1769
|
+
async function executeSequence(nodes, ctx) {
|
|
1770
|
+
let result;
|
|
1771
|
+
for (const node of nodes) {
|
|
1772
|
+
if (node.type === 'command') {
|
|
1773
|
+
result = await executeCommand(node, ctx);
|
|
1774
|
+
}${hasBlocks ? ` else if (['if', 'repeat', 'for', 'while', 'fetch'].includes(node.type)) {
|
|
1775
|
+
result = await executeBlock(node, ctx);
|
|
1776
|
+
}` : ""}
|
|
1777
|
+
}
|
|
1778
|
+
return result;
|
|
1779
|
+
}
|
|
1780
|
+
${hasBlocks ? `
|
|
1781
|
+
async function executeSequenceWithBlocks(nodes, ctx) {
|
|
1782
|
+
try {
|
|
1783
|
+
return await executeSequence(nodes, ctx);
|
|
1784
|
+
} catch (e) {
|
|
1785
|
+
if (e?.type === 'return') throw e;
|
|
1786
|
+
throw e;
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
` : ""}
|
|
1790
|
+
async function executeAST(ast, me, event) {
|
|
1791
|
+
const ctx = { me, event, locals: new Map() };
|
|
1792
|
+
|
|
1793
|
+
if (ast.type === 'sequence') {
|
|
1794
|
+
${hasReturn || hasBlocks ? "try { return await executeSequence(ast.commands, ctx); } catch (e) { if (e?.type === 'return') return e.value; throw e; }" : "return executeSequence(ast.commands, ctx);"}
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
if (ast.type === 'event') {
|
|
1798
|
+
const eventNode = ast;
|
|
1799
|
+
const eventName = eventNode.event;
|
|
1800
|
+
|
|
1801
|
+
if (eventName === 'init') {
|
|
1802
|
+
${hasReturn || hasBlocks ? "try { await executeSequence(eventNode.body, ctx); } catch (e) { if (e?.type !== 'return') throw e; }" : "await executeSequence(eventNode.body, ctx);"}
|
|
1803
|
+
return;
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
const target = eventNode.filter ? await evaluate(eventNode.filter, ctx) : me;
|
|
1807
|
+
const targetEl = target instanceof Element ? target : me;
|
|
1808
|
+
const mods = eventNode.modifiers;
|
|
1809
|
+
|
|
1810
|
+
let handler = async (e) => {
|
|
1811
|
+
if (mods.prevent) e.preventDefault();
|
|
1812
|
+
if (mods.stop) e.stopPropagation();
|
|
1813
|
+
|
|
1814
|
+
const handlerCtx = {
|
|
1815
|
+
me, event: e,
|
|
1816
|
+
you: e.target instanceof Element ? e.target : undefined,
|
|
1817
|
+
locals: new Map(),
|
|
1818
|
+
};
|
|
1819
|
+
${hasReturn || hasBlocks ? "try { await executeSequence(eventNode.body, handlerCtx); } catch (err) { if (err?.type !== 'return') throw err; }" : "await executeSequence(eventNode.body, handlerCtx);"}
|
|
1820
|
+
};
|
|
1821
|
+
|
|
1822
|
+
if (mods.debounce) {
|
|
1823
|
+
let timeout;
|
|
1824
|
+
const orig = handler;
|
|
1825
|
+
handler = async (e) => {
|
|
1826
|
+
clearTimeout(timeout);
|
|
1827
|
+
timeout = setTimeout(() => orig(e), mods.debounce);
|
|
1828
|
+
};
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
if (mods.throttle) {
|
|
1832
|
+
let lastCall = 0;
|
|
1833
|
+
const orig = handler;
|
|
1834
|
+
handler = async (e) => {
|
|
1835
|
+
const now = Date.now();
|
|
1836
|
+
if (now - lastCall >= mods.throttle) {
|
|
1837
|
+
lastCall = now;
|
|
1838
|
+
await orig(e);
|
|
1839
|
+
}
|
|
1840
|
+
};
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
targetEl.addEventListener(eventName, handler, { once: !!mods.once });
|
|
1844
|
+
return;
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
// Handle single command (not wrapped in event or sequence)
|
|
1848
|
+
if (ast.type === 'command') {
|
|
1849
|
+
return executeCommand(ast, ctx);
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
return null;
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
function processElement(el) {
|
|
1856
|
+
const code = el.getAttribute('_');
|
|
1857
|
+
if (!code) return;
|
|
1858
|
+
|
|
1859
|
+
try {
|
|
1860
|
+
const parser = new HybridParser(code);
|
|
1861
|
+
const ast = parser.parse();
|
|
1862
|
+
executeAST(ast, el);
|
|
1863
|
+
} catch (err) {
|
|
1864
|
+
console.error('HyperFixi ${name} error:', err, 'Code:', code);
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
function processElements(root = document) {
|
|
1869
|
+
const elements = root.querySelectorAll('[_]');
|
|
1870
|
+
elements.forEach(processElement);
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
const api = {
|
|
1874
|
+
version: '1.0.0-${name.toLowerCase().replace(/\s+/g, "-")}',
|
|
1875
|
+
|
|
1876
|
+
parse(code) {
|
|
1877
|
+
const parser = new HybridParser(code);
|
|
1878
|
+
return parser.parse();
|
|
1879
|
+
},
|
|
1880
|
+
|
|
1881
|
+
async execute(code, element) {
|
|
1882
|
+
const me = element || document.body;
|
|
1883
|
+
const parser = new HybridParser(code);
|
|
1884
|
+
const ast = parser.parse();
|
|
1885
|
+
return executeAST(ast, me);
|
|
1886
|
+
},
|
|
1887
|
+
|
|
1888
|
+
run: async (code, element) => api.execute(code, element),
|
|
1889
|
+
eval: async (code, element) => api.execute(code, element),
|
|
1890
|
+
|
|
1891
|
+
init: processElements,
|
|
1892
|
+
process: processElements,
|
|
1893
|
+
|
|
1894
|
+
commands: ${JSON.stringify(commands)},
|
|
1895
|
+
${blocks.length > 0 ? `blocks: ${JSON.stringify(blocks)},` : ""}
|
|
1896
|
+
parserName: 'hybrid',
|
|
1897
|
+
};
|
|
1898
|
+
${autoInit ? `
|
|
1899
|
+
if (typeof window !== 'undefined') {
|
|
1900
|
+
window.${globalName} = api;
|
|
1901
|
+
window._hyperscript = api;
|
|
1902
|
+
|
|
1903
|
+
if (document.readyState === 'loading') {
|
|
1904
|
+
document.addEventListener('DOMContentLoaded', () => processElements());
|
|
1905
|
+
} else {
|
|
1906
|
+
processElements();
|
|
1907
|
+
}
|
|
1908
|
+
${htmxIntegration ? `
|
|
1909
|
+
document.addEventListener('htmx:afterSettle', (e) => {
|
|
1910
|
+
const target = e.detail?.target;
|
|
1911
|
+
if (target) processElements(target);
|
|
1912
|
+
});
|
|
1913
|
+
` : ""}
|
|
1914
|
+
}
|
|
1915
|
+
` : ""}
|
|
1916
|
+
${esModule ? `
|
|
1917
|
+
export default api;
|
|
1918
|
+
export { api, processElements };
|
|
1919
|
+
` : ""}`;
|
|
1920
|
+
}
|
|
1921
|
+
var Generator = class {
|
|
1922
|
+
constructor(options) {
|
|
1923
|
+
this.debug = options.debug ?? false;
|
|
1924
|
+
}
|
|
1925
|
+
/**
|
|
1926
|
+
* Generate bundle code from aggregated usage
|
|
1927
|
+
*/
|
|
1928
|
+
generate(usage, options) {
|
|
1929
|
+
const commands = [...usage.commands, ...options.extraCommands ?? []];
|
|
1930
|
+
const blocks = [...usage.blocks, ...options.extraBlocks ?? []];
|
|
1931
|
+
const positional = usage.positional || options.positional || false;
|
|
1932
|
+
const semanticConfig = resolveSemanticConfig(options, usage.detectedLanguages);
|
|
1933
|
+
if (commands.length === 0 && blocks.length === 0 && !positional && !semanticConfig.enabled) {
|
|
1934
|
+
return this.generateEmptyBundle(options);
|
|
1935
|
+
}
|
|
1936
|
+
const config = {
|
|
1937
|
+
name: options.bundleName ?? "ViteAutoGenerated",
|
|
1938
|
+
commands,
|
|
1939
|
+
blocks,
|
|
1940
|
+
positionalExpressions: positional,
|
|
1941
|
+
htmxIntegration: options.htmx ?? false,
|
|
1942
|
+
globalName: options.globalName ?? "hyperfixi",
|
|
1943
|
+
// Use @lokascript/core package path for virtual module
|
|
1944
|
+
parserImportPath: "@lokascript/core/parser/hybrid",
|
|
1945
|
+
autoInit: true,
|
|
1946
|
+
esModule: true
|
|
1947
|
+
};
|
|
1948
|
+
if (this.debug) {
|
|
1949
|
+
const bundleInfo = {
|
|
1950
|
+
commands,
|
|
1951
|
+
blocks,
|
|
1952
|
+
positional,
|
|
1953
|
+
htmx: config.htmxIntegration,
|
|
1954
|
+
semantic: semanticConfig.enabled
|
|
1955
|
+
};
|
|
1956
|
+
if (semanticConfig.enabled && semanticConfig.bundleType) {
|
|
1957
|
+
const sizeInfo = getSemanticBundleSize(semanticConfig.bundleType);
|
|
1958
|
+
bundleInfo.semanticBundle = semanticConfig.bundleType;
|
|
1959
|
+
bundleInfo.semanticSize = sizeInfo.gzip;
|
|
1960
|
+
bundleInfo.languages = [...semanticConfig.languages];
|
|
1961
|
+
bundleInfo.grammar = semanticConfig.grammarEnabled;
|
|
1962
|
+
}
|
|
1963
|
+
console.log("[hyperfixi] Generating bundle:", bundleInfo);
|
|
1964
|
+
if (semanticConfig.bundleType === "all" || semanticConfig.bundleType === "priority") {
|
|
1965
|
+
console.log(
|
|
1966
|
+
`[hyperfixi] Note: Using '${semanticConfig.bundleType}' semantic bundle (${getSemanticBundleSize(semanticConfig.bundleType).gzip}). Consider using 'region' option to select a smaller regional bundle if all languages aren't needed.`
|
|
1967
|
+
);
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
let bundleCode = generateBundleCode(config);
|
|
1971
|
+
if (semanticConfig.enabled) {
|
|
1972
|
+
bundleCode = this.addSemanticIntegration(bundleCode, semanticConfig);
|
|
1973
|
+
}
|
|
1974
|
+
return bundleCode;
|
|
1975
|
+
}
|
|
1976
|
+
/**
|
|
1977
|
+
* Add semantic integration code to the bundle
|
|
1978
|
+
*/
|
|
1979
|
+
addSemanticIntegration(bundleCode, config) {
|
|
1980
|
+
const semanticCode = generateSemanticIntegrationCode(config);
|
|
1981
|
+
const semanticExports = getSemanticExports(config);
|
|
1982
|
+
const parserImportEnd = bundleCode.indexOf("// Runtime state");
|
|
1983
|
+
if (parserImportEnd === -1) {
|
|
1984
|
+
bundleCode = semanticCode + "\n" + bundleCode;
|
|
1985
|
+
} else {
|
|
1986
|
+
bundleCode = bundleCode.slice(0, parserImportEnd) + semanticCode + "\n\n" + bundleCode.slice(parserImportEnd);
|
|
1987
|
+
}
|
|
1988
|
+
bundleCode = bundleCode.replace(
|
|
1989
|
+
/function processElement\(el\) \{\s*const code = el\.getAttribute\('_'\);\s*if \(!code\) return;\s*try \{\s*const parser = new HybridParser\(code\);\s*const ast = parser\.parse\(\);/g,
|
|
1990
|
+
`function processElement(el) {
|
|
1991
|
+
const code = el.getAttribute('_');
|
|
1992
|
+
if (!code) return;
|
|
1993
|
+
|
|
1994
|
+
try {
|
|
1995
|
+
const ast = parseWithSemantic(code);`
|
|
1996
|
+
);
|
|
1997
|
+
bundleCode = bundleCode.replace(
|
|
1998
|
+
/parse\(code\) \{\s*const parser = new HybridParser\(code\);\s*return parser\.parse\(\);/g,
|
|
1999
|
+
`parse(code, lang = null) {
|
|
2000
|
+
return parseWithSemantic(code, lang);`
|
|
2001
|
+
);
|
|
2002
|
+
bundleCode = bundleCode.replace(
|
|
2003
|
+
/async execute\(code, element\) \{\s*const me = element \|\| document\.body;\s*const parser = new HybridParser\(code\);\s*const ast = parser\.parse\(\);/g,
|
|
2004
|
+
`async execute(code, element, lang = null) {
|
|
2005
|
+
const me = element || document.body;
|
|
2006
|
+
const ast = parseWithSemantic(code, lang);`
|
|
2007
|
+
);
|
|
2008
|
+
if (semanticExports.length > 0) {
|
|
2009
|
+
const apiExportsMarker = "parserName: 'hybrid',";
|
|
2010
|
+
const additionalApiProps = semanticExports.map((exp) => ` ${exp},`).join("\n");
|
|
2011
|
+
bundleCode = bundleCode.replace(
|
|
2012
|
+
apiExportsMarker,
|
|
2013
|
+
`parserName: 'hybrid',
|
|
2014
|
+
${additionalApiProps}`
|
|
2015
|
+
);
|
|
2016
|
+
}
|
|
2017
|
+
return bundleCode;
|
|
2018
|
+
}
|
|
2019
|
+
/**
|
|
2020
|
+
* Generate an empty bundle when no hyperscript is detected
|
|
2021
|
+
*/
|
|
2022
|
+
generateEmptyBundle(options) {
|
|
2023
|
+
const globalName = options.globalName ?? "hyperfixi";
|
|
2024
|
+
return `/**
|
|
2025
|
+
* HyperFixi Empty Bundle (Auto-Generated)
|
|
2026
|
+
*
|
|
2027
|
+
* No hyperscript usage detected. This bundle provides a minimal API.
|
|
2028
|
+
* Add hyperscript attributes (_="...") to your HTML to enable features.
|
|
2029
|
+
*
|
|
2030
|
+
* Generated by: @lokascript/vite-plugin
|
|
2031
|
+
*/
|
|
2032
|
+
|
|
2033
|
+
const api = {
|
|
2034
|
+
version: '1.0.0-empty',
|
|
2035
|
+
commands: [],
|
|
2036
|
+
parserName: 'none',
|
|
2037
|
+
|
|
2038
|
+
parse() {
|
|
2039
|
+
console.warn('HyperFixi: No parser loaded. Add hyperscript to your HTML to enable parsing.');
|
|
2040
|
+
return { type: 'empty' };
|
|
2041
|
+
},
|
|
2042
|
+
|
|
2043
|
+
async execute(code, element) {
|
|
2044
|
+
console.warn('HyperFixi: No commands loaded. Detected commands will be automatically included.');
|
|
2045
|
+
return null;
|
|
2046
|
+
},
|
|
2047
|
+
|
|
2048
|
+
run: async (code, element) => api.execute(code, element),
|
|
2049
|
+
eval: async (code, element) => api.execute(code, element),
|
|
2050
|
+
|
|
2051
|
+
init() {},
|
|
2052
|
+
process() {},
|
|
2053
|
+
};
|
|
2054
|
+
|
|
2055
|
+
if (typeof window !== 'undefined') {
|
|
2056
|
+
(window).${globalName} = api;
|
|
2057
|
+
(window)._hyperscript = api;
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
export default api;
|
|
2061
|
+
export { api };
|
|
2062
|
+
`;
|
|
2063
|
+
}
|
|
2064
|
+
/**
|
|
2065
|
+
* Generate a development fallback bundle
|
|
2066
|
+
*/
|
|
2067
|
+
generateDevFallback(fallback) {
|
|
2068
|
+
const bundle = fallback === "full" ? "@lokascript/core/browser" : "@lokascript/core/browser/hybrid-complete";
|
|
2069
|
+
return `/**
|
|
2070
|
+
* HyperFixi Dev Fallback Bundle
|
|
2071
|
+
*
|
|
2072
|
+
* Using pre-built ${fallback} bundle for faster development.
|
|
2073
|
+
* Production builds will generate minimal bundles.
|
|
2074
|
+
*
|
|
2075
|
+
* Generated by: @lokascript/vite-plugin
|
|
2076
|
+
*/
|
|
2077
|
+
|
|
2078
|
+
export * from '${bundle}';
|
|
2079
|
+
export { default } from '${bundle}';
|
|
2080
|
+
`;
|
|
2081
|
+
}
|
|
2082
|
+
};
|
|
2083
|
+
|
|
2084
|
+
// src/compiler.ts
|
|
2085
|
+
var import_parser_core = require("@lokascript/core/parser/hybrid/parser-core");
|
|
2086
|
+
var semanticAnalyzer = null;
|
|
2087
|
+
var buildASTFn = null;
|
|
2088
|
+
function setSemanticParser(analyzer, buildAST) {
|
|
2089
|
+
semanticAnalyzer = analyzer;
|
|
2090
|
+
buildASTFn = buildAST;
|
|
2091
|
+
}
|
|
2092
|
+
function clearSemanticParser() {
|
|
2093
|
+
semanticAnalyzer = null;
|
|
2094
|
+
buildASTFn = null;
|
|
2095
|
+
}
|
|
2096
|
+
function hasSemanticParser() {
|
|
2097
|
+
return semanticAnalyzer !== null && buildASTFn !== null;
|
|
2098
|
+
}
|
|
2099
|
+
var SEMANTIC_CONFIDENCE_THRESHOLD = 0.7;
|
|
2100
|
+
var multilingualAliases = {};
|
|
2101
|
+
var multilingualRegex = null;
|
|
2102
|
+
function setMultilingualAliases(aliases) {
|
|
2103
|
+
multilingualAliases = { ...aliases };
|
|
2104
|
+
if (Object.keys(aliases).length > 0) {
|
|
2105
|
+
const escapedKeys = Object.keys(aliases).map((k) => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
2106
|
+
multilingualRegex = new RegExp(`(^|\\s)(${escapedKeys})(?=\\s|\\.|$)`, "g");
|
|
2107
|
+
} else {
|
|
2108
|
+
multilingualRegex = null;
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
function preprocessMultilingual(code) {
|
|
2112
|
+
if (!multilingualRegex) return code;
|
|
2113
|
+
return code.replace(multilingualRegex, (match, prefix, keyword) => {
|
|
2114
|
+
const english = multilingualAliases[keyword];
|
|
2115
|
+
return english ? prefix + english : match;
|
|
2116
|
+
});
|
|
2117
|
+
}
|
|
2118
|
+
function sanitizeClassName(name) {
|
|
2119
|
+
if (!/^-?[a-zA-Z_][a-zA-Z0-9_-]*$/.test(name)) {
|
|
2120
|
+
return null;
|
|
2121
|
+
}
|
|
2122
|
+
return name;
|
|
2123
|
+
}
|
|
2124
|
+
function sanitizeSelector(selector) {
|
|
2125
|
+
return selector.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\0/g, "");
|
|
2126
|
+
}
|
|
2127
|
+
function hashScript(script) {
|
|
2128
|
+
let hash = 5381;
|
|
2129
|
+
for (let i = 0; i < script.length; i++) {
|
|
2130
|
+
hash = (hash << 5) + hash ^ script.charCodeAt(i);
|
|
2131
|
+
}
|
|
2132
|
+
return Math.abs(hash).toString(36).slice(0, 4);
|
|
2133
|
+
}
|
|
2134
|
+
var usedIds = /* @__PURE__ */ new Set();
|
|
2135
|
+
function resetCompiler() {
|
|
2136
|
+
usedIds.clear();
|
|
2137
|
+
}
|
|
2138
|
+
function generateHandlerId(event, command, script) {
|
|
2139
|
+
const hash = hashScript(script);
|
|
2140
|
+
let id = `${event}_${command}_${hash}`;
|
|
2141
|
+
let suffix = 0;
|
|
2142
|
+
while (usedIds.has(id)) {
|
|
2143
|
+
id = `${event}_${command}_${hash}${suffix++}`;
|
|
2144
|
+
}
|
|
2145
|
+
usedIds.add(id);
|
|
2146
|
+
return id;
|
|
2147
|
+
}
|
|
2148
|
+
function compile(script, options = {}) {
|
|
2149
|
+
const { language = "en", debug = false } = options;
|
|
2150
|
+
try {
|
|
2151
|
+
let ast;
|
|
2152
|
+
if (language !== "en" && semanticAnalyzer && buildASTFn) {
|
|
2153
|
+
if (semanticAnalyzer.supportsLanguage(language)) {
|
|
2154
|
+
const result = semanticAnalyzer.analyze(script, language);
|
|
2155
|
+
if (result.node && result.confidence >= SEMANTIC_CONFIDENCE_THRESHOLD) {
|
|
2156
|
+
const { ast: builtAST, warnings } = buildASTFn(result.node);
|
|
2157
|
+
if (debug && warnings.length > 0) {
|
|
2158
|
+
console.log(`[hyperfixi] Semantic AST warnings for "${script}":`, warnings);
|
|
2159
|
+
}
|
|
2160
|
+
ast = builtAST;
|
|
2161
|
+
if (debug) {
|
|
2162
|
+
console.log(
|
|
2163
|
+
`[hyperfixi] Compiled ${language}: "${script}" (confidence: ${result.confidence.toFixed(2)})`
|
|
2164
|
+
);
|
|
2165
|
+
}
|
|
2166
|
+
} else {
|
|
2167
|
+
if (debug) {
|
|
2168
|
+
const reason = result.errors?.join(", ") || `low confidence (${result.confidence.toFixed(2)})`;
|
|
2169
|
+
console.log(`[hyperfixi] Semantic parse failed for "${script}": ${reason}`);
|
|
2170
|
+
}
|
|
2171
|
+
return null;
|
|
2172
|
+
}
|
|
2173
|
+
} else {
|
|
2174
|
+
if (debug) {
|
|
2175
|
+
console.log(`[hyperfixi] Language "${language}" not supported by semantic parser`);
|
|
2176
|
+
}
|
|
2177
|
+
return null;
|
|
2178
|
+
}
|
|
2179
|
+
} else if (language !== "en") {
|
|
2180
|
+
if (debug) {
|
|
2181
|
+
console.log(
|
|
2182
|
+
`[hyperfixi] Semantic parser not available for "${language}". Install @lokascript/semantic and call setSemanticParser().`
|
|
2183
|
+
);
|
|
2184
|
+
}
|
|
2185
|
+
return null;
|
|
2186
|
+
} else {
|
|
2187
|
+
const preprocessedScript = preprocessMultilingual(script);
|
|
2188
|
+
const parser = new import_parser_core.HybridParser(preprocessedScript);
|
|
2189
|
+
ast = parser.parse();
|
|
2190
|
+
}
|
|
2191
|
+
return compileAST(ast, script);
|
|
2192
|
+
} catch (error) {
|
|
2193
|
+
if (debug) {
|
|
2194
|
+
console.warn(`[hyperfixi] Failed to compile: ${script}`, error);
|
|
2195
|
+
}
|
|
2196
|
+
return null;
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
function extractPrimaryCommand(body) {
|
|
2200
|
+
if (body.length === 0) return "handler";
|
|
2201
|
+
const first = body[0];
|
|
2202
|
+
if (first.type === "command") {
|
|
2203
|
+
return first.name || "cmd";
|
|
2204
|
+
}
|
|
2205
|
+
return first.type || "handler";
|
|
2206
|
+
}
|
|
2207
|
+
function compileAST(ast, original) {
|
|
2208
|
+
if (ast.type !== "event") {
|
|
2209
|
+
return null;
|
|
2210
|
+
}
|
|
2211
|
+
const eventNode = ast;
|
|
2212
|
+
const event = eventNode.event;
|
|
2213
|
+
const modifiers = eventNode.modifiers || {};
|
|
2214
|
+
const body = eventNode.body || [];
|
|
2215
|
+
const { code, needsEvaluator, needsLocals, needsGlobals } = compileBody(body);
|
|
2216
|
+
if (code === null || code === "") {
|
|
2217
|
+
return null;
|
|
2218
|
+
}
|
|
2219
|
+
const command = extractPrimaryCommand(body);
|
|
2220
|
+
const id = generateHandlerId(event, command, original);
|
|
2221
|
+
return {
|
|
2222
|
+
id,
|
|
2223
|
+
event,
|
|
2224
|
+
modifiers: {
|
|
2225
|
+
prevent: modifiers.prevent,
|
|
2226
|
+
stop: modifiers.stop,
|
|
2227
|
+
once: modifiers.once,
|
|
2228
|
+
debounce: modifiers.debounce,
|
|
2229
|
+
throttle: modifiers.throttle
|
|
2230
|
+
},
|
|
2231
|
+
code,
|
|
2232
|
+
needsEvaluator: needsEvaluator || needsLocals || needsGlobals,
|
|
2233
|
+
original
|
|
2234
|
+
};
|
|
2235
|
+
}
|
|
2236
|
+
function compileBody(nodes) {
|
|
2237
|
+
const statements = [];
|
|
2238
|
+
let needsEvaluator = false;
|
|
2239
|
+
let needsLocals = false;
|
|
2240
|
+
let needsGlobals = false;
|
|
2241
|
+
for (const node of nodes) {
|
|
2242
|
+
const result = compileNode(node);
|
|
2243
|
+
if (result === null) {
|
|
2244
|
+
return { code: null, needsEvaluator: false, needsLocals: false, needsGlobals: false };
|
|
2245
|
+
}
|
|
2246
|
+
statements.push(result.code);
|
|
2247
|
+
needsEvaluator = needsEvaluator || result.needsEvaluator;
|
|
2248
|
+
needsLocals = needsLocals || result.needsLocals;
|
|
2249
|
+
needsGlobals = needsGlobals || result.needsGlobals;
|
|
2250
|
+
}
|
|
2251
|
+
return {
|
|
2252
|
+
code: statements.join("\n"),
|
|
2253
|
+
needsEvaluator,
|
|
2254
|
+
needsLocals,
|
|
2255
|
+
needsGlobals
|
|
2256
|
+
};
|
|
2257
|
+
}
|
|
2258
|
+
function compileNode(node) {
|
|
2259
|
+
if (node.type === "command") {
|
|
2260
|
+
return compileCommand(node);
|
|
2261
|
+
}
|
|
2262
|
+
return null;
|
|
2263
|
+
}
|
|
2264
|
+
function compileCommand(cmd) {
|
|
2265
|
+
const target = cmd.target ? compileTarget(cmd.target) : "m";
|
|
2266
|
+
switch (cmd.name) {
|
|
2267
|
+
case "toggle":
|
|
2268
|
+
return compileToggle(cmd.args, target);
|
|
2269
|
+
case "add":
|
|
2270
|
+
return compileAdd(cmd.args, target);
|
|
2271
|
+
case "remove":
|
|
2272
|
+
return compileRemove(cmd.args, target);
|
|
2273
|
+
case "removeClass":
|
|
2274
|
+
return compileRemoveClass(cmd.args, target);
|
|
2275
|
+
case "show":
|
|
2276
|
+
return {
|
|
2277
|
+
code: `${target}.style.display = ''`,
|
|
2278
|
+
needsEvaluator: false,
|
|
2279
|
+
needsLocals: false,
|
|
2280
|
+
needsGlobals: false
|
|
2281
|
+
};
|
|
2282
|
+
case "hide":
|
|
2283
|
+
return {
|
|
2284
|
+
code: `${target}.style.display = 'none'`,
|
|
2285
|
+
needsEvaluator: false,
|
|
2286
|
+
needsLocals: false,
|
|
2287
|
+
needsGlobals: false
|
|
2288
|
+
};
|
|
2289
|
+
case "focus":
|
|
2290
|
+
return {
|
|
2291
|
+
code: `${target}.focus()`,
|
|
2292
|
+
needsEvaluator: false,
|
|
2293
|
+
needsLocals: false,
|
|
2294
|
+
needsGlobals: false
|
|
2295
|
+
};
|
|
2296
|
+
case "blur":
|
|
2297
|
+
return {
|
|
2298
|
+
code: `${target}.blur()`,
|
|
2299
|
+
needsEvaluator: false,
|
|
2300
|
+
needsLocals: false,
|
|
2301
|
+
needsGlobals: false
|
|
2302
|
+
};
|
|
2303
|
+
case "log":
|
|
2304
|
+
return compileLog(cmd.args);
|
|
2305
|
+
case "set":
|
|
2306
|
+
return compileSet(cmd.args);
|
|
2307
|
+
case "increment":
|
|
2308
|
+
return compileIncrement(cmd.args);
|
|
2309
|
+
case "decrement":
|
|
2310
|
+
return compileDecrement(cmd.args);
|
|
2311
|
+
case "put":
|
|
2312
|
+
return compilePut(cmd.args, target, cmd.modifier);
|
|
2313
|
+
case "send":
|
|
2314
|
+
case "trigger":
|
|
2315
|
+
return compileTrigger(cmd.args, target);
|
|
2316
|
+
case "wait":
|
|
2317
|
+
return compileWait(cmd.args);
|
|
2318
|
+
default:
|
|
2319
|
+
return null;
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
function compileToggle(args, target) {
|
|
2323
|
+
const className = extractClassName(args[0]);
|
|
2324
|
+
if (!className) return null;
|
|
2325
|
+
if (target === "m") {
|
|
2326
|
+
return {
|
|
2327
|
+
code: `m.classList.toggle('${className}')`,
|
|
2328
|
+
needsEvaluator: false,
|
|
2329
|
+
needsLocals: false,
|
|
2330
|
+
needsGlobals: false
|
|
2331
|
+
};
|
|
2332
|
+
}
|
|
2333
|
+
return {
|
|
2334
|
+
code: `${target}.forEach(el => el.classList.toggle('${className}'))`,
|
|
2335
|
+
needsEvaluator: false,
|
|
2336
|
+
needsLocals: false,
|
|
2337
|
+
needsGlobals: false
|
|
2338
|
+
};
|
|
2339
|
+
}
|
|
2340
|
+
function compileAdd(args, target) {
|
|
2341
|
+
const className = extractClassName(args[0]);
|
|
2342
|
+
if (!className) return null;
|
|
2343
|
+
if (target === "m") {
|
|
2344
|
+
return {
|
|
2345
|
+
code: `m.classList.add('${className}')`,
|
|
2346
|
+
needsEvaluator: false,
|
|
2347
|
+
needsLocals: false,
|
|
2348
|
+
needsGlobals: false
|
|
2349
|
+
};
|
|
2350
|
+
}
|
|
2351
|
+
return {
|
|
2352
|
+
code: `${target}.forEach(el => el.classList.add('${className}'))`,
|
|
2353
|
+
needsEvaluator: false,
|
|
2354
|
+
needsLocals: false,
|
|
2355
|
+
needsGlobals: false
|
|
2356
|
+
};
|
|
2357
|
+
}
|
|
2358
|
+
function compileRemove(args, target) {
|
|
2359
|
+
if (!args || args.length === 0) {
|
|
2360
|
+
return {
|
|
2361
|
+
code: `${target}.remove()`,
|
|
2362
|
+
needsEvaluator: false,
|
|
2363
|
+
needsLocals: false,
|
|
2364
|
+
needsGlobals: false
|
|
2365
|
+
};
|
|
2366
|
+
}
|
|
2367
|
+
const className = extractClassName(args[0]);
|
|
2368
|
+
if (!className) return null;
|
|
2369
|
+
if (target === "m") {
|
|
2370
|
+
return {
|
|
2371
|
+
code: `m.classList.remove('${className}')`,
|
|
2372
|
+
needsEvaluator: false,
|
|
2373
|
+
needsLocals: false,
|
|
2374
|
+
needsGlobals: false
|
|
2375
|
+
};
|
|
2376
|
+
}
|
|
2377
|
+
return {
|
|
2378
|
+
code: `${target}.forEach(el => el.classList.remove('${className}'))`,
|
|
2379
|
+
needsEvaluator: false,
|
|
2380
|
+
needsLocals: false,
|
|
2381
|
+
needsGlobals: false
|
|
2382
|
+
};
|
|
2383
|
+
}
|
|
2384
|
+
function compileRemoveClass(args, target) {
|
|
2385
|
+
const className = extractClassName(args[0]);
|
|
2386
|
+
if (!className) return null;
|
|
2387
|
+
if (target === "m") {
|
|
2388
|
+
return {
|
|
2389
|
+
code: `m.classList.remove('${className}')`,
|
|
2390
|
+
needsEvaluator: false,
|
|
2391
|
+
needsLocals: false,
|
|
2392
|
+
needsGlobals: false
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2395
|
+
return {
|
|
2396
|
+
code: `${target}.forEach(el => el.classList.remove('${className}'))`,
|
|
2397
|
+
needsEvaluator: false,
|
|
2398
|
+
needsLocals: false,
|
|
2399
|
+
needsGlobals: false
|
|
2400
|
+
};
|
|
2401
|
+
}
|
|
2402
|
+
function compileLog(args) {
|
|
2403
|
+
const compiled = args.map(compileExpression).filter(Boolean);
|
|
2404
|
+
if (compiled.length !== args.length) {
|
|
2405
|
+
return {
|
|
2406
|
+
code: `console.log(${compiled.join(", ")})`,
|
|
2407
|
+
needsEvaluator: true,
|
|
2408
|
+
needsLocals: false,
|
|
2409
|
+
needsGlobals: false
|
|
2410
|
+
};
|
|
2411
|
+
}
|
|
2412
|
+
return {
|
|
2413
|
+
code: `console.log(${compiled.join(", ")})`,
|
|
2414
|
+
needsEvaluator: false,
|
|
2415
|
+
needsLocals: false,
|
|
2416
|
+
needsGlobals: false
|
|
2417
|
+
};
|
|
2418
|
+
}
|
|
2419
|
+
function compileSet(args) {
|
|
2420
|
+
if (args.length < 2) return null;
|
|
2421
|
+
const [target, value] = args;
|
|
2422
|
+
const compiledValue = compileExpression(value);
|
|
2423
|
+
if (!compiledValue) return null;
|
|
2424
|
+
if (target.type === "variable") {
|
|
2425
|
+
const varNode = target;
|
|
2426
|
+
if (varNode.scope === "local") {
|
|
2427
|
+
const varName = varNode.name.slice(1);
|
|
2428
|
+
return {
|
|
2429
|
+
code: `L.${varName} = ${compiledValue}`,
|
|
2430
|
+
needsEvaluator: false,
|
|
2431
|
+
needsLocals: true,
|
|
2432
|
+
needsGlobals: false
|
|
2433
|
+
};
|
|
2434
|
+
}
|
|
2435
|
+
if (varNode.scope === "global") {
|
|
2436
|
+
const varName = varNode.name.slice(1);
|
|
2437
|
+
return {
|
|
2438
|
+
code: `G.${varName} = ${compiledValue}`,
|
|
2439
|
+
needsEvaluator: false,
|
|
2440
|
+
needsLocals: false,
|
|
2441
|
+
needsGlobals: true
|
|
2442
|
+
};
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
if (target.type === "possessive") {
|
|
2446
|
+
const possNode = target;
|
|
2447
|
+
const obj = compileExpression(possNode.object);
|
|
2448
|
+
const prop = possNode.property;
|
|
2449
|
+
if (!obj) return null;
|
|
2450
|
+
if (prop.startsWith("*")) {
|
|
2451
|
+
const styleProp = prop.slice(1);
|
|
2452
|
+
return {
|
|
2453
|
+
code: `${obj}.style.${styleProp} = ${compiledValue}`,
|
|
2454
|
+
needsEvaluator: false,
|
|
2455
|
+
needsLocals: false,
|
|
2456
|
+
needsGlobals: false
|
|
2457
|
+
};
|
|
2458
|
+
}
|
|
2459
|
+
return {
|
|
2460
|
+
code: `${obj}.${prop} = ${compiledValue}`,
|
|
2461
|
+
needsEvaluator: false,
|
|
2462
|
+
needsLocals: false,
|
|
2463
|
+
needsGlobals: false
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2466
|
+
if (target.type === "member") {
|
|
2467
|
+
const memNode = target;
|
|
2468
|
+
const obj = compileExpression(memNode.object);
|
|
2469
|
+
const prop = typeof memNode.property === "string" ? memNode.property : null;
|
|
2470
|
+
if (!obj || !prop) return null;
|
|
2471
|
+
if (prop.startsWith("*")) {
|
|
2472
|
+
const styleProp = prop.slice(1);
|
|
2473
|
+
return {
|
|
2474
|
+
code: `${obj}.style.${styleProp} = ${compiledValue}`,
|
|
2475
|
+
needsEvaluator: false,
|
|
2476
|
+
needsLocals: false,
|
|
2477
|
+
needsGlobals: false
|
|
2478
|
+
};
|
|
2479
|
+
}
|
|
2480
|
+
return {
|
|
2481
|
+
code: `${obj}.${prop} = ${compiledValue}`,
|
|
2482
|
+
needsEvaluator: false,
|
|
2483
|
+
needsLocals: false,
|
|
2484
|
+
needsGlobals: false
|
|
2485
|
+
};
|
|
2486
|
+
}
|
|
2487
|
+
return null;
|
|
2488
|
+
}
|
|
2489
|
+
function compileIncrement(args) {
|
|
2490
|
+
if (args.length < 1) return null;
|
|
2491
|
+
const target = args[0];
|
|
2492
|
+
const amount = args.length > 1 ? compileExpression(args[1]) : "1";
|
|
2493
|
+
if (target.type === "variable") {
|
|
2494
|
+
const varNode = target;
|
|
2495
|
+
if (varNode.scope === "local") {
|
|
2496
|
+
const varName = varNode.name.slice(1);
|
|
2497
|
+
return {
|
|
2498
|
+
code: `L.${varName} = (L.${varName} || 0) + ${amount}`,
|
|
2499
|
+
needsEvaluator: false,
|
|
2500
|
+
needsLocals: true,
|
|
2501
|
+
needsGlobals: false
|
|
2502
|
+
};
|
|
2503
|
+
}
|
|
2504
|
+
if (varNode.scope === "global") {
|
|
2505
|
+
const varName = varNode.name.slice(1);
|
|
2506
|
+
return {
|
|
2507
|
+
code: `G.${varName} = (G.${varName} || 0) + ${amount}`,
|
|
2508
|
+
needsEvaluator: false,
|
|
2509
|
+
needsLocals: false,
|
|
2510
|
+
needsGlobals: true
|
|
2511
|
+
};
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
const compiled = compileExpression(target);
|
|
2515
|
+
if (compiled) {
|
|
2516
|
+
return {
|
|
2517
|
+
code: `${compiled}.textContent = (parseFloat(${compiled}.textContent) || 0) + ${amount}`,
|
|
2518
|
+
needsEvaluator: false,
|
|
2519
|
+
needsLocals: false,
|
|
2520
|
+
needsGlobals: false
|
|
2521
|
+
};
|
|
2522
|
+
}
|
|
2523
|
+
return null;
|
|
2524
|
+
}
|
|
2525
|
+
function compileDecrement(args) {
|
|
2526
|
+
if (args.length < 1) return null;
|
|
2527
|
+
const target = args[0];
|
|
2528
|
+
const amount = args.length > 1 ? compileExpression(args[1]) : "1";
|
|
2529
|
+
if (target.type === "variable") {
|
|
2530
|
+
const varNode = target;
|
|
2531
|
+
if (varNode.scope === "local") {
|
|
2532
|
+
const varName = varNode.name.slice(1);
|
|
2533
|
+
return {
|
|
2534
|
+
code: `L.${varName} = (L.${varName} || 0) - ${amount}`,
|
|
2535
|
+
needsEvaluator: false,
|
|
2536
|
+
needsLocals: true,
|
|
2537
|
+
needsGlobals: false
|
|
2538
|
+
};
|
|
2539
|
+
}
|
|
2540
|
+
if (varNode.scope === "global") {
|
|
2541
|
+
const varName = varNode.name.slice(1);
|
|
2542
|
+
return {
|
|
2543
|
+
code: `G.${varName} = (G.${varName} || 0) - ${amount}`,
|
|
2544
|
+
needsEvaluator: false,
|
|
2545
|
+
needsLocals: false,
|
|
2546
|
+
needsGlobals: true
|
|
2547
|
+
};
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
const compiled = compileExpression(target);
|
|
2551
|
+
if (compiled) {
|
|
2552
|
+
return {
|
|
2553
|
+
code: `${compiled}.textContent = (parseFloat(${compiled}.textContent) || 0) - ${amount}`,
|
|
2554
|
+
needsEvaluator: false,
|
|
2555
|
+
needsLocals: false,
|
|
2556
|
+
needsGlobals: false
|
|
2557
|
+
};
|
|
2558
|
+
}
|
|
2559
|
+
return null;
|
|
2560
|
+
}
|
|
2561
|
+
function compilePut(args, target, modifier) {
|
|
2562
|
+
if (args.length < 1) return null;
|
|
2563
|
+
const content = compileExpression(args[0]);
|
|
2564
|
+
if (!content) return null;
|
|
2565
|
+
const mod = modifier || "into";
|
|
2566
|
+
switch (mod) {
|
|
2567
|
+
case "into":
|
|
2568
|
+
return {
|
|
2569
|
+
code: `${target}.innerHTML = ${content}`,
|
|
2570
|
+
needsEvaluator: false,
|
|
2571
|
+
needsLocals: false,
|
|
2572
|
+
needsGlobals: false
|
|
2573
|
+
};
|
|
2574
|
+
case "before":
|
|
2575
|
+
return {
|
|
2576
|
+
code: `${target}.insertAdjacentHTML('beforebegin', ${content})`,
|
|
2577
|
+
needsEvaluator: false,
|
|
2578
|
+
needsLocals: false,
|
|
2579
|
+
needsGlobals: false
|
|
2580
|
+
};
|
|
2581
|
+
case "after":
|
|
2582
|
+
return {
|
|
2583
|
+
code: `${target}.insertAdjacentHTML('afterend', ${content})`,
|
|
2584
|
+
needsEvaluator: false,
|
|
2585
|
+
needsLocals: false,
|
|
2586
|
+
needsGlobals: false
|
|
2587
|
+
};
|
|
2588
|
+
case "at start of":
|
|
2589
|
+
return {
|
|
2590
|
+
code: `${target}.insertAdjacentHTML('afterbegin', ${content})`,
|
|
2591
|
+
needsEvaluator: false,
|
|
2592
|
+
needsLocals: false,
|
|
2593
|
+
needsGlobals: false
|
|
2594
|
+
};
|
|
2595
|
+
case "at end of":
|
|
2596
|
+
return {
|
|
2597
|
+
code: `${target}.insertAdjacentHTML('beforeend', ${content})`,
|
|
2598
|
+
needsEvaluator: false,
|
|
2599
|
+
needsLocals: false,
|
|
2600
|
+
needsGlobals: false
|
|
2601
|
+
};
|
|
2602
|
+
default:
|
|
2603
|
+
return {
|
|
2604
|
+
code: `${target}.innerHTML = ${content}`,
|
|
2605
|
+
needsEvaluator: false,
|
|
2606
|
+
needsLocals: false,
|
|
2607
|
+
needsGlobals: false
|
|
2608
|
+
};
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
function compileTrigger(args, target) {
|
|
2612
|
+
if (args.length < 1) return null;
|
|
2613
|
+
const eventName = compileExpression(args[0]);
|
|
2614
|
+
if (!eventName) return null;
|
|
2615
|
+
return {
|
|
2616
|
+
code: `${target}.dispatchEvent(new CustomEvent(${eventName}, { bubbles: true }))`,
|
|
2617
|
+
needsEvaluator: false,
|
|
2618
|
+
needsLocals: false,
|
|
2619
|
+
needsGlobals: false
|
|
2620
|
+
};
|
|
2621
|
+
}
|
|
2622
|
+
function compileWait(args) {
|
|
2623
|
+
if (args.length < 1) return null;
|
|
2624
|
+
const duration = compileExpression(args[0]);
|
|
2625
|
+
if (!duration) return null;
|
|
2626
|
+
return {
|
|
2627
|
+
code: `await new Promise(r => setTimeout(r, ${duration}))`,
|
|
2628
|
+
needsEvaluator: false,
|
|
2629
|
+
needsLocals: false,
|
|
2630
|
+
needsGlobals: false
|
|
2631
|
+
};
|
|
2632
|
+
}
|
|
2633
|
+
function compileExpression(node) {
|
|
2634
|
+
if (!node) return null;
|
|
2635
|
+
switch (node.type) {
|
|
2636
|
+
case "literal": {
|
|
2637
|
+
const litNode = node;
|
|
2638
|
+
return JSON.stringify(litNode.value);
|
|
2639
|
+
}
|
|
2640
|
+
case "identifier": {
|
|
2641
|
+
const idNode = node;
|
|
2642
|
+
const val = idNode.value;
|
|
2643
|
+
if (val === "me" || val === "my") return "m";
|
|
2644
|
+
if (val === "you") return "y";
|
|
2645
|
+
if (val === "it") return "it";
|
|
2646
|
+
if (val === "event") return "e";
|
|
2647
|
+
if (val === "body") return "document.body";
|
|
2648
|
+
if (val === "document") return "document";
|
|
2649
|
+
if (val === "window") return "window";
|
|
2650
|
+
return val;
|
|
2651
|
+
}
|
|
2652
|
+
case "variable": {
|
|
2653
|
+
const varNode = node;
|
|
2654
|
+
const name = varNode.name.slice(1);
|
|
2655
|
+
return varNode.scope === "local" ? `L.${name}` : `G.${name}`;
|
|
2656
|
+
}
|
|
2657
|
+
case "selector": {
|
|
2658
|
+
const selNode = node;
|
|
2659
|
+
const sanitized = sanitizeSelector(selNode.value);
|
|
2660
|
+
return `document.querySelector('${sanitized}')`;
|
|
2661
|
+
}
|
|
2662
|
+
case "possessive": {
|
|
2663
|
+
const possNode = node;
|
|
2664
|
+
const obj = compileExpression(possNode.object);
|
|
2665
|
+
const prop = possNode.property;
|
|
2666
|
+
if (!obj) return null;
|
|
2667
|
+
if (prop.startsWith("*")) {
|
|
2668
|
+
return `${obj}.style.${prop.slice(1)}`;
|
|
2669
|
+
}
|
|
2670
|
+
return `${obj}.${prop}`;
|
|
2671
|
+
}
|
|
2672
|
+
case "member": {
|
|
2673
|
+
const memNode = node;
|
|
2674
|
+
const obj = compileExpression(memNode.object);
|
|
2675
|
+
const prop = typeof memNode.property === "string" ? memNode.property : null;
|
|
2676
|
+
if (!obj || !prop) return null;
|
|
2677
|
+
if (prop.startsWith("*")) {
|
|
2678
|
+
return `${obj}.style.${prop.slice(1)}`;
|
|
2679
|
+
}
|
|
2680
|
+
return `${obj}.${prop}`;
|
|
2681
|
+
}
|
|
2682
|
+
case "binary": {
|
|
2683
|
+
const binNode = node;
|
|
2684
|
+
const left = compileExpression(binNode.left);
|
|
2685
|
+
const right = compileExpression(binNode.right);
|
|
2686
|
+
if (!left || !right) return null;
|
|
2687
|
+
const op = binNode.operator;
|
|
2688
|
+
switch (op) {
|
|
2689
|
+
case "+":
|
|
2690
|
+
case "-":
|
|
2691
|
+
case "*":
|
|
2692
|
+
case "/":
|
|
2693
|
+
case "%":
|
|
2694
|
+
return `(${left} ${op} ${right})`;
|
|
2695
|
+
case "==":
|
|
2696
|
+
case "is":
|
|
2697
|
+
return `(${left} == ${right})`;
|
|
2698
|
+
case "!=":
|
|
2699
|
+
case "is not":
|
|
2700
|
+
return `(${left} != ${right})`;
|
|
2701
|
+
case "<":
|
|
2702
|
+
case ">":
|
|
2703
|
+
case "<=":
|
|
2704
|
+
case ">=":
|
|
2705
|
+
return `(${left} ${op} ${right})`;
|
|
2706
|
+
case "and":
|
|
2707
|
+
case "&&":
|
|
2708
|
+
return `(${left} && ${right})`;
|
|
2709
|
+
case "or":
|
|
2710
|
+
case "||":
|
|
2711
|
+
return `(${left} || ${right})`;
|
|
2712
|
+
case "has": {
|
|
2713
|
+
const rightSel = binNode.right;
|
|
2714
|
+
const className = rightSel.value?.slice(1) || "";
|
|
2715
|
+
const sanitizedClass = sanitizeClassName(className);
|
|
2716
|
+
if (!sanitizedClass) return null;
|
|
2717
|
+
return `${left}.classList.contains('${sanitizedClass}')`;
|
|
2718
|
+
}
|
|
2719
|
+
default:
|
|
2720
|
+
return null;
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
case "call": {
|
|
2724
|
+
const callNode = node;
|
|
2725
|
+
const callee = callNode.callee;
|
|
2726
|
+
const args = (callNode.args || []).map(compileExpression);
|
|
2727
|
+
if (args.some((a) => a === null)) return null;
|
|
2728
|
+
if (callee.type === "member" || callee.type === "possessive") {
|
|
2729
|
+
const memCallee = callee;
|
|
2730
|
+
const obj = compileExpression(memCallee.object);
|
|
2731
|
+
const prop = typeof memCallee.property === "string" ? memCallee.property : null;
|
|
2732
|
+
if (!obj || !prop) return null;
|
|
2733
|
+
return `${obj}.${prop}(${args.join(", ")})`;
|
|
2734
|
+
}
|
|
2735
|
+
const fn = compileExpression(callee);
|
|
2736
|
+
if (!fn) return null;
|
|
2737
|
+
return `${fn}(${args.join(", ")})`;
|
|
2738
|
+
}
|
|
2739
|
+
case "positional": {
|
|
2740
|
+
const posNode = node;
|
|
2741
|
+
const position = posNode.position;
|
|
2742
|
+
const target = posNode.target;
|
|
2743
|
+
switch (position) {
|
|
2744
|
+
case "first":
|
|
2745
|
+
if (target?.type === "selector") {
|
|
2746
|
+
const selNode = target;
|
|
2747
|
+
const sanitized = sanitizeSelector(selNode.value);
|
|
2748
|
+
return `document.querySelector('${sanitized}')`;
|
|
2749
|
+
}
|
|
2750
|
+
return null;
|
|
2751
|
+
// Arrays need runtime
|
|
2752
|
+
case "last":
|
|
2753
|
+
if (target?.type === "selector") {
|
|
2754
|
+
const selNode = target;
|
|
2755
|
+
const sanitized = sanitizeSelector(selNode.value);
|
|
2756
|
+
return `(()=>{const e=document.querySelectorAll('${sanitized}');return e[e.length-1]})()`;
|
|
2757
|
+
}
|
|
2758
|
+
return null;
|
|
2759
|
+
// Arrays need runtime
|
|
2760
|
+
case "next":
|
|
2761
|
+
return "m.nextElementSibling";
|
|
2762
|
+
case "previous":
|
|
2763
|
+
return "m.previousElementSibling";
|
|
2764
|
+
case "closest":
|
|
2765
|
+
if (target?.type === "selector") {
|
|
2766
|
+
const selNode = target;
|
|
2767
|
+
const sanitized = sanitizeSelector(selNode.value);
|
|
2768
|
+
return `m.closest('${sanitized}')`;
|
|
2769
|
+
}
|
|
2770
|
+
return null;
|
|
2771
|
+
case "parent":
|
|
2772
|
+
return "m.parentElement";
|
|
2773
|
+
default:
|
|
2774
|
+
return null;
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
default:
|
|
2778
|
+
return null;
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
function compileTarget(target) {
|
|
2782
|
+
if (target.type === "identifier") {
|
|
2783
|
+
const idNode = target;
|
|
2784
|
+
if (idNode.value === "me" || idNode.value === "my") return "m";
|
|
2785
|
+
if (idNode.value === "you") return "y";
|
|
2786
|
+
}
|
|
2787
|
+
if (target.type === "selector") {
|
|
2788
|
+
const selNode = target;
|
|
2789
|
+
const sanitized = sanitizeSelector(selNode.value);
|
|
2790
|
+
return `document.querySelectorAll('${sanitized}')`;
|
|
2791
|
+
}
|
|
2792
|
+
const compiled = compileExpression(target);
|
|
2793
|
+
return compiled || "m";
|
|
2794
|
+
}
|
|
2795
|
+
function extractClassName(node) {
|
|
2796
|
+
if (!node) return null;
|
|
2797
|
+
if (node.type === "selector") {
|
|
2798
|
+
const selNode = node;
|
|
2799
|
+
const val = selNode.value;
|
|
2800
|
+
const rawClass = val.startsWith(".") ? val.slice(1) : val;
|
|
2801
|
+
return sanitizeClassName(rawClass);
|
|
2802
|
+
}
|
|
2803
|
+
if (node.type === "literal" || node.type === "string") {
|
|
2804
|
+
const litNode = node;
|
|
2805
|
+
const val = litNode.value;
|
|
2806
|
+
if (typeof val === "string") {
|
|
2807
|
+
const rawClass = val.startsWith(".") ? val.slice(1) : val;
|
|
2808
|
+
return sanitizeClassName(rawClass);
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
if (node.type === "identifier") {
|
|
2812
|
+
const idNode = node;
|
|
2813
|
+
return sanitizeClassName(idNode.value);
|
|
2814
|
+
}
|
|
2815
|
+
return null;
|
|
2816
|
+
}
|
|
2817
|
+
|
|
2818
|
+
// src/compiled-generator.ts
|
|
2819
|
+
function generateSourceMapTable(handlers) {
|
|
2820
|
+
if (handlers.length === 0) return "";
|
|
2821
|
+
const lines = [
|
|
2822
|
+
" *",
|
|
2823
|
+
" * Handler Source Map:",
|
|
2824
|
+
" * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"
|
|
2825
|
+
];
|
|
2826
|
+
for (const h of handlers) {
|
|
2827
|
+
const original = h.original.replace(/\n/g, " ").slice(0, 40);
|
|
2828
|
+
const truncated = original.length < h.original.length ? original + "..." : original;
|
|
2829
|
+
lines.push(` * \u2502 ${h.id.padEnd(20)} \u2190 ${truncated.padEnd(40)} \u2502`);
|
|
2830
|
+
}
|
|
2831
|
+
lines.push(" * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
|
|
2832
|
+
lines.push(" *");
|
|
2833
|
+
return lines.join("\n");
|
|
2834
|
+
}
|
|
2835
|
+
function generateCompiledBundle(options) {
|
|
2836
|
+
const {
|
|
2837
|
+
handlers,
|
|
2838
|
+
needsLocals,
|
|
2839
|
+
needsGlobals,
|
|
2840
|
+
globalName = "hyperfixi",
|
|
2841
|
+
htmx = false,
|
|
2842
|
+
debug = false
|
|
2843
|
+
} = options;
|
|
2844
|
+
const handlerEntries = handlers.map((h) => {
|
|
2845
|
+
const isAsync = h.code.includes("await");
|
|
2846
|
+
const fn = isAsync ? `async(m,e,y)=>{${h.code}}` : `(m,e,y)=>{${h.code}}`;
|
|
2847
|
+
if (debug) {
|
|
2848
|
+
const escapedOriginal = h.original.replace(/\*/g, "\\*").replace(/\n/g, " ");
|
|
2849
|
+
return `
|
|
2850
|
+
/* ${escapedOriginal} */
|
|
2851
|
+
${h.id}:${fn}`;
|
|
2852
|
+
}
|
|
2853
|
+
return `${h.id}:${fn}`;
|
|
2854
|
+
});
|
|
2855
|
+
const registrations = handlers.map((h) => {
|
|
2856
|
+
const modsCode = generateModifiersCode(h);
|
|
2857
|
+
return ` case '${h.id}': r(el,'${h.event}',H.${h.id}${modsCode}); break;`;
|
|
2858
|
+
});
|
|
2859
|
+
const localsCode = needsLocals ? "const L={};" : "";
|
|
2860
|
+
const globalsCode = needsGlobals ? "const G={};" : "";
|
|
2861
|
+
const sourceMapTable = debug ? generateSourceMapTable(handlers) : "";
|
|
2862
|
+
return `/**
|
|
2863
|
+
* HyperFixi Compiled Bundle (Auto-Generated)
|
|
2864
|
+
*
|
|
2865
|
+
* Pre-compiled hyperscript - no runtime parser needed!
|
|
2866
|
+
* Handlers: ${handlers.length}
|
|
2867
|
+
*
|
|
2868
|
+
* DO NOT EDIT - Regenerate with build.
|
|
2869
|
+
${sourceMapTable} */
|
|
2870
|
+
|
|
2871
|
+
${localsCode}${globalsCode}
|
|
2872
|
+
const H={${handlerEntries.join(",")}};
|
|
2873
|
+
|
|
2874
|
+
function r(el,ev,fn${hasModifiers(handlers) ? ",m" : ""}){
|
|
2875
|
+
let h=e=>fn(el,e,e.target);
|
|
2876
|
+
${generateModifierWrappers(handlers)}
|
|
2877
|
+
el.addEventListener(ev,h${hasOnce(handlers) ? ",{once:m?.o}" : ""});
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
function init(root=document){
|
|
2881
|
+
root.querySelectorAll('[data-h]').forEach(el=>{
|
|
2882
|
+
switch(el.dataset.h){
|
|
2883
|
+
${registrations.join("\n")}
|
|
2884
|
+
}
|
|
2885
|
+
});
|
|
2886
|
+
}
|
|
2887
|
+
|
|
2888
|
+
${htmx ? `document.addEventListener('htmx:afterSettle',e=>init(e.detail?.target));` : ""}
|
|
2889
|
+
|
|
2890
|
+
const api={
|
|
2891
|
+
version:'1.0.0-compiled',
|
|
2892
|
+
commands:${JSON.stringify(handlers.map((h) => h.id))},
|
|
2893
|
+
init,
|
|
2894
|
+
process:init,
|
|
2895
|
+
};
|
|
2896
|
+
|
|
2897
|
+
if(typeof window!=='undefined'){
|
|
2898
|
+
window.${globalName}=api;
|
|
2899
|
+
window._hyperscript=api;
|
|
2900
|
+
document.readyState==='loading'
|
|
2901
|
+
?document.addEventListener('DOMContentLoaded',()=>init())
|
|
2902
|
+
:init();
|
|
2903
|
+
}
|
|
2904
|
+
|
|
2905
|
+
export default api;
|
|
2906
|
+
export{api,init};
|
|
2907
|
+
`;
|
|
2908
|
+
}
|
|
2909
|
+
function generateModifiersCode(h) {
|
|
2910
|
+
const mods = [];
|
|
2911
|
+
if (h.modifiers.prevent) mods.push("p:1");
|
|
2912
|
+
if (h.modifiers.stop) mods.push("s:1");
|
|
2913
|
+
if (h.modifiers.once) mods.push("o:1");
|
|
2914
|
+
if (h.modifiers.debounce) mods.push(`d:${h.modifiers.debounce}`);
|
|
2915
|
+
if (h.modifiers.throttle) mods.push(`t:${h.modifiers.throttle}`);
|
|
2916
|
+
if (mods.length === 0) return "";
|
|
2917
|
+
return `,{${mods.join(",")}}`;
|
|
2918
|
+
}
|
|
2919
|
+
function hasModifiers(handlers) {
|
|
2920
|
+
return handlers.some(
|
|
2921
|
+
(h) => h.modifiers.prevent || h.modifiers.stop || h.modifiers.once || h.modifiers.debounce || h.modifiers.throttle
|
|
2922
|
+
);
|
|
2923
|
+
}
|
|
2924
|
+
function hasOnce(handlers) {
|
|
2925
|
+
return handlers.some((h) => h.modifiers.once);
|
|
2926
|
+
}
|
|
2927
|
+
function generateModifierWrappers(handlers) {
|
|
2928
|
+
const lines = [];
|
|
2929
|
+
if (handlers.some((h) => h.modifiers.prevent || h.modifiers.stop)) {
|
|
2930
|
+
lines.push(
|
|
2931
|
+
` if(m?.p||m?.s){const _h=h;h=e=>{m.p&&e.preventDefault();m.s&&e.stopPropagation();_h(e.currentTarget,e,e.target)};}`
|
|
2932
|
+
);
|
|
2933
|
+
}
|
|
2934
|
+
if (handlers.some((h) => h.modifiers.debounce)) {
|
|
2935
|
+
lines.push(
|
|
2936
|
+
` if(m?.d){let t;const _h=h;h=e=>{clearTimeout(t);t=setTimeout(()=>_h(e.currentTarget,e,e.target),m.d)};}`
|
|
2937
|
+
);
|
|
2938
|
+
}
|
|
2939
|
+
if (handlers.some((h) => h.modifiers.throttle)) {
|
|
2940
|
+
lines.push(
|
|
2941
|
+
` if(m?.t){let l=0;const _h=h;h=e=>{const n=Date.now();if(n-l>=m.t){l=n;_h(e.currentTarget,e,e.target)}};}`
|
|
2942
|
+
);
|
|
2943
|
+
}
|
|
2944
|
+
return lines.join("\n");
|
|
2945
|
+
}
|
|
2946
|
+
|
|
2947
|
+
// src/html-transformer.ts
|
|
2948
|
+
function transformHTML(html, handlerMap, fallbackScripts) {
|
|
2949
|
+
let modified = false;
|
|
2950
|
+
const fallbacks = [];
|
|
2951
|
+
const patterns = [
|
|
2952
|
+
/(\s)_\s*=\s*"([^"]+)"/g,
|
|
2953
|
+
// _="..."
|
|
2954
|
+
/(\s)_\s*=\s*'([^']+)'/g,
|
|
2955
|
+
// _='...'
|
|
2956
|
+
/(\s)_\s*=\s*`([^`]+)`/g
|
|
2957
|
+
// _=`...`
|
|
2958
|
+
];
|
|
2959
|
+
let result = html;
|
|
2960
|
+
for (const pattern of patterns) {
|
|
2961
|
+
result = result.replace(pattern, (match, whitespace, script) => {
|
|
2962
|
+
const handlerId = handlerMap.get(script);
|
|
2963
|
+
if (handlerId) {
|
|
2964
|
+
modified = true;
|
|
2965
|
+
return `${whitespace}data-h="${handlerId}"`;
|
|
2966
|
+
}
|
|
2967
|
+
if (fallbackScripts.has(script)) {
|
|
2968
|
+
fallbacks.push(script);
|
|
2969
|
+
return match;
|
|
2970
|
+
}
|
|
2971
|
+
fallbacks.push(script);
|
|
2972
|
+
return match;
|
|
2973
|
+
});
|
|
2974
|
+
}
|
|
2975
|
+
return {
|
|
2976
|
+
code: result,
|
|
2977
|
+
modified,
|
|
2978
|
+
fallbacks
|
|
2979
|
+
};
|
|
2980
|
+
}
|
|
2981
|
+
function extractScripts(html) {
|
|
2982
|
+
const scripts = [];
|
|
2983
|
+
const patterns = [/_\s*=\s*"([^"]+)"/g, /_\s*=\s*'([^']+)'/g, /_\s*=\s*`([^`]+)`/g];
|
|
2984
|
+
for (const pattern of patterns) {
|
|
2985
|
+
let match;
|
|
2986
|
+
while (match = pattern.exec(html)) {
|
|
2987
|
+
scripts.push(match[1]);
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
return scripts;
|
|
2991
|
+
}
|
|
2992
|
+
|
|
2993
|
+
// src/index.ts
|
|
2994
|
+
var VIRTUAL_MODULE_ID = "virtual:hyperfixi";
|
|
2995
|
+
var RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
|
|
2996
|
+
var IMPORT_ALIASES = ["hyperfixi", "@lokascript/core", "virtual:hyperfixi"];
|
|
2997
|
+
function hyperfixi(options = {}) {
|
|
2998
|
+
const mode = options.mode ?? "interpret";
|
|
2999
|
+
const scanner = new Scanner(options);
|
|
3000
|
+
const aggregator = new Aggregator();
|
|
3001
|
+
const generator = new Generator(options);
|
|
3002
|
+
let server = null;
|
|
3003
|
+
let cachedBundle = null;
|
|
3004
|
+
let lastUsageHash = "";
|
|
3005
|
+
let isDev = false;
|
|
3006
|
+
const compiledHandlers = [];
|
|
3007
|
+
const handlerMap = /* @__PURE__ */ new Map();
|
|
3008
|
+
const fallbackScripts = /* @__PURE__ */ new Set();
|
|
3009
|
+
let needsLocals = false;
|
|
3010
|
+
let needsGlobals = false;
|
|
3011
|
+
function computeUsageHash(usage) {
|
|
3012
|
+
const commands = [...usage.commands].sort().join(",");
|
|
3013
|
+
const blocks = [...usage.blocks].sort().join(",");
|
|
3014
|
+
const languages = [...usage.detectedLanguages].sort().join(",");
|
|
3015
|
+
return `${commands}|${blocks}|${usage.positional}|${languages}`;
|
|
3016
|
+
}
|
|
3017
|
+
function invalidateVirtualModule() {
|
|
3018
|
+
if (!server) return;
|
|
3019
|
+
const mod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_MODULE_ID);
|
|
3020
|
+
if (mod) {
|
|
3021
|
+
server.moduleGraph.invalidateModule(mod);
|
|
3022
|
+
server.ws.send({ type: "full-reload" });
|
|
3023
|
+
if (options.debug) {
|
|
3024
|
+
console.log("[hyperfixi] Virtual module invalidated, triggering reload");
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
function compileScript(script) {
|
|
3029
|
+
if (handlerMap.has(script)) {
|
|
3030
|
+
return handlerMap.get(script);
|
|
3031
|
+
}
|
|
3032
|
+
if (fallbackScripts.has(script)) {
|
|
3033
|
+
return null;
|
|
3034
|
+
}
|
|
3035
|
+
const handler = compile(script);
|
|
3036
|
+
if (handler) {
|
|
3037
|
+
compiledHandlers.push(handler);
|
|
3038
|
+
handlerMap.set(script, handler.id);
|
|
3039
|
+
if (handler.needsEvaluator) {
|
|
3040
|
+
if (handler.code.includes("L.")) needsLocals = true;
|
|
3041
|
+
if (handler.code.includes("G.")) needsGlobals = true;
|
|
3042
|
+
}
|
|
3043
|
+
if (options.debug) {
|
|
3044
|
+
console.log(`[hyperfixi] Compiled: "${script}" -> ${handler.id}`);
|
|
3045
|
+
}
|
|
3046
|
+
return handler.id;
|
|
3047
|
+
}
|
|
3048
|
+
fallbackScripts.add(script);
|
|
3049
|
+
if (options.debug) {
|
|
3050
|
+
console.log(`[hyperfixi] Fallback (not compilable): "${script}"`);
|
|
3051
|
+
}
|
|
3052
|
+
return null;
|
|
3053
|
+
}
|
|
3054
|
+
function generateInterpretBundle() {
|
|
3055
|
+
const usage = aggregator.getUsage();
|
|
3056
|
+
const usageHash = computeUsageHash(usage);
|
|
3057
|
+
if (cachedBundle && usageHash === lastUsageHash) {
|
|
3058
|
+
return cachedBundle;
|
|
3059
|
+
}
|
|
3060
|
+
if (isDev && options.devFallback && options.devFallback !== "auto") {
|
|
3061
|
+
cachedBundle = generator.generateDevFallback(options.devFallback);
|
|
3062
|
+
} else {
|
|
3063
|
+
cachedBundle = generator.generate(usage, options);
|
|
3064
|
+
}
|
|
3065
|
+
lastUsageHash = usageHash;
|
|
3066
|
+
if (options.debug) {
|
|
3067
|
+
const summary = aggregator.getSummary();
|
|
3068
|
+
console.log("[hyperfixi] Bundle generated:", summary);
|
|
3069
|
+
}
|
|
3070
|
+
return cachedBundle;
|
|
3071
|
+
}
|
|
3072
|
+
function generateCompiledBundleCode() {
|
|
3073
|
+
if (fallbackScripts.size > 0) {
|
|
3074
|
+
if (options.debug) {
|
|
3075
|
+
console.log(`[hyperfixi] ${fallbackScripts.size} scripts need interpreter fallback`);
|
|
3076
|
+
}
|
|
3077
|
+
return generateInterpretBundle();
|
|
3078
|
+
}
|
|
3079
|
+
const bundle = generateCompiledBundle({
|
|
3080
|
+
handlers: compiledHandlers,
|
|
3081
|
+
needsLocals,
|
|
3082
|
+
needsGlobals,
|
|
3083
|
+
globalName: options.globalName,
|
|
3084
|
+
htmx: options.htmx,
|
|
3085
|
+
debug: options.debug
|
|
3086
|
+
});
|
|
3087
|
+
if (options.debug) {
|
|
3088
|
+
console.log(`[hyperfixi] Compiled bundle: ${compiledHandlers.length} handlers`);
|
|
3089
|
+
}
|
|
3090
|
+
return bundle;
|
|
3091
|
+
}
|
|
3092
|
+
function generateBundle() {
|
|
3093
|
+
if (mode === "compile") {
|
|
3094
|
+
return generateCompiledBundleCode();
|
|
3095
|
+
}
|
|
3096
|
+
return generateInterpretBundle();
|
|
3097
|
+
}
|
|
3098
|
+
return {
|
|
3099
|
+
name: "vite-plugin-hyperfixi",
|
|
3100
|
+
enforce: "pre",
|
|
3101
|
+
/**
|
|
3102
|
+
* Configure plugin based on Vite mode
|
|
3103
|
+
*/
|
|
3104
|
+
configResolved(config) {
|
|
3105
|
+
isDev = config.command === "serve";
|
|
3106
|
+
if (options.debug) {
|
|
3107
|
+
console.log("[hyperfixi] Plugin initialized, mode:", isDev ? "development" : "production");
|
|
3108
|
+
}
|
|
3109
|
+
},
|
|
3110
|
+
/**
|
|
3111
|
+
* Store server reference and pre-scan HTML files for HMR
|
|
3112
|
+
*/
|
|
3113
|
+
async configureServer(_server) {
|
|
3114
|
+
server = _server;
|
|
3115
|
+
const cwd = _server.config.root;
|
|
3116
|
+
if (options.debug) {
|
|
3117
|
+
console.log("[hyperfixi] Pre-scanning project:", cwd);
|
|
3118
|
+
}
|
|
3119
|
+
const scannedFiles = await scanner.scanProject(cwd);
|
|
3120
|
+
aggregator.loadFromScan(scannedFiles);
|
|
3121
|
+
if (options.debug) {
|
|
3122
|
+
const summary = aggregator.getSummary();
|
|
3123
|
+
console.log("[hyperfixi] Pre-scan complete:", summary);
|
|
3124
|
+
}
|
|
3125
|
+
},
|
|
3126
|
+
/**
|
|
3127
|
+
* Resolve virtual module imports
|
|
3128
|
+
*/
|
|
3129
|
+
resolveId(id) {
|
|
3130
|
+
if (IMPORT_ALIASES.includes(id)) {
|
|
3131
|
+
return RESOLVED_VIRTUAL_MODULE_ID;
|
|
3132
|
+
}
|
|
3133
|
+
return null;
|
|
3134
|
+
},
|
|
3135
|
+
/**
|
|
3136
|
+
* Load the virtual module with generated bundle
|
|
3137
|
+
*/
|
|
3138
|
+
load(id) {
|
|
3139
|
+
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
|
|
3140
|
+
return generateBundle();
|
|
3141
|
+
}
|
|
3142
|
+
return null;
|
|
3143
|
+
},
|
|
3144
|
+
/**
|
|
3145
|
+
* Scan files during transform for hyperscript usage
|
|
3146
|
+
*/
|
|
3147
|
+
transform(code, id) {
|
|
3148
|
+
if (!scanner.shouldScan(id)) {
|
|
3149
|
+
return null;
|
|
3150
|
+
}
|
|
3151
|
+
if (mode === "compile" && !isDev) {
|
|
3152
|
+
const scripts = extractScripts(code);
|
|
3153
|
+
for (const script of scripts) {
|
|
3154
|
+
compileScript(script);
|
|
3155
|
+
}
|
|
3156
|
+
const result = transformHTML(code, handlerMap, fallbackScripts);
|
|
3157
|
+
if (result.modified) {
|
|
3158
|
+
if (options.debug) {
|
|
3159
|
+
console.log(`[hyperfixi] Transformed: ${id.split("/").pop()}`);
|
|
3160
|
+
}
|
|
3161
|
+
return { code: result.code, map: null };
|
|
3162
|
+
}
|
|
3163
|
+
return null;
|
|
3164
|
+
}
|
|
3165
|
+
const usage = scanner.scan(code, id);
|
|
3166
|
+
const changed = aggregator.add(id, usage);
|
|
3167
|
+
if (changed && server) {
|
|
3168
|
+
setImmediate(() => {
|
|
3169
|
+
const currentHash = computeUsageHash(aggregator.getUsage());
|
|
3170
|
+
if (currentHash !== lastUsageHash) {
|
|
3171
|
+
invalidateVirtualModule();
|
|
3172
|
+
}
|
|
3173
|
+
});
|
|
3174
|
+
}
|
|
3175
|
+
return null;
|
|
3176
|
+
},
|
|
3177
|
+
/**
|
|
3178
|
+
* Handle file changes in HMR
|
|
3179
|
+
*/
|
|
3180
|
+
async handleHotUpdate(ctx) {
|
|
3181
|
+
const { file, read } = ctx;
|
|
3182
|
+
if (scanner.shouldScan(file)) {
|
|
3183
|
+
try {
|
|
3184
|
+
const content = await read();
|
|
3185
|
+
const usage = scanner.scan(content, file);
|
|
3186
|
+
const changed = aggregator.add(file, usage);
|
|
3187
|
+
if (options.debug) {
|
|
3188
|
+
console.log("[hyperfixi] HMR: Re-scanned", file.split("/").pop(), usage);
|
|
3189
|
+
}
|
|
3190
|
+
if (changed) {
|
|
3191
|
+
const currentHash = computeUsageHash(aggregator.getUsage());
|
|
3192
|
+
if (currentHash !== lastUsageHash) {
|
|
3193
|
+
invalidateVirtualModule();
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
} catch {
|
|
3197
|
+
if (aggregator.remove(file)) {
|
|
3198
|
+
invalidateVirtualModule();
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
3202
|
+
return void 0;
|
|
3203
|
+
},
|
|
3204
|
+
/**
|
|
3205
|
+
* Scan entire project before production build
|
|
3206
|
+
*/
|
|
3207
|
+
async buildStart() {
|
|
3208
|
+
if (!isDev) {
|
|
3209
|
+
if (mode === "compile") {
|
|
3210
|
+
resetCompiler();
|
|
3211
|
+
compiledHandlers.length = 0;
|
|
3212
|
+
handlerMap.clear();
|
|
3213
|
+
fallbackScripts.clear();
|
|
3214
|
+
needsLocals = false;
|
|
3215
|
+
needsGlobals = false;
|
|
3216
|
+
if (options.debug) {
|
|
3217
|
+
console.log("[hyperfixi] Compile mode: ready for build");
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
const cwd = process.cwd();
|
|
3221
|
+
if (options.debug) {
|
|
3222
|
+
console.log("[hyperfixi] Scanning project for hyperscript usage...");
|
|
3223
|
+
}
|
|
3224
|
+
const scannedFiles = await scanner.scanProject(cwd);
|
|
3225
|
+
aggregator.loadFromScan(scannedFiles);
|
|
3226
|
+
if (mode === "compile") {
|
|
3227
|
+
const usage = aggregator.getUsage();
|
|
3228
|
+
if (usage.detectedLanguages.size > 0) {
|
|
3229
|
+
const aliases = getMultilingualCommandAliases(
|
|
3230
|
+
usage.detectedLanguages
|
|
3231
|
+
);
|
|
3232
|
+
if (Object.keys(aliases).length > 0) {
|
|
3233
|
+
setMultilingualAliases(aliases);
|
|
3234
|
+
if (options.debug) {
|
|
3235
|
+
console.log(
|
|
3236
|
+
`[hyperfixi] Compile mode: configured ${Object.keys(aliases).length} multilingual aliases`
|
|
3237
|
+
);
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
if (options.debug) {
|
|
3243
|
+
const summary = aggregator.getSummary();
|
|
3244
|
+
console.log(`[hyperfixi] Found ${summary.fileCount} files with hyperscript:`, {
|
|
3245
|
+
commands: summary.commands,
|
|
3246
|
+
blocks: summary.blocks,
|
|
3247
|
+
positional: summary.positional,
|
|
3248
|
+
languages: summary.languages
|
|
3249
|
+
});
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
};
|
|
3254
|
+
}
|
|
3255
|
+
var index_default = hyperfixi;
|
|
3256
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
3257
|
+
0 && (module.exports = {
|
|
3258
|
+
REGIONS,
|
|
3259
|
+
SUPPORTED_LANGUAGES,
|
|
3260
|
+
clearCustomKeywords,
|
|
3261
|
+
clearSemanticParser,
|
|
3262
|
+
detectLanguages,
|
|
3263
|
+
getAllLanguageCodes,
|
|
3264
|
+
getKeywordsForLanguage,
|
|
3265
|
+
getOptimalRegion,
|
|
3266
|
+
hasSemanticParser,
|
|
3267
|
+
hyperfixi,
|
|
3268
|
+
isNonLatinLanguage,
|
|
3269
|
+
registerCustomKeywords,
|
|
3270
|
+
setSemanticParser
|
|
3271
|
+
});
|
|
3272
|
+
//# sourceMappingURL=index.cjs.map
|