@elurjs/language-server 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +71 -0
  2. package/bin/elur-language-server.js +3 -0
  3. package/dist/capabilities.d.ts +6 -0
  4. package/dist/capabilities.d.ts.map +1 -0
  5. package/dist/capabilities.js +22 -0
  6. package/dist/capabilities.js.map +1 -0
  7. package/dist/codeActions/fixes.d.ts +16 -0
  8. package/dist/codeActions/fixes.d.ts.map +1 -0
  9. package/dist/codeActions/fixes.js +94 -0
  10. package/dist/codeActions/fixes.js.map +1 -0
  11. package/dist/codeActions/provider.d.ts +7 -0
  12. package/dist/codeActions/provider.d.ts.map +1 -0
  13. package/dist/codeActions/provider.js +46 -0
  14. package/dist/codeActions/provider.js.map +1 -0
  15. package/dist/completion/directives.d.ts +6 -0
  16. package/dist/completion/directives.d.ts.map +1 -0
  17. package/dist/completion/directives.js +16 -0
  18. package/dist/completion/directives.js.map +1 -0
  19. package/dist/completion/events.d.ts +6 -0
  20. package/dist/completion/events.d.ts.map +1 -0
  21. package/dist/completion/events.js +20 -0
  22. package/dist/completion/events.js.map +1 -0
  23. package/dist/completion/modifiers.d.ts +6 -0
  24. package/dist/completion/modifiers.d.ts.map +1 -0
  25. package/dist/completion/modifiers.js +19 -0
  26. package/dist/completion/modifiers.js.map +1 -0
  27. package/dist/completion/provider.d.ts +7 -0
  28. package/dist/completion/provider.d.ts.map +1 -0
  29. package/dist/completion/provider.js +46 -0
  30. package/dist/completion/provider.js.map +1 -0
  31. package/dist/diagnostics/provider.d.ts +7 -0
  32. package/dist/diagnostics/provider.d.ts.map +1 -0
  33. package/dist/diagnostics/provider.js +49 -0
  34. package/dist/diagnostics/provider.js.map +1 -0
  35. package/dist/diagnostics/rules.d.ts +29 -0
  36. package/dist/diagnostics/rules.d.ts.map +1 -0
  37. package/dist/diagnostics/rules.js +46 -0
  38. package/dist/diagnostics/rules.js.map +1 -0
  39. package/dist/formatting/ast.d.ts +37 -0
  40. package/dist/formatting/ast.d.ts.map +1 -0
  41. package/dist/formatting/ast.js +112 -0
  42. package/dist/formatting/ast.js.map +1 -0
  43. package/dist/formatting/attributes.d.ts +7 -0
  44. package/dist/formatting/attributes.d.ts.map +1 -0
  45. package/dist/formatting/attributes.js +7 -0
  46. package/dist/formatting/attributes.js.map +1 -0
  47. package/dist/formatting/printer.d.ts +34 -0
  48. package/dist/formatting/printer.d.ts.map +1 -0
  49. package/dist/formatting/printer.js +380 -0
  50. package/dist/formatting/printer.js.map +1 -0
  51. package/dist/formatting/provider.d.ts +10 -0
  52. package/dist/formatting/provider.d.ts.map +1 -0
  53. package/dist/formatting/provider.js +82 -0
  54. package/dist/formatting/provider.js.map +1 -0
  55. package/dist/formatting/renderer.d.ts +11 -0
  56. package/dist/formatting/renderer.d.ts.map +1 -0
  57. package/dist/formatting/renderer.js +175 -0
  58. package/dist/formatting/renderer.js.map +1 -0
  59. package/dist/formatting/tokenizer.d.ts +7 -0
  60. package/dist/formatting/tokenizer.d.ts.map +1 -0
  61. package/dist/formatting/tokenizer.js +7 -0
  62. package/dist/formatting/tokenizer.js.map +1 -0
  63. package/dist/hover/provider.d.ts +7 -0
  64. package/dist/hover/provider.d.ts.map +1 -0
  65. package/dist/hover/provider.js +48 -0
  66. package/dist/hover/provider.js.map +1 -0
  67. package/dist/modifiers/analyzer.d.ts +18 -0
  68. package/dist/modifiers/analyzer.d.ts.map +1 -0
  69. package/dist/modifiers/analyzer.js +75 -0
  70. package/dist/modifiers/analyzer.js.map +1 -0
  71. package/dist/modifiers/constants.d.ts +17 -0
  72. package/dist/modifiers/constants.d.ts.map +1 -0
  73. package/dist/modifiers/constants.js +58 -0
  74. package/dist/modifiers/constants.js.map +1 -0
  75. package/dist/modifiers/normalizer.d.ts +20 -0
  76. package/dist/modifiers/normalizer.d.ts.map +1 -0
  77. package/dist/modifiers/normalizer.js +62 -0
  78. package/dist/modifiers/normalizer.js.map +1 -0
  79. package/dist/modifiers/parser.d.ts +33 -0
  80. package/dist/modifiers/parser.d.ts.map +1 -0
  81. package/dist/modifiers/parser.js +73 -0
  82. package/dist/modifiers/parser.js.map +1 -0
  83. package/dist/modifiers/suggestions.d.ts +20 -0
  84. package/dist/modifiers/suggestions.d.ts.map +1 -0
  85. package/dist/modifiers/suggestions.js +60 -0
  86. package/dist/modifiers/suggestions.js.map +1 -0
  87. package/dist/server-browser.d.ts +16 -0
  88. package/dist/server-browser.d.ts.map +1 -0
  89. package/dist/server-browser.js +16 -0
  90. package/dist/server-browser.js.map +1 -0
  91. package/dist/server.d.ts +8 -0
  92. package/dist/server.d.ts.map +1 -0
  93. package/dist/server.js +29 -0
  94. package/dist/server.js.map +1 -0
  95. package/dist/template/detector.d.ts +43 -0
  96. package/dist/template/detector.d.ts.map +1 -0
  97. package/dist/template/detector.js +184 -0
  98. package/dist/template/detector.js.map +1 -0
  99. package/dist/template/parser.d.ts +42 -0
  100. package/dist/template/parser.d.ts.map +1 -0
  101. package/dist/template/parser.js +225 -0
  102. package/dist/template/parser.js.map +1 -0
  103. package/dist/template/scope.d.ts +18 -0
  104. package/dist/template/scope.d.ts.map +1 -0
  105. package/dist/template/scope.js +44 -0
  106. package/dist/template/scope.js.map +1 -0
  107. package/dist/utils/config.d.ts +14 -0
  108. package/dist/utils/config.d.ts.map +1 -0
  109. package/dist/utils/config.js +13 -0
  110. package/dist/utils/config.js.map +1 -0
  111. package/dist/utils/levenshtein.d.ts +7 -0
  112. package/dist/utils/levenshtein.d.ts.map +1 -0
  113. package/dist/utils/levenshtein.js +7 -0
  114. package/dist/utils/levenshtein.js.map +1 -0
  115. package/package.json +61 -0
