@lokascript/language-server 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.js CHANGED
@@ -322,6 +322,1226 @@ function formatHyperscript(code, indentStr = " ") {
322
322
  return formattedLines.join("\n");
323
323
  }
324
324
 
325
+ // src/chevrotain-parser.ts
326
+ import { CstParser } from "chevrotain";
327
+
328
+ // src/generated/chevrotain-vocabulary.ts
329
+ import { createToken, Lexer } from "chevrotain";
330
+ var Identifier = createToken({ name: "Identifier", pattern: /[a-zA-Z\u00C0-\u024F\u0400-\u04FF\u0600-\u06FF\u0900-\u09FF\u0E00-\u0E7F\u3040-\u9FFF\uAC00-\uD7AF][\w\u00C0-\u024F\u0400-\u04FF\u0600-\u06FF\u0900-\u09FF\u0E00-\u0E7F\u3040-\u9FFF\uAC00-\uD7AF'-]*/ });
331
+ var WhiteSpace = createToken({ name: "WhiteSpace", pattern: /\s+/ });
332
+ var StringLiteral = createToken({ name: "StringLiteral", pattern: /'[^']*'|"[^"]*"/ });
333
+ var NumberLiteral = createToken({ name: "NumberLiteral", pattern: /\d+(\.\d+)?/ });
334
+ var URLLiteral = createToken({ name: "URLLiteral", pattern: /\/[a-zA-Z0-9_\-.\/]+/ });
335
+ var CSSSelector = createToken({ name: "CSSSelector", pattern: /[#.][a-zA-Z_][\w-]*/ });
336
+ var AttributeSelector = createToken({ name: "AttributeSelector", pattern: /@[a-zA-Z_][\w-]*/ });
337
+ var HTMLSelector = createToken({ name: "HTMLSelector", pattern: /<[a-zA-Z][\w.-]*\/>/ });
338
+ var LocalVariable = createToken({ name: "LocalVariable", pattern: /:[a-zA-Z_][\w]*/ });
339
+ var GlobalVariable = createToken({ name: "GlobalVariable", pattern: /\$[a-zA-Z_][\w]*/ });
340
+ var LParen = createToken({ name: "LParen", pattern: /\(/ });
341
+ var RParen = createToken({ name: "RParen", pattern: /\)/ });
342
+ var Comma = createToken({ name: "Comma", pattern: /,/ });
343
+ var Dot = createToken({ name: "Dot", pattern: /\./ });
344
+ var Kw_previous = createToken({ name: "Kw_previous", pattern: /previous/, longer_alt: Identifier });
345
+ var Kw_closest = createToken({ name: "Kw_closest", pattern: /closest/, longer_alt: Identifier });
346
+ var Kw_while = createToken({ name: "Kw_while", pattern: /while/, longer_alt: Identifier });
347
+ var Kw_until = createToken({ name: "Kw_until", pattern: /until/, longer_alt: Identifier });
348
+ var Kw_times = createToken({ name: "Kw_times", pattern: /times/, longer_alt: Identifier });
349
+ var Kw_first = createToken({ name: "Kw_first", pattern: /first/, longer_alt: Identifier });
350
+ var Kw_false = createToken({ name: "Kw_false", pattern: /false/, longer_alt: Identifier });
351
+ var Kw_then = createToken({ name: "Kw_then", pattern: /then/, longer_alt: Identifier });
352
+ var Kw_else = createToken({ name: "Kw_else", pattern: /else/, longer_alt: Identifier });
353
+ var Kw_from = createToken({ name: "Kw_from", pattern: /from/, longer_alt: Identifier });
354
+ var Kw_into = createToken({ name: "Kw_into", pattern: /into/, longer_alt: Identifier });
355
+ var Kw_with = createToken({ name: "Kw_with", pattern: /with/, longer_alt: Identifier });
356
+ var Kw_have = createToken({ name: "Kw_have", pattern: /have/, longer_alt: Identifier });
357
+ var Kw_last = createToken({ name: "Kw_last", pattern: /last/, longer_alt: Identifier });
358
+ var Kw_next = createToken({ name: "Kw_next", pattern: /next/, longer_alt: Identifier });
359
+ var Kw_true = createToken({ name: "Kw_true", pattern: /true/, longer_alt: Identifier });
360
+ var Kw_null = createToken({ name: "Kw_null", pattern: /null/, longer_alt: Identifier });
361
+ var Kw_end = createToken({ name: "Kw_end", pattern: /end/, longer_alt: Identifier });
362
+ var Kw_for = createToken({ name: "Kw_for", pattern: /for/, longer_alt: Identifier });
363
+ var Kw_and = createToken({ name: "Kw_and", pattern: /and/, longer_alt: Identifier });
364
+ var Kw_not = createToken({ name: "Kw_not", pattern: /not/, longer_alt: Identifier });
365
+ var Kw_has = createToken({ name: "Kw_has", pattern: /has/, longer_alt: Identifier });
366
+ var Kw_you = createToken({ name: "Kw_you", pattern: /you/, longer_alt: Identifier });
367
+ var Kw_its = createToken({ name: "Kw_its", pattern: /its/, longer_alt: Identifier });
368
+ var Kw_the = createToken({ name: "Kw_the", pattern: /the/, longer_alt: Identifier });
369
+ var Kw_on = createToken({ name: "Kw_on", pattern: /on/, longer_alt: Identifier });
370
+ var Kw_if = createToken({ name: "Kw_if", pattern: /if/, longer_alt: Identifier });
371
+ var Kw_to = createToken({ name: "Kw_to", pattern: /to/, longer_alt: Identifier });
372
+ var Kw_in = createToken({ name: "Kw_in", pattern: /in/, longer_alt: Identifier });
373
+ var Kw_of = createToken({ name: "Kw_of", pattern: /of/, longer_alt: Identifier });
374
+ var Kw_as = createToken({ name: "Kw_as", pattern: /as/, longer_alt: Identifier });
375
+ var Kw_at = createToken({ name: "Kw_at", pattern: /at/, longer_alt: Identifier });
376
+ var Kw_by = createToken({ name: "Kw_by", pattern: /by/, longer_alt: Identifier });
377
+ var Kw_or = createToken({ name: "Kw_or", pattern: /or/, longer_alt: Identifier });
378
+ var Kw_is = createToken({ name: "Kw_is", pattern: /is/, longer_alt: Identifier });
379
+ var Kw_me = createToken({ name: "Kw_me", pattern: /me/, longer_alt: Identifier });
380
+ var Kw_it = createToken({ name: "Kw_it", pattern: /it/, longer_alt: Identifier });
381
+ var Kw_my = createToken({ name: "Kw_my", pattern: /my/, longer_alt: Identifier });
382
+ var Kw_no = createToken({ name: "Kw_no", pattern: /no/, longer_alt: Identifier });
383
+ var Cmd_transition = createToken({ name: "Cmd_transition", pattern: /transition/, longer_alt: Identifier });
384
+ var Cmd_show = createToken({ name: "Cmd_show", pattern: /show/, longer_alt: Identifier });
385
+ var Cmd_hide = createToken({ name: "Cmd_hide", pattern: /hide/, longer_alt: Identifier });
386
+ var Cmd_increment = createToken({ name: "Cmd_increment", pattern: /increment/, longer_alt: Identifier });
387
+ var Cmd_decrement = createToken({ name: "Cmd_decrement", pattern: /decrement/, longer_alt: Identifier });
388
+ var Cmd_default = createToken({ name: "Cmd_default", pattern: /default/, longer_alt: Identifier });
389
+ var Cmd_beep = createToken({ name: "Cmd_beep", pattern: /beep/, longer_alt: Identifier });
390
+ var Cmd_pick = createToken({ name: "Cmd_pick", pattern: /pick/, longer_alt: Identifier });
391
+ var Cmd_set = createToken({ name: "Cmd_set", pattern: /set/, longer_alt: Identifier });
392
+ var Cmd_log = createToken({ name: "Cmd_log", pattern: /log/, longer_alt: Identifier });
393
+ var Cmd_get = createToken({ name: "Cmd_get", pattern: /get/, longer_alt: Identifier });
394
+ var Cmd_continue = createToken({ name: "Cmd_continue", pattern: /continue/, longer_alt: Identifier });
395
+ var Cmd_behavior = createToken({ name: "Cmd_behavior", pattern: /behavior/, longer_alt: Identifier });
396
+ var Cmd_compound = createToken({ name: "Cmd_compound", pattern: /compound/, longer_alt: Identifier });
397
+ var Cmd_install = createToken({ name: "Cmd_install", pattern: /install/, longer_alt: Identifier });
398
+ var Cmd_unless = createToken({ name: "Cmd_unless", pattern: /unless/, longer_alt: Identifier });
399
+ var Cmd_repeat = createToken({ name: "Cmd_repeat", pattern: /repeat/, longer_alt: Identifier });
400
+ var Cmd_return = createToken({ name: "Cmd_return", pattern: /return/, longer_alt: Identifier });
401
+ var Cmd_throw = createToken({ name: "Cmd_throw", pattern: /throw/, longer_alt: Identifier });
402
+ var Cmd_break = createToken({ name: "Cmd_break", pattern: /break/, longer_alt: Identifier });
403
+ var Cmd_halt = createToken({ name: "Cmd_halt", pattern: /halt/, longer_alt: Identifier });
404
+ var Cmd_call = createToken({ name: "Cmd_call", pattern: /call/, longer_alt: Identifier });
405
+ var Cmd_tell = createToken({ name: "Cmd_tell", pattern: /tell/, longer_alt: Identifier });
406
+ var Cmd_init = createToken({ name: "Cmd_init", pattern: /init/, longer_alt: Identifier });
407
+ var Cmd_exit = createToken({ name: "Cmd_exit", pattern: /exit/, longer_alt: Identifier });
408
+ var Cmd_js = createToken({ name: "Cmd_js", pattern: /js/, longer_alt: Identifier });
409
+ var Cmd_trigger = createToken({ name: "Cmd_trigger", pattern: /trigger/, longer_alt: Identifier });
410
+ var Cmd_send = createToken({ name: "Cmd_send", pattern: /send/, longer_alt: Identifier });
411
+ var Cmd_prepend = createToken({ name: "Cmd_prepend", pattern: /prepend/, longer_alt: Identifier });
412
+ var Cmd_measure = createToken({ name: "Cmd_measure", pattern: /measure/, longer_alt: Identifier });
413
+ var Cmd_append = createToken({ name: "Cmd_append", pattern: /append/, longer_alt: Identifier });
414
+ var Cmd_render = createToken({ name: "Cmd_render", pattern: /render/, longer_alt: Identifier });
415
+ var Cmd_clone = createToken({ name: "Cmd_clone", pattern: /clone/, longer_alt: Identifier });
416
+ var Cmd_focus = createToken({ name: "Cmd_focus", pattern: /focus/, longer_alt: Identifier });
417
+ var Cmd_morph = createToken({ name: "Cmd_morph", pattern: /morph/, longer_alt: Identifier });
418
+ var Cmd_take = createToken({ name: "Cmd_take", pattern: /take/, longer_alt: Identifier });
419
+ var Cmd_make = createToken({ name: "Cmd_make", pattern: /make/, longer_alt: Identifier });
420
+ var Cmd_blur = createToken({ name: "Cmd_blur", pattern: /blur/, longer_alt: Identifier });
421
+ var Cmd_swap = createToken({ name: "Cmd_swap", pattern: /swap/, longer_alt: Identifier });
422
+ var Cmd_copy = createToken({ name: "Cmd_copy", pattern: /copy/, longer_alt: Identifier });
423
+ var Cmd_put = createToken({ name: "Cmd_put", pattern: /put/, longer_alt: Identifier });
424
+ var Cmd_toggle = createToken({ name: "Cmd_toggle", pattern: /toggle/, longer_alt: Identifier });
425
+ var Cmd_remove = createToken({ name: "Cmd_remove", pattern: /remove/, longer_alt: Identifier });
426
+ var Cmd_add = createToken({ name: "Cmd_add", pattern: /add/, longer_alt: Identifier });
427
+ var Cmd_settle = createToken({ name: "Cmd_settle", pattern: /settle/, longer_alt: Identifier });
428
+ var Cmd_fetch = createToken({ name: "Cmd_fetch", pattern: /fetch/, longer_alt: Identifier });
429
+ var Cmd_async = createToken({ name: "Cmd_async", pattern: /async/, longer_alt: Identifier });
430
+ var Cmd_wait = createToken({ name: "Cmd_wait", pattern: /wait/, longer_alt: Identifier });
431
+ var Cmd_go = createToken({ name: "Cmd_go", pattern: /go/, longer_alt: Identifier });
432
+ var Event_intersection = createToken({ name: "Event_intersection", pattern: /intersection/, longer_alt: Identifier });
433
+ var Event_mouseenter = createToken({ name: "Event_mouseenter", pattern: /mouseenter/, longer_alt: Identifier });
434
+ var Event_mouseleave = createToken({ name: "Event_mouseleave", pattern: /mouseleave/, longer_alt: Identifier });
435
+ var Event_mousedown = createToken({ name: "Event_mousedown", pattern: /mousedown/, longer_alt: Identifier });
436
+ var Event_mousemove = createToken({ name: "Event_mousemove", pattern: /mousemove/, longer_alt: Identifier });
437
+ var Event_dblclick = createToken({ name: "Event_dblclick", pattern: /dblclick/, longer_alt: Identifier });
438
+ var Event_keypress = createToken({ name: "Event_keypress", pattern: /keypress/, longer_alt: Identifier });
439
+ var Event_mutation = createToken({ name: "Event_mutation", pattern: /mutation/, longer_alt: Identifier });
440
+ var Event_mouseup = createToken({ name: "Event_mouseup", pattern: /mouseup/, longer_alt: Identifier });
441
+ var Event_keydown = createToken({ name: "Event_keydown", pattern: /keydown/, longer_alt: Identifier });
442
+ var Event_change = createToken({ name: "Event_change", pattern: /change/, longer_alt: Identifier });
443
+ var Event_submit = createToken({ name: "Event_submit", pattern: /submit/, longer_alt: Identifier });
444
+ var Event_scroll = createToken({ name: "Event_scroll", pattern: /scroll/, longer_alt: Identifier });
445
+ var Event_resize = createToken({ name: "Event_resize", pattern: /resize/, longer_alt: Identifier });
446
+ var Event_click = createToken({ name: "Event_click", pattern: /click/, longer_alt: Identifier });
447
+ var Event_keyup = createToken({ name: "Event_keyup", pattern: /keyup/, longer_alt: Identifier });
448
+ var Event_input = createToken({ name: "Event_input", pattern: /input/, longer_alt: Identifier });
449
+ var Event_every = createToken({ name: "Event_every", pattern: /every/, longer_alt: Identifier });
450
+ var Event_load = createToken({ name: "Event_load", pattern: /load/, longer_alt: Identifier });
451
+ var allTokens = [
452
+ // Whitespace
453
+ WhiteSpace,
454
+ // Literals
455
+ StringLiteral,
456
+ NumberLiteral,
457
+ URLLiteral,
458
+ // Selectors
459
+ CSSSelector,
460
+ AttributeSelector,
461
+ HTMLSelector,
462
+ // Variables
463
+ LocalVariable,
464
+ GlobalVariable,
465
+ // Punctuation
466
+ LParen,
467
+ RParen,
468
+ Comma,
469
+ Dot,
470
+ // Event names
471
+ Event_intersection,
472
+ Event_mouseenter,
473
+ Event_mouseleave,
474
+ Event_mousedown,
475
+ Event_mousemove,
476
+ Event_dblclick,
477
+ Event_keypress,
478
+ Event_mutation,
479
+ Event_mouseup,
480
+ Event_keydown,
481
+ Event_change,
482
+ Event_submit,
483
+ Event_scroll,
484
+ Event_resize,
485
+ Event_click,
486
+ Event_keyup,
487
+ Event_input,
488
+ Event_every,
489
+ Event_load,
490
+ // Command keywords
491
+ Cmd_transition,
492
+ Cmd_increment,
493
+ Cmd_decrement,
494
+ Cmd_continue,
495
+ Cmd_behavior,
496
+ Cmd_compound,
497
+ Cmd_trigger,
498
+ Cmd_prepend,
499
+ Cmd_default,
500
+ Cmd_install,
501
+ Cmd_measure,
502
+ Cmd_toggle,
503
+ Cmd_remove,
504
+ Cmd_append,
505
+ Cmd_settle,
506
+ Cmd_unless,
507
+ Cmd_repeat,
508
+ Cmd_return,
509
+ Cmd_render,
510
+ Cmd_fetch,
511
+ Cmd_throw,
512
+ Cmd_clone,
513
+ Cmd_focus,
514
+ Cmd_async,
515
+ Cmd_morph,
516
+ Cmd_break,
517
+ Cmd_show,
518
+ Cmd_hide,
519
+ Cmd_wait,
520
+ Cmd_take,
521
+ Cmd_make,
522
+ Cmd_halt,
523
+ Cmd_send,
524
+ Cmd_blur,
525
+ Cmd_call,
526
+ Cmd_tell,
527
+ Cmd_init,
528
+ Cmd_swap,
529
+ Cmd_beep,
530
+ Cmd_copy,
531
+ Cmd_exit,
532
+ Cmd_pick,
533
+ Cmd_add,
534
+ Cmd_put,
535
+ Cmd_set,
536
+ Cmd_log,
537
+ Cmd_get,
538
+ Cmd_go,
539
+ Cmd_js,
540
+ // Structural keywords
541
+ Kw_previous,
542
+ Kw_closest,
543
+ Kw_while,
544
+ Kw_until,
545
+ Kw_times,
546
+ Kw_first,
547
+ Kw_false,
548
+ Kw_then,
549
+ Kw_else,
550
+ Kw_from,
551
+ Kw_into,
552
+ Kw_with,
553
+ Kw_have,
554
+ Kw_last,
555
+ Kw_next,
556
+ Kw_true,
557
+ Kw_null,
558
+ Kw_end,
559
+ Kw_for,
560
+ Kw_and,
561
+ Kw_not,
562
+ Kw_has,
563
+ Kw_you,
564
+ Kw_its,
565
+ Kw_the,
566
+ Kw_on,
567
+ Kw_if,
568
+ Kw_to,
569
+ Kw_in,
570
+ Kw_of,
571
+ Kw_as,
572
+ Kw_at,
573
+ Kw_by,
574
+ Kw_or,
575
+ Kw_is,
576
+ Kw_me,
577
+ Kw_it,
578
+ Kw_my,
579
+ Kw_no,
580
+ // Identifier (catch-all)
581
+ Identifier
582
+ ];
583
+ var hyperscriptLexer = new Lexer(allTokens, {
584
+ positionTracking: "full",
585
+ ensureOptimizations: true
586
+ });
587
+ var COMMAND_SCHEMAS = [
588
+ { action: "toggle", category: "dom-class", roles: [{ role: "patient", required: true, expectedTypes: ["selector"] }, { role: "destination", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
589
+ { action: "add", category: "dom-class", roles: [{ role: "patient", required: true, expectedTypes: ["selector"] }, { role: "destination", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
590
+ { action: "remove", category: "dom-class", roles: [{ role: "patient", required: true, expectedTypes: ["selector"] }, { role: "source", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
591
+ { action: "put", category: "dom-content", roles: [{ role: "patient", required: true, expectedTypes: ["literal", "selector", "reference", "expression"] }, { role: "destination", required: true, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
592
+ { action: "set", category: "variable", roles: [{ role: "destination", required: true, expectedTypes: ["selector", "reference", "expression"] }, { role: "patient", required: true, expectedTypes: ["literal", "expression", "reference"] }], primaryRole: "destination" },
593
+ { action: "show", category: "dom-visibility", roles: [{ role: "patient", required: true, expectedTypes: ["selector", "reference"] }, { role: "style", required: false, expectedTypes: ["literal"] }], primaryRole: "patient" },
594
+ { action: "hide", category: "dom-visibility", roles: [{ role: "patient", required: true, expectedTypes: ["selector", "reference"] }, { role: "style", required: false, expectedTypes: ["literal"] }], primaryRole: "patient" },
595
+ { action: "on", category: "event", roles: [{ role: "event", required: true, expectedTypes: ["literal"] }, { role: "source", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "event" },
596
+ { action: "trigger", category: "event", roles: [{ role: "event", required: true, expectedTypes: ["literal", "expression"] }, { role: "destination", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "event" },
597
+ { action: "wait", category: "async", roles: [{ role: "patient", required: true, expectedTypes: ["literal", "expression"] }], primaryRole: "patient" },
598
+ { action: "fetch", category: "async", roles: [{ role: "source", required: true, expectedTypes: ["literal", "expression"] }, { role: "responseType", required: false, expectedTypes: ["literal", "expression"] }, { role: "method", required: false, expectedTypes: ["literal"] }, { role: "destination", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "source" },
599
+ { action: "increment", category: "variable", roles: [{ role: "patient", required: true, expectedTypes: ["selector", "reference", "expression"] }, { role: "quantity", required: false, expectedTypes: ["literal"] }], primaryRole: "patient" },
600
+ { action: "decrement", category: "variable", roles: [{ role: "patient", required: true, expectedTypes: ["selector", "reference", "expression"] }, { role: "quantity", required: false, expectedTypes: ["literal"] }], primaryRole: "patient" },
601
+ { action: "append", category: "dom-content", roles: [{ role: "patient", required: true, expectedTypes: ["literal", "selector", "expression"] }, { role: "destination", required: true, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
602
+ { action: "prepend", category: "dom-content", roles: [{ role: "patient", required: true, expectedTypes: ["literal", "selector", "expression"] }, { role: "destination", required: true, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
603
+ { action: "log", category: "variable", roles: [{ role: "patient", required: true, expectedTypes: ["literal", "selector", "reference", "expression"] }], primaryRole: "patient" },
604
+ { action: "get", category: "variable", roles: [{ role: "source", required: true, expectedTypes: ["selector", "reference", "expression"] }, { role: "destination", required: false, expectedTypes: ["reference"] }], primaryRole: "source" },
605
+ { action: "take", category: "dom-content", roles: [{ role: "patient", required: true, expectedTypes: ["selector"] }, { role: "source", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
606
+ { action: "make", category: "dom-content", roles: [{ role: "patient", required: true, expectedTypes: ["literal", "selector"] }], primaryRole: "patient" },
607
+ { action: "halt", category: "control-flow", roles: [{ role: "patient", required: false, expectedTypes: ["literal", "reference", "expression"] }], primaryRole: "patient" },
608
+ { action: "settle", category: "async", roles: [{ role: "patient", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
609
+ { action: "throw", category: "control-flow", roles: [{ role: "patient", required: true, expectedTypes: ["literal", "expression"] }], primaryRole: "patient" },
610
+ { action: "send", category: "event", roles: [{ role: "event", required: true, expectedTypes: ["literal", "expression"] }, { role: "destination", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "event" },
611
+ { action: "if", category: "control-flow", roles: [{ role: "condition", required: true, expectedTypes: ["expression"] }], primaryRole: "condition" },
612
+ { action: "unless", category: "control-flow", roles: [{ role: "condition", required: true, expectedTypes: ["expression"] }], primaryRole: "condition" },
613
+ { action: "else", category: "control-flow", roles: [], primaryRole: "patient" },
614
+ { action: "repeat", category: "control-flow", roles: [{ role: "loopType", required: true, expectedTypes: ["literal"] }, { role: "quantity", required: false, expectedTypes: ["literal", "expression"] }, { role: "event", required: false, expectedTypes: ["literal", "expression"] }, { role: "source", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "loopType" },
615
+ { action: "for", category: "control-flow", roles: [{ role: "patient", required: true, expectedTypes: ["reference"] }, { role: "source", required: true, expectedTypes: ["selector", "reference", "expression"] }], primaryRole: "patient" },
616
+ { action: "while", category: "control-flow", roles: [{ role: "condition", required: true, expectedTypes: ["expression"] }], primaryRole: "condition" },
617
+ { action: "continue", category: "control-flow", roles: [], primaryRole: "patient" },
618
+ { action: "go", category: "navigation", roles: [{ role: "destination", required: true, expectedTypes: ["literal", "expression"] }], primaryRole: "destination" },
619
+ { action: "transition", category: "dom-visibility", roles: [{ role: "patient", required: true, expectedTypes: ["literal"] }, { role: "goal", required: true, expectedTypes: ["literal", "expression"] }, { role: "destination", required: false, expectedTypes: ["selector", "reference"] }, { role: "duration", required: false, expectedTypes: ["literal"] }, { role: "style", required: false, expectedTypes: ["literal"] }], primaryRole: "patient" },
620
+ { action: "clone", category: "dom-content", roles: [{ role: "patient", required: true, expectedTypes: ["selector", "reference"] }, { role: "destination", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
621
+ { action: "focus", category: "dom-content", roles: [{ role: "patient", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
622
+ { action: "blur", category: "dom-content", roles: [{ role: "patient", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
623
+ { action: "call", category: "control-flow", roles: [{ role: "patient", required: true, expectedTypes: ["expression", "reference"] }], primaryRole: "patient" },
624
+ { action: "return", category: "control-flow", roles: [{ role: "patient", required: false, expectedTypes: ["literal", "expression", "reference"] }], primaryRole: "patient" },
625
+ { action: "js", category: "control-flow", roles: [{ role: "patient", required: false, expectedTypes: ["expression"] }], primaryRole: "patient" },
626
+ { action: "async", category: "async", roles: [], primaryRole: "patient" },
627
+ { action: "tell", category: "control-flow", roles: [{ role: "destination", required: true, expectedTypes: ["selector", "reference"] }], primaryRole: "destination" },
628
+ { action: "default", category: "variable", roles: [{ role: "destination", required: true, expectedTypes: ["reference"] }, { role: "patient", required: true, expectedTypes: ["literal", "expression"] }], primaryRole: "destination" },
629
+ { action: "init", category: "control-flow", roles: [], primaryRole: "patient" },
630
+ { action: "behavior", category: "control-flow", roles: [{ role: "patient", required: true, expectedTypes: ["literal", "reference", "expression"] }], primaryRole: "patient" },
631
+ { action: "install", category: "control-flow", roles: [{ role: "patient", required: true, expectedTypes: ["literal", "reference", "expression"] }, { role: "destination", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
632
+ { action: "measure", category: "dom-content", roles: [{ role: "patient", required: false, expectedTypes: ["literal", "expression"] }, { role: "source", required: false, expectedTypes: ["selector", "reference"] }], primaryRole: "patient" },
633
+ { action: "swap", category: "dom-content", roles: [{ role: "method", required: false, expectedTypes: ["literal"] }, { role: "destination", required: true, expectedTypes: ["selector", "reference"] }, { role: "patient", required: false, expectedTypes: ["literal", "expression", "selector"] }], primaryRole: "destination" },
634
+ { action: "morph", category: "dom-content", roles: [{ role: "destination", required: true, expectedTypes: ["selector", "reference"] }, { role: "patient", required: true, expectedTypes: ["literal", "expression", "selector"] }], primaryRole: "destination" },
635
+ { action: "beep", category: "variable", roles: [{ role: "patient", required: false, expectedTypes: ["literal", "selector", "reference", "expression"] }], primaryRole: "patient" },
636
+ { action: "break", category: "control-flow", roles: [], primaryRole: "patient" },
637
+ { action: "copy", category: "dom-content", roles: [{ role: "patient", required: true, expectedTypes: ["literal", "selector", "reference", "expression"] }], primaryRole: "patient" },
638
+ { action: "exit", category: "control-flow", roles: [], primaryRole: "patient" },
639
+ { action: "pick", category: "variable", roles: [{ role: "patient", required: true, expectedTypes: ["literal", "expression", "reference"] }, { role: "source", required: false, expectedTypes: ["reference", "expression"] }], primaryRole: "patient" },
640
+ { action: "render", category: "dom-content", roles: [{ role: "patient", required: true, expectedTypes: ["selector", "reference", "expression"] }, { role: "style", required: false, expectedTypes: ["expression", "reference"] }], primaryRole: "patient" },
641
+ { action: "compound", category: "control-flow", roles: [], primaryRole: "patient" }
642
+ ];
643
+
644
+ // src/chevrotain-parser.ts
645
+ var HyperscriptParser = class extends CstParser {
646
+ constructor() {
647
+ super(allTokens, {
648
+ recoveryEnabled: true,
649
+ maxLookahead: 3
650
+ });
651
+ this.performSelfAnalysis();
652
+ }
653
+ // -------------------------------------------------------------------------
654
+ // Top-level rules
655
+ // -------------------------------------------------------------------------
656
+ program = this.RULE("program", () => {
657
+ this.MANY(() => {
658
+ this.SUBRULE(this.statement);
659
+ });
660
+ });
661
+ statement = this.RULE("statement", () => {
662
+ this.OR([
663
+ { ALT: () => this.SUBRULE(this.eventHandler) },
664
+ { ALT: () => this.SUBRULE(this.commandChain) },
665
+ { ALT: () => this.SUBRULE(this.behaviorDef) }
666
+ ]);
667
+ });
668
+ // -------------------------------------------------------------------------
669
+ // Event handlers
670
+ // -------------------------------------------------------------------------
671
+ eventHandler = this.RULE("eventHandler", () => {
672
+ this.CONSUME(Kw_on);
673
+ this.SUBRULE(this.eventName);
674
+ this.OPTION(() => {
675
+ this.SUBRULE(this.eventModifiers);
676
+ });
677
+ this.OPTION2(() => {
678
+ this.SUBRULE(this.commandChain);
679
+ });
680
+ this.OPTION3(() => {
681
+ this.CONSUME(Kw_end);
682
+ });
683
+ });
684
+ eventName = this.RULE("eventName", () => {
685
+ this.OR([
686
+ { ALT: () => this.CONSUME(Event_click) },
687
+ { ALT: () => this.CONSUME(Event_dblclick) },
688
+ { ALT: () => this.CONSUME(Event_mousedown) },
689
+ { ALT: () => this.CONSUME(Event_mouseup) },
690
+ { ALT: () => this.CONSUME(Event_mousemove) },
691
+ { ALT: () => this.CONSUME(Event_mouseenter) },
692
+ { ALT: () => this.CONSUME(Event_mouseleave) },
693
+ { ALT: () => this.CONSUME(Event_keydown) },
694
+ { ALT: () => this.CONSUME(Event_keyup) },
695
+ { ALT: () => this.CONSUME(Event_input) },
696
+ { ALT: () => this.CONSUME(Event_change) },
697
+ { ALT: () => this.CONSUME(Event_submit) },
698
+ { ALT: () => this.CONSUME(Event_load) },
699
+ { ALT: () => this.CONSUME(Event_scroll) },
700
+ { ALT: () => this.CONSUME(Event_resize) },
701
+ { ALT: () => this.CONSUME(Event_mutation) },
702
+ { ALT: () => this.CONSUME(Event_intersection) },
703
+ { ALT: () => this.CONSUME(Event_every) },
704
+ { ALT: () => this.CONSUME(Identifier) }
705
+ // Custom event name
706
+ ]);
707
+ });
708
+ eventModifiers = this.RULE("eventModifiers", () => {
709
+ this.MANY(() => {
710
+ this.CONSUME(Dot);
711
+ this.CONSUME(Identifier);
712
+ this.OPTION(() => {
713
+ this.CONSUME(LParen);
714
+ this.SUBRULE(this.expression);
715
+ this.CONSUME(RParen);
716
+ });
717
+ });
718
+ });
719
+ // -------------------------------------------------------------------------
720
+ // Command chain (commands connected by 'then')
721
+ // -------------------------------------------------------------------------
722
+ commandChain = this.RULE("commandChain", () => {
723
+ this.SUBRULE(this.command);
724
+ this.MANY(() => {
725
+ this.CONSUME(Kw_then);
726
+ this.SUBRULE2(this.command);
727
+ });
728
+ });
729
+ // -------------------------------------------------------------------------
730
+ // Commands (grouped by category for error messages)
731
+ // -------------------------------------------------------------------------
732
+ command = this.RULE("command", () => {
733
+ this.OR([
734
+ // DOM class/attribute
735
+ { ALT: () => this.SUBRULE(this.toggleCommand) },
736
+ { ALT: () => this.SUBRULE(this.addCommand) },
737
+ { ALT: () => this.SUBRULE(this.removeCommand) },
738
+ // DOM content
739
+ { ALT: () => this.SUBRULE(this.putCommand) },
740
+ { ALT: () => this.SUBRULE(this.setCommand) },
741
+ { ALT: () => this.SUBRULE(this.appendCommand) },
742
+ { ALT: () => this.SUBRULE(this.prependCommand) },
743
+ // DOM visibility
744
+ { ALT: () => this.SUBRULE(this.showCommand) },
745
+ { ALT: () => this.SUBRULE(this.hideCommand) },
746
+ { ALT: () => this.SUBRULE(this.transitionCommand) },
747
+ // Variable
748
+ { ALT: () => this.SUBRULE(this.logCommand) },
749
+ { ALT: () => this.SUBRULE(this.incrementCommand) },
750
+ { ALT: () => this.SUBRULE(this.decrementCommand) },
751
+ // Async
752
+ { ALT: () => this.SUBRULE(this.fetchCommand) },
753
+ { ALT: () => this.SUBRULE(this.waitCommand) },
754
+ // Event
755
+ { ALT: () => this.SUBRULE(this.sendCommand) },
756
+ { ALT: () => this.SUBRULE(this.triggerCommand) },
757
+ // Navigation
758
+ { ALT: () => this.SUBRULE(this.goCommand) },
759
+ // Control flow
760
+ { ALT: () => this.SUBRULE(this.ifCommand) },
761
+ { ALT: () => this.SUBRULE(this.repeatCommand) },
762
+ // Execution
763
+ { ALT: () => this.SUBRULE(this.callCommand) },
764
+ { ALT: () => this.SUBRULE(this.jsCommand) },
765
+ { ALT: () => this.SUBRULE(this.returnCommand) },
766
+ { ALT: () => this.SUBRULE(this.throwCommand) },
767
+ { ALT: () => this.SUBRULE(this.haltCommand) }
768
+ ]);
769
+ });
770
+ // --- DOM class/attribute ---
771
+ toggleCommand = this.RULE("toggleCommand", () => {
772
+ this.CONSUME(Cmd_toggle);
773
+ this.SUBRULE(this.selectorOrExpression);
774
+ this.OPTION(() => {
775
+ this.CONSUME(Kw_on);
776
+ this.SUBRULE2(this.selectorOrExpression);
777
+ });
778
+ });
779
+ addCommand = this.RULE("addCommand", () => {
780
+ this.CONSUME(Cmd_add);
781
+ this.SUBRULE(this.selectorOrExpression);
782
+ this.OPTION(() => {
783
+ this.CONSUME(Kw_to);
784
+ this.SUBRULE2(this.selectorOrExpression);
785
+ });
786
+ });
787
+ removeCommand = this.RULE("removeCommand", () => {
788
+ this.CONSUME(Cmd_remove);
789
+ this.SUBRULE(this.selectorOrExpression);
790
+ this.OPTION(() => {
791
+ this.CONSUME(Kw_from);
792
+ this.SUBRULE2(this.selectorOrExpression);
793
+ });
794
+ });
795
+ // --- DOM content ---
796
+ putCommand = this.RULE("putCommand", () => {
797
+ this.CONSUME(Cmd_put);
798
+ this.SUBRULE(this.expression);
799
+ this.OPTION(() => {
800
+ this.OR([
801
+ { ALT: () => this.CONSUME(Kw_into) },
802
+ { ALT: () => this.CONSUME(Identifier, { LABEL: "putMarker" }) }
803
+ // before/after
804
+ ]);
805
+ this.SUBRULE2(this.selectorOrExpression);
806
+ });
807
+ });
808
+ setCommand = this.RULE("setCommand", () => {
809
+ this.CONSUME(Cmd_set);
810
+ this.SUBRULE(this.selectorOrExpression);
811
+ this.CONSUME(Kw_to);
812
+ this.SUBRULE2(this.expression);
813
+ });
814
+ appendCommand = this.RULE("appendCommand", () => {
815
+ this.CONSUME(Cmd_append);
816
+ this.SUBRULE(this.expression);
817
+ this.CONSUME(Kw_to);
818
+ this.SUBRULE2(this.selectorOrExpression);
819
+ });
820
+ prependCommand = this.RULE("prependCommand", () => {
821
+ this.CONSUME(Cmd_prepend);
822
+ this.SUBRULE(this.expression);
823
+ this.CONSUME(Kw_to);
824
+ this.SUBRULE2(this.selectorOrExpression);
825
+ });
826
+ // --- DOM visibility ---
827
+ showCommand = this.RULE("showCommand", () => {
828
+ this.CONSUME(Cmd_show);
829
+ this.OPTION(() => this.SUBRULE(this.selectorOrExpression));
830
+ });
831
+ hideCommand = this.RULE("hideCommand", () => {
832
+ this.CONSUME(Cmd_hide);
833
+ this.OPTION(() => this.SUBRULE(this.selectorOrExpression));
834
+ });
835
+ transitionCommand = this.RULE("transitionCommand", () => {
836
+ this.CONSUME(Cmd_transition);
837
+ this.SUBRULE(this.selectorOrExpression);
838
+ });
839
+ // --- Variable ---
840
+ logCommand = this.RULE("logCommand", () => {
841
+ this.CONSUME(Cmd_log);
842
+ this.SUBRULE(this.expression);
843
+ });
844
+ incrementCommand = this.RULE("incrementCommand", () => {
845
+ this.CONSUME(Cmd_increment);
846
+ this.SUBRULE(this.selectorOrExpression);
847
+ this.OPTION(() => {
848
+ this.CONSUME(Kw_by);
849
+ this.SUBRULE2(this.expression);
850
+ });
851
+ });
852
+ decrementCommand = this.RULE("decrementCommand", () => {
853
+ this.CONSUME(Cmd_decrement);
854
+ this.SUBRULE(this.selectorOrExpression);
855
+ this.OPTION(() => {
856
+ this.CONSUME(Kw_by);
857
+ this.SUBRULE2(this.expression);
858
+ });
859
+ });
860
+ // --- Async ---
861
+ fetchCommand = this.RULE("fetchCommand", () => {
862
+ this.CONSUME(Cmd_fetch);
863
+ this.SUBRULE(this.expression);
864
+ this.OPTION(() => {
865
+ this.CONSUME(Kw_as);
866
+ this.CONSUME(Identifier, { LABEL: "responseType" });
867
+ });
868
+ });
869
+ waitCommand = this.RULE("waitCommand", () => {
870
+ this.CONSUME(Cmd_wait);
871
+ this.OPTION(() => this.SUBRULE(this.expression));
872
+ });
873
+ // --- Event ---
874
+ sendCommand = this.RULE("sendCommand", () => {
875
+ this.CONSUME(Cmd_send);
876
+ this.CONSUME(Identifier, { LABEL: "eventName" });
877
+ this.OPTION(() => {
878
+ this.CONSUME(Kw_to);
879
+ this.SUBRULE(this.selectorOrExpression);
880
+ });
881
+ });
882
+ triggerCommand = this.RULE("triggerCommand", () => {
883
+ this.CONSUME(Cmd_trigger);
884
+ this.CONSUME(Identifier, { LABEL: "eventName" });
885
+ this.OPTION(() => {
886
+ this.CONSUME(Kw_on);
887
+ this.SUBRULE(this.selectorOrExpression);
888
+ });
889
+ });
890
+ // --- Navigation ---
891
+ goCommand = this.RULE("goCommand", () => {
892
+ this.CONSUME(Cmd_go);
893
+ this.OPTION(() => this.CONSUME(Kw_to));
894
+ this.SUBRULE(this.expression);
895
+ });
896
+ // --- Control flow ---
897
+ ifCommand = this.RULE("ifCommand", () => {
898
+ this.CONSUME(Kw_if);
899
+ this.SUBRULE(this.expression);
900
+ this.OPTION(() => this.SUBRULE(this.commandChain));
901
+ this.OPTION2(() => {
902
+ this.CONSUME(Kw_else);
903
+ this.OPTION3(() => this.SUBRULE2(this.commandChain));
904
+ });
905
+ this.OPTION4(() => this.CONSUME(Kw_end));
906
+ });
907
+ repeatCommand = this.RULE("repeatCommand", () => {
908
+ this.CONSUME(Cmd_repeat);
909
+ this.OR([
910
+ {
911
+ ALT: () => {
912
+ this.SUBRULE(this.expression);
913
+ this.CONSUME(Kw_times);
914
+ }
915
+ },
916
+ {
917
+ ALT: () => {
918
+ this.CONSUME(Kw_for);
919
+ this.CONSUME(Identifier, { LABEL: "loopVar" });
920
+ this.CONSUME(Kw_in);
921
+ this.SUBRULE2(this.expression);
922
+ }
923
+ },
924
+ {
925
+ ALT: () => {
926
+ this.CONSUME(Kw_while);
927
+ this.SUBRULE3(this.expression);
928
+ }
929
+ },
930
+ {
931
+ ALT: () => {
932
+ this.CONSUME(Kw_until);
933
+ this.SUBRULE4(this.expression);
934
+ }
935
+ },
936
+ {
937
+ ALT: () => {
938
+ }
939
+ }
940
+ ]);
941
+ this.OPTION(() => this.SUBRULE(this.commandChain));
942
+ this.OPTION2(() => this.CONSUME(Kw_end));
943
+ });
944
+ // --- Execution ---
945
+ callCommand = this.RULE("callCommand", () => {
946
+ this.CONSUME(Cmd_call);
947
+ this.SUBRULE(this.expression);
948
+ });
949
+ jsCommand = this.RULE("jsCommand", () => {
950
+ this.CONSUME(Cmd_js);
951
+ this.MANY(() => {
952
+ this.OR([
953
+ { ALT: () => this.CONSUME(Identifier) },
954
+ { ALT: () => this.CONSUME(StringLiteral) },
955
+ { ALT: () => this.CONSUME(NumberLiteral) },
956
+ { ALT: () => this.CONSUME(CSSSelector) },
957
+ { ALT: () => this.CONSUME(LocalVariable) },
958
+ { ALT: () => this.CONSUME(LParen) },
959
+ { ALT: () => this.CONSUME(RParen) },
960
+ { ALT: () => this.CONSUME(Comma) },
961
+ { ALT: () => this.CONSUME(Dot) }
962
+ ]);
963
+ });
964
+ this.CONSUME(Kw_end);
965
+ });
966
+ returnCommand = this.RULE("returnCommand", () => {
967
+ this.CONSUME(Cmd_return);
968
+ this.OPTION(() => this.SUBRULE(this.expression));
969
+ });
970
+ throwCommand = this.RULE("throwCommand", () => {
971
+ this.CONSUME(Cmd_throw);
972
+ this.SUBRULE(this.expression);
973
+ });
974
+ haltCommand = this.RULE("haltCommand", () => {
975
+ this.CONSUME(Cmd_halt);
976
+ });
977
+ // -------------------------------------------------------------------------
978
+ // Behavior definitions
979
+ // -------------------------------------------------------------------------
980
+ behaviorDef = this.RULE("behaviorDef", () => {
981
+ this.CONSUME(Cmd_behavior);
982
+ this.CONSUME(Identifier, { LABEL: "behaviorName" });
983
+ this.OPTION(() => {
984
+ this.CONSUME(LParen);
985
+ this.AT_LEAST_ONE_SEP({
986
+ SEP: Comma,
987
+ DEF: () => this.CONSUME2(Identifier, { LABEL: "param" })
988
+ });
989
+ this.CONSUME(RParen);
990
+ });
991
+ this.MANY(() => this.SUBRULE(this.statement));
992
+ this.CONSUME(Kw_end);
993
+ });
994
+ // -------------------------------------------------------------------------
995
+ // Expressions (simplified for LSP — full expression parsing is in core)
996
+ // -------------------------------------------------------------------------
997
+ expression = this.RULE("expression", () => {
998
+ this.SUBRULE(this.primaryExpression);
999
+ this.MANY(() => {
1000
+ this.OR([
1001
+ {
1002
+ ALT: () => {
1003
+ this.OR2([
1004
+ { ALT: () => this.CONSUME(Kw_is) },
1005
+ { ALT: () => this.CONSUME(Kw_and) },
1006
+ { ALT: () => this.CONSUME(Kw_or) }
1007
+ ]);
1008
+ this.SUBRULE2(this.primaryExpression);
1009
+ }
1010
+ },
1011
+ {
1012
+ ALT: () => {
1013
+ this.CONSUME(Dot);
1014
+ this.CONSUME(Identifier);
1015
+ }
1016
+ }
1017
+ ]);
1018
+ });
1019
+ });
1020
+ primaryExpression = this.RULE("primaryExpression", () => {
1021
+ this.OPTION(() => {
1022
+ this.OR([
1023
+ { ALT: () => this.CONSUME(Kw_not) },
1024
+ { ALT: () => this.CONSUME(Kw_the) },
1025
+ { ALT: () => this.CONSUME(Kw_no) }
1026
+ ]);
1027
+ });
1028
+ this.OR2([
1029
+ { ALT: () => this.CONSUME(StringLiteral) },
1030
+ { ALT: () => this.CONSUME(NumberLiteral) },
1031
+ { ALT: () => this.CONSUME(CSSSelector) },
1032
+ { ALT: () => this.CONSUME(AttributeSelector) },
1033
+ { ALT: () => this.CONSUME(HTMLSelector) },
1034
+ { ALT: () => this.CONSUME(LocalVariable) },
1035
+ { ALT: () => this.CONSUME(GlobalVariable) },
1036
+ { ALT: () => this.CONSUME(Kw_me) },
1037
+ { ALT: () => this.CONSUME(Kw_it) },
1038
+ { ALT: () => this.CONSUME(Kw_true) },
1039
+ { ALT: () => this.CONSUME(Kw_false) },
1040
+ { ALT: () => this.CONSUME(Identifier) },
1041
+ {
1042
+ ALT: () => {
1043
+ this.CONSUME(LParen);
1044
+ this.SUBRULE(this.expression);
1045
+ this.CONSUME(RParen);
1046
+ }
1047
+ }
1048
+ ]);
1049
+ });
1050
+ // -------------------------------------------------------------------------
1051
+ // Selectors or expressions
1052
+ // -------------------------------------------------------------------------
1053
+ selectorOrExpression = this.RULE("selectorOrExpression", () => {
1054
+ this.OR([
1055
+ { ALT: () => this.CONSUME(CSSSelector) },
1056
+ { ALT: () => this.CONSUME(AttributeSelector) },
1057
+ { ALT: () => this.CONSUME(HTMLSelector) },
1058
+ { ALT: () => this.CONSUME(Kw_me) },
1059
+ { ALT: () => this.CONSUME(Kw_it) },
1060
+ { ALT: () => this.CONSUME(LocalVariable) },
1061
+ { ALT: () => this.CONSUME(GlobalVariable) },
1062
+ { ALT: () => this.CONSUME(Identifier) }
1063
+ ]);
1064
+ });
1065
+ };
1066
+ var parserInstance = new HyperscriptParser();
1067
+ function parseWithRecovery(code) {
1068
+ const lexResult = hyperscriptLexer.tokenize(code);
1069
+ const diagnostics = lexResult.errors.map((err) => ({
1070
+ message: err.message,
1071
+ severity: "error",
1072
+ startOffset: err.offset,
1073
+ endOffset: err.offset + (err.length || 1),
1074
+ startLine: err.line ?? 1,
1075
+ startColumn: err.column ?? 1,
1076
+ code: "lex-error"
1077
+ }));
1078
+ const nonWS = lexResult.tokens.filter((t) => t.tokenType !== WhiteSpace);
1079
+ parserInstance.input = nonWS;
1080
+ const cst = parserInstance.program();
1081
+ for (const err of parserInstance.errors) {
1082
+ diagnostics.push(recognitionExceptionToDiagnostic(err));
1083
+ }
1084
+ return {
1085
+ cst,
1086
+ diagnostics,
1087
+ tokens: lexResult.tokens
1088
+ };
1089
+ }
1090
+ function getContentAssist(code, offset) {
1091
+ const lexResult = hyperscriptLexer.tokenize(code);
1092
+ const nonWS = lexResult.tokens.filter((t) => t.tokenType !== WhiteSpace);
1093
+ const suggestions = [];
1094
+ const tokenBefore = findTokenBefore(nonWS, offset);
1095
+ const context = inferContextFromTokens(nonWS, tokenBefore);
1096
+ switch (context) {
1097
+ case "start":
1098
+ case "after-then":
1099
+ suggestions.push(...getCommandSuggestions());
1100
+ suggestions.push({
1101
+ label: "on",
1102
+ kind: "keyword",
1103
+ detail: "Event handler",
1104
+ insertText: "on "
1105
+ });
1106
+ break;
1107
+ case "after-on":
1108
+ suggestions.push(...getEventSuggestions());
1109
+ break;
1110
+ case "after-command":
1111
+ if (tokenBefore) {
1112
+ suggestions.push(...getRoleMarkerSuggestions(tokenBefore));
1113
+ }
1114
+ break;
1115
+ case "after-marker":
1116
+ suggestions.push(...getSelectorSuggestions());
1117
+ break;
1118
+ default:
1119
+ suggestions.push(...getCommandSuggestions());
1120
+ suggestions.push(...getSelectorSuggestions());
1121
+ break;
1122
+ }
1123
+ return suggestions;
1124
+ }
1125
+ function recognitionExceptionToDiagnostic(err) {
1126
+ const token = err.token;
1127
+ const startOffset = token.startOffset ?? 0;
1128
+ const endOffset = token.endOffset ?? startOffset + 1;
1129
+ let message = err.message;
1130
+ const match = message.match(/Expecting (.*?) but found/);
1131
+ if (match) {
1132
+ const expected = match[1].replace(/token of type --> /g, "").replace(/ <--/g, "").replace(/one of these possible Token Types:\s*/g, "").replace(/\[.*?\]/g, (m) => {
1133
+ const names = m.slice(1, -1).split(",").map((n) => n.trim());
1134
+ return names.slice(0, 5).join(", ") + (names.length > 5 ? "..." : "");
1135
+ });
1136
+ message = `Expected ${expected}`;
1137
+ if (token.image) {
1138
+ message += ` but found '${token.image}'`;
1139
+ }
1140
+ }
1141
+ return {
1142
+ message,
1143
+ severity: "error",
1144
+ startOffset,
1145
+ endOffset,
1146
+ startLine: token.startLine ?? 1,
1147
+ startColumn: token.startColumn ?? 1,
1148
+ code: "parse-error"
1149
+ };
1150
+ }
1151
+ function findTokenBefore(tokens, offset) {
1152
+ let best = null;
1153
+ for (const t of tokens) {
1154
+ if (t.startOffset <= offset) {
1155
+ best = t;
1156
+ } else {
1157
+ break;
1158
+ }
1159
+ }
1160
+ return best;
1161
+ }
1162
+ function inferContextFromTokens(tokens, tokenBefore) {
1163
+ if (!tokenBefore || tokens.length === 0) return "start";
1164
+ const type = tokenBefore.tokenType;
1165
+ if (type === Kw_on) return "after-on";
1166
+ if (type === Kw_then) return "after-then";
1167
+ if (type.name.startsWith("Cmd_")) return "after-command";
1168
+ const markers = [Kw_to, Kw_from, Kw_into, Kw_in, Kw_of, Kw_on, Kw_as, Kw_with];
1169
+ if (markers.includes(type)) return "after-marker";
1170
+ return "general";
1171
+ }
1172
+ function getCommandSuggestions() {
1173
+ return COMMAND_SCHEMAS.map((schema) => ({
1174
+ label: schema.action,
1175
+ kind: "command",
1176
+ detail: getCategoryLabel(schema.category),
1177
+ insertText: schema.action + " ",
1178
+ category: schema.category
1179
+ }));
1180
+ }
1181
+ function getEventSuggestions() {
1182
+ const events = [
1183
+ "click",
1184
+ "dblclick",
1185
+ "mousedown",
1186
+ "mouseup",
1187
+ "mousemove",
1188
+ "mouseenter",
1189
+ "mouseleave",
1190
+ "keydown",
1191
+ "keyup",
1192
+ "keypress",
1193
+ "input",
1194
+ "change",
1195
+ "submit",
1196
+ "focus",
1197
+ "blur",
1198
+ "load",
1199
+ "scroll",
1200
+ "resize",
1201
+ "mutation",
1202
+ "intersection",
1203
+ "every"
1204
+ ];
1205
+ return events.map((e) => ({
1206
+ label: e,
1207
+ kind: "event",
1208
+ detail: `${e} event`,
1209
+ insertText: e + " "
1210
+ }));
1211
+ }
1212
+ function getRoleMarkerSuggestions(commandToken) {
1213
+ const cmdName = commandToken.tokenType.name.replace("Cmd_", "");
1214
+ const schema = COMMAND_SCHEMAS.find((s) => s.action === cmdName);
1215
+ if (!schema) return [];
1216
+ const suggestions = [];
1217
+ for (const role of schema.roles) {
1218
+ if (role.role === schema.primaryRole) continue;
1219
+ const markers = getRoleMarkers(role.role);
1220
+ for (const marker of markers) {
1221
+ suggestions.push({
1222
+ label: marker,
1223
+ kind: "keyword",
1224
+ detail: `${role.role} marker`,
1225
+ insertText: marker + " "
1226
+ });
1227
+ }
1228
+ }
1229
+ return suggestions;
1230
+ }
1231
+ function getSelectorSuggestions() {
1232
+ return [
1233
+ { label: "me", kind: "keyword", detail: "Current element" },
1234
+ { label: "it", kind: "keyword", detail: "Last result" },
1235
+ { label: ".", kind: "selector", detail: "CSS class selector", insertText: "." },
1236
+ { label: "#", kind: "selector", detail: "CSS ID selector", insertText: "#" },
1237
+ { label: "@", kind: "selector", detail: "Attribute selector", insertText: "@" },
1238
+ { label: ":", kind: "variable", detail: "Local variable", insertText: ":" },
1239
+ { label: "$", kind: "variable", detail: "Global variable", insertText: "$" }
1240
+ ];
1241
+ }
1242
+ function getRoleMarkers(role) {
1243
+ switch (role) {
1244
+ case "destination":
1245
+ return ["to", "into"];
1246
+ case "source":
1247
+ return ["from"];
1248
+ case "target":
1249
+ return ["on"];
1250
+ case "container":
1251
+ return ["in"];
1252
+ case "instrument":
1253
+ return ["with"];
1254
+ case "beneficiary":
1255
+ return ["for"];
1256
+ default:
1257
+ return [];
1258
+ }
1259
+ }
1260
+ function getCategoryLabel(category) {
1261
+ const labels = {
1262
+ "dom-class": "DOM Class/Attribute",
1263
+ "dom-content": "DOM Content",
1264
+ "dom-visibility": "DOM Visibility",
1265
+ variable: "Variable",
1266
+ event: "Event",
1267
+ async: "Async",
1268
+ navigation: "Navigation",
1269
+ "control-flow": "Control Flow"
1270
+ };
1271
+ return labels[category] || category;
1272
+ }
1273
+
1274
+ // src/localized-descriptions.ts
1275
+ var DESCRIPTIONS = {
1276
+ en: {
1277
+ toggle: {
1278
+ detail: "Toggle class/visibility",
1279
+ documentation: "Toggles a CSS class or attribute on an element. If the class exists, it is removed; otherwise, it is added."
1280
+ },
1281
+ add: {
1282
+ detail: "Add class/attribute",
1283
+ documentation: "Adds a CSS class or attribute to an element."
1284
+ },
1285
+ remove: {
1286
+ detail: "Remove class/element",
1287
+ documentation: "Removes a CSS class, attribute, or element from the DOM."
1288
+ },
1289
+ show: {
1290
+ detail: "Show element",
1291
+ documentation: "Makes an element visible by removing display:none."
1292
+ },
1293
+ hide: { detail: "Hide element", documentation: "Hides an element by setting display:none." },
1294
+ put: {
1295
+ detail: "Set content",
1296
+ documentation: "Sets the content of an element (innerHTML, textContent, or value)."
1297
+ },
1298
+ set: { detail: "Set variable", documentation: "Assigns a value to a variable or property." },
1299
+ get: {
1300
+ detail: "Get value",
1301
+ documentation: "Retrieves a value from an expression and stores it in the result variable."
1302
+ },
1303
+ fetch: {
1304
+ detail: "HTTP request",
1305
+ documentation: "Makes an HTTP request (GET, POST, etc.) and stores the response."
1306
+ },
1307
+ call: { detail: "Call function", documentation: "Calls a JavaScript function or method." },
1308
+ send: { detail: "Send event", documentation: "Dispatches a custom event on an element." },
1309
+ trigger: { detail: "Trigger event", documentation: "Triggers an event on an element." },
1310
+ wait: {
1311
+ detail: "Delay execution",
1312
+ documentation: "Pauses execution for a specified duration."
1313
+ },
1314
+ log: { detail: "Log to console", documentation: "Outputs a value to the browser console." },
1315
+ increment: {
1316
+ detail: "Increment value",
1317
+ documentation: "Increases a numeric value by 1 or a specified amount."
1318
+ },
1319
+ decrement: {
1320
+ detail: "Decrement value",
1321
+ documentation: "Decreases a numeric value by 1 or a specified amount."
1322
+ },
1323
+ append: { detail: "Append content", documentation: "Appends content to an element or array." },
1324
+ settle: {
1325
+ detail: "Wait for transitions",
1326
+ documentation: "Waits for CSS transitions/animations to complete."
1327
+ },
1328
+ go: { detail: "Navigate", documentation: "Navigates to a URL or page location." },
1329
+ throw: { detail: "Throw error", documentation: "Throws an error with a specified message." }
1330
+ },
1331
+ ja: {
1332
+ toggle: {
1333
+ detail: "\u30AF\u30E9\u30B9/\u8868\u793A\u5207\u66FF",
1334
+ documentation: "\u8981\u7D20\u306ECSS\u30AF\u30E9\u30B9\u307E\u305F\u306F\u5C5E\u6027\u3092\u5207\u308A\u66FF\u3048\u307E\u3059\u3002\u30AF\u30E9\u30B9\u304C\u5B58\u5728\u3059\u308B\u5834\u5408\u306F\u524A\u9664\u3057\u3001\u5B58\u5728\u3057\u306A\u3044\u5834\u5408\u306F\u8FFD\u52A0\u3057\u307E\u3059\u3002"
1335
+ },
1336
+ add: { detail: "\u30AF\u30E9\u30B9/\u5C5E\u6027\u8FFD\u52A0", documentation: "\u8981\u7D20\u306BCSS\u30AF\u30E9\u30B9\u307E\u305F\u306F\u5C5E\u6027\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002" },
1337
+ remove: {
1338
+ detail: "\u30AF\u30E9\u30B9/\u8981\u7D20\u524A\u9664",
1339
+ documentation: "CSS\u30AF\u30E9\u30B9\u3001\u5C5E\u6027\u3001\u307E\u305F\u306FDOM\u8981\u7D20\u3092\u524A\u9664\u3057\u307E\u3059\u3002"
1340
+ },
1341
+ show: { detail: "\u8981\u7D20\u8868\u793A", documentation: "display:none\u3092\u524A\u9664\u3057\u3066\u8981\u7D20\u3092\u8868\u793A\u3057\u307E\u3059\u3002" },
1342
+ hide: { detail: "\u8981\u7D20\u975E\u8868\u793A", documentation: "display:none\u3092\u8A2D\u5B9A\u3057\u3066\u8981\u7D20\u3092\u975E\u8868\u793A\u306B\u3057\u307E\u3059\u3002" },
1343
+ put: {
1344
+ detail: "\u30B3\u30F3\u30C6\u30F3\u30C4\u8A2D\u5B9A",
1345
+ documentation: "\u8981\u7D20\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\uFF08innerHTML\u3001textContent\u3001\u307E\u305F\u306Fvalue\uFF09\u3092\u8A2D\u5B9A\u3057\u307E\u3059\u3002"
1346
+ },
1347
+ set: { detail: "\u5909\u6570\u8A2D\u5B9A", documentation: "\u5909\u6570\u307E\u305F\u306F\u30D7\u30ED\u30D1\u30C6\u30A3\u306B\u5024\u3092\u4EE3\u5165\u3057\u307E\u3059\u3002" },
1348
+ get: { detail: "\u5024\u53D6\u5F97", documentation: "\u5F0F\u304B\u3089\u5024\u3092\u53D6\u5F97\u3057\u3001result\u5909\u6570\u306B\u683C\u7D0D\u3057\u307E\u3059\u3002" },
1349
+ fetch: {
1350
+ detail: "HTTP\u30EA\u30AF\u30A8\u30B9\u30C8",
1351
+ documentation: "HTTP\u30EA\u30AF\u30A8\u30B9\u30C8\uFF08GET\u3001POST\u306A\u3069\uFF09\u3092\u5B9F\u884C\u3057\u3001\u30EC\u30B9\u30DD\u30F3\u30B9\u3092\u683C\u7D0D\u3057\u307E\u3059\u3002"
1352
+ },
1353
+ call: { detail: "\u95A2\u6570\u547C\u3073\u51FA\u3057", documentation: "JavaScript\u95A2\u6570\u307E\u305F\u306F\u30E1\u30BD\u30C3\u30C9\u3092\u547C\u3073\u51FA\u3057\u307E\u3059\u3002" },
1354
+ send: { detail: "\u30A4\u30D9\u30F3\u30C8\u9001\u4FE1", documentation: "\u8981\u7D20\u306B\u30AB\u30B9\u30BF\u30E0\u30A4\u30D9\u30F3\u30C8\u3092\u30C7\u30A3\u30B9\u30D1\u30C3\u30C1\u3057\u307E\u3059\u3002" },
1355
+ trigger: { detail: "\u30A4\u30D9\u30F3\u30C8\u30C8\u30EA\u30AC\u30FC", documentation: "\u8981\u7D20\u3067\u30A4\u30D9\u30F3\u30C8\u3092\u30C8\u30EA\u30AC\u30FC\u3057\u307E\u3059\u3002" },
1356
+ wait: { detail: "\u5B9F\u884C\u9045\u5EF6", documentation: "\u6307\u5B9A\u3055\u308C\u305F\u6642\u9593\u3060\u3051\u5B9F\u884C\u3092\u4E00\u6642\u505C\u6B62\u3057\u307E\u3059\u3002" },
1357
+ log: { detail: "\u30B3\u30F3\u30BD\u30FC\u30EB\u51FA\u529B", documentation: "\u30D6\u30E9\u30A6\u30B6\u30B3\u30F3\u30BD\u30FC\u30EB\u306B\u5024\u3092\u51FA\u529B\u3057\u307E\u3059\u3002" },
1358
+ increment: { detail: "\u5024\u5897\u52A0", documentation: "\u6570\u5024\u30921\u307E\u305F\u306F\u6307\u5B9A\u91CF\u3060\u3051\u5897\u52A0\u3055\u305B\u307E\u3059\u3002" },
1359
+ decrement: { detail: "\u5024\u6E1B\u5C11", documentation: "\u6570\u5024\u30921\u307E\u305F\u306F\u6307\u5B9A\u91CF\u3060\u3051\u6E1B\u5C11\u3055\u305B\u307E\u3059\u3002" },
1360
+ append: { detail: "\u30B3\u30F3\u30C6\u30F3\u30C4\u8FFD\u52A0", documentation: "\u8981\u7D20\u307E\u305F\u306F\u914D\u5217\u306B\u30B3\u30F3\u30C6\u30F3\u30C4\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002" },
1361
+ settle: {
1362
+ detail: "\u30C8\u30E9\u30F3\u30B8\u30B7\u30E7\u30F3\u5F85\u6A5F",
1363
+ documentation: "CSS\u30C8\u30E9\u30F3\u30B8\u30B7\u30E7\u30F3/\u30A2\u30CB\u30E1\u30FC\u30B7\u30E7\u30F3\u306E\u5B8C\u4E86\u3092\u5F85\u3061\u307E\u3059\u3002"
1364
+ },
1365
+ go: { detail: "\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3", documentation: "URL\u307E\u305F\u306F\u30DA\u30FC\u30B8\u4F4D\u7F6E\u306B\u79FB\u52D5\u3057\u307E\u3059\u3002" },
1366
+ throw: { detail: "\u30A8\u30E9\u30FC\u9001\u51FA", documentation: "\u6307\u5B9A\u3055\u308C\u305F\u30E1\u30C3\u30BB\u30FC\u30B8\u3067\u30A8\u30E9\u30FC\u3092\u9001\u51FA\u3057\u307E\u3059\u3002" }
1367
+ },
1368
+ es: {
1369
+ toggle: {
1370
+ detail: "Alternar clase/visibilidad",
1371
+ documentation: "Alterna una clase CSS o atributo en un elemento. Si la clase existe, se elimina; de lo contrario, se agrega."
1372
+ },
1373
+ add: {
1374
+ detail: "Agregar clase/atributo",
1375
+ documentation: "Agrega una clase CSS o atributo a un elemento."
1376
+ },
1377
+ remove: {
1378
+ detail: "Eliminar clase/elemento",
1379
+ documentation: "Elimina una clase CSS, atributo o elemento del DOM."
1380
+ },
1381
+ show: {
1382
+ detail: "Mostrar elemento",
1383
+ documentation: "Hace visible un elemento eliminando display:none."
1384
+ },
1385
+ hide: {
1386
+ detail: "Ocultar elemento",
1387
+ documentation: "Oculta un elemento estableciendo display:none."
1388
+ },
1389
+ put: {
1390
+ detail: "Establecer contenido",
1391
+ documentation: "Establece el contenido de un elemento (innerHTML, textContent o value)."
1392
+ },
1393
+ set: {
1394
+ detail: "Establecer variable",
1395
+ documentation: "Asigna un valor a una variable o propiedad."
1396
+ },
1397
+ get: {
1398
+ detail: "Obtener valor",
1399
+ documentation: "Recupera un valor de una expresion y lo almacena en la variable result."
1400
+ },
1401
+ fetch: {
1402
+ detail: "Solicitud HTTP",
1403
+ documentation: "Realiza una solicitud HTTP (GET, POST, etc.) y almacena la respuesta."
1404
+ },
1405
+ call: {
1406
+ detail: "Llamar funcion",
1407
+ documentation: "Llama a una funcion o metodo de JavaScript."
1408
+ },
1409
+ send: {
1410
+ detail: "Enviar evento",
1411
+ documentation: "Despacha un evento personalizado en un elemento."
1412
+ },
1413
+ trigger: { detail: "Activar evento", documentation: "Activa un evento en un elemento." },
1414
+ wait: {
1415
+ detail: "Retrasar ejecucion",
1416
+ documentation: "Pausa la ejecucion durante un tiempo especificado."
1417
+ },
1418
+ log: {
1419
+ detail: "Registrar en consola",
1420
+ documentation: "Muestra un valor en la consola del navegador."
1421
+ },
1422
+ increment: {
1423
+ detail: "Incrementar valor",
1424
+ documentation: "Aumenta un valor numerico en 1 o una cantidad especificada."
1425
+ },
1426
+ decrement: {
1427
+ detail: "Decrementar valor",
1428
+ documentation: "Disminuye un valor numerico en 1 o una cantidad especificada."
1429
+ },
1430
+ append: {
1431
+ detail: "Agregar contenido",
1432
+ documentation: "Agrega contenido a un elemento o arreglo."
1433
+ },
1434
+ settle: {
1435
+ detail: "Esperar transiciones",
1436
+ documentation: "Espera a que las transiciones/animaciones CSS se completen."
1437
+ },
1438
+ go: { detail: "Navegar", documentation: "Navega a una URL o ubicacion de pagina." },
1439
+ throw: { detail: "Lanzar error", documentation: "Lanza un error con un mensaje especificado." }
1440
+ },
1441
+ zh: {
1442
+ toggle: {
1443
+ detail: "\u5207\u6362\u7C7B/\u53EF\u89C1\u6027",
1444
+ documentation: "\u5207\u6362\u5143\u7D20\u4E0A\u7684CSS\u7C7B\u6216\u5C5E\u6027\u3002\u5982\u679C\u7C7B\u5B58\u5728\u5219\u5220\u9664\uFF0C\u5426\u5219\u6DFB\u52A0\u3002"
1445
+ },
1446
+ add: { detail: "\u6DFB\u52A0\u7C7B/\u5C5E\u6027", documentation: "\u5411\u5143\u7D20\u6DFB\u52A0CSS\u7C7B\u6216\u5C5E\u6027\u3002" },
1447
+ remove: { detail: "\u5220\u9664\u7C7B/\u5143\u7D20", documentation: "\u4ECEDOM\u4E2D\u5220\u9664CSS\u7C7B\u3001\u5C5E\u6027\u6216\u5143\u7D20\u3002" },
1448
+ show: { detail: "\u663E\u793A\u5143\u7D20", documentation: "\u901A\u8FC7\u79FB\u9664display:none\u4F7F\u5143\u7D20\u53EF\u89C1\u3002" },
1449
+ hide: { detail: "\u9690\u85CF\u5143\u7D20", documentation: "\u901A\u8FC7\u8BBE\u7F6Edisplay:none\u9690\u85CF\u5143\u7D20\u3002" },
1450
+ put: { detail: "\u8BBE\u7F6E\u5185\u5BB9", documentation: "\u8BBE\u7F6E\u5143\u7D20\u7684\u5185\u5BB9\uFF08innerHTML\u3001textContent\u6216value\uFF09\u3002" },
1451
+ set: { detail: "\u8BBE\u7F6E\u53D8\u91CF", documentation: "\u5C06\u503C\u8D4B\u7ED9\u53D8\u91CF\u6216\u5C5E\u6027\u3002" },
1452
+ get: { detail: "\u83B7\u53D6\u503C", documentation: "\u4ECE\u8868\u8FBE\u5F0F\u83B7\u53D6\u503C\u5E76\u5B58\u50A8\u5728result\u53D8\u91CF\u4E2D\u3002" },
1453
+ fetch: { detail: "HTTP\u8BF7\u6C42", documentation: "\u53D1\u8D77HTTP\u8BF7\u6C42\uFF08GET\u3001POST\u7B49\uFF09\u5E76\u5B58\u50A8\u54CD\u5E94\u3002" },
1454
+ call: { detail: "\u8C03\u7528\u51FD\u6570", documentation: "\u8C03\u7528JavaScript\u51FD\u6570\u6216\u65B9\u6CD5\u3002" },
1455
+ send: { detail: "\u53D1\u9001\u4E8B\u4EF6", documentation: "\u5728\u5143\u7D20\u4E0A\u6D3E\u53D1\u81EA\u5B9A\u4E49\u4E8B\u4EF6\u3002" },
1456
+ trigger: { detail: "\u89E6\u53D1\u4E8B\u4EF6", documentation: "\u5728\u5143\u7D20\u4E0A\u89E6\u53D1\u4E8B\u4EF6\u3002" },
1457
+ wait: { detail: "\u5EF6\u8FDF\u6267\u884C", documentation: "\u6682\u505C\u6267\u884C\u6307\u5B9A\u7684\u65F6\u95F4\u3002" },
1458
+ log: { detail: "\u63A7\u5236\u53F0\u8F93\u51FA", documentation: "\u5C06\u503C\u8F93\u51FA\u5230\u6D4F\u89C8\u5668\u63A7\u5236\u53F0\u3002" },
1459
+ increment: { detail: "\u9012\u589E\u503C", documentation: "\u5C06\u6570\u503C\u589E\u52A01\u6216\u6307\u5B9A\u91CF\u3002" },
1460
+ decrement: { detail: "\u9012\u51CF\u503C", documentation: "\u5C06\u6570\u503C\u51CF\u5C111\u6216\u6307\u5B9A\u91CF\u3002" },
1461
+ append: { detail: "\u8FFD\u52A0\u5185\u5BB9", documentation: "\u5411\u5143\u7D20\u6216\u6570\u7EC4\u8FFD\u52A0\u5185\u5BB9\u3002" },
1462
+ settle: { detail: "\u7B49\u5F85\u8FC7\u6E21", documentation: "\u7B49\u5F85CSS\u8FC7\u6E21/\u52A8\u753B\u5B8C\u6210\u3002" },
1463
+ go: { detail: "\u5BFC\u822A", documentation: "\u5BFC\u822A\u5230URL\u6216\u9875\u9762\u4F4D\u7F6E\u3002" },
1464
+ throw: { detail: "\u629B\u51FA\u9519\u8BEF", documentation: "\u4F7F\u7528\u6307\u5B9A\u6D88\u606F\u629B\u51FA\u9519\u8BEF\u3002" }
1465
+ },
1466
+ ko: {
1467
+ toggle: {
1468
+ detail: "\uD074\uB798\uC2A4/\uD45C\uC2DC \uC804\uD658",
1469
+ documentation: "\uC694\uC18C\uC758 CSS \uD074\uB798\uC2A4 \uB610\uB294 \uC18D\uC131\uC744 \uC804\uD658\uD569\uB2C8\uB2E4. \uD074\uB798\uC2A4\uAC00 \uC788\uC73C\uBA74 \uC81C\uAC70\uD558\uACE0, \uC5C6\uC73C\uBA74 \uCD94\uAC00\uD569\uB2C8\uB2E4."
1470
+ },
1471
+ add: { detail: "\uD074\uB798\uC2A4/\uC18D\uC131 \uCD94\uAC00", documentation: "\uC694\uC18C\uC5D0 CSS \uD074\uB798\uC2A4 \uB610\uB294 \uC18D\uC131\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4." },
1472
+ remove: {
1473
+ detail: "\uD074\uB798\uC2A4/\uC694\uC18C \uC81C\uAC70",
1474
+ documentation: "DOM\uC5D0\uC11C CSS \uD074\uB798\uC2A4, \uC18D\uC131 \uB610\uB294 \uC694\uC18C\uB97C \uC81C\uAC70\uD569\uB2C8\uB2E4."
1475
+ },
1476
+ show: { detail: "\uC694\uC18C \uD45C\uC2DC", documentation: "display:none\uC744 \uC81C\uAC70\uD558\uC5EC \uC694\uC18C\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4." },
1477
+ hide: { detail: "\uC694\uC18C \uC228\uAE30\uAE30", documentation: "display:none\uC744 \uC124\uC815\uD558\uC5EC \uC694\uC18C\uB97C \uC228\uAE41\uB2C8\uB2E4." },
1478
+ put: {
1479
+ detail: "\uCF58\uD150\uCE20 \uC124\uC815",
1480
+ documentation: "\uC694\uC18C\uC758 \uCF58\uD150\uCE20(innerHTML, textContent \uB610\uB294 value)\uB97C \uC124\uC815\uD569\uB2C8\uB2E4."
1481
+ },
1482
+ set: { detail: "\uBCC0\uC218 \uC124\uC815", documentation: "\uBCC0\uC218 \uB610\uB294 \uC18D\uC131\uC5D0 \uAC12\uC744 \uD560\uB2F9\uD569\uB2C8\uB2E4." },
1483
+ get: {
1484
+ detail: "\uAC12 \uAC00\uC838\uC624\uAE30",
1485
+ documentation: "\uD45C\uD604\uC2DD\uC5D0\uC11C \uAC12\uC744 \uAC00\uC838\uC640 result \uBCC0\uC218\uC5D0 \uC800\uC7A5\uD569\uB2C8\uB2E4."
1486
+ },
1487
+ fetch: {
1488
+ detail: "HTTP \uC694\uCCAD",
1489
+ documentation: "HTTP \uC694\uCCAD(GET, POST \uB4F1)\uC744 \uC2E4\uD589\uD558\uACE0 \uC751\uB2F5\uC744 \uC800\uC7A5\uD569\uB2C8\uB2E4."
1490
+ },
1491
+ call: { detail: "\uD568\uC218 \uD638\uCD9C", documentation: "JavaScript \uD568\uC218 \uB610\uB294 \uBA54\uC11C\uB4DC\uB97C \uD638\uCD9C\uD569\uB2C8\uB2E4." },
1492
+ send: { detail: "\uC774\uBCA4\uD2B8 \uC804\uC1A1", documentation: "\uC694\uC18C\uC5D0 \uCEE4\uC2A4\uD140 \uC774\uBCA4\uD2B8\uB97C \uB514\uC2A4\uD328\uCE58\uD569\uB2C8\uB2E4." },
1493
+ trigger: { detail: "\uC774\uBCA4\uD2B8 \uD2B8\uB9AC\uAC70", documentation: "\uC694\uC18C\uC5D0\uC11C \uC774\uBCA4\uD2B8\uB97C \uD2B8\uB9AC\uAC70\uD569\uB2C8\uB2E4." },
1494
+ wait: { detail: "\uC2E4\uD589 \uC9C0\uC5F0", documentation: "\uC9C0\uC815\uB41C \uC2DC\uAC04 \uB3D9\uC548 \uC2E4\uD589\uC744 \uC77C\uC2DC \uC911\uC9C0\uD569\uB2C8\uB2E4." },
1495
+ log: { detail: "\uCF58\uC194 \uCD9C\uB825", documentation: "\uBE0C\uB77C\uC6B0\uC800 \uCF58\uC194\uC5D0 \uAC12\uC744 \uCD9C\uB825\uD569\uB2C8\uB2E4." },
1496
+ increment: { detail: "\uAC12 \uC99D\uAC00", documentation: "\uC22B\uC790 \uAC12\uC744 1 \uB610\uB294 \uC9C0\uC815\uB41C \uC591\uB9CC\uD07C \uC99D\uAC00\uC2DC\uD0B5\uB2C8\uB2E4." },
1497
+ decrement: { detail: "\uAC12 \uAC10\uC18C", documentation: "\uC22B\uC790 \uAC12\uC744 1 \uB610\uB294 \uC9C0\uC815\uB41C \uC591\uB9CC\uD07C \uAC10\uC18C\uC2DC\uD0B5\uB2C8\uB2E4." },
1498
+ append: { detail: "\uCF58\uD150\uCE20 \uCD94\uAC00", documentation: "\uC694\uC18C \uB610\uB294 \uBC30\uC5F4\uC5D0 \uCF58\uD150\uCE20\uB97C \uCD94\uAC00\uD569\uB2C8\uB2E4." },
1499
+ settle: {
1500
+ detail: "\uD2B8\uB79C\uC9C0\uC158 \uB300\uAE30",
1501
+ documentation: "CSS \uD2B8\uB79C\uC9C0\uC158/\uC560\uB2C8\uBA54\uC774\uC158\uC774 \uC644\uB8CC\uB420 \uB54C\uAE4C\uC9C0 \uB300\uAE30\uD569\uB2C8\uB2E4."
1502
+ },
1503
+ go: { detail: "\uB0B4\uBE44\uAC8C\uC774\uC158", documentation: "URL \uB610\uB294 \uD398\uC774\uC9C0 \uC704\uCE58\uB85C \uC774\uB3D9\uD569\uB2C8\uB2E4." },
1504
+ throw: { detail: "\uC624\uB958 \uBC1C\uC0DD", documentation: "\uC9C0\uC815\uB41C \uBA54\uC2DC\uC9C0\uB85C \uC624\uB958\uB97C \uBC1C\uC0DD\uC2DC\uD0B5\uB2C8\uB2E4." }
1505
+ },
1506
+ ar: {
1507
+ toggle: {
1508
+ detail: "\u062A\u0628\u062F\u064A\u0644 \u0627\u0644\u0641\u0626\u0629/\u0627\u0644\u0631\u0624\u064A\u0629",
1509
+ documentation: "\u064A\u0628\u062F\u0644 \u0641\u0626\u0629 CSS \u0623\u0648 \u0633\u0645\u0629 \u0639\u0644\u0649 \u0639\u0646\u0635\u0631. \u0625\u0630\u0627 \u0643\u0627\u0646\u062A \u0627\u0644\u0641\u0626\u0629 \u0645\u0648\u062C\u0648\u062F\u0629\u060C \u064A\u062A\u0645 \u0625\u0632\u0627\u0644\u062A\u0647\u0627\u061B \u0648\u0625\u0644\u0627\u060C \u064A\u062A\u0645 \u0625\u0636\u0627\u0641\u062A\u0647\u0627."
1510
+ },
1511
+ add: { detail: "\u0625\u0636\u0627\u0641\u0629 \u0641\u0626\u0629/\u0633\u0645\u0629", documentation: "\u064A\u0636\u064A\u0641 \u0641\u0626\u0629 CSS \u0623\u0648 \u0633\u0645\u0629 \u0625\u0644\u0649 \u0639\u0646\u0635\u0631." },
1512
+ remove: { detail: "\u0625\u0632\u0627\u0644\u0629 \u0641\u0626\u0629/\u0639\u0646\u0635\u0631", documentation: "\u064A\u0632\u064A\u0644 \u0641\u0626\u0629 CSS \u0623\u0648 \u0633\u0645\u0629 \u0623\u0648 \u0639\u0646\u0635\u0631 \u0645\u0646 DOM." },
1513
+ show: {
1514
+ detail: "\u0625\u0638\u0647\u0627\u0631 \u0627\u0644\u0639\u0646\u0635\u0631",
1515
+ documentation: "\u064A\u062C\u0639\u0644 \u0627\u0644\u0639\u0646\u0635\u0631 \u0645\u0631\u0626\u064A\u064B\u0627 \u0639\u0646 \u0637\u0631\u064A\u0642 \u0625\u0632\u0627\u0644\u0629 display:none."
1516
+ },
1517
+ hide: { detail: "\u0625\u062E\u0641\u0627\u0621 \u0627\u0644\u0639\u0646\u0635\u0631", documentation: "\u064A\u062E\u0641\u064A \u0627\u0644\u0639\u0646\u0635\u0631 \u0639\u0646 \u0637\u0631\u064A\u0642 \u062A\u0639\u064A\u064A\u0646 display:none." },
1518
+ put: {
1519
+ detail: "\u062A\u0639\u064A\u064A\u0646 \u0627\u0644\u0645\u062D\u062A\u0648\u0649",
1520
+ documentation: "\u064A\u0639\u064A\u0651\u0646 \u0645\u062D\u062A\u0648\u0649 \u0627\u0644\u0639\u0646\u0635\u0631 (innerHTML \u0623\u0648 textContent \u0623\u0648 value)."
1521
+ },
1522
+ set: { detail: "\u062A\u0639\u064A\u064A\u0646 \u0627\u0644\u0645\u062A\u063A\u064A\u0631", documentation: "\u064A\u0639\u064A\u0651\u0646 \u0642\u064A\u0645\u0629 \u0644\u0645\u062A\u063A\u064A\u0631 \u0623\u0648 \u062E\u0627\u0635\u064A\u0629." },
1523
+ get: {
1524
+ detail: "\u0627\u0644\u062D\u0635\u0648\u0644 \u0639\u0644\u0649 \u0642\u064A\u0645\u0629",
1525
+ documentation: "\u064A\u0633\u062A\u0631\u062C\u0639 \u0642\u064A\u0645\u0629 \u0645\u0646 \u062A\u0639\u0628\u064A\u0631 \u0648\u064A\u062E\u0632\u0646\u0647\u0627 \u0641\u064A \u0645\u062A\u063A\u064A\u0631 result."
1526
+ },
1527
+ fetch: { detail: "\u0637\u0644\u0628 HTTP", documentation: "\u064A\u0646\u0641\u0630 \u0637\u0644\u0628 HTTP (GET\u060C POST\u060C \u0625\u0644\u062E) \u0648\u064A\u062E\u0632\u0646 \u0627\u0644\u0627\u0633\u062A\u062C\u0627\u0628\u0629." },
1528
+ call: { detail: "\u0627\u0633\u062A\u062F\u0639\u0627\u0621 \u062F\u0627\u0644\u0629", documentation: "\u064A\u0633\u062A\u062F\u0639\u064A \u062F\u0627\u0644\u0629 \u0623\u0648 \u0637\u0631\u064A\u0642\u0629 JavaScript." },
1529
+ send: { detail: "\u0625\u0631\u0633\u0627\u0644 \u062D\u062F\u062B", documentation: "\u064A\u0631\u0633\u0644 \u062D\u062F\u062B\u064B\u0627 \u0645\u062E\u0635\u0635\u064B\u0627 \u0639\u0644\u0649 \u0639\u0646\u0635\u0631." },
1530
+ trigger: { detail: "\u062A\u0634\u063A\u064A\u0644 \u062D\u062F\u062B", documentation: "\u064A\u0634\u063A\u0644 \u062D\u062F\u062B\u064B\u0627 \u0639\u0644\u0649 \u0639\u0646\u0635\u0631." },
1531
+ wait: { detail: "\u062A\u0623\u062E\u064A\u0631 \u0627\u0644\u062A\u0646\u0641\u064A\u0630", documentation: "\u064A\u0648\u0642\u0641 \u0627\u0644\u062A\u0646\u0641\u064A\u0630 \u0645\u0624\u0642\u062A\u064B\u0627 \u0644\u0645\u062F\u0629 \u0645\u062D\u062F\u062F\u0629." },
1532
+ log: { detail: "\u062A\u0633\u062C\u064A\u0644 \u0641\u064A \u0648\u062D\u062F\u0629 \u0627\u0644\u062A\u062D\u0643\u0645", documentation: "\u064A\u062E\u0631\u062C \u0642\u064A\u0645\u0629 \u0625\u0644\u0649 \u0648\u062D\u062F\u0629 \u062A\u062D\u0643\u0645 \u0627\u0644\u0645\u062A\u0635\u0641\u062D." },
1533
+ increment: { detail: "\u0632\u064A\u0627\u062F\u0629 \u0627\u0644\u0642\u064A\u0645\u0629", documentation: "\u064A\u0632\u064A\u062F \u0642\u064A\u0645\u0629 \u0631\u0642\u0645\u064A\u0629 \u0628\u0645\u0642\u062F\u0627\u0631 1 \u0623\u0648 \u0645\u0642\u062F\u0627\u0631 \u0645\u062D\u062F\u062F." },
1534
+ decrement: { detail: "\u0625\u0646\u0642\u0627\u0635 \u0627\u0644\u0642\u064A\u0645\u0629", documentation: "\u064A\u0646\u0642\u0635 \u0642\u064A\u0645\u0629 \u0631\u0642\u0645\u064A\u0629 \u0628\u0645\u0642\u062F\u0627\u0631 1 \u0623\u0648 \u0645\u0642\u062F\u0627\u0631 \u0645\u062D\u062F\u062F." },
1535
+ append: { detail: "\u0625\u0644\u062D\u0627\u0642 \u0645\u062D\u062A\u0648\u0649", documentation: "\u064A\u0644\u062D\u0642 \u0645\u062D\u062A\u0648\u0649 \u0628\u0639\u0646\u0635\u0631 \u0623\u0648 \u0645\u0635\u0641\u0648\u0641\u0629." },
1536
+ settle: { detail: "\u0627\u0646\u062A\u0638\u0627\u0631 \u0627\u0644\u062A\u062D\u0648\u0644\u0627\u062A", documentation: "\u064A\u0646\u062A\u0638\u0631 \u0627\u0643\u062A\u0645\u0627\u0644 \u062A\u062D\u0648\u0644\u0627\u062A/\u0631\u0633\u0648\u0645 CSS \u0627\u0644\u0645\u062A\u062D\u0631\u0643\u0629." },
1537
+ go: { detail: "\u0627\u0644\u062A\u0646\u0642\u0644", documentation: "\u064A\u0646\u062A\u0642\u0644 \u0625\u0644\u0649 \u0639\u0646\u0648\u0627\u0646 URL \u0623\u0648 \u0645\u0648\u0642\u0639 \u0635\u0641\u062D\u0629." },
1538
+ throw: { detail: "\u0631\u0645\u064A \u062E\u0637\u0623", documentation: "\u064A\u0631\u0645\u064A \u062E\u0637\u0623 \u0628\u0631\u0633\u0627\u0644\u0629 \u0645\u062D\u062F\u062F\u0629." }
1539
+ }
1540
+ };
1541
+ function getCommandDescription(command, language) {
1542
+ return DESCRIPTIONS[language]?.[command] ?? DESCRIPTIONS.en?.[command];
1543
+ }
1544
+
325
1545
  // src/server.ts
326
1546
  import * as semanticImport from "@lokascript/semantic";
327
1547
  var semanticPackage = semanticImport;
@@ -338,8 +1558,9 @@ try {
338
1558
  parseFunction = core.parse;
339
1559
  fromCoreASTFn = core.fromCoreAST;
340
1560
  interchangeLSP = await import("@hyperfixi/core/ast-utils");
1561
+ console.error("[lokascript-ls] @hyperfixi/core loaded \u2014 AST parsing + interchange LSP enabled");
341
1562
  } catch {
342
- console.error("[lokascript-ls] @hyperfixi/core not available");
1563
+ console.error("[lokascript-ls] @hyperfixi/core not available \u2014 diagnostics and hover degraded");
343
1564
  }
344
1565
  try {
345
1566
  lspMetadata = await import("@hyperfixi/core/lsp-metadata");
@@ -348,6 +1569,21 @@ try {
348
1569
  "[lokascript-ls] @hyperfixi/core/lsp-metadata not available - using fallback keywords"
349
1570
  );
350
1571
  }
1572
+ var frameworkIR = null;
1573
+ try {
1574
+ const fw = await import("./dist-V7SKUZF5.js");
1575
+ frameworkIR = { fromInterchangeNode: fw.fromInterchangeNode, renderExplicit: fw.renderExplicit };
1576
+ console.error(
1577
+ "[lokascript-ls] @lokascript/framework loaded \u2014 LSE bracket notation in hover enabled"
1578
+ );
1579
+ } catch {
1580
+ console.error(
1581
+ "[lokascript-ls] @lokascript/framework not available \u2014 hover will omit LSE bracket notation"
1582
+ );
1583
+ }
1584
+ console.error(
1585
+ `[lokascript-ls] capabilities: core=${!!parseFunction}, interchange=${!!interchangeLSP}, metadata=${!!lspMetadata}, framework=${!!frameworkIR}`
1586
+ );
351
1587
  var FALLBACK_KEYWORDS = [
352
1588
  "toggle",
353
1589
  "add",
@@ -717,12 +1953,47 @@ async function getDiagnostics(code, language) {
717
1953
  });
718
1954
  }
719
1955
  }
1956
+ if (diagnostics.length === 0) {
1957
+ try {
1958
+ const chevrotainResult = parseWithRecovery(code);
1959
+ for (const diag of chevrotainResult.diagnostics) {
1960
+ const lines = code.split("\n");
1961
+ const { line: startLine, character: startChar } = offsetToLineChar(code, diag.startOffset);
1962
+ const { line: endLine, character: endChar } = offsetToLineChar(code, diag.endOffset);
1963
+ diagnostics.push({
1964
+ range: {
1965
+ start: { line: startLine, character: startChar },
1966
+ end: { line: endLine, character: endChar }
1967
+ },
1968
+ severity: diag.severity === "error" ? DiagnosticSeverity.Error : diag.severity === "warning" ? DiagnosticSeverity.Warning : DiagnosticSeverity.Information,
1969
+ code: diag.code,
1970
+ source: brand,
1971
+ message: diag.message
1972
+ });
1973
+ }
1974
+ } catch (e) {
1975
+ connection.console.log(`[${brand}-ls] Chevrotain parsing failed: ${e}`);
1976
+ }
1977
+ }
720
1978
  if (diagnostics.length === 0) {
721
1979
  const simpleDiagnostics = runSimpleDiagnostics(code, language);
722
1980
  diagnostics.push(...simpleDiagnostics.map((d) => ({ ...d, source: brand })));
723
1981
  }
724
1982
  return diagnostics.slice(0, globalSettings.maxDiagnostics);
725
1983
  }
1984
+ function offsetToLineChar(text, offset) {
1985
+ let line = 0;
1986
+ let col = 0;
1987
+ for (let i = 0; i < offset && i < text.length; i++) {
1988
+ if (text[i] === "\n") {
1989
+ line++;
1990
+ col = 0;
1991
+ } else {
1992
+ col++;
1993
+ }
1994
+ }
1995
+ return { line, character: col };
1996
+ }
726
1997
  function runSimpleDiagnostics(code, _language) {
727
1998
  const diagnostics = [];
728
1999
  const lines = code.split("\n");
@@ -790,7 +2061,22 @@ connection.onCompletion((params) => {
790
2061
  const offset = document.offsetAt(position);
791
2062
  const beforeCursor = text.slice(0, offset);
792
2063
  const context = inferContext(beforeCursor);
793
- return getContextualCompletions(context, language);
2064
+ const completions = getContextualCompletions(context, language);
2065
+ try {
2066
+ const chevrotainSuggestions = getContentAssist(beforeCursor, offset);
2067
+ const existingLabels = new Set(completions.map((c) => c.label));
2068
+ for (const s of chevrotainSuggestions) {
2069
+ if (existingLabels.has(s.label)) continue;
2070
+ completions.push({
2071
+ label: s.label,
2072
+ kind: s.kind === "command" ? CompletionItemKind.Method : s.kind === "event" ? CompletionItemKind.Event : s.kind === "selector" ? CompletionItemKind.Field : s.kind === "variable" ? CompletionItemKind.Variable : CompletionItemKind.Keyword,
2073
+ detail: s.detail,
2074
+ insertText: s.insertText
2075
+ });
2076
+ }
2077
+ } catch {
2078
+ }
2079
+ return completions;
794
2080
  }
795
2081
  });
796
2082
  function inferContext(beforeCursor) {
@@ -824,6 +2110,10 @@ function getContextualCompletions(context, language) {
824
2110
  const commandMode = isHyperscriptCompatMode(resolvedMode) ? "hyperscript" : "lokascript";
825
2111
  const availableCommands = getCommandsForMode(commandMode);
826
2112
  const isCommandAvailable = (cmd) => availableCommands.includes(cmd);
2113
+ const getDetail = (command, fallback) => {
2114
+ const desc = getCommandDescription(command, effectiveLanguage);
2115
+ return desc?.detail ?? fallback;
2116
+ };
827
2117
  switch (context) {
828
2118
  case "event":
829
2119
  const eventNames = lspMetadata?.EVENT_NAMES ?? FALLBACK_EVENT_NAMES;
@@ -840,55 +2130,71 @@ function getContextualCompletions(context, language) {
840
2130
  {
841
2131
  label: getKeyword("toggle"),
842
2132
  kind: CompletionItemKind.Method,
843
- detail: "Toggle class/visibility",
2133
+ detail: getDetail("toggle", "Toggle class/visibility"),
844
2134
  insertText: `${getKeyword("toggle")} .\${1:class}`
845
2135
  },
846
2136
  {
847
2137
  label: getKeyword("add"),
848
2138
  kind: CompletionItemKind.Method,
849
- detail: "Add class/attribute",
2139
+ detail: getDetail("add", "Add class/attribute"),
850
2140
  insertText: `${getKeyword("add")} .\${1:class} to \${2:me}`
851
2141
  },
852
2142
  {
853
2143
  label: getKeyword("remove"),
854
2144
  kind: CompletionItemKind.Method,
855
- detail: "Remove class/element",
2145
+ detail: getDetail("remove", "Remove class/element"),
856
2146
  insertText: `${getKeyword("remove")} .\${1:class} from \${2:me}`
857
2147
  },
858
- { label: getKeyword("show"), kind: CompletionItemKind.Method, detail: "Show element" },
859
- { label: getKeyword("hide"), kind: CompletionItemKind.Method, detail: "Hide element" },
2148
+ {
2149
+ label: getKeyword("show"),
2150
+ kind: CompletionItemKind.Method,
2151
+ detail: getDetail("show", "Show element")
2152
+ },
2153
+ {
2154
+ label: getKeyword("hide"),
2155
+ kind: CompletionItemKind.Method,
2156
+ detail: getDetail("hide", "Hide element")
2157
+ },
860
2158
  {
861
2159
  label: getKeyword("put"),
862
2160
  kind: CompletionItemKind.Method,
863
- detail: "Set content",
2161
+ detail: getDetail("put", "Set content"),
864
2162
  insertText: `${getKeyword("put")} \${1:value} into \${2:target}`
865
2163
  },
866
2164
  {
867
2165
  label: getKeyword("set"),
868
2166
  kind: CompletionItemKind.Method,
869
- detail: "Set variable",
2167
+ detail: getDetail("set", "Set variable"),
870
2168
  insertText: `${getKeyword("set")} \${1:variable} to \${2:value}`
871
2169
  },
872
2170
  {
873
2171
  label: getKeyword("fetch"),
874
2172
  kind: CompletionItemKind.Method,
875
- detail: "HTTP request",
2173
+ detail: getDetail("fetch", "HTTP request"),
876
2174
  insertText: `${getKeyword("fetch")} \${1:/api/endpoint}`
877
2175
  },
878
2176
  {
879
2177
  label: getKeyword("wait"),
880
2178
  kind: CompletionItemKind.Method,
881
- detail: "Pause execution",
2179
+ detail: getDetail("wait", "Pause execution"),
882
2180
  insertText: `${getKeyword("wait")} \${1:1s}`
883
2181
  },
884
2182
  {
885
2183
  label: getKeyword("send"),
886
2184
  kind: CompletionItemKind.Method,
887
- detail: "Dispatch event",
2185
+ detail: getDetail("send", "Dispatch event"),
888
2186
  insertText: `${getKeyword("send")} \${1:eventName} to \${2:target}`
889
2187
  },
890
- { label: getKeyword("trigger"), kind: CompletionItemKind.Method, detail: "Trigger event" },
891
- { label: getKeyword("log"), kind: CompletionItemKind.Method, detail: "Console log" },
2188
+ {
2189
+ label: getKeyword("trigger"),
2190
+ kind: CompletionItemKind.Method,
2191
+ detail: getDetail("trigger", "Trigger event")
2192
+ },
2193
+ {
2194
+ label: getKeyword("log"),
2195
+ kind: CompletionItemKind.Method,
2196
+ detail: getDetail("log", "Console log")
2197
+ },
892
2198
  { label: getKeyword("if"), kind: CompletionItemKind.Keyword, detail: "Conditional" },
893
2199
  { label: getKeyword("repeat"), kind: CompletionItemKind.Keyword, detail: "Loop" }
894
2200
  );
@@ -999,8 +2305,14 @@ connection.onHover((params) => {
999
2305
  if (!currentLine2) return null;
1000
2306
  const word2 = getWordAtPosition(currentLine2, found.localChar);
1001
2307
  if (!word2) return null;
1002
- const doc2 = getHoverDocumentation(word2.text, globalSettings.language);
2308
+ let doc2 = getHoverDocumentation(word2.text, globalSettings.language);
1003
2309
  if (!doc2) return null;
2310
+ const lse2 = tryGetLSE(found.region.code);
2311
+ if (lse2) {
2312
+ doc2 += `
2313
+
2314
+ **LSE:** \`${lse2}\``;
2315
+ }
1004
2316
  const startChar = found.localLine === 0 ? found.region.startChar + word2.start : word2.start;
1005
2317
  const endChar = found.localLine === 0 ? found.region.startChar + word2.end : word2.end;
1006
2318
  return {
@@ -1016,8 +2328,14 @@ connection.onHover((params) => {
1016
2328
  if (!currentLine) return null;
1017
2329
  const word = getWordAtPosition(currentLine, position.character);
1018
2330
  if (!word) return null;
1019
- const doc = getHoverDocumentation(word.text, globalSettings.language);
2331
+ let doc = getHoverDocumentation(word.text, globalSettings.language);
1020
2332
  if (!doc) return null;
2333
+ const lse = tryGetLSE(text);
2334
+ if (lse) {
2335
+ doc += `
2336
+
2337
+ **LSE:** \`${lse}\``;
2338
+ }
1021
2339
  return {
1022
2340
  contents: { kind: MarkupKind.Markdown, value: doc },
1023
2341
  range: {
@@ -1030,19 +2348,34 @@ connection.onHover((params) => {
1030
2348
  return null;
1031
2349
  }
1032
2350
  });
2351
+ function tryGetLSE(code) {
2352
+ if (!interchangeLSP || !parseFunction || !fromCoreASTFn || !frameworkIR) return null;
2353
+ try {
2354
+ const ast = parseFunction(code);
2355
+ if (!ast) return null;
2356
+ const interchange = fromCoreASTFn(ast);
2357
+ if (!interchange) return null;
2358
+ const semanticNode = frameworkIR.fromInterchangeNode(interchange);
2359
+ return frameworkIR.renderExplicit(semanticNode);
2360
+ } catch {
2361
+ return null;
2362
+ }
2363
+ }
1033
2364
  function getHoverDocumentation(word, language) {
1034
2365
  const wordLower = word.toLowerCase();
1035
2366
  const canonicalKey = isMultilingualEnabled(resolvedMode) ? resolveCanonicalKeyword(wordLower, language) : wordLower;
1036
2367
  const docs = lspMetadata?.HOVER_DOCS ?? FALLBACK_HOVER_DOCS;
1037
2368
  const doc = docs[canonicalKey];
1038
2369
  if (!doc) return null;
2370
+ const localizedDesc = getCommandDescription(canonicalKey, language);
1039
2371
  let content = `**${doc.title}**`;
1040
2372
  if (isMultilingualEnabled(resolvedMode) && wordLower !== canonicalKey) {
1041
2373
  content = `**${word}** (${canonicalKey})`;
1042
2374
  }
2375
+ const description = localizedDesc?.documentation ?? doc.description;
1043
2376
  content += `
1044
2377
 
1045
- ${doc.description}`;
2378
+ ${description}`;
1046
2379
  content += `
1047
2380
 
1048
2381
  \`\`\`hyperscript