@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.
- package/README.md +71 -0
- package/bin/elur-language-server.js +3 -0
- package/dist/capabilities.d.ts +6 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +22 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/codeActions/fixes.d.ts +16 -0
- package/dist/codeActions/fixes.d.ts.map +1 -0
- package/dist/codeActions/fixes.js +94 -0
- package/dist/codeActions/fixes.js.map +1 -0
- package/dist/codeActions/provider.d.ts +7 -0
- package/dist/codeActions/provider.d.ts.map +1 -0
- package/dist/codeActions/provider.js +46 -0
- package/dist/codeActions/provider.js.map +1 -0
- package/dist/completion/directives.d.ts +6 -0
- package/dist/completion/directives.d.ts.map +1 -0
- package/dist/completion/directives.js +16 -0
- package/dist/completion/directives.js.map +1 -0
- package/dist/completion/events.d.ts +6 -0
- package/dist/completion/events.d.ts.map +1 -0
- package/dist/completion/events.js +20 -0
- package/dist/completion/events.js.map +1 -0
- package/dist/completion/modifiers.d.ts +6 -0
- package/dist/completion/modifiers.d.ts.map +1 -0
- package/dist/completion/modifiers.js +19 -0
- package/dist/completion/modifiers.js.map +1 -0
- package/dist/completion/provider.d.ts +7 -0
- package/dist/completion/provider.d.ts.map +1 -0
- package/dist/completion/provider.js +46 -0
- package/dist/completion/provider.js.map +1 -0
- package/dist/diagnostics/provider.d.ts +7 -0
- package/dist/diagnostics/provider.d.ts.map +1 -0
- package/dist/diagnostics/provider.js +49 -0
- package/dist/diagnostics/provider.js.map +1 -0
- package/dist/diagnostics/rules.d.ts +29 -0
- package/dist/diagnostics/rules.d.ts.map +1 -0
- package/dist/diagnostics/rules.js +46 -0
- package/dist/diagnostics/rules.js.map +1 -0
- package/dist/formatting/ast.d.ts +37 -0
- package/dist/formatting/ast.d.ts.map +1 -0
- package/dist/formatting/ast.js +112 -0
- package/dist/formatting/ast.js.map +1 -0
- package/dist/formatting/attributes.d.ts +7 -0
- package/dist/formatting/attributes.d.ts.map +1 -0
- package/dist/formatting/attributes.js +7 -0
- package/dist/formatting/attributes.js.map +1 -0
- package/dist/formatting/printer.d.ts +34 -0
- package/dist/formatting/printer.d.ts.map +1 -0
- package/dist/formatting/printer.js +380 -0
- package/dist/formatting/printer.js.map +1 -0
- package/dist/formatting/provider.d.ts +10 -0
- package/dist/formatting/provider.d.ts.map +1 -0
- package/dist/formatting/provider.js +82 -0
- package/dist/formatting/provider.js.map +1 -0
- package/dist/formatting/renderer.d.ts +11 -0
- package/dist/formatting/renderer.d.ts.map +1 -0
- package/dist/formatting/renderer.js +175 -0
- package/dist/formatting/renderer.js.map +1 -0
- package/dist/formatting/tokenizer.d.ts +7 -0
- package/dist/formatting/tokenizer.d.ts.map +1 -0
- package/dist/formatting/tokenizer.js +7 -0
- package/dist/formatting/tokenizer.js.map +1 -0
- package/dist/hover/provider.d.ts +7 -0
- package/dist/hover/provider.d.ts.map +1 -0
- package/dist/hover/provider.js +48 -0
- package/dist/hover/provider.js.map +1 -0
- package/dist/modifiers/analyzer.d.ts +18 -0
- package/dist/modifiers/analyzer.d.ts.map +1 -0
- package/dist/modifiers/analyzer.js +75 -0
- package/dist/modifiers/analyzer.js.map +1 -0
- package/dist/modifiers/constants.d.ts +17 -0
- package/dist/modifiers/constants.d.ts.map +1 -0
- package/dist/modifiers/constants.js +58 -0
- package/dist/modifiers/constants.js.map +1 -0
- package/dist/modifiers/normalizer.d.ts +20 -0
- package/dist/modifiers/normalizer.d.ts.map +1 -0
- package/dist/modifiers/normalizer.js +62 -0
- package/dist/modifiers/normalizer.js.map +1 -0
- package/dist/modifiers/parser.d.ts +33 -0
- package/dist/modifiers/parser.d.ts.map +1 -0
- package/dist/modifiers/parser.js +73 -0
- package/dist/modifiers/parser.js.map +1 -0
- package/dist/modifiers/suggestions.d.ts +20 -0
- package/dist/modifiers/suggestions.d.ts.map +1 -0
- package/dist/modifiers/suggestions.js +60 -0
- package/dist/modifiers/suggestions.js.map +1 -0
- package/dist/server-browser.d.ts +16 -0
- package/dist/server-browser.d.ts.map +1 -0
- package/dist/server-browser.js +16 -0
- package/dist/server-browser.js.map +1 -0
- package/dist/server.d.ts +8 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +29 -0
- package/dist/server.js.map +1 -0
- package/dist/template/detector.d.ts +43 -0
- package/dist/template/detector.d.ts.map +1 -0
- package/dist/template/detector.js +184 -0
- package/dist/template/detector.js.map +1 -0
- package/dist/template/parser.d.ts +42 -0
- package/dist/template/parser.d.ts.map +1 -0
- package/dist/template/parser.js +225 -0
- package/dist/template/parser.js.map +1 -0
- package/dist/template/scope.d.ts +18 -0
- package/dist/template/scope.d.ts.map +1 -0
- package/dist/template/scope.js +44 -0
- package/dist/template/scope.js.map +1 -0
- package/dist/utils/config.d.ts +14 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +13 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/levenshtein.d.ts +7 -0
- package/dist/utils/levenshtein.d.ts.map +1 -0
- package/dist/utils/levenshtein.js +7 -0
- package/dist/utils/levenshtein.js.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# @elurjs/language-server
|
|
2
|
+
|
|
3
|
+
LSP (Language Server Protocol) server for [Elur](https://elur.dev/) `html\`\`` tagged templates.
|
|
4
|
+
|
|
5
|
+
Provides diagnostics, autocompletion, hover help, quick fixes, and formatting —
|
|
6
|
+
works in **any** editor that supports LSP.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Diagnostics**: unknown modifiers, duplicate modifiers, passive+prevent conflict,
|
|
11
|
+
key modifiers on non-key events, non-canonical modifier order
|
|
12
|
+
- **Completion**: `@event` names, `.modifier` suggestions, `ref`/`show`/`hide` directives
|
|
13
|
+
- **Hover**: help text for each modifier (`.prevent`, `.stop`, `.enter`, etc.)
|
|
14
|
+
- **Quick fixes**: dedupe modifiers, normalize order, resolve conflicts, replace unknowns
|
|
15
|
+
- **Formatting**: indents and wraps `html\`\`` template content
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @elurjs/language-server
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Editor setup
|
|
24
|
+
|
|
25
|
+
### VS Code
|
|
26
|
+
|
|
27
|
+
The `vscode-elur` extension launches this server automatically.
|
|
28
|
+
|
|
29
|
+
### Neovim
|
|
30
|
+
|
|
31
|
+
```lua
|
|
32
|
+
require("lspconfig").elur = {
|
|
33
|
+
cmd = { "elur-language-server", "--stdio" },
|
|
34
|
+
filetypes = { "typescript", "javascript", "typescriptreact", "javascriptreact" },
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Helix
|
|
39
|
+
|
|
40
|
+
```toml
|
|
41
|
+
# ~/.config/helix/languages.toml
|
|
42
|
+
[[language]]
|
|
43
|
+
name = "typescript"
|
|
44
|
+
language-servers = ["elur-language-server"]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Zed
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
"language_servers": ["elur-language-server"]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Emacs (eglot)
|
|
54
|
+
|
|
55
|
+
```elisp
|
|
56
|
+
(add-to-list 'eglot-server-programs
|
|
57
|
+
'((typescript-mode) . ("elur-language-server" "--stdio")))
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Development
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm install
|
|
64
|
+
npm run typecheck
|
|
65
|
+
npm test
|
|
66
|
+
npm run build
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## License
|
|
70
|
+
|
|
71
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGtE,wBAAgB,eAAe,IAAI,gBAAgB,CAgBlD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* capabilities.ts — LSP capability declarations.
|
|
3
|
+
*/
|
|
4
|
+
import { TextDocumentSyncKind } from "vscode-languageserver/node.js";
|
|
5
|
+
export function getCapabilities() {
|
|
6
|
+
return {
|
|
7
|
+
capabilities: {
|
|
8
|
+
textDocumentSync: TextDocumentSyncKind.Incremental,
|
|
9
|
+
completionProvider: {
|
|
10
|
+
triggerCharacters: ["@", ".", "="],
|
|
11
|
+
resolveProvider: true,
|
|
12
|
+
},
|
|
13
|
+
hoverProvider: true,
|
|
14
|
+
codeActionProvider: {
|
|
15
|
+
codeActionKinds: ["quickfix"],
|
|
16
|
+
},
|
|
17
|
+
documentFormattingProvider: true,
|
|
18
|
+
documentRangeFormattingProvider: true,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,YAAY,EAAE;YACZ,gBAAgB,EAAE,oBAAoB,CAAC,WAAW;YAClD,kBAAkB,EAAE;gBAClB,iBAAiB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;gBAClC,eAAe,EAAE,IAAI;aACtB;YACD,aAAa,EAAE,IAAI;YACnB,kBAAkB,EAAE;gBAClB,eAAe,EAAE,CAAC,UAAU,CAAC;aAC9B;YACD,0BAA0B,EAAE,IAAI;YAChC,+BAA+B,EAAE,IAAI;SACtC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fixes.ts — Generate quick fixes for modifier issues.
|
|
3
|
+
*
|
|
4
|
+
* Ported from elur-vscode/event-modifiers.js createModifierQuickFixes().
|
|
5
|
+
*/
|
|
6
|
+
interface RawFix {
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
modifiers: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface QuickFix extends RawFix {
|
|
12
|
+
chain: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function createModifierQuickFixes(eventName: string, modifiers: string[]): QuickFix[];
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=fixes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixes.d.ts","sourceRoot":"","sources":["../../src/codeActions/fixes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,UAAU,MAAM;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,QAAS,SAAQ,MAAM;IACtC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EAAE,GAClB,QAAQ,EAAE,CAyFZ"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fixes.ts — Generate quick fixes for modifier issues.
|
|
3
|
+
*
|
|
4
|
+
* Ported from elur-vscode/event-modifiers.js createModifierQuickFixes().
|
|
5
|
+
*/
|
|
6
|
+
import { analyzeEventModifiers, isKeyEventName } from "../modifiers/analyzer.js";
|
|
7
|
+
import { uniqueModifiers, removeModifier, normalizeModifierOrder } from "../modifiers/normalizer.js";
|
|
8
|
+
import { suggestClosestModifier } from "../modifiers/suggestions.js";
|
|
9
|
+
import { buildEventBindingChain } from "../modifiers/parser.js";
|
|
10
|
+
import { KEY_MODIFIERS } from "../modifiers/constants.js";
|
|
11
|
+
export function createModifierQuickFixes(eventName, modifiers) {
|
|
12
|
+
const fixes = [];
|
|
13
|
+
const issues = analyzeEventModifiers(eventName, modifiers);
|
|
14
|
+
// Dedupe
|
|
15
|
+
const deduped = uniqueModifiers(modifiers);
|
|
16
|
+
if (deduped.length !== modifiers.length) {
|
|
17
|
+
fixes.push({
|
|
18
|
+
id: "remove-duplicate-modifiers",
|
|
19
|
+
title: "Remove duplicate modifiers",
|
|
20
|
+
modifiers: deduped,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// Normalize order
|
|
24
|
+
const normalizedOrder = normalizeModifierOrder(eventName, modifiers);
|
|
25
|
+
if (normalizedOrder.join(".") !== (modifiers || []).join(".")) {
|
|
26
|
+
fixes.push({
|
|
27
|
+
id: "normalize-modifier-order",
|
|
28
|
+
title: "Normalize modifier order",
|
|
29
|
+
modifiers: normalizedOrder,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
// passive + prevent conflict
|
|
33
|
+
const hasPassive = modifiers.includes("passive");
|
|
34
|
+
const hasPrevent = modifiers.includes("prevent");
|
|
35
|
+
if (hasPassive && hasPrevent) {
|
|
36
|
+
fixes.push({
|
|
37
|
+
id: "drop-prevent",
|
|
38
|
+
title: "Remove .prevent (keep .passive)",
|
|
39
|
+
modifiers: removeModifier(modifiers, "prevent"),
|
|
40
|
+
});
|
|
41
|
+
fixes.push({
|
|
42
|
+
id: "drop-passive",
|
|
43
|
+
title: "Remove .passive (keep .prevent)",
|
|
44
|
+
modifiers: removeModifier(modifiers, "passive"),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// Unknown modifiers
|
|
48
|
+
const seenUnknown = new Set();
|
|
49
|
+
for (const issue of issues) {
|
|
50
|
+
if (issue.code !== "unknown-modifier")
|
|
51
|
+
continue;
|
|
52
|
+
const unknown = issue.message.replace("Unknown modifier .", "").trim().toLowerCase();
|
|
53
|
+
if (!unknown || seenUnknown.has(unknown))
|
|
54
|
+
continue;
|
|
55
|
+
seenUnknown.add(unknown);
|
|
56
|
+
const suggestion = suggestClosestModifier(unknown, eventName);
|
|
57
|
+
if (!suggestion) {
|
|
58
|
+
fixes.push({
|
|
59
|
+
id: `remove-unknown-${unknown}`,
|
|
60
|
+
title: `Remove unknown modifier .${unknown}`,
|
|
61
|
+
modifiers: removeModifier(modifiers, unknown),
|
|
62
|
+
});
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
fixes.push({
|
|
66
|
+
id: `replace-${unknown}-with-${suggestion}`,
|
|
67
|
+
title: `Replace .${unknown} with .${suggestion}`,
|
|
68
|
+
modifiers: modifiers.map((mod) => (mod === unknown ? suggestion : mod)),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
// Key modifiers on non-key event
|
|
72
|
+
if (!isKeyEventName(eventName)) {
|
|
73
|
+
const keyMods = modifiers.filter((mod) => KEY_MODIFIERS.includes(mod));
|
|
74
|
+
if (keyMods.length > 0) {
|
|
75
|
+
fixes.push({
|
|
76
|
+
id: "remove-key-modifiers",
|
|
77
|
+
title: "Remove key-only modifiers",
|
|
78
|
+
modifiers: modifiers.filter((mod) => !KEY_MODIFIERS.includes(mod)),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Deduplicate by chain
|
|
83
|
+
const uniqueFixes = [];
|
|
84
|
+
const seenChains = new Set();
|
|
85
|
+
for (const fix of fixes) {
|
|
86
|
+
const chain = buildEventBindingChain(eventName, fix.modifiers);
|
|
87
|
+
if (seenChains.has(chain))
|
|
88
|
+
continue;
|
|
89
|
+
seenChains.add(chain);
|
|
90
|
+
uniqueFixes.push({ ...fix, chain });
|
|
91
|
+
}
|
|
92
|
+
return uniqueFixes;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=fixes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixes.js","sourceRoot":"","sources":["../../src/codeActions/fixes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* provider.ts — Code actions provider for the LSP server.
|
|
3
|
+
*/
|
|
4
|
+
import type { Connection, TextDocuments } from "vscode-languageserver/node.js";
|
|
5
|
+
import type { TextDocument } from "vscode-languageserver-textdocument";
|
|
6
|
+
export declare function registerCodeActions(connection: Connection, documents: TextDocuments<TextDocument>): void;
|
|
7
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/codeActions/provider.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAKvE,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,aAAa,CAAC,YAAY,CAAC,GACrC,IAAI,CA0CN"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* provider.ts — Code actions provider for the LSP server.
|
|
3
|
+
*/
|
|
4
|
+
import { CodeActionKind } from "vscode-languageserver/node.js";
|
|
5
|
+
import { parseEventBindingChain } from "../modifiers/parser.js";
|
|
6
|
+
import { createModifierQuickFixes } from "./fixes.js";
|
|
7
|
+
export function registerCodeActions(connection, documents) {
|
|
8
|
+
connection.onCodeAction((params) => {
|
|
9
|
+
const document = documents.get(params.textDocument.uri);
|
|
10
|
+
if (!document)
|
|
11
|
+
return null;
|
|
12
|
+
const actions = [];
|
|
13
|
+
for (const diagnostic of params.context.diagnostics) {
|
|
14
|
+
if (diagnostic.source !== "elur")
|
|
15
|
+
continue;
|
|
16
|
+
const chainText = document.getText(diagnostic.range);
|
|
17
|
+
const parsed = parseEventBindingChain(chainText);
|
|
18
|
+
if (!parsed)
|
|
19
|
+
continue;
|
|
20
|
+
const fixes = createModifierQuickFixes(parsed.eventName, parsed.modifiers);
|
|
21
|
+
for (const fix of fixes) {
|
|
22
|
+
const action = {
|
|
23
|
+
title: fix.title,
|
|
24
|
+
kind: CodeActionKind.QuickFix,
|
|
25
|
+
diagnostics: [diagnostic],
|
|
26
|
+
edit: {
|
|
27
|
+
changes: {
|
|
28
|
+
[document.uri]: [
|
|
29
|
+
{
|
|
30
|
+
range: diagnostic.range,
|
|
31
|
+
newText: fix.chain,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
isPreferred: fix.id === "remove-duplicate-modifiers" ||
|
|
37
|
+
fix.id === "drop-prevent" ||
|
|
38
|
+
fix.id === "normalize-modifier-order",
|
|
39
|
+
};
|
|
40
|
+
actions.push(action);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return actions;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/codeActions/provider.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAc,cAAc,EAAiB,MAAM,+BAA+B,CAAC;AAC1F,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,UAAU,mBAAmB,CACjC,UAAsB,EACtB,SAAsC;IAEtC,UAAU,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,EAAE;QACjC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAE3B,MAAM,OAAO,GAAiB,EAAE,CAAC;QAEjC,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YACpD,IAAI,UAAU,CAAC,MAAM,KAAK,MAAM;gBAAE,SAAS;YAE3C,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YACrD,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;YACjD,IAAI,CAAC,MAAM;gBAAE,SAAS;YAEtB,MAAM,KAAK,GAAG,wBAAwB,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;YAE3E,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;gBACxB,MAAM,MAAM,GAAe;oBACzB,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,IAAI,EAAE,cAAc,CAAC,QAAQ;oBAC7B,WAAW,EAAE,CAAC,UAAU,CAAC;oBACzB,IAAI,EAAE;wBACJ,OAAO,EAAE;4BACP,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;gCACd;oCACE,KAAK,EAAE,UAAU,CAAC,KAAK;oCACvB,OAAO,EAAE,GAAG,CAAC,KAAK;iCACnB;6BACF;yBACF;qBACe;oBAClB,WAAW,EACT,GAAG,CAAC,EAAE,KAAK,4BAA4B;wBACvC,GAAG,CAAC,EAAE,KAAK,cAAc;wBACzB,GAAG,CAAC,EAAE,KAAK,0BAA0B;iBACxC,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* directives.ts — Directive attribute completion items (ref, show, hide).
|
|
3
|
+
*/
|
|
4
|
+
import type { CompletionItem } from "vscode-languageserver/node.js";
|
|
5
|
+
export declare function buildDirectiveCompletions(): CompletionItem[];
|
|
6
|
+
//# sourceMappingURL=directives.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directives.d.ts","sourceRoot":"","sources":["../../src/completion/directives.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAGpE,wBAAgB,yBAAyB,IAAI,cAAc,EAAE,CAS5D"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* directives.ts — Directive attribute completion items (ref, show, hide).
|
|
3
|
+
*/
|
|
4
|
+
import { DIRECTIVE_ATTRIBUTES } from "../modifiers/constants.js";
|
|
5
|
+
import { CompletionItemKind } from "vscode-languageserver/node.js";
|
|
6
|
+
export function buildDirectiveCompletions() {
|
|
7
|
+
return DIRECTIVE_ATTRIBUTES.map((directive) => ({
|
|
8
|
+
label: directive,
|
|
9
|
+
kind: CompletionItemKind.Property,
|
|
10
|
+
insertText: `${directive}=\${1}`,
|
|
11
|
+
insertTextFormat: 2,
|
|
12
|
+
detail: "Elur directive",
|
|
13
|
+
documentation: `Elur directive attribute: ${directive}.`,
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=directives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directives.js","sourceRoot":"","sources":["../../src/completion/directives.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,MAAM,UAAU,yBAAyB;IACvC,OAAO,oBAAoB,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAC9C,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,kBAAkB,CAAC,QAAQ;QACjC,UAAU,EAAE,GAAG,SAAS,QAAQ;QAChC,gBAAgB,EAAE,CAAC;QACnB,MAAM,EAAE,gBAAgB;QACxB,aAAa,EAAE,6BAA6B,SAAS,GAAG;KACzD,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/completion/events.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAGpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,EAAE,CAatE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* events.ts — Event name completion items.
|
|
3
|
+
*/
|
|
4
|
+
import { EVENT_BINDINGS } from "../modifiers/constants.js";
|
|
5
|
+
import { CompletionItemKind } from "vscode-languageserver/node.js";
|
|
6
|
+
export function buildEventCompletions(prefix) {
|
|
7
|
+
const p = (prefix || "").toLowerCase();
|
|
8
|
+
return EVENT_BINDINGS
|
|
9
|
+
.filter((eventName) => eventName.startsWith(p))
|
|
10
|
+
.map((eventName) => ({
|
|
11
|
+
label: `@${eventName}`,
|
|
12
|
+
kind: CompletionItemKind.Event,
|
|
13
|
+
filterText: `@${eventName}`,
|
|
14
|
+
insertText: `@${eventName}=\${1}`,
|
|
15
|
+
insertTextFormat: 2,
|
|
16
|
+
detail: "Elur event binding",
|
|
17
|
+
documentation: `Bind ${eventName} inside html tagged templates.`,
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/completion/events.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACvC,OAAO,cAAc;SAClB,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;SAC9C,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACnB,KAAK,EAAE,IAAI,SAAS,EAAE;QACtB,IAAI,EAAE,kBAAkB,CAAC,KAAK;QAC9B,UAAU,EAAE,IAAI,SAAS,EAAE;QAC3B,UAAU,EAAE,IAAI,SAAS,QAAQ;QACjC,gBAAgB,EAAE,CAAC;QACnB,MAAM,EAAE,oBAAoB;QAC5B,aAAa,EAAE,QAAQ,SAAS,gCAAgC;KACjE,CAAC,CAAC,CAAC;AACR,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* modifiers.ts — Modifier completion items.
|
|
3
|
+
*/
|
|
4
|
+
import type { CompletionItem } from "vscode-languageserver/node.js";
|
|
5
|
+
export declare function buildModifierCompletions(eventName: string, usedModifiers: string[], modifierPrefix: string): CompletionItem[];
|
|
6
|
+
//# sourceMappingURL=modifiers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modifiers.d.ts","sourceRoot":"","sources":["../../src/completion/modifiers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAGpE,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EAAE,EACvB,cAAc,EAAE,MAAM,GACrB,cAAc,EAAE,CAWlB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* modifiers.ts — Modifier completion items.
|
|
3
|
+
*/
|
|
4
|
+
import { getModifierSuggestions } from "../modifiers/suggestions.js";
|
|
5
|
+
import { MODIFIER_HELP } from "../modifiers/constants.js";
|
|
6
|
+
import { isKeyEventName } from "../modifiers/analyzer.js";
|
|
7
|
+
import { CompletionItemKind } from "vscode-languageserver/node.js";
|
|
8
|
+
export function buildModifierCompletions(eventName, usedModifiers, modifierPrefix) {
|
|
9
|
+
const suggestions = getModifierSuggestions(eventName, usedModifiers, modifierPrefix);
|
|
10
|
+
const isKey = isKeyEventName(eventName);
|
|
11
|
+
return suggestions.map((modifier) => ({
|
|
12
|
+
label: `.${modifier}`,
|
|
13
|
+
kind: CompletionItemKind.EnumMember,
|
|
14
|
+
insertText: modifier,
|
|
15
|
+
detail: isKey ? "Elur key/event modifier" : "Elur event modifier",
|
|
16
|
+
documentation: MODIFIER_HELP[modifier] || "Elur event modifier",
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=modifiers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modifiers.js","sourceRoot":"","sources":["../../src/completion/modifiers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,MAAM,UAAU,wBAAwB,CACtC,SAAiB,EACjB,aAAuB,EACvB,cAAsB;IAEtB,MAAM,WAAW,GAAG,sBAAsB,CAAC,SAAS,EAAE,aAAa,EAAE,cAAc,CAAC,CAAC;IACrF,MAAM,KAAK,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAExC,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACpC,KAAK,EAAE,IAAI,QAAQ,EAAE;QACrB,IAAI,EAAE,kBAAkB,CAAC,UAAU;QACnC,UAAU,EAAE,QAAQ;QACpB,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,qBAAqB;QACjE,aAAa,EAAE,aAAa,CAAC,QAAQ,CAAC,IAAI,qBAAqB;KAChE,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* provider.ts — Completion provider for the LSP server.
|
|
3
|
+
*/
|
|
4
|
+
import type { Connection, TextDocuments } from "vscode-languageserver/node.js";
|
|
5
|
+
import type { TextDocument } from "vscode-languageserver-textdocument";
|
|
6
|
+
export declare function registerCompletion(connection: Connection, documents: TextDocuments<TextDocument>): void;
|
|
7
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/completion/provider.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAYvE,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,aAAa,CAAC,YAAY,CAAC,GACrC,IAAI,CA4CN"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* provider.ts — Completion provider for the LSP server.
|
|
3
|
+
*/
|
|
4
|
+
import { Position } from "vscode-languageserver/node.js";
|
|
5
|
+
import { parseEventContextFromPrefix } from "../modifiers/parser.js";
|
|
6
|
+
import { isInsideTaggedTemplate } from "../template/detector.js";
|
|
7
|
+
import { buildEventCompletions } from "./events.js";
|
|
8
|
+
import { buildModifierCompletions } from "./modifiers.js";
|
|
9
|
+
import { buildDirectiveCompletions } from "./directives.js";
|
|
10
|
+
const SUPPORTED_LANGUAGES = new Set([
|
|
11
|
+
"javascript", "typescript", "javascriptreact", "typescriptreact",
|
|
12
|
+
]);
|
|
13
|
+
export function registerCompletion(connection, documents) {
|
|
14
|
+
connection.onCompletion((params) => {
|
|
15
|
+
const document = documents.get(params.textDocument.uri);
|
|
16
|
+
if (!document || !SUPPORTED_LANGUAGES.has(document.languageId)) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const text = document.getText();
|
|
20
|
+
const offset = document.offsetAt(params.position);
|
|
21
|
+
if (!isInsideTaggedTemplate(text, offset)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const linePrefix = document.getText({
|
|
25
|
+
start: Position.create(params.position.line, 0),
|
|
26
|
+
end: params.position,
|
|
27
|
+
});
|
|
28
|
+
const eventContext = parseEventContextFromPrefix(linePrefix);
|
|
29
|
+
if (eventContext?.mode === "modifier") {
|
|
30
|
+
const items = buildModifierCompletions(eventContext.eventName || "", eventContext.usedModifiers || [], eventContext.modifierPrefix || "");
|
|
31
|
+
return { items, isIncomplete: false };
|
|
32
|
+
}
|
|
33
|
+
if (eventContext?.mode === "event") {
|
|
34
|
+
const items = buildEventCompletions(eventContext.eventPrefix || "");
|
|
35
|
+
return { items, isIncomplete: false };
|
|
36
|
+
}
|
|
37
|
+
// Default: offer events + directives
|
|
38
|
+
const items = [
|
|
39
|
+
...buildEventCompletions(""),
|
|
40
|
+
...buildDirectiveCompletions(),
|
|
41
|
+
];
|
|
42
|
+
return { items, isIncomplete: false };
|
|
43
|
+
});
|
|
44
|
+
connection.onCompletionResolve((item) => item);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/completion/provider.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAkC,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAE5D,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB;CACjE,CAAC,CAAC;AAEH,MAAM,UAAU,kBAAkB,CAChC,UAAsB,EACtB,SAAsC;IAEtC,UAAU,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,EAAE;QACjC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAElD,IAAI,CAAC,sBAAsB,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC;YAClC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;YAC/C,GAAG,EAAE,MAAM,CAAC,QAAQ;SACrB,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,2BAA2B,CAAC,UAAU,CAAC,CAAC;QAE7D,IAAI,YAAY,EAAE,IAAI,KAAK,UAAU,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,wBAAwB,CACpC,YAAY,CAAC,SAAS,IAAI,EAAE,EAC5B,YAAY,CAAC,aAAa,IAAI,EAAE,EAChC,YAAY,CAAC,cAAc,IAAI,EAAE,CAClC,CAAC;YACF,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAoB,CAAC;QAC1D,CAAC;QAED,IAAI,YAAY,EAAE,IAAI,KAAK,OAAO,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,qBAAqB,CAAC,YAAY,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;YACpE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAoB,CAAC;QAC1D,CAAC;QAED,qCAAqC;QACrC,MAAM,KAAK,GAAqB;YAC9B,GAAG,qBAAqB,CAAC,EAAE,CAAC;YAC5B,GAAG,yBAAyB,EAAE;SAC/B,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAoB,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,mBAAmB,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* provider.ts — Diagnostics provider for the LSP server.
|
|
3
|
+
*/
|
|
4
|
+
import type { Connection, TextDocuments } from "vscode-languageserver/node.js";
|
|
5
|
+
import type { TextDocument } from "vscode-languageserver-textdocument";
|
|
6
|
+
export declare function registerDiagnostics(connection: Connection, documents: TextDocuments<TextDocument>): void;
|
|
7
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/diagnostics/provider.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAQvE,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,aAAa,CAAC,YAAY,CAAC,GACrC,IAAI,CA2CN"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* provider.ts — Diagnostics provider for the LSP server.
|
|
3
|
+
*/
|
|
4
|
+
import { DiagnosticSeverity } from "vscode-languageserver/node.js";
|
|
5
|
+
import { scanDiagnostics } from "./rules.js";
|
|
6
|
+
const SUPPORTED_LANGUAGES = new Set([
|
|
7
|
+
"javascript", "typescript", "javascriptreact", "typescriptreact",
|
|
8
|
+
]);
|
|
9
|
+
export function registerDiagnostics(connection, documents) {
|
|
10
|
+
function validate(document) {
|
|
11
|
+
if (!SUPPORTED_LANGUAGES.has(document.languageId))
|
|
12
|
+
return;
|
|
13
|
+
const scheme = document.uri.startsWith("file:") ? "file"
|
|
14
|
+
: document.uri.startsWith("untitled:") ? "untitled"
|
|
15
|
+
: "other";
|
|
16
|
+
if (scheme !== "file" && scheme !== "untitled")
|
|
17
|
+
return;
|
|
18
|
+
const text = document.getText();
|
|
19
|
+
if (!text.includes("@")) {
|
|
20
|
+
connection.sendDiagnostics({ uri: document.uri, diagnostics: [] });
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const enableStyleHints = true; // TODO: read from client config
|
|
24
|
+
const rawDiags = scanDiagnostics(text, enableStyleHints);
|
|
25
|
+
const diagnostics = rawDiags.map((d) => {
|
|
26
|
+
const severity = d.severity === "information"
|
|
27
|
+
? DiagnosticSeverity.Information
|
|
28
|
+
: DiagnosticSeverity.Warning;
|
|
29
|
+
return {
|
|
30
|
+
severity,
|
|
31
|
+
code: d.code,
|
|
32
|
+
message: d.message,
|
|
33
|
+
source: "elur",
|
|
34
|
+
range: {
|
|
35
|
+
start: document.positionAt(d.range.start),
|
|
36
|
+
end: document.positionAt(d.range.end),
|
|
37
|
+
},
|
|
38
|
+
data: d.data,
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
connection.sendDiagnostics({ uri: document.uri, diagnostics });
|
|
42
|
+
}
|
|
43
|
+
documents.onDidOpen((e) => validate(e.document));
|
|
44
|
+
documents.onDidChangeContent((e) => validate(e.document));
|
|
45
|
+
documents.onDidClose((e) => {
|
|
46
|
+
connection.sendDiagnostics({ uri: e.document.uri, diagnostics: [] });
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/diagnostics/provider.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAc,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAuB,MAAM,YAAY,CAAC;AAElE,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB;CACjE,CAAC,CAAC;AAEH,MAAM,UAAU,mBAAmB,CACjC,UAAsB,EACtB,SAAsC;IAEtC,SAAS,QAAQ,CAAC,QAAsB;QACtC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC;YAAE,OAAO;QAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM;YACtD,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,UAAU;gBACjD,CAAC,CAAC,OAAO,CAAC;QACd,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,UAAU;YAAE,OAAO;QAEvD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,UAAU,CAAC,eAAe,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;YACnE,OAAO;QACT,CAAC;QAED,MAAM,gBAAgB,GAAG,IAAI,CAAC,CAAC,gCAAgC;QAC/D,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAEzD,MAAM,WAAW,GAAiB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAiB,EAAE,EAAE;YACnE,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,KAAK,aAAa;gBAC3C,CAAC,CAAC,kBAAkB,CAAC,WAAW;gBAChC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC;YAE/B,OAAO;gBACL,QAAQ;gBACR,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,MAAM,EAAE,MAAM;gBACd,KAAK,EAAE;oBACL,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC;oBACzC,GAAG,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;iBACtC;gBACD,IAAI,EAAE,CAAC,CAAC,IAAI;aACb,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,eAAe,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjD,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1D,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE;QACzB,UAAU,CAAC,eAAe,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rules.ts — Diagnostic rules for event modifiers.
|
|
3
|
+
*
|
|
4
|
+
* Ported from elur-vscode/extension.js validateDocument().
|
|
5
|
+
*/
|
|
6
|
+
export interface DiagnosticData {
|
|
7
|
+
code: string;
|
|
8
|
+
eventName: string;
|
|
9
|
+
modifiers: string[];
|
|
10
|
+
range: {
|
|
11
|
+
start: number;
|
|
12
|
+
end: number;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export interface TextDiagnostic {
|
|
16
|
+
code: string;
|
|
17
|
+
severity: "warning" | "information";
|
|
18
|
+
message: string;
|
|
19
|
+
range: {
|
|
20
|
+
start: number;
|
|
21
|
+
end: number;
|
|
22
|
+
};
|
|
23
|
+
data: DiagnosticData;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Scans text for @event.modifier chains and returns diagnostics for all issues.
|
|
27
|
+
*/
|
|
28
|
+
export declare function scanDiagnostics(text: string, enableStyleHints: boolean): TextDiagnostic[];
|
|
29
|
+
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/diagnostics/rules.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,GAAG,aAAa,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,IAAI,EAAE,cAAc,CAAC;CACtB;AAMD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,OAAO,GACxB,cAAc,EAAE,CAqClB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rules.ts — Diagnostic rules for event modifiers.
|
|
3
|
+
*
|
|
4
|
+
* Ported from elur-vscode/extension.js validateDocument().
|
|
5
|
+
*/
|
|
6
|
+
import { analyzeEventModifiers } from "../modifiers/analyzer.js";
|
|
7
|
+
// Match @event.modifier chains with or without trailing = (so diagnostics
|
|
8
|
+
// appear while the user is still typing, before completing the binding).
|
|
9
|
+
const EVENT_CHAIN_RE = /@([a-zA-Z][a-zA-Z0-9:-]*)((?:\.[a-zA-Z0-9-]+)*)(?:\s*=(?![=]))?/g;
|
|
10
|
+
/**
|
|
11
|
+
* Scans text for @event.modifier chains and returns diagnostics for all issues.
|
|
12
|
+
*/
|
|
13
|
+
export function scanDiagnostics(text, enableStyleHints) {
|
|
14
|
+
if (!text.includes("@"))
|
|
15
|
+
return [];
|
|
16
|
+
const diagnostics = [];
|
|
17
|
+
let match;
|
|
18
|
+
while ((match = EVENT_CHAIN_RE.exec(text)) !== null) {
|
|
19
|
+
const eventName = (match[1] || "").toLowerCase();
|
|
20
|
+
const modifiers = (match[2] || "")
|
|
21
|
+
.split(".")
|
|
22
|
+
.map((mod) => mod.toLowerCase())
|
|
23
|
+
.filter(Boolean);
|
|
24
|
+
let issues = analyzeEventModifiers(eventName, modifiers, enableStyleHints);
|
|
25
|
+
if (!enableStyleHints) {
|
|
26
|
+
issues = issues.filter((issue) => issue.code !== "modifier-order-noncanonical");
|
|
27
|
+
}
|
|
28
|
+
if (issues.length === 0)
|
|
29
|
+
continue;
|
|
30
|
+
const eqIndex = match[0].indexOf("=");
|
|
31
|
+
const highlightLength = eqIndex >= 0 ? eqIndex : match[0].length;
|
|
32
|
+
const start = match.index;
|
|
33
|
+
const end = match.index + highlightLength;
|
|
34
|
+
for (const issue of issues) {
|
|
35
|
+
diagnostics.push({
|
|
36
|
+
code: issue.code,
|
|
37
|
+
severity: issue.severity,
|
|
38
|
+
message: issue.message,
|
|
39
|
+
range: { start, end },
|
|
40
|
+
data: { code: issue.code, eventName, modifiers, range: { start, end } },
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return diagnostics;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/diagnostics/rules.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAiBjE,0EAA0E;AAC1E,yEAAyE;AACzE,MAAM,cAAc,GAAG,kEAAkE,CAAC;AAE1F;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAY,EACZ,gBAAyB;IAEzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,MAAM,WAAW,GAAqB,EAAE,CAAC;IACzC,IAAI,KAA6B,CAAC;IAElC,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACpD,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QACjD,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aAC/B,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;aAC/B,MAAM,CAAC,OAAO,CAAC,CAAC;QAEnB,IAAI,MAAM,GAAG,qBAAqB,CAAC,SAAS,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;QAC3E,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,6BAA6B,CAAC,CAAC;QAClF,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAElC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,eAAe,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACjE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,GAAG,eAAe,CAAC;QAE1C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,WAAW,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;gBACrB,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;aACxE,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC"}
|