@lokascript/compilation-service 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CoreParserAdapter,
3
3
  createCoreParserAdapter
4
- } from "./chunk-JDOSUTCM.js";
4
+ } from "./chunk-UQULNKOC.js";
5
5
  import {
6
6
  SemanticParserAdapter,
7
7
  createSemanticAdapter
@@ -9,6 +9,11 @@ import {
9
9
  import "./chunk-HMLY7DHA.js";
10
10
 
11
11
  // ../aot-compiler/dist/index.js
12
+ import {
13
+ isExplicitSyntax,
14
+ parseExplicit,
15
+ fromProtocolJSON
16
+ } from "@lokascript/framework";
12
17
  var DEFAULT_OPTIONS = {
13
18
  attributeNames: ["_", "data-hs", "data-hyperscript"],
14
19
  includeScriptTags: true,
@@ -683,6 +688,166 @@ function analyze(ast) {
683
688
  const analyzer = new Analyzer();
684
689
  return analyzer.analyze(ast);
685
690
  }
691
+ var CLASS_COMMANDS = /* @__PURE__ */ new Set(["add", "remove", "toggle"]);
692
+ function extractClassOp(node) {
693
+ if (node.type !== "command") return null;
694
+ const cmd = node;
695
+ if (!CLASS_COMMANDS.has(cmd.name)) return null;
696
+ const args = cmd.args ?? [];
697
+ if (args.length === 0) return null;
698
+ const arg = args[0];
699
+ if (arg.type !== "selector") return null;
700
+ const selector = arg.value;
701
+ if (!selector.startsWith(".")) return null;
702
+ const className = selector.slice(1);
703
+ if (!className) return null;
704
+ return {
705
+ command: cmd.name,
706
+ className,
707
+ hasExplicitTarget: !!cmd.target
708
+ };
709
+ }
710
+ function isSameTarget(a, b) {
711
+ if (a.type !== "command" || b.type !== "command") return false;
712
+ const cmdA = a;
713
+ const cmdB = b;
714
+ if (!cmdA.target && !cmdB.target) return true;
715
+ if (cmdA.target && cmdB.target) {
716
+ return getTargetKey(cmdA.target) === getTargetKey(cmdB.target);
717
+ }
718
+ return false;
719
+ }
720
+ function getTargetKey(target) {
721
+ if (target.type === "selector") {
722
+ return `selector:${target.value}`;
723
+ }
724
+ if (target.type === "identifier") {
725
+ return `identifier:${target.value}`;
726
+ }
727
+ return null;
728
+ }
729
+ function resolveTarget(cmd) {
730
+ if (!cmd.target) return "_ctx.me";
731
+ if (cmd.target.type === "selector") {
732
+ const sel = cmd.target.value;
733
+ if (sel.startsWith("#") && !sel.includes(" ") && !sel.includes(".")) {
734
+ return `document.getElementById('${sel.slice(1)}')`;
735
+ }
736
+ return `document.querySelector('${sel}')`;
737
+ }
738
+ if (cmd.target.type === "identifier") {
739
+ const val = cmd.target.value;
740
+ if (val === "me") return "_ctx.me";
741
+ return val;
742
+ }
743
+ return "_ctx.me";
744
+ }
745
+ function createBatchNode(run) {
746
+ const adds = [];
747
+ const removes = [];
748
+ const toggles = [];
749
+ for (const node of run) {
750
+ const op = extractClassOp(node);
751
+ switch (op.command) {
752
+ case "add":
753
+ adds.push(op.className);
754
+ break;
755
+ case "remove":
756
+ removes.push(op.className);
757
+ break;
758
+ case "toggle":
759
+ toggles.push(op.className);
760
+ break;
761
+ }
762
+ }
763
+ const target = resolveTarget(run[0]);
764
+ return {
765
+ type: "batchedClassOps",
766
+ target,
767
+ adds,
768
+ removes,
769
+ toggles
770
+ };
771
+ }
772
+ function batchBody(nodes) {
773
+ const result = [];
774
+ let currentRun = [];
775
+ function flushRun() {
776
+ if (currentRun.length >= 2) {
777
+ result.push(createBatchNode(currentRun));
778
+ } else if (currentRun.length === 1) {
779
+ result.push(currentRun[0]);
780
+ }
781
+ currentRun = [];
782
+ }
783
+ for (const node of nodes) {
784
+ const op = extractClassOp(node);
785
+ if (op) {
786
+ if (currentRun.length > 0 && isSameTarget(currentRun[0], node)) {
787
+ currentRun.push(node);
788
+ } else {
789
+ flushRun();
790
+ currentRun = [node];
791
+ }
792
+ } else {
793
+ flushRun();
794
+ result.push(node);
795
+ }
796
+ }
797
+ flushRun();
798
+ return result;
799
+ }
800
+ function walkAndBatch(node) {
801
+ switch (node.type) {
802
+ case "event": {
803
+ const event = node;
804
+ if (event.body && event.body.length > 0) {
805
+ return { ...event, body: batchBody(event.body).map(walkAndBatch) };
806
+ }
807
+ return node;
808
+ }
809
+ case "if": {
810
+ const ifNode = node;
811
+ const result = { ...ifNode };
812
+ result.thenBranch = batchBody(ifNode.thenBranch).map(walkAndBatch);
813
+ if (ifNode.elseBranch) {
814
+ result.elseBranch = batchBody(ifNode.elseBranch).map(walkAndBatch);
815
+ }
816
+ if (ifNode.elseIfBranches) {
817
+ result.elseIfBranches = ifNode.elseIfBranches.map((branch) => ({
818
+ condition: branch.condition,
819
+ body: batchBody(branch.body).map(walkAndBatch)
820
+ }));
821
+ }
822
+ return result;
823
+ }
824
+ case "repeat": {
825
+ const repeat = node;
826
+ return { ...repeat, body: batchBody(repeat.body).map(walkAndBatch) };
827
+ }
828
+ case "foreach": {
829
+ const forEach = node;
830
+ return { ...forEach, body: batchBody(forEach.body).map(walkAndBatch) };
831
+ }
832
+ case "while": {
833
+ const whileNode = node;
834
+ return { ...whileNode, body: batchBody(whileNode.body).map(walkAndBatch) };
835
+ }
836
+ default:
837
+ return node;
838
+ }
839
+ }
840
+ var ClassBatchingPass = class {
841
+ constructor() {
842
+ this.name = "class-batching";
843
+ }
844
+ shouldRun(analysis) {
845
+ return analysis.commandsUsed.has("add") || analysis.commandsUsed.has("remove") || analysis.commandsUsed.has("toggle");
846
+ }
847
+ transform(ast, _analysis) {
848
+ return walkAndBatch(ast);
849
+ }
850
+ };
686
851
  var ConstantFoldingPass = class {
687
852
  constructor() {
688
853
  this.name = "constant-folding";
@@ -1007,6 +1172,7 @@ var OptimizationPipeline = class {
1007
1172
  new ConstantFoldingPass(),
1008
1173
  new SelectorCachingPass(),
1009
1174
  new DeadCodeEliminationPass(),
1175
+ new ClassBatchingPass(),
1010
1176
  new LoopUnrollingPass()
1011
1177
  ];
1012
1178
  }
@@ -1039,12 +1205,184 @@ var OptimizationPipeline = class {
1039
1205
  }
1040
1206
  };
1041
1207
  function createOptimizer() {
1042
- return new OptimizationPipeline();
1208
+ return /* @__PURE__ */ new OptimizationPipeline();
1043
1209
  }
1044
1210
  function optimize(ast, analysis, level = 2) {
1045
1211
  const pipeline = new OptimizationPipeline();
1046
1212
  return pipeline.optimize(ast, analysis, level);
1047
1213
  }
1214
+ function classifyCommand(node) {
1215
+ if (node.type !== "command") return null;
1216
+ const cmd = node;
1217
+ switch (cmd.name) {
1218
+ case "add":
1219
+ return classifyAddCommand(cmd);
1220
+ case "remove":
1221
+ return classifyRemoveCommand(cmd);
1222
+ case "put":
1223
+ return classifyPutCommand(cmd);
1224
+ case "set":
1225
+ return classifySetCommand(cmd);
1226
+ default:
1227
+ return null;
1228
+ }
1229
+ }
1230
+ function getIdTarget(cmd) {
1231
+ if (!cmd.target) return null;
1232
+ if (cmd.target.type !== "selector") return null;
1233
+ const sel = cmd.target.value;
1234
+ if (!sel.startsWith("#")) return null;
1235
+ return sel.slice(1);
1236
+ }
1237
+ function classifyAddCommand(cmd) {
1238
+ const targetId = getIdTarget(cmd);
1239
+ if (!targetId) return null;
1240
+ const args = cmd.args ?? [];
1241
+ if (args.length === 0) return null;
1242
+ const arg = args[0];
1243
+ if (arg.type !== "selector") return null;
1244
+ const val = arg.value;
1245
+ if (!val.startsWith(".")) return null;
1246
+ return { type: "addClass", targetId, value: val.slice(1) };
1247
+ }
1248
+ function classifyRemoveCommand(cmd) {
1249
+ const targetId = getIdTarget(cmd);
1250
+ if (!targetId) return null;
1251
+ const args = cmd.args ?? [];
1252
+ if (args.length === 0) return null;
1253
+ const arg = args[0];
1254
+ if (arg.type !== "selector") return null;
1255
+ const val = arg.value;
1256
+ if (!val.startsWith(".")) return null;
1257
+ return { type: "removeClass", targetId, value: val.slice(1) };
1258
+ }
1259
+ function classifyPutCommand(cmd) {
1260
+ const targetId = getIdTarget(cmd);
1261
+ if (!targetId) return null;
1262
+ const args = cmd.args ?? [];
1263
+ if (args.length === 0) return null;
1264
+ const arg = args[0];
1265
+ if (arg.type !== "literal") return null;
1266
+ const val = arg.value;
1267
+ if (typeof val !== "string") return null;
1268
+ return { type: "putContent", targetId, value: val };
1269
+ }
1270
+ function classifySetCommand(cmd) {
1271
+ const targetId = getIdTarget(cmd);
1272
+ if (!targetId) return null;
1273
+ const args = cmd.args ?? [];
1274
+ if (args.length < 2) return null;
1275
+ const attrArg = args[0];
1276
+ if (attrArg.type !== "identifier") return null;
1277
+ const attrValue = attrArg.value;
1278
+ if (!attrValue || !attrValue.startsWith("@")) return null;
1279
+ const attrName = attrValue.slice(1);
1280
+ const valArg = args[1];
1281
+ if (valArg.type !== "literal") return null;
1282
+ const val = valArg.value;
1283
+ if (typeof val !== "string" && typeof val !== "number") return null;
1284
+ return { type: "setAttribute", targetId, value: String(val), attrName };
1285
+ }
1286
+ function classifyInitCommands(commands) {
1287
+ const pure = [];
1288
+ const impure = [];
1289
+ for (let i = 0; i < commands.length; i++) {
1290
+ const classified = classifyCommand(commands[i]);
1291
+ if (classified) {
1292
+ pure.push({ index: i, command: classified });
1293
+ } else {
1294
+ impure.push({ index: i, node: commands[i] });
1295
+ }
1296
+ }
1297
+ return { pure, impure };
1298
+ }
1299
+ function applyPureCommand(html, cmd) {
1300
+ switch (cmd.type) {
1301
+ case "addClass":
1302
+ return addClassToElement(html, cmd.targetId, cmd.value);
1303
+ case "removeClass":
1304
+ return removeClassFromElement(html, cmd.targetId, cmd.value);
1305
+ case "putContent":
1306
+ return putContentIntoElement(html, cmd.targetId, cmd.value);
1307
+ case "setAttribute":
1308
+ return setAttributeOnElement(html, cmd.targetId, cmd.attrName, cmd.value);
1309
+ default:
1310
+ return html;
1311
+ }
1312
+ }
1313
+ function transformElementById(html, id, transform) {
1314
+ const idPattern = new RegExp(`(<[^>]*\\bid=["']${escapeRegExp(id)}["'][^>]*>)`, "i");
1315
+ const match = html.match(idPattern);
1316
+ if (!match) return html;
1317
+ return html.replace(match[1], transform(match[1]));
1318
+ }
1319
+ function addClassToElement(html, id, className) {
1320
+ return transformElementById(html, id, (tag) => {
1321
+ const classMatch = tag.match(/\bclass=["']([^"']*)["']/i);
1322
+ if (classMatch) {
1323
+ const existing = classMatch[1];
1324
+ const classes = existing.split(/\s+/).filter(Boolean);
1325
+ if (!classes.includes(className)) {
1326
+ classes.push(className);
1327
+ }
1328
+ return tag.replace(classMatch[0], `class="${classes.join(" ")}"`);
1329
+ }
1330
+ return tag.replace(/>$/, ` class="${className}">`);
1331
+ });
1332
+ }
1333
+ function removeClassFromElement(html, id, className) {
1334
+ return transformElementById(html, id, (tag) => {
1335
+ const classMatch = tag.match(/\bclass=["']([^"']*)["']/i);
1336
+ if (!classMatch) return tag;
1337
+ const classes = classMatch[1].split(/\s+/).filter((c) => c !== className);
1338
+ if (classes.length === 0) {
1339
+ return tag.replace(classMatch[0], "").replace(/\s+>/, ">");
1340
+ }
1341
+ return tag.replace(classMatch[0], `class="${classes.join(" ")}"`);
1342
+ });
1343
+ }
1344
+ function putContentIntoElement(html, id, content) {
1345
+ const idPattern = new RegExp(
1346
+ `(<[a-zA-Z][^>]*\\bid=["']${escapeRegExp(id)}["'][^>]*>)((?:(?!<\\/[a-zA-Z]).)*?)(<\\/[a-zA-Z][^>]*>)`,
1347
+ "is"
1348
+ );
1349
+ const match = html.match(idPattern);
1350
+ if (!match) return html;
1351
+ return html.replace(match[0], `${match[1]}${escapeHtml(content)}${match[3]}`);
1352
+ }
1353
+ function setAttributeOnElement(html, id, attrName, value) {
1354
+ return transformElementById(html, id, (tag) => {
1355
+ const attrPattern = new RegExp(`\\b${escapeRegExp(attrName)}=["'][^"']*["']`, "i");
1356
+ const attrMatch = tag.match(attrPattern);
1357
+ if (attrMatch) {
1358
+ return tag.replace(attrMatch[0], `${attrName}="${escapeHtml(value)}"`);
1359
+ }
1360
+ return tag.replace(/>$/, ` ${attrName}="${escapeHtml(value)}">`);
1361
+ });
1362
+ }
1363
+ function escapeRegExp(str) {
1364
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1365
+ }
1366
+ function escapeHtml(str) {
1367
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1368
+ }
1369
+ function preRenderInitBlock(html, initCommands) {
1370
+ const { pure, impure } = classifyInitCommands(initCommands);
1371
+ let modifiedHtml = html;
1372
+ let preRenderedCount = 0;
1373
+ for (const { command } of pure) {
1374
+ const before = modifiedHtml;
1375
+ modifiedHtml = applyPureCommand(modifiedHtml, command);
1376
+ if (modifiedHtml !== before) {
1377
+ preRenderedCount++;
1378
+ }
1379
+ }
1380
+ return {
1381
+ html: modifiedHtml,
1382
+ remainingInitCommands: impure.map((i) => i.node),
1383
+ preRenderedCount
1384
+ };
1385
+ }
1048
1386
  function sanitizeClassName(name) {
1049
1387
  if (!/^-?[a-zA-Z_][a-zA-Z0-9_-]*$/.test(name)) {
1050
1388
  return null;
@@ -2918,6 +3256,22 @@ var EventHandlerCodegen = class {
2918
3256
  const nested = node;
2919
3257
  return this.generateBody(nested.body ?? []);
2920
3258
  }
3259
+ case "batchedClassOps": {
3260
+ const batch = node;
3261
+ const lines = [];
3262
+ if (batch.adds.length > 0) {
3263
+ lines.push(`${batch.target}.classList.add(${batch.adds.map((c) => `'${c}'`).join(", ")})`);
3264
+ }
3265
+ if (batch.removes.length > 0) {
3266
+ lines.push(
3267
+ `${batch.target}.classList.remove(${batch.removes.map((c) => `'${c}'`).join(", ")})`
3268
+ );
3269
+ }
3270
+ for (const t of batch.toggles) {
3271
+ lines.push(`${batch.target}.classList.toggle('${t}')`);
3272
+ }
3273
+ return lines.join(";\n");
3274
+ }
2921
3275
  default:
2922
3276
  return null;
2923
3277
  }
@@ -3165,10 +3519,40 @@ var AOTCompiler = class {
3165
3519
  // ===========================================================================
3166
3520
  /**
3167
3521
  * Parse a hyperscript string to AST.
3522
+ * Supports natural language, explicit bracket syntax, and JSON input.
3168
3523
  */
3169
3524
  parse(code, options = {}) {
3170
3525
  const { language = "en", confidenceThreshold = 0.7, debug = false } = options;
3171
3526
  let ast = null;
3527
+ if (isExplicitSyntax(code)) {
3528
+ try {
3529
+ const node = parseExplicit(code);
3530
+ ast = this.semanticNodeToAOT(node);
3531
+ if (debug) {
3532
+ console.log(`[aot] Parsed explicit syntax: "${code}"`);
3533
+ }
3534
+ } catch (error) {
3535
+ if (debug) {
3536
+ console.log(`[aot] Explicit parse error for "${code}":`, error);
3537
+ }
3538
+ }
3539
+ if (ast) return this.ensureEventHandler(ast);
3540
+ }
3541
+ if (this.looksLikeJSON(code)) {
3542
+ try {
3543
+ const json = JSON.parse(code.trim());
3544
+ const node = fromProtocolJSON(json);
3545
+ ast = this.semanticNodeToAOT(node);
3546
+ if (debug) {
3547
+ console.log(`[aot] Parsed JSON input: "${code.slice(0, 80)}..."`);
3548
+ }
3549
+ } catch (error) {
3550
+ if (debug) {
3551
+ console.log(`[aot] JSON parse error for "${code.slice(0, 80)}":`, error);
3552
+ }
3553
+ }
3554
+ if (ast) return this.ensureEventHandler(ast);
3555
+ }
3172
3556
  if (language !== "en" && this.semanticParser?.supportsLanguage(language)) {
3173
3557
  const result = this.semanticParser.analyze(code, language);
3174
3558
  if (result.node && result.confidence >= confidenceThreshold) {
@@ -3195,15 +3579,7 @@ var AOTCompiler = class {
3195
3579
  if (!ast) {
3196
3580
  ast = this.createSimpleAST(code);
3197
3581
  }
3198
- if (ast && ast.type !== "event") {
3199
- ast = {
3200
- type: "event",
3201
- event: "click",
3202
- modifiers: {},
3203
- body: [ast]
3204
- };
3205
- }
3206
- return ast;
3582
+ return this.ensureEventHandler(ast);
3207
3583
  }
3208
3584
  /**
3209
3585
  * Create a simple AST from code (for testing without full parser).
@@ -3368,6 +3744,86 @@ var AOTCompiler = class {
3368
3744
  return { type: "identifier", value: trimmed };
3369
3745
  }
3370
3746
  // ===========================================================================
3747
+ // EXPLICIT / JSON INPUT HELPERS
3748
+ // ===========================================================================
3749
+ /**
3750
+ * Check if input looks like JSON (LLM JSON format).
3751
+ */
3752
+ looksLikeJSON(code) {
3753
+ const trimmed = code.trim();
3754
+ return trimmed.startsWith("{") && trimmed.includes('"action"');
3755
+ }
3756
+ /**
3757
+ * Ensure top-level node is always an event handler.
3758
+ * The codegen pipeline (EventHandlerCodegen) requires this.
3759
+ */
3760
+ ensureEventHandler(ast) {
3761
+ if (ast && ast.type !== "event") {
3762
+ return {
3763
+ type: "event",
3764
+ event: "click",
3765
+ modifiers: {},
3766
+ body: [ast]
3767
+ };
3768
+ }
3769
+ return ast;
3770
+ }
3771
+ /**
3772
+ * Convert a framework SemanticNode to an AOT ASTNode.
3773
+ * Handles the simple cases produced by explicit/JSON parsing.
3774
+ */
3775
+ semanticNodeToAOT(node) {
3776
+ if (node.kind === "event-handler") {
3777
+ const eh = node;
3778
+ const eventValue = eh.roles.get("event");
3779
+ const eventName = eventValue && "value" in eventValue ? String(eventValue.value) : "click";
3780
+ return {
3781
+ type: "event",
3782
+ event: eventName,
3783
+ modifiers: {},
3784
+ body: (eh.body ?? []).map((child) => this.semanticNodeToAOT(child))
3785
+ };
3786
+ }
3787
+ const roles = {};
3788
+ const args = [];
3789
+ for (const [roleName, value] of node.roles) {
3790
+ const astValue = this.semanticValueToAOT(value);
3791
+ roles[roleName] = astValue;
3792
+ args.push(astValue);
3793
+ }
3794
+ return {
3795
+ type: "command",
3796
+ name: node.action,
3797
+ args,
3798
+ roles
3799
+ };
3800
+ }
3801
+ /**
3802
+ * Convert a SemanticValue to an ASTNode.
3803
+ */
3804
+ semanticValueToAOT(value) {
3805
+ switch (value.type) {
3806
+ case "selector":
3807
+ return { type: "selector", value: value.value };
3808
+ case "reference":
3809
+ return { type: "identifier", value: value.value };
3810
+ case "literal": {
3811
+ const lit = value;
3812
+ if (lit.dataType === "duration") {
3813
+ const str = String(lit.value);
3814
+ const match = /^(\d+(?:\.\d+)?)(ms|s)$/.exec(str);
3815
+ if (match) {
3816
+ const ms = match[2] === "s" ? parseFloat(match[1]) * 1e3 : parseFloat(match[1]);
3817
+ return { type: "literal", value: ms };
3818
+ }
3819
+ }
3820
+ return { type: "literal", value: lit.value };
3821
+ }
3822
+ default:
3823
+ return { type: "literal", value: String(value.value ?? "") };
3824
+ }
3825
+ }
3826
+ // ===========================================================================
3371
3827
  // ANALYSIS
3372
3828
  // ===========================================================================
3373
3829
  /**
@@ -3377,6 +3833,63 @@ var AOTCompiler = class {
3377
3833
  return this.analyzer.analyze(ast);
3378
3834
  }
3379
3835
  // ===========================================================================
3836
+ // INIT PRE-RENDERING
3837
+ // ===========================================================================
3838
+ /**
3839
+ * Pre-render pure init block commands into an HTML template at build time.
3840
+ *
3841
+ * Analyzes init block commands for purity (static DOM writes with literal
3842
+ * values targeting #id selectors) and applies them directly to the HTML.
3843
+ * Impure commands are preserved for normal runtime execution.
3844
+ *
3845
+ * @param html - The HTML template string
3846
+ * @param initCommands - Parsed commands from an init block
3847
+ * @returns Modified HTML, remaining impure commands, and count of pre-rendered commands
3848
+ */
3849
+ preRenderInit(html, initCommands) {
3850
+ return preRenderInitBlock(html, initCommands);
3851
+ }
3852
+ /**
3853
+ * Extract init blocks from HTML, pre-render pure commands, and return modified HTML.
3854
+ * This is a higher-level convenience that combines extraction, parsing, and pre-rendering.
3855
+ *
3856
+ * @param html - The HTML template string
3857
+ * @param options - Compile options (language, etc.)
3858
+ * @returns Modified HTML with pre-rendered init effects and compilation results
3859
+ */
3860
+ preRenderInitBlocks(html, options = {}) {
3861
+ const scripts = this.extract(html, "template.html");
3862
+ let modifiedHtml = html;
3863
+ let totalPreRendered = 0;
3864
+ const remainingScripts = [];
3865
+ for (const script of scripts) {
3866
+ const ast = this.parse(script.code, {
3867
+ ...options,
3868
+ language: script.language ?? options.language ?? "en"
3869
+ });
3870
+ if (!ast) {
3871
+ remainingScripts.push(script);
3872
+ continue;
3873
+ }
3874
+ const eventNode = ast;
3875
+ if (eventNode.type === "event" && eventNode.event === "init" && eventNode.body) {
3876
+ const result = preRenderInitBlock(modifiedHtml, eventNode.body);
3877
+ modifiedHtml = result.html;
3878
+ totalPreRendered += result.preRenderedCount;
3879
+ if (result.remainingInitCommands.length > 0) {
3880
+ remainingScripts.push(script);
3881
+ }
3882
+ } else {
3883
+ remainingScripts.push(script);
3884
+ }
3885
+ }
3886
+ return {
3887
+ html: modifiedHtml,
3888
+ preRenderedCount: totalPreRendered,
3889
+ remainingScripts
3890
+ };
3891
+ }
3892
+ // ===========================================================================
3380
3893
  // COMPILATION
3381
3894
  // ===========================================================================
3382
3895
  /**
@@ -3499,6 +4012,30 @@ var AOTCompiler = class {
3499
4012
  }
3500
4013
  };
3501
4014
  }
4015
+ /**
4016
+ * Compile explicit bracket syntax or LLM JSON to JavaScript.
4017
+ * Uses the framework IR directly — no semantic or traditional parser needed.
4018
+ */
4019
+ compileExplicit(code, options = {}) {
4020
+ try {
4021
+ const ast = isExplicitSyntax(code) ? this.semanticNodeToAOT(parseExplicit(code)) : this.semanticNodeToAOT(fromProtocolJSON(JSON.parse(code.trim())));
4022
+ return this.compileAST(ast, options);
4023
+ } catch (error) {
4024
+ return {
4025
+ success: false,
4026
+ errors: [error instanceof Error ? error.message : String(error)],
4027
+ warnings: [],
4028
+ metadata: {
4029
+ handlerId: "",
4030
+ parserUsed: "traditional",
4031
+ commandsUsed: [],
4032
+ optimizationsApplied: [],
4033
+ needsRuntime: false,
4034
+ runtimeHelpers: []
4035
+ }
4036
+ };
4037
+ }
4038
+ }
3502
4039
  /**
3503
4040
  * Compile multiple extracted scripts.
3504
4041
  */
@@ -3734,7 +4271,7 @@ async function compileHyperscript(code, options) {
3734
4271
  async function createMultilingualCompiler() {
3735
4272
  const compiler = new AOTCompiler();
3736
4273
  try {
3737
- const { createCoreParserAdapter: createCoreParserAdapter2 } = await import("./core-parser-adapter-VCJB52SO-MDHRIVZ7.js");
4274
+ const { createCoreParserAdapter: createCoreParserAdapter2 } = await import("./core-parser-adapter-VCJB52SO-5HK2TL6Q.js");
3738
4275
  compiler.setParser(await createCoreParserAdapter2());
3739
4276
  } catch {
3740
4277
  }
@@ -3787,4 +4324,4 @@ export {
3787
4324
  sanitizeSelector,
3788
4325
  scanFiles
3789
4326
  };
3790
- //# sourceMappingURL=dist-ICUX26U7.js.map
4327
+ //# sourceMappingURL=dist-SWJWTU4Z.js.map