css-variable-lsp 1.0.17 → 1.0.18
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/package.json +1 -1
- package/docs/SCSS_SASS_SUPPORT_RESEARCH.md +0 -96
- package/out/handlers/callHierarchy.js +0 -128
- package/out/handlers/callHierarchy.js.map +0 -1
- package/out/handlers/codeAction.js +0 -142
- package/out/handlers/codeAction.js.map +0 -1
- package/out/handlers/codeLens.js +0 -41
- package/out/handlers/codeLens.js.map +0 -1
- package/out/handlers/declaration.js +0 -34
- package/out/handlers/declaration.js.map +0 -1
- package/out/handlers/documentHighlight.js +0 -45
- package/out/handlers/documentHighlight.js.map +0 -1
- package/out/handlers/documentLink.js +0 -61
- package/out/handlers/documentLink.js.map +0 -1
- package/out/handlers/documentSync.js +0 -15
- package/out/handlers/documentSync.js.map +0 -1
- package/out/handlers/foldingRange.js +0 -77
- package/out/handlers/foldingRange.js.map +0 -1
- package/out/handlers/formatting.js +0 -99
- package/out/handlers/formatting.js.map +0 -1
- package/out/handlers/implementation.js +0 -35
- package/out/handlers/implementation.js.map +0 -1
- package/out/handlers/inlayHint.js +0 -46
- package/out/handlers/inlayHint.js.map +0 -1
- package/out/handlers/linkedEditingRange.js +0 -45
- package/out/handlers/linkedEditingRange.js.map +0 -1
- package/out/handlers/prepareRename.js +0 -44
- package/out/handlers/prepareRename.js.map +0 -1
- package/out/handlers/selectionRange.js +0 -100
- package/out/handlers/selectionRange.js.map +0 -1
- package/out/handlers/semanticTokens.js +0 -57
- package/out/handlers/semanticTokens.js.map +0 -1
- package/out/handlers/signatureHelp.js +0 -54
- package/out/handlers/signatureHelp.js.map +0 -1
- package/out/handlers/typeDefinition.js +0 -35
- package/out/handlers/typeDefinition.js.map +0 -1
- package/out/hierarchy/callHierarchy.js +0 -119
- package/out/hierarchy/callHierarchy.js.map +0 -1
- package/out/hierarchy/shared/hierarchyTypes.js +0 -45
- package/out/hierarchy/shared/hierarchyTypes.js.map +0 -1
- package/out/hierarchy/shared/variableAnalyzer.js +0 -43
- package/out/hierarchy/shared/variableAnalyzer.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# Deep Research: Full SCSS/Sass Support for CSS Variable LSP
|
|
2
|
-
|
|
3
|
-
Last updated: 2026-01-21
|
|
4
|
-
|
|
5
|
-
## Executive summary
|
|
6
|
-
|
|
7
|
-
- Full SCSS/Sass semantics require a real Sass compiler (Dart Sass). Parser-only libraries can accept syntax but cannot evaluate variables, mixins, @use/@forward modules, interpolation, or control flow.
|
|
8
|
-
- In Node.js, the practical compiler choices are `sass` (Dart Sass compiled to JavaScript) and `sass-embedded` (embedded Dart executable with the same JS API, usually faster but platform-limited).
|
|
9
|
-
- Sass module features (`@use`, `@forward`, and built-in `sass:` modules) are only supported by Dart Sass, not LibSass.
|
|
10
|
-
|
|
11
|
-
## What "full support" means
|
|
12
|
-
|
|
13
|
-
A "full" SCSS/Sass implementation must evaluate:
|
|
14
|
-
|
|
15
|
-
- `$` variables, mixins, functions, and control flow (`@if`, `@for`, `@each`, `@while`).
|
|
16
|
-
- Interpolation in selectors, property names, and values.
|
|
17
|
-
- Module system semantics for `@use` and `@forward` (including namespaces and configuration).
|
|
18
|
-
- Built-in modules such as `sass:color`, `sass:math`, etc.
|
|
19
|
-
- Both syntaxes: SCSS (`.scss`) and indented Sass (`.sass`).
|
|
20
|
-
|
|
21
|
-
These features are not recoverable with syntax-only parsing; they require compilation.
|
|
22
|
-
|
|
23
|
-
## Library landscape
|
|
24
|
-
|
|
25
|
-
### 1) Compiler-backed (full semantics)
|
|
26
|
-
|
|
27
|
-
#### Dart Sass via the JS API
|
|
28
|
-
|
|
29
|
-
- The `sass` npm package is Dart Sass compiled to JavaScript. It includes the CLI and exposes the JavaScript API (`compile`, `compileString`, and async variants).
|
|
30
|
-
- The `sass-embedded` package wraps the embedded Dart Sass executable using the Embedded Sass protocol. It exposes the same JS API and is typically faster, but only on platforms where the embedded Dart binary is available.
|
|
31
|
-
- Dart Sass itself can be started in embedded mode via `sass --embedded`, but the npm build of Dart Sass does not provide the `--embedded` flag.
|
|
32
|
-
|
|
33
|
-
#### JS API surface that matters for an LSP
|
|
34
|
-
|
|
35
|
-
Key API parts for integration:
|
|
36
|
-
|
|
37
|
-
- `compile` / `compileString` and their async equivalents.
|
|
38
|
-
- Options that affect source mapping (`sourceMap`, `sourceMapIncludeSources`).
|
|
39
|
-
- Resolution controls (`loadPaths`) and custom `importers` (for `@use`/`@import`).
|
|
40
|
-
- `FileImporter` lets the compiler resolve partials and extensions (e.g., `_name.scss`, `.sass`, `.scss`) without manual logic.
|
|
41
|
-
- The legacy JS API (`render`, `renderSync`) is deprecated and scheduled for removal in Dart Sass 2.0.0.
|
|
42
|
-
|
|
43
|
-
### 2) Parser-only (syntax-level, not semantic)
|
|
44
|
-
|
|
45
|
-
- `postcss-scss` parses SCSS syntax but does not compile; it represents mixins and variables as custom at-rules/properties rather than evaluating them.
|
|
46
|
-
- `gonzales-pe` provides an AST for SCSS/Sass/LESS syntax but does not evaluate Sass semantics.
|
|
47
|
-
- Tree-sitter provides incremental parsing and syntax trees; grammars exist for SCSS, but they do not execute Sass logic.
|
|
48
|
-
|
|
49
|
-
## Implications for CSS Variable LSP
|
|
50
|
-
|
|
51
|
-
### Option A: Compile SCSS/Sass to CSS (recommended for "full support")
|
|
52
|
-
|
|
53
|
-
Pipeline:
|
|
54
|
-
|
|
55
|
-
1. On `.scss`/`.sass` file change, compile with `sass` or `sass-embedded`.
|
|
56
|
-
2. Feed resulting CSS into the existing CSS custom property extractor.
|
|
57
|
-
3. Use source maps to map CSS locations back to original SCSS/Sass documents.
|
|
58
|
-
4. Use custom importers to align `@use`/`@import` resolution with the workspace layout.
|
|
59
|
-
5. Track dependencies so changes in partials or shared modules trigger recompilation of dependents.
|
|
60
|
-
6. Surface Sass compiler errors as diagnostics and avoid indexing stale outputs.
|
|
61
|
-
|
|
62
|
-
Notes:
|
|
63
|
-
|
|
64
|
-
- `sass-embedded` is usually faster and keeps the main thread more responsive, but it adds a native dependency and is limited by platform support. A practical approach is to prefer `sass-embedded` and fall back to `sass` when not available.
|
|
65
|
-
- Source maps are essential for precise diagnostics, hover, and definitions. Without them, results will point to generated CSS instead of the original SCSS/Sass.
|
|
66
|
-
|
|
67
|
-
### Option B: Syntax-only parsing to tolerate SCSS/Sass syntax
|
|
68
|
-
|
|
69
|
-
You can swap the parser to `postcss-scss` or gonzales-pe to prevent parse failures and still extract literal `--custom-prop` declarations, but this cannot provide accurate semantics when Sass generates custom properties dynamically (mixins, interpolation, control flow). This is "best-effort" only.
|
|
70
|
-
|
|
71
|
-
### Mixed approach
|
|
72
|
-
|
|
73
|
-
A hybrid strategy is to run a fast syntax-only parse for responsiveness, then refine results after a background Sass compilation finishes. This can reduce editor latency while still delivering correct results once compilation completes.
|
|
74
|
-
|
|
75
|
-
## Recommendation
|
|
76
|
-
|
|
77
|
-
If the goal is truly "full SCSS/Sass support", integrate Dart Sass compilation. Use `sass-embedded` for performance where available, fall back to `sass` otherwise, and rely on source maps plus custom importers to map results back to source files. Parser-only libraries can improve tolerance for incomplete edits, but they cannot replace a compiler for correctness.
|
|
78
|
-
|
|
79
|
-
## Sources
|
|
80
|
-
|
|
81
|
-
- https://sass-lang.com/documentation/js-api/
|
|
82
|
-
- https://sass-lang.com/documentation/js-api/functions/compile/
|
|
83
|
-
- https://sass-lang.com/documentation/js-api/interfaces/options/
|
|
84
|
-
- https://sass-lang.com/documentation/js-api/interfaces/importer/
|
|
85
|
-
- https://sass-lang.com/documentation/js-api/interfaces/fileimporter/
|
|
86
|
-
- https://sass-lang.com/documentation/at-rules/use/
|
|
87
|
-
- https://sass-lang.com/documentation/at-rules/forward/
|
|
88
|
-
- https://sass-lang.com/documentation/modules/
|
|
89
|
-
- https://sass-lang.com/documentation/breaking-changes/legacy-js-api/
|
|
90
|
-
- https://github.com/sass/embedded-host-node
|
|
91
|
-
- https://github.com/sass/dart-sass
|
|
92
|
-
- https://github.com/postcss/postcss-scss
|
|
93
|
-
- https://www.npmjs.com/package/gonzales-pe
|
|
94
|
-
- https://github.com/tree-sitter/tree-sitter
|
|
95
|
-
- https://www.npmjs.com/package/tree-sitter
|
|
96
|
-
- https://docs.rs/tree-sitter-scss
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleCallHierarchyPrepare = handleCallHierarchyPrepare;
|
|
4
|
-
exports.handleCallHierarchyIncomingCalls = handleCallHierarchyIncomingCalls;
|
|
5
|
-
exports.handleCallHierarchyOutgoingCalls = handleCallHierarchyOutgoingCalls;
|
|
6
|
-
const node_1 = require("vscode-languageserver/node");
|
|
7
|
-
/**
|
|
8
|
-
* Handle call hierarchy prepare.
|
|
9
|
-
* Resolves the item at the cursor position to start the hierarchy.
|
|
10
|
-
*/
|
|
11
|
-
function handleCallHierarchyPrepare(params, documents, cssVariableManager) {
|
|
12
|
-
const document = documents.get(params.textDocument.uri);
|
|
13
|
-
if (!document) {
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
const text = document.getText();
|
|
17
|
-
const offset = document.offsetAt(params.position);
|
|
18
|
-
const left = text.slice(0, offset).match(/[\w-]*$/);
|
|
19
|
-
const right = text.slice(offset).match(/^[\w-]*/);
|
|
20
|
-
if (!left || !right) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
const word = left[0] + right[0];
|
|
24
|
-
if (!word.startsWith("--")) {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
const variables = cssVariableManager.getVariables(word);
|
|
28
|
-
if (variables.length === 0) {
|
|
29
|
-
// If definition not found, try usage
|
|
30
|
-
const usages = cssVariableManager.getVariableUsages(word);
|
|
31
|
-
if (usages.length > 0) {
|
|
32
|
-
// Return item based on usage, but pointing to definition if possible
|
|
33
|
-
// Ideally we resolve to the definition.
|
|
34
|
-
// For now, create a virtual item if definition is missing?
|
|
35
|
-
// Actually, hierarchy works best on definitions.
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
const variable = variables[0]; // Use first definition
|
|
41
|
-
return [
|
|
42
|
-
{
|
|
43
|
-
name: variable.name,
|
|
44
|
-
kind: node_1.SymbolKind.Variable,
|
|
45
|
-
uri: variable.uri,
|
|
46
|
-
range: variable.range,
|
|
47
|
-
selectionRange: variable.nameRange || variable.range,
|
|
48
|
-
detail: variable.value,
|
|
49
|
-
},
|
|
50
|
-
];
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Handle incoming calls (Functions that call this function).
|
|
54
|
-
* For CSS variables: Where is this variable used?
|
|
55
|
-
*/
|
|
56
|
-
function handleCallHierarchyIncomingCalls(params, cssVariableManager) {
|
|
57
|
-
const item = params.item;
|
|
58
|
-
const variableName = item.name;
|
|
59
|
-
const usages = cssVariableManager.getVariableUsages(variableName);
|
|
60
|
-
const incomingCalls = [];
|
|
61
|
-
for (const usage of usages) {
|
|
62
|
-
// We need to identify the "caller".
|
|
63
|
-
// In CSS, the "caller" is the rule or selector that uses the variable.
|
|
64
|
-
// Or if inside another variable definition: --foo: var(--bar);
|
|
65
|
-
// Simplification: We'll create an item for the file/range where it's used
|
|
66
|
-
const fromRange = usage.range;
|
|
67
|
-
// We ideally need a "container" symbol (like the selector name).
|
|
68
|
-
// cssVariableManager doesn't easily give us the "parent rule" of a usage yet without re-parsing.
|
|
69
|
-
// But we know the file URI.
|
|
70
|
-
const callerItem = {
|
|
71
|
-
name: usage.usageContext || "root", // Fallback if no selector known
|
|
72
|
-
kind: node_1.SymbolKind.Property,
|
|
73
|
-
uri: usage.uri,
|
|
74
|
-
range: usage.range, // Approx range (usage site)
|
|
75
|
-
selectionRange: usage.range,
|
|
76
|
-
detail: "Usage",
|
|
77
|
-
};
|
|
78
|
-
incomingCalls.push({
|
|
79
|
-
from: callerItem,
|
|
80
|
-
fromRanges: [usage.range],
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
return incomingCalls;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Handle outgoing calls (Functions called by this function).
|
|
87
|
-
* For CSS variables: What other variables does this variable use?
|
|
88
|
-
*/
|
|
89
|
-
function handleCallHierarchyOutgoingCalls(params, cssVariableManager) {
|
|
90
|
-
const item = params.item;
|
|
91
|
-
// This requires analyzing the value of the variable to find var() calls
|
|
92
|
-
// `item.detail` might hold the value if we populated it.
|
|
93
|
-
const variableValue = item.detail;
|
|
94
|
-
if (!variableValue)
|
|
95
|
-
return null;
|
|
96
|
-
const outgoingCalls = [];
|
|
97
|
-
const varRegex = /var\((--[\w-]+)/g;
|
|
98
|
-
let match;
|
|
99
|
-
while ((match = varRegex.exec(variableValue)) !== null) {
|
|
100
|
-
const usedVarName = match[1];
|
|
101
|
-
const definitions = cssVariableManager.getVariables(usedVarName);
|
|
102
|
-
if (definitions.length > 0) {
|
|
103
|
-
const def = definitions[0];
|
|
104
|
-
const toItem = {
|
|
105
|
-
name: def.name,
|
|
106
|
-
kind: node_1.SymbolKind.Variable,
|
|
107
|
-
uri: def.uri,
|
|
108
|
-
range: def.range,
|
|
109
|
-
selectionRange: def.nameRange || def.range,
|
|
110
|
-
detail: def.value,
|
|
111
|
-
};
|
|
112
|
-
// Where in the value string is it used?
|
|
113
|
-
// We don't have absolute position in file easily here without reparsing definition location.
|
|
114
|
-
// We'll approximate or leave empty.
|
|
115
|
-
// Range is required.
|
|
116
|
-
const dummyRange = {
|
|
117
|
-
start: { line: 0, character: 0 },
|
|
118
|
-
end: { line: 0, character: 0 },
|
|
119
|
-
};
|
|
120
|
-
outgoingCalls.push({
|
|
121
|
-
to: toItem,
|
|
122
|
-
fromRanges: [dummyRange],
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return outgoingCalls;
|
|
127
|
-
}
|
|
128
|
-
//# sourceMappingURL=callHierarchy.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"callHierarchy.js","sourceRoot":"","sources":["../../src/handlers/callHierarchy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleCodeActions = handleCodeActions;
|
|
4
|
-
const node_1 = require("vscode-languageserver/node");
|
|
5
|
-
/**
|
|
6
|
-
* Handle code action requests for CSS documents.
|
|
7
|
-
* Provides quick fixes for undefined CSS variables.
|
|
8
|
-
*/
|
|
9
|
-
function handleCodeActions(params, documents, cssVariableManager) {
|
|
10
|
-
const document = documents.get(params.textDocument.uri);
|
|
11
|
-
if (!document) {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
const codeActions = [];
|
|
15
|
-
// Process diagnostics for undefined variables
|
|
16
|
-
for (const diagnostic of params.context.diagnostics) {
|
|
17
|
-
if (diagnostic.source !== "css-variable-lsp") {
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
// Extract variable name from the diagnostic message
|
|
21
|
-
const match = diagnostic.message.match(/CSS variable '(--[\w-]+)' is not defined/);
|
|
22
|
-
if (!match) {
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
const variableName = match[1];
|
|
26
|
-
// Code action: Create variable in :root
|
|
27
|
-
const createInRootAction = createVariableInRoot(document, variableName, diagnostic);
|
|
28
|
-
if (createInRootAction) {
|
|
29
|
-
codeActions.push(createInRootAction);
|
|
30
|
-
}
|
|
31
|
-
// Code action: Suggest similar existing variables
|
|
32
|
-
const suggestions = getSimilarVariables(variableName, cssVariableManager);
|
|
33
|
-
for (const suggestion of suggestions) {
|
|
34
|
-
codeActions.push(createReplacementAction(document, diagnostic, variableName, suggestion));
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return codeActions;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Create a code action to define the variable in :root
|
|
41
|
-
*/
|
|
42
|
-
function createVariableInRoot(document, variableName, diagnostic) {
|
|
43
|
-
const text = document.getText();
|
|
44
|
-
// Find :root selector
|
|
45
|
-
const rootMatch = text.match(/:root\s*\{/);
|
|
46
|
-
let edit;
|
|
47
|
-
if (rootMatch) {
|
|
48
|
-
// Add variable after :root {
|
|
49
|
-
const insertPosition = document.positionAt(rootMatch.index + rootMatch[0].length);
|
|
50
|
-
edit = {
|
|
51
|
-
changes: {
|
|
52
|
-
[document.uri]: [
|
|
53
|
-
{
|
|
54
|
-
range: { start: insertPosition, end: insertPosition },
|
|
55
|
-
newText: `\n ${variableName}: /* TODO: add value */;`,
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
// Add :root at the start of the file
|
|
63
|
-
const startPos = { line: 0, character: 0 };
|
|
64
|
-
edit = {
|
|
65
|
-
changes: {
|
|
66
|
-
[document.uri]: [
|
|
67
|
-
{
|
|
68
|
-
range: { start: startPos, end: startPos },
|
|
69
|
-
newText: `:root {\n ${variableName}: /* TODO: add value */;\n}\n\n`,
|
|
70
|
-
},
|
|
71
|
-
],
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
title: `Create '${variableName}' in :root`,
|
|
77
|
-
kind: node_1.CodeActionKind.QuickFix,
|
|
78
|
-
diagnostics: [diagnostic],
|
|
79
|
-
edit,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Find similar variable names that might be typos
|
|
84
|
-
*/
|
|
85
|
-
function getSimilarVariables(variableName, cssVariableManager) {
|
|
86
|
-
const allVariables = cssVariableManager.getAllVariables();
|
|
87
|
-
const uniqueNames = new Set(allVariables.map((v) => v.name));
|
|
88
|
-
const similar = [];
|
|
89
|
-
const varNameLower = variableName.toLowerCase();
|
|
90
|
-
for (const name of uniqueNames) {
|
|
91
|
-
const nameLower = name.toLowerCase();
|
|
92
|
-
// Simple similarity check: same prefix or few character difference
|
|
93
|
-
if (nameLower.startsWith(varNameLower.slice(0, 5)) ||
|
|
94
|
-
varNameLower.startsWith(nameLower.slice(0, 5)) ||
|
|
95
|
-
levenshteinDistance(varNameLower, nameLower) <= 3) {
|
|
96
|
-
similar.push(name);
|
|
97
|
-
if (similar.length >= 3)
|
|
98
|
-
break; // Limit suggestions
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return similar;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Create a code action to replace variable with a suggestion
|
|
105
|
-
*/
|
|
106
|
-
function createReplacementAction(document, diagnostic, original, replacement) {
|
|
107
|
-
return {
|
|
108
|
-
title: `Replace with '${replacement}'`,
|
|
109
|
-
kind: node_1.CodeActionKind.QuickFix,
|
|
110
|
-
diagnostics: [diagnostic],
|
|
111
|
-
edit: {
|
|
112
|
-
changes: {
|
|
113
|
-
[document.uri]: [
|
|
114
|
-
{
|
|
115
|
-
range: diagnostic.range,
|
|
116
|
-
newText: `var(${replacement})`,
|
|
117
|
-
},
|
|
118
|
-
],
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Simple Levenshtein distance for typo detection
|
|
125
|
-
*/
|
|
126
|
-
function levenshteinDistance(a, b) {
|
|
127
|
-
const matrix = [];
|
|
128
|
-
for (let i = 0; i <= a.length; i++) {
|
|
129
|
-
matrix[i] = [i];
|
|
130
|
-
}
|
|
131
|
-
for (let j = 0; j <= b.length; j++) {
|
|
132
|
-
matrix[0][j] = j;
|
|
133
|
-
}
|
|
134
|
-
for (let i = 1; i <= a.length; i++) {
|
|
135
|
-
for (let j = 1; j <= b.length; j++) {
|
|
136
|
-
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
137
|
-
matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return matrix[a.length][b.length];
|
|
141
|
-
}
|
|
142
|
-
//# sourceMappingURL=codeAction.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codeAction.js","sourceRoot":"","sources":["../../src/handlers/codeAction.ts"],"names":[],"mappings":"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"}
|
package/out/handlers/codeLens.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleCodeLens = handleCodeLens;
|
|
4
|
-
/**
|
|
5
|
-
* Handle code lens requests for CSS documents.
|
|
6
|
-
* Shows usage counts above CSS variable definitions.
|
|
7
|
-
*/
|
|
8
|
-
function handleCodeLens(params, documents, cssVariableManager) {
|
|
9
|
-
const document = documents.get(params.textDocument.uri);
|
|
10
|
-
if (!document) {
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
const codeLenses = [];
|
|
14
|
-
const allVariables = cssVariableManager.getAllVariables();
|
|
15
|
-
// Find variables defined in this document
|
|
16
|
-
const documentVariables = allVariables.filter((v) => v.uri === document.uri);
|
|
17
|
-
// Group by variable name to avoid duplicate lenses
|
|
18
|
-
const seen = new Set();
|
|
19
|
-
for (const variable of documentVariables) {
|
|
20
|
-
if (seen.has(variable.name))
|
|
21
|
-
continue;
|
|
22
|
-
seen.add(variable.name);
|
|
23
|
-
// Get usage count for this variable
|
|
24
|
-
const references = cssVariableManager.getReferences(variable.name);
|
|
25
|
-
// Filter to only usages (not definitions)
|
|
26
|
-
const usages = references.filter((ref) => !("selector" in ref));
|
|
27
|
-
const usageCount = usages.length;
|
|
28
|
-
// Use the nameRange if available, otherwise fall back to range
|
|
29
|
-
const range = variable.nameRange || variable.range;
|
|
30
|
-
const command = {
|
|
31
|
-
title: usageCount === 1 ? `${usageCount} usage` : `${usageCount} usages`,
|
|
32
|
-
command: "", // No command, just informational
|
|
33
|
-
};
|
|
34
|
-
codeLenses.push({
|
|
35
|
-
range,
|
|
36
|
-
command,
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
return codeLenses;
|
|
40
|
-
}
|
|
41
|
-
//# sourceMappingURL=codeLens.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codeLens.js","sourceRoot":"","sources":["../../src/handlers/codeLens.ts"],"names":[],"mappings":";;AAQA,wCA4CC;AAhDD;;;GAGG;AACH,SAAgB,cAAc,CAC5B,MAAsB,EACtB,SAAyD,EACzD,kBAAsC;IAEtC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACxD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAe,EAAE,CAAC;IAClC,MAAM,YAAY,GAAG,kBAAkB,CAAC,eAAe,EAAE,CAAC;IAE1D,0CAA0C;IAC1C,MAAM,iBAAiB,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,GAAG,CAAC,CAAC;IAE7E,mDAAmD;IACnD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,QAAQ,IAAI,iBAAiB,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,SAAS;QACtC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAExB,oCAAoC;QACpC,MAAM,UAAU,GAAG,kBAAkB,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACnE,0CAA0C;QAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC;QAChE,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;QAEjC,+DAA+D;QAC/D,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC;QAEnD,MAAM,OAAO,GAAY;YACvB,KAAK,EAAE,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,QAAQ,CAAC,CAAC,CAAC,GAAG,UAAU,SAAS;YACxE,OAAO,EAAE,EAAE,EAAE,iCAAiC;SAC/C,CAAC;QAEF,UAAU,CAAC,IAAI,CAAC;YACd,KAAK;YACL,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleDeclaration = handleDeclaration;
|
|
4
|
-
const node_1 = require("vscode-languageserver/node");
|
|
5
|
-
/**
|
|
6
|
-
* Handle declaration requests for CSS variables.
|
|
7
|
-
* For CSS variables, declaration and definition are the same.
|
|
8
|
-
*/
|
|
9
|
-
function handleDeclaration(params, documents, cssVariableManager) {
|
|
10
|
-
const document = documents.get(params.textDocument.uri);
|
|
11
|
-
if (!document) {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
const text = document.getText();
|
|
15
|
-
const offset = document.offsetAt(params.position);
|
|
16
|
-
// Find the word at the cursor position
|
|
17
|
-
const left = text.slice(0, offset).match(/[\w-]*$/);
|
|
18
|
-
const right = text.slice(offset).match(/^[\w-]*/);
|
|
19
|
-
if (!left || !right) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
const word = left[0] + right[0];
|
|
23
|
-
// Check if it's a CSS variable
|
|
24
|
-
if (word.startsWith("--")) {
|
|
25
|
-
const variables = cssVariableManager.getVariables(word);
|
|
26
|
-
if (variables.length > 0) {
|
|
27
|
-
// For CSS variables, return the first definition location
|
|
28
|
-
// This could be enhanced to handle multiple declarations
|
|
29
|
-
return node_1.Location.create(variables[0].uri, variables[0].range);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
//# sourceMappingURL=declaration.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"declaration.js","sourceRoot":"","sources":["../../src/handlers/declaration.ts"],"names":[],"mappings":";;AAaA,8CAkCC;AAxCD,qDAAsD;AAEtD;;;GAGG;AACH,SAAgB,iBAAiB,CAC/B,MAAkC,EAClC,SAAyD,EACzD,kBAAsC;IAEtC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACxD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAElD,uCAAuC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAElD,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAEhC,+BAA+B;IAC/B,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,MAAM,SAAS,GAAG,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACxD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,0DAA0D;YAC1D,yDAAyD;YACzD,OAAO,eAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleDocumentHighlight = handleDocumentHighlight;
|
|
4
|
-
const node_1 = require("vscode-languageserver/node");
|
|
5
|
-
/**
|
|
6
|
-
* Handle document highlight requests for CSS variables.
|
|
7
|
-
* Highlights all occurrences of the variable at the cursor position.
|
|
8
|
-
*/
|
|
9
|
-
function handleDocumentHighlight(params, documents, cssVariableManager) {
|
|
10
|
-
const document = documents.get(params.textDocument.uri);
|
|
11
|
-
if (!document) {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
const text = document.getText();
|
|
15
|
-
const offset = document.offsetAt(params.position);
|
|
16
|
-
// Find the word at the cursor position
|
|
17
|
-
const left = text.slice(0, offset).match(/[\w-]*$/);
|
|
18
|
-
const right = text.slice(offset).match(/^[\w-]*/);
|
|
19
|
-
if (!left || !right) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
const word = left[0] + right[0];
|
|
23
|
-
// Check if it's a CSS variable
|
|
24
|
-
if (word.startsWith("--")) {
|
|
25
|
-
const highlights = [];
|
|
26
|
-
// Get all references to this variable
|
|
27
|
-
const references = cssVariableManager.getReferences(word);
|
|
28
|
-
// Filter references to only those in the current document
|
|
29
|
-
const currentDocRefs = references.filter(ref => ref.uri === document.uri);
|
|
30
|
-
// Create highlights for each reference
|
|
31
|
-
for (const ref of currentDocRefs) {
|
|
32
|
-
// Check if it's a definition by checking if it has a selector property
|
|
33
|
-
const isDefinition = 'selector' in ref;
|
|
34
|
-
const highlight = {
|
|
35
|
-
range: ref.range,
|
|
36
|
-
// Use Write kind for definitions, Text kind for usages
|
|
37
|
-
kind: isDefinition ? node_1.DocumentHighlightKind.Write : node_1.DocumentHighlightKind.Text,
|
|
38
|
-
};
|
|
39
|
-
highlights.push(highlight);
|
|
40
|
-
}
|
|
41
|
-
return highlights;
|
|
42
|
-
}
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
//# sourceMappingURL=documentHighlight.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentHighlight.js","sourceRoot":"","sources":["../../src/handlers/documentHighlight.ts"],"names":[],"mappings":";;AAaA,0DAiDC;AA9DD,qDAIoC;AAKpC;;;GAGG;AACH,SAAgB,uBAAuB,CACrC,MAA+B,EAC/B,SAAyD,EACzD,kBAAsC;IAEtC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACxD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAElD,uCAAuC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAElD,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAEhC,+BAA+B;IAC/B,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,MAAM,UAAU,GAAwB,EAAE,CAAC;QAE3C,sCAAsC;QACtC,MAAM,UAAU,GAAG,kBAAkB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAE1D,0DAA0D;QAC1D,MAAM,cAAc,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,GAAG,CAAC,CAAC;QAE1E,uCAAuC;QACvC,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;YACjC,uEAAuE;YACvE,MAAM,YAAY,GAAG,UAAU,IAAI,GAAG,CAAC;YACvC,MAAM,SAAS,GAAsB;gBACnC,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,uDAAuD;gBACvD,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,4BAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,4BAAqB,CAAC,IAAI;aAC9E,CAAC;YACF,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleDocumentLinks = handleDocumentLinks;
|
|
4
|
-
const vscode_uri_1 = require("vscode-uri");
|
|
5
|
-
const path = require("path");
|
|
6
|
-
/**
|
|
7
|
-
* Handle document link requests for CSS documents.
|
|
8
|
-
* Returns clickable links for @import and url() references.
|
|
9
|
-
*/
|
|
10
|
-
function handleDocumentLinks(params, documents) {
|
|
11
|
-
const document = documents.get(params.textDocument.uri);
|
|
12
|
-
if (!document) {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
const text = document.getText();
|
|
16
|
-
const documentUri = vscode_uri_1.URI.parse(document.uri);
|
|
17
|
-
const documentDir = path.dirname(documentUri.fsPath);
|
|
18
|
-
const links = [];
|
|
19
|
-
// Match @import statements
|
|
20
|
-
// @import "path"; @import url("path"); @import url(path);
|
|
21
|
-
const importRegex = /@import\s+(?:url\s*\(\s*)?["']?([^"';\)\s]+)["']?\s*\)?/g;
|
|
22
|
-
let match;
|
|
23
|
-
while ((match = importRegex.exec(text)) !== null) {
|
|
24
|
-
const importPath = match[1];
|
|
25
|
-
if (!importPath ||
|
|
26
|
-
importPath.startsWith("http") ||
|
|
27
|
-
importPath.startsWith("//")) {
|
|
28
|
-
continue; // Skip external URLs
|
|
29
|
-
}
|
|
30
|
-
const startPos = document.positionAt(match.index + match[0].indexOf(importPath));
|
|
31
|
-
const endPos = document.positionAt(match.index + match[0].indexOf(importPath) + importPath.length);
|
|
32
|
-
const resolvedPath = path.resolve(documentDir, importPath);
|
|
33
|
-
const targetUri = vscode_uri_1.URI.file(resolvedPath).toString();
|
|
34
|
-
links.push({
|
|
35
|
-
range: { start: startPos, end: endPos },
|
|
36
|
-
target: targetUri,
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
// Match url() references in CSS properties
|
|
40
|
-
// background: url("image.png"); src: url(font.woff);
|
|
41
|
-
const urlRegex = /url\s*\(\s*["']?([^"'\)\s]+)["']?\s*\)/g;
|
|
42
|
-
while ((match = urlRegex.exec(text)) !== null) {
|
|
43
|
-
const urlPath = match[1];
|
|
44
|
-
if (!urlPath ||
|
|
45
|
-
urlPath.startsWith("http") ||
|
|
46
|
-
urlPath.startsWith("//") ||
|
|
47
|
-
urlPath.startsWith("data:")) {
|
|
48
|
-
continue; // Skip external URLs and data URIs
|
|
49
|
-
}
|
|
50
|
-
const startPos = document.positionAt(match.index + match[0].indexOf(urlPath));
|
|
51
|
-
const endPos = document.positionAt(match.index + match[0].indexOf(urlPath) + urlPath.length);
|
|
52
|
-
const resolvedPath = path.resolve(documentDir, urlPath);
|
|
53
|
-
const targetUri = vscode_uri_1.URI.file(resolvedPath).toString();
|
|
54
|
-
links.push({
|
|
55
|
-
range: { start: startPos, end: endPos },
|
|
56
|
-
target: targetUri,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
return links;
|
|
60
|
-
}
|
|
61
|
-
//# sourceMappingURL=documentLink.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentLink.js","sourceRoot":"","sources":["../../src/handlers/documentLink.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.setupDocumentSync = setupDocumentSync;
|
|
4
|
-
/**
|
|
5
|
-
* Document sync setup for CSS LSP.
|
|
6
|
-
* Note: In the current version, document save events are handled
|
|
7
|
-
* through the existing file watching mechanism.
|
|
8
|
-
*/
|
|
9
|
-
function setupDocumentSync(documents, cssVariableManager) {
|
|
10
|
-
// The TextDocuments manager already handles document changes
|
|
11
|
-
// Save events are handled through the existing file watching system
|
|
12
|
-
// in server.ts via connection.onDidChangeWatchedFiles
|
|
13
|
-
console.log("[css-lsp] Document sync setup complete");
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=documentSync.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentSync.js","sourceRoot":"","sources":["../../src/handlers/documentSync.ts"],"names":[],"mappings":";;AASA,8CASC;AAdD;;;;GAIG;AACH,SAAgB,iBAAiB,CAC/B,SAAsC,EACtC,kBAAsC;IAEtC,6DAA6D;IAC7D,oEAAoE;IACpE,sDAAsD;IAEtD,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;AACxD,CAAC"}
|