@@ -0,0 +1,62 @@
1
+ /**
2
+ * normalizer.ts — Normalize modifier order.
3
+ *
4
+ * Ported from elur-vscode/event-modifiers.js.
5
+ */
6
+ import { EVENT_MODIFIER_ORDER, KEY_MODIFIER_ORDER, EVENT_MODIFIERS, KEY_MODIFIERS } from "./constants.js";
7
+ import { isKeyEventName } from "./analyzer.js";
8
+ function modifierRank(modifier, isKeyEvent) {
9
+ if (modifier in EVENT_MODIFIER_ORDER) {
10
+ return EVENT_MODIFIER_ORDER[modifier];
11
+ }
12
+ if (modifier in KEY_MODIFIER_ORDER) {
13
+ const base = EVENT_MODIFIERS.length;
14
+ return isKeyEvent
15
+ ? base + KEY_MODIFIER_ORDER[modifier]
16
+ : base + KEY_MODIFIERS.length;
17
+ }
18
+ return Number.POSITIVE_INFINITY;
19
+ }
20
+ /**
21
+ * Sorts modifiers into canonical order: event modifiers first (in their
22
+ * declared order), then key modifiers (in their declared order), then
23
+ * unknown modifiers (stable — preserve original relative order).
24
+ */
25
+ export function normalizeModifierOrder(eventName, modifiers) {
26
+ const lowerEvent = (eventName || "").toLowerCase();
27
+ const isKey = isKeyEventName(lowerEvent);
28
+ return (modifiers || [])
29
+ .map((mod, index) => ({ value: (mod || "").toLowerCase(), index }))
30
+ .filter((entry) => entry.value.length > 0)
31
+ .sort((a, b) => {
32
+ const rankA = modifierRank(a.value, isKey);
33
+ const rankB = modifierRank(b.value, isKey);
34
+ if (rankA !== rankB)
35
+ return rankA - rankB;
36
+ return a.index - b.index;
37
+ })
38
+ .map((entry) => entry.value);
39
+ }
40
+ /**
41
+ * Deduplicates modifiers, preserving first occurrence order.
42
+ */
43
+ export function uniqueModifiers(modifiers) {
44
+ const seen = new Set();
45
+ const out = [];
46
+ for (const mod of modifiers || []) {
47
+ const value = (mod || "").toLowerCase();
48
+ if (!value || seen.has(value))
49
+ continue;
50
+ seen.add(value);
51
+ out.push(value);
52
+ }
53
+ return out;
54
+ }
55
+ /**
56
+ * Removes all occurrences of a modifier from the list.
57
+ */
58
+ export function removeModifier(modifiers, modifierToRemove) {
59
+ const target = (modifierToRemove || "").toLowerCase();
60
+ return (modifiers || []).filter((mod) => (mod || "").toLowerCase() !== target);
61
+ }
62
+ //# sourceMappingURL=normalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizer.js","sourceRoot":"","sources":["../../src/modifiers/normalizer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC1G,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,SAAS,YAAY,CAAC,QAAgB,EAAE,UAAmB;IACzD,IAAI,QAAQ,IAAI,oBAAoB,EAAE,CAAC;QACrC,OAAO,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,QAAQ,IAAI,kBAAkB,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC;QACpC,OAAO,UAAU;YACf,CAAC,CAAC,IAAI,GAAG,kBAAkB,CAAC,QAAQ,CAAC;YACrC,CAAC,CAAC,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC;IAClC,CAAC;IAED,OAAO,MAAM,CAAC,iBAAiB,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB,EAAE,SAAmB;IAC3E,MAAM,UAAU,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,MAAM,KAAK,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAEzC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC;SACrB,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;SAClE,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;SACzC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACb,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC3C,IAAI,KAAK,KAAK,KAAK;YAAE,OAAO,KAAK,GAAG,KAAK,CAAC;QAC1C,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;IAC3B,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,SAAmB;IACjD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,GAAG,IAAI,SAAS,IAAI,EAAE,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QACxC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAS;QACxC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,SAAmB,EAAE,gBAAwB;IAC1E,MAAM,MAAM,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACtD,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC;AACjF,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * parser.ts — Parse @event.modifier chains from text.
3
+ *
4
+ * Ported from elur-vscode/event-modifiers.js.
5
+ */
6
+ export interface EventContext {
7
+ mode: "event" | "modifier";
8
+ tokenStart: number;
9
+ eventPrefix?: string;
10
+ eventName?: string;
11
+ modifierPrefix?: string;
12
+ usedModifiers?: string[];
13
+ trailingDot?: boolean;
14
+ }
15
+ export interface ParsedEventChain {
16
+ eventName: string;
17
+ modifiers: string[];
18
+ }
19
+ /**
20
+ * Parses the @event.modifier context from the line prefix before the cursor.
21
+ * Returns null if no @ token is found.
22
+ */
23
+ export declare function parseEventContextFromPrefix(linePrefix: string): EventContext | null;
24
+ /**
25
+ * Parses a full @event.modifier chain string like "@click.prevent.stop".
26
+ * Returns null if the input doesn't start with @.
27
+ */
28
+ export declare function parseEventBindingChain(chainText: string): ParsedEventChain | null;
29
+ /**
30
+ * Builds an @event.modifier chain string from parts.
31
+ */
32
+ export declare function buildEventBindingChain(eventName: string, modifiers: string[]): string;
33
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/modifiers/parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAmCnF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAgBjF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAQrF"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * parser.ts — Parse @event.modifier chains from text.
3
+ *
4
+ * Ported from elur-vscode/event-modifiers.js.
5
+ */
6
+ /**
7
+ * Parses the @event.modifier context from the line prefix before the cursor.
8
+ * Returns null if no @ token is found.
9
+ */
10
+ export function parseEventContextFromPrefix(linePrefix) {
11
+ const tokenMatch = linePrefix.match(/@[a-zA-Z0-9.:-]*$/);
12
+ if (!tokenMatch)
13
+ return null;
14
+ const token = tokenMatch[0];
15
+ const tokenStart = linePrefix.length - token.length;
16
+ if (token === "@") {
17
+ return { mode: "event", tokenStart, eventPrefix: "" };
18
+ }
19
+ const withoutAt = token.slice(1);
20
+ if (!withoutAt.includes(".")) {
21
+ return { mode: "event", tokenStart, eventPrefix: withoutAt.toLowerCase() };
22
+ }
23
+ const parts = withoutAt.split(".");
24
+ const eventName = (parts[0] || "").toLowerCase();
25
+ const trailingDot = token.endsWith(".");
26
+ const modifierPrefix = trailingDot
27
+ ? ""
28
+ : (parts[parts.length - 1] || "").toLowerCase();
29
+ const usedModifiers = (trailingDot ? parts.slice(1) : parts.slice(1, -1))
30
+ .map((mod) => mod.toLowerCase())
31
+ .filter(Boolean);
32
+ return {
33
+ mode: "modifier",
34
+ tokenStart,
35
+ eventName,
36
+ modifierPrefix,
37
+ usedModifiers,
38
+ trailingDot,
39
+ };
40
+ }
41
+ /**
42
+ * Parses a full @event.modifier chain string like "@click.prevent.stop".
43
+ * Returns null if the input doesn't start with @.
44
+ */
45
+ export function parseEventBindingChain(chainText) {
46
+ const raw = (chainText || "").trim();
47
+ if (!raw.startsWith("@"))
48
+ return null;
49
+ const noEq = raw.split("=")[0].trim();
50
+ const body = noEq.slice(1);
51
+ if (!body)
52
+ return null;
53
+ const parts = body.split(".").filter(Boolean);
54
+ if (parts.length === 0)
55
+ return null;
56
+ const eventName = (parts[0] || "").toLowerCase();
57
+ if (!eventName)
58
+ return null;
59
+ const modifiers = parts.slice(1).map((mod) => mod.toLowerCase());
60
+ return { eventName, modifiers };
61
+ }
62
+ /**
63
+ * Builds an @event.modifier chain string from parts.
64
+ */
65
+ export function buildEventBindingChain(eventName, modifiers) {
66
+ const safeEvent = (eventName || "").toLowerCase();
67
+ const safeModifiers = (modifiers || [])
68
+ .map((mod) => (mod || "").toLowerCase())
69
+ .filter(Boolean);
70
+ const suffix = safeModifiers.map((mod) => `.${mod}`).join("");
71
+ return `@${safeEvent}${suffix}`;
72
+ }
73
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/modifiers/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * suggestions.ts — Modifier completion suggestions and fuzzy matching.
3
+ *
4
+ * Ported from elur-vscode/event-modifiers.js.
5
+ */
6
+ /**
7
+ * Returns the set of valid modifiers for the given event, filtered by
8
+ * prefix and excluding already-used modifiers.
9
+ */
10
+ export declare function getModifierSuggestions(eventName: string, usedModifiers: string[], modifierPrefix: string): string[];
11
+ /**
12
+ * Levenshtein edit distance between two strings (case-insensitive).
13
+ */
14
+ export declare function levenshtein(a: string, b: string): number;
15
+ /**
16
+ * Suggests the closest known modifier to an unknown one.
17
+ * Returns null if no close match (distance > 2).
18
+ */
19
+ export declare function suggestClosestModifier(unknownModifier: string, eventName: string): string | null;
20
+ //# sourceMappingURL=suggestions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggestions.d.ts","sourceRoot":"","sources":["../../src/modifiers/suggestions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EAAE,EACvB,cAAc,EAAE,MAAM,GACrB,MAAM,EAAE,CAWV;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAoBxD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBhG"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * suggestions.ts — Modifier completion suggestions and fuzzy matching.
3
+ *
4
+ * Ported from elur-vscode/event-modifiers.js.
5
+ */
6
+ import { EVENT_MODIFIERS, KEY_MODIFIERS } from "./constants.js";
7
+ import { isKeyEventName } from "./analyzer.js";
8
+ /**
9
+ * Returns the set of valid modifiers for the given event, filtered by
10
+ * prefix and excluding already-used modifiers.
11
+ */
12
+ export function getModifierSuggestions(eventName, usedModifiers, modifierPrefix) {
13
+ const used = new Set((usedModifiers || []).map((mod) => mod.toLowerCase()));
14
+ const prefix = (modifierPrefix || "").toLowerCase();
15
+ const candidates = isKeyEventName(eventName)
16
+ ? [...EVENT_MODIFIERS, ...KEY_MODIFIERS]
17
+ : [...EVENT_MODIFIERS];
18
+ return candidates
19
+ .filter((mod) => !used.has(mod))
20
+ .filter((mod) => mod.startsWith(prefix));
21
+ }
22
+ /**
23
+ * Levenshtein edit distance between two strings (case-insensitive).
24
+ */
25
+ export function levenshtein(a, b) {
26
+ const x = (a || "").toLowerCase();
27
+ const y = (b || "").toLowerCase();
28
+ const dp = Array.from({ length: x.length + 1 }, () => new Array(y.length + 1).fill(0));
29
+ for (let i = 0; i <= x.length; i++)
30
+ dp[i][0] = i;
31
+ for (let j = 0; j <= y.length; j++)
32
+ dp[0][j] = j;
33
+ for (let i = 1; i <= x.length; i++) {
34
+ for (let j = 1; j <= y.length; j++) {
35
+ const cost = x[i - 1] === y[j - 1] ? 0 : 1;
36
+ dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
37
+ }
38
+ }
39
+ return dp[x.length][y.length];
40
+ }
41
+ /**
42
+ * Suggests the closest known modifier to an unknown one.
43
+ * Returns null if no close match (distance > 2).
44
+ */
45
+ export function suggestClosestModifier(unknownModifier, eventName) {
46
+ const source = isKeyEventName(eventName)
47
+ ? [...EVENT_MODIFIERS, ...KEY_MODIFIERS]
48
+ : [...EVENT_MODIFIERS];
49
+ let best = null;
50
+ let bestDistance = Number.POSITIVE_INFINITY;
51
+ for (const candidate of source) {
52
+ const distance = levenshtein(unknownModifier, candidate);
53
+ if (distance < bestDistance) {
54
+ bestDistance = distance;
55
+ best = candidate;
56
+ }
57
+ }
58
+ return bestDistance <= 2 ? best : null;
59
+ }
60
+ //# sourceMappingURL=suggestions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggestions.js","sourceRoot":"","sources":["../../src/modifiers/suggestions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,SAAiB,EACjB,aAAuB,EACvB,cAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAEpD,MAAM,UAAU,GAAG,cAAc,CAAC,SAAS,CAAC;QAC1C,CAAC,CAAC,CAAC,GAAG,eAAe,EAAE,GAAG,aAAa,CAAC;QACxC,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC;IAEzB,OAAO,UAAU;SACd,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;SAC/B,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS,EAAE,CAAS;IAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAClC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAElC,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,KAAK,CAAS,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAEjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CACjB,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAChB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAChB,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CACxB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,eAAuB,EAAE,SAAiB;IAC/E,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC;QACtC,CAAC,CAAC,CAAC,GAAG,eAAe,EAAE,GAAG,aAAa,CAAC;QACxC,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC;IAEzB,IAAI,IAAI,GAAkB,IAAI,CAAC;IAC/B,IAAI,YAAY,GAAG,MAAM,CAAC,iBAAiB,CAAC;IAE5C,KAAK,MAAM,SAAS,IAAI,MAAM,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,WAAW,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;QACzD,IAAI,QAAQ,GAAG,YAAY,EAAE,CAAC;YAC5B,YAAY,GAAG,QAAQ,CAAC;YACxB,IAAI,GAAG,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED,OAAO,YAAY,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACzC,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * server-browser.ts — Browser-compatible entry (no Node-specific imports).
3
+ *
4
+ * Exports the core analysis functions for use in browser-based editors
5
+ * (e.g. Monaco-based web editors) that don't need the full LSP connection.
6
+ */
7
+ export { analyzeEventModifiers, isKeyEventName, type ModifierIssue } from "./modifiers/analyzer.js";
8
+ export { normalizeModifierOrder, uniqueModifiers, removeModifier } from "./modifiers/normalizer.js";
9
+ export { getModifierSuggestions, suggestClosestModifier, levenshtein } from "./modifiers/suggestions.js";
10
+ export { parseEventContextFromPrefix, parseEventBindingChain, buildEventBindingChain } from "./modifiers/parser.js";
11
+ export { createModifierQuickFixes, type QuickFix } from "./codeActions/fixes.js";
12
+ export { scanDiagnostics, type TextDiagnostic } from "./diagnostics/rules.js";
13
+ export { findTemplateRegions, isInsideTaggedTemplate } from "./template/detector.js";
14
+ export { tokenize, parseAttributes, type Token } from "./template/parser.js";
15
+ export { EVENT_MODIFIERS, KEY_MODIFIERS, KEY_EVENTS, EVENT_BINDINGS, DIRECTIVE_ATTRIBUTES, TEMPLATE_TAGS, MODIFIER_HELP, } from "./modifiers/constants.js";
16
+ //# sourceMappingURL=server-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-browser.d.ts","sourceRoot":"","sources":["../src/server-browser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACpG,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACpG,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzG,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpH,OAAO,EAAE,wBAAwB,EAAE,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,KAAK,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EACL,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAC1D,oBAAoB,EAAE,aAAa,EAAE,aAAa,GACnD,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * server-browser.ts — Browser-compatible entry (no Node-specific imports).
3
+ *
4
+ * Exports the core analysis functions for use in browser-based editors
5
+ * (e.g. Monaco-based web editors) that don't need the full LSP connection.
6
+ */
7
+ export { analyzeEventModifiers, isKeyEventName } from "./modifiers/analyzer.js";
8
+ export { normalizeModifierOrder, uniqueModifiers, removeModifier } from "./modifiers/normalizer.js";
9
+ export { getModifierSuggestions, suggestClosestModifier, levenshtein } from "./modifiers/suggestions.js";
10
+ export { parseEventContextFromPrefix, parseEventBindingChain, buildEventBindingChain } from "./modifiers/parser.js";
11
+ export { createModifierQuickFixes } from "./codeActions/fixes.js";
12
+ export { scanDiagnostics } from "./diagnostics/rules.js";
13
+ export { findTemplateRegions, isInsideTaggedTemplate } from "./template/detector.js";
14
+ export { tokenize, parseAttributes } from "./template/parser.js";
15
+ export { EVENT_MODIFIERS, KEY_MODIFIERS, KEY_EVENTS, EVENT_BINDINGS, DIRECTIVE_ATTRIBUTES, TEMPLATE_TAGS, MODIFIER_HELP, } from "./modifiers/constants.js";
16
+ //# sourceMappingURL=server-browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-browser.js","sourceRoot":"","sources":["../src/server-browser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAsB,MAAM,yBAAyB,CAAC;AACpG,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACpG,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzG,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpH,OAAO,EAAE,wBAAwB,EAAiB,MAAM,wBAAwB,CAAC;AACjF,OAAO,EAAE,eAAe,EAAuB,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAc,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EACL,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAC1D,oBAAoB,EAAE,aAAa,EAAE,aAAa,GACnD,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * server.ts — LSP server entry point.
3
+ *
4
+ * Wires up all providers: completion, diagnostics, hover, code actions, formatting.
5
+ */
6
+ declare const connection: import("vscode-languageserver/node.js")._Connection<import("vscode-languageserver/node.js")._, import("vscode-languageserver/node.js")._, import("vscode-languageserver/node.js")._, import("vscode-languageserver/node.js")._, import("vscode-languageserver/node.js")._, import("vscode-languageserver/node.js")._, import("vscode-languageserver/lib/common/inlineCompletion.proposed.js").InlineCompletionFeatureShape, import("vscode-languageserver/node.js")._>;
7
+ export { connection as startServer };
8
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgBH,QAAA,MAAM,UAAU,wcAAyC,CAAC;AAkB1D,OAAO,EAAE,UAAU,IAAI,WAAW,EAAE,CAAC"}
package/dist/server.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * server.ts — LSP server entry point.
3
+ *
4
+ * Wires up all providers: completion, diagnostics, hover, code actions, formatting.
5
+ */
6
+ import { createConnection, TextDocuments, ProposedFeatures, } from "vscode-languageserver/node.js";
7
+ import { TextDocument } from "vscode-languageserver-textdocument";
8
+ import { getCapabilities } from "./capabilities.js";
9
+ import { registerCompletion } from "./completion/provider.js";
10
+ import { registerDiagnostics } from "./diagnostics/provider.js";
11
+ import { registerHover } from "./hover/provider.js";
12
+ import { registerCodeActions } from "./codeActions/provider.js";
13
+ import { registerFormatting } from "./formatting/provider.js";
14
+ const connection = createConnection(ProposedFeatures.all);
15
+ const documents = new TextDocuments(TextDocument);
16
+ connection.onInitialize((_params) => {
17
+ return getCapabilities();
18
+ });
19
+ connection.onInitialized(() => {
20
+ registerCompletion(connection, documents);
21
+ registerDiagnostics(connection, documents);
22
+ registerHover(connection, documents);
23
+ registerCodeActions(connection, documents);
24
+ registerFormatting(connection, documents);
25
+ });
26
+ documents.listen(connection);
27
+ connection.listen();
28
+ export { connection as startServer };
29
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,gBAAgB,GAEjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,UAAU,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;AAC1D,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC,YAAY,CAAC,CAAC;AAElD,UAAU,CAAC,YAAY,CAAC,CAAC,OAAyB,EAAE,EAAE;IACpD,OAAO,eAAe,EAAE,CAAC;AAC3B,CAAC,CAAC,CAAC;AAEH,UAAU,CAAC,aAAa,CAAC,GAAG,EAAE;IAC5B,kBAAkB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC1C,mBAAmB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC3C,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACrC,mBAAmB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC3C,kBAAkB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AAC7B,UAAU,CAAC,MAAM,EAAE,CAAC;AAEpB,OAAO,EAAE,UAAU,IAAI,WAAW,EAAE,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * detector.ts — Detect html`` and raw(``) template regions in source text.
3
+ *
4
+ * Recognizes both tagged templates (html`...`) and function-wrapped template
5
+ * literals (raw(`...`)). The inner HTML content is treated identically.
6
+ *
7
+ * Ported from elur-vscode/template-tags.js.
8
+ */
9
+ export interface TemplateRegion {
10
+ /** Absolute offset of the opening backtick + 1 (start of inner content). */
11
+ innerStart: number;
12
+ /** Absolute offset of the closing backtick. */
13
+ innerEnd: number;
14
+ /** The inner content string. */
15
+ inner: string;
16
+ /** Base indentation depth (in indent units) of the tag line. */
17
+ baseIndent: number;
18
+ }
19
+ /**
20
+ * Extracts the template tag name immediately before a backtick.
21
+ * Returns null if no valid tag is found.
22
+ */
23
+ export declare function extractTemplateTagBeforeBacktick(textBeforeCursor: string): string | null;
24
+ /**
25
+ * Returns true if the cursor at `cursorOffset` is inside a html`` or raw(``)
26
+ * template region.
27
+ *
28
+ * Uses findTemplateRegions to correctly handle nested template literals
29
+ * (e.g. `html\`<div>${() => \`inner\`}</div>\``).
30
+ */
31
+ export declare function isInsideTaggedTemplate(documentText: string, cursorOffset: number, allowedTags?: readonly string[]): boolean;
32
+ /**
33
+ * Finds the closing backtick of a template starting at `from` (position after
34
+ * the opening backtick). Handles nested ${...} and nested template literals.
35
+ * Returns -1 if not found.
36
+ */
37
+ export declare function findTemplateClose(text: string, from: number): number;
38
+ /**
39
+ * Scans the document text and returns all html`` and raw(``) template regions.
40
+ * Regions are returned in order of appearance. Nested templates are included.
41
+ */
42
+ export declare function findTemplateRegions(text: string, tabSize?: number, allowedTags?: readonly string[]): TemplateRegion[];
43
+ //# sourceMappingURL=detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../src/template/detector.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,WAAW,cAAc;IAC7B,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAcxF;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,WAAW,GAAE,SAAS,MAAM,EAAuB,GAClD,OAAO,CAKT;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAiCpE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,SAAI,EACX,WAAW,GAAE,SAAS,MAAM,EAAuB,GAClD,cAAc,EAAE,CAKlB"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * detector.ts — Detect html`` and raw(``) template regions in source text.
3
+ *
4
+ * Recognizes both tagged templates (html`...`) and function-wrapped template
5
+ * literals (raw(`...`)). The inner HTML content is treated identically.
6
+ *
7
+ * Ported from elur-vscode/template-tags.js.
8
+ */
9
+ const TEMPLATE_TAGS = new Set(["html", "raw"]);
10
+ /**
11
+ * Extracts the template tag name immediately before a backtick.
12
+ * Returns null if no valid tag is found.
13
+ */
14
+ export function extractTemplateTagBeforeBacktick(textBeforeCursor) {
15
+ const lastBacktick = textBeforeCursor.lastIndexOf("`");
16
+ if (lastBacktick < 0)
17
+ return null;
18
+ const beforeBacktick = textBeforeCursor.slice(0, lastBacktick);
19
+ let i = beforeBacktick.length - 1;
20
+ while (i >= 0 && /\s/.test(beforeBacktick[i]))
21
+ i--;
22
+ const end = i;
23
+ while (i >= 0 && /[\w$]/.test(beforeBacktick[i]))
24
+ i--;
25
+ const tagName = beforeBacktick.slice(i + 1, end + 1).toLowerCase();
26
+ return tagName || null;
27
+ }
28
+ /**
29
+ * Returns true if the cursor at `cursorOffset` is inside a html`` or raw(``)
30
+ * template region.
31
+ *
32
+ * Uses findTemplateRegions to correctly handle nested template literals
33
+ * (e.g. `html\`<div>${() => \`inner\`}</div>\``).
34
+ */
35
+ export function isInsideTaggedTemplate(documentText, cursorOffset, allowedTags = [...TEMPLATE_TAGS]) {
36
+ const regions = findTemplateRegions(documentText, 2, allowedTags);
37
+ return regions.some((r) => cursorOffset >= r.innerStart && cursorOffset <= r.innerEnd);
38
+ }
39
+ /**
40
+ * Finds the closing backtick of a template starting at `from` (position after
41
+ * the opening backtick). Handles nested ${...} and nested template literals.
42
+ * Returns -1 if not found.
43
+ */
44
+ export function findTemplateClose(text, from) {
45
+ let i = from;
46
+ const len = text.length;
47
+ while (i < len) {
48
+ if (text[i] === "`")
49
+ return i;
50
+ if (text[i] === "$" && text[i + 1] === "{") {
51
+ i += 2;
52
+ let depth = 1;
53
+ while (i < len && depth > 0) {
54
+ if (text[i] === "{")
55
+ depth++;
56
+ else if (text[i] === "}")
57
+ depth--;
58
+ else if (text[i] === "`") {
59
+ i++;
60
+ const nestedClose = findTemplateClose(text, i);
61
+ if (nestedClose === -1)
62
+ return -1;
63
+ i = nestedClose;
64
+ }
65
+ else if (text[i] === '"' || text[i] === "'") {
66
+ const q = text[i];
67
+ i++;
68
+ while (i < len && text[i] !== q) {
69
+ if (text[i] === "\\")
70
+ i++;
71
+ i++;
72
+ }
73
+ }
74
+ i++;
75
+ }
76
+ continue;
77
+ }
78
+ i++;
79
+ }
80
+ return -1;
81
+ }
82
+ /**
83
+ * Scans the document text and returns all html`` and raw(``) template regions.
84
+ * Regions are returned in order of appearance. Nested templates are included.
85
+ */
86
+ export function findTemplateRegions(text, tabSize = 2, allowedTags = [...TEMPLATE_TAGS]) {
87
+ const regions = [];
88
+ const tagSet = new Set(allowedTags.map((t) => t.toLowerCase()));
89
+ scanRegions(text, 0, regions, tabSize, tagSet);
90
+ return regions;
91
+ }
92
+ function scanRegions(text, baseOffset, regions, tabSize, tagSet) {
93
+ const len = text.length;
94
+ let i = 0;
95
+ while (i < len) {
96
+ // Skip line comments
97
+ if (text[i] === "/" && text[i + 1] === "/") {
98
+ while (i < len && text[i] !== "\n")
99
+ i++;
100
+ continue;
101
+ }
102
+ // Skip block comments
103
+ if (text[i] === "/" && text[i + 1] === "*") {
104
+ i += 2;
105
+ while (i < len - 1 && !(text[i] === "*" && text[i + 1] === "/"))
106
+ i++;
107
+ i += 2;
108
+ continue;
109
+ }
110
+ // Skip strings
111
+ if (text[i] === '"' || text[i] === "'") {
112
+ const q = text[i];
113
+ i++;
114
+ while (i < len && text[i] !== q) {
115
+ if (text[i] === "\\")
116
+ i++;
117
+ i++;
118
+ }
119
+ i++;
120
+ continue;
121
+ }
122
+ if (/[a-zA-Z_$]/.test(text[i])) {
123
+ const tagStart = i;
124
+ while (i < len && /[\w$]/.test(text[i]))
125
+ i++;
126
+ const tag = text.slice(tagStart, i).toLowerCase();
127
+ if (tagSet.has(tag)) {
128
+ let j = i;
129
+ while (j < len && (text[j] === " " || text[j] === "\t"))
130
+ j++;
131
+ // Determine if this is a tagged template (html`...`) or a
132
+ // function-wrapped template literal (raw(`...`)).
133
+ let isFunctionWrapped = false;
134
+ if (j < len && text[j] === "(") {
135
+ isFunctionWrapped = true;
136
+ j++;
137
+ while (j < len && /\s/.test(text[j]))
138
+ j++;
139
+ }
140
+ if (j < len && text[j] === "`") {
141
+ const openBacktick = j;
142
+ const innerStart = openBacktick + 1;
143
+ // Compute base indent
144
+ let lineStart = tagStart;
145
+ while (lineStart > 0 && text[lineStart - 1] !== "\n")
146
+ lineStart--;
147
+ let spaceCount = 0;
148
+ let k = lineStart;
149
+ while (k < tagStart && (text[k] === " " || text[k] === "\t")) {
150
+ spaceCount += text[k] === "\t" ? tabSize : 1;
151
+ k++;
152
+ }
153
+ const baseIndent = Math.round(spaceCount / tabSize);
154
+ const closeBacktick = findTemplateClose(text, innerStart);
155
+ if (closeBacktick === -1) {
156
+ i = j + 1;
157
+ continue;
158
+ }
159
+ const inner = text.slice(innerStart, closeBacktick);
160
+ const innerStartAbs = baseOffset + innerStart;
161
+ const innerEndAbs = baseOffset + closeBacktick;
162
+ scanRegions(inner, innerStartAbs, regions, tabSize, tagSet);
163
+ regions.push({
164
+ innerStart: innerStartAbs,
165
+ innerEnd: innerEndAbs,
166
+ inner,
167
+ baseIndent,
168
+ });
169
+ // Skip past the closing `)` for function-wrapped templates
170
+ i = closeBacktick + 1;
171
+ if (isFunctionWrapped) {
172
+ while (i < len && /\s/.test(text[i]))
173
+ i++;
174
+ if (i < len && text[i] === ")")
175
+ i++;
176
+ }
177
+ continue;
178
+ }
179
+ }
180
+ }
181
+ i++;
182
+ }
183
+ }
184
+ //# sourceMappingURL=detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.js","sourceRoot":"","sources":["../../src/template/detector.ts"],"names":[],"mappings":"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"}