vscode-css-languageservice 5.4.2 → 6.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/CHANGELOG.md +7 -1
- package/SECURITY.md +41 -0
- package/lib/esm/beautify/beautify-css.js +11 -4
- package/lib/esm/cssLanguageService.d.ts +2 -1
- package/lib/esm/cssLanguageService.js +15 -17
- package/lib/esm/cssLanguageTypes.js +2 -2
- package/lib/esm/data/webCustomData.js +356 -232
- package/lib/esm/languageFacts/builtinData.js +15 -15
- package/lib/esm/languageFacts/colors.js +66 -69
- package/lib/esm/languageFacts/dataManager.js +38 -42
- package/lib/esm/languageFacts/dataProvider.js +17 -23
- package/lib/esm/languageFacts/entry.js +22 -23
- package/lib/esm/parser/cssErrors.js +5 -7
- package/lib/esm/parser/cssNodes.js +869 -1377
- package/lib/esm/parser/cssParser.js +419 -376
- package/lib/esm/parser/cssScanner.js +168 -175
- package/lib/esm/parser/cssSymbolScope.js +107 -137
- package/lib/esm/parser/lessParser.js +177 -202
- package/lib/esm/parser/lessScanner.js +22 -43
- package/lib/esm/parser/scssErrors.js +5 -7
- package/lib/esm/parser/scssParser.js +196 -208
- package/lib/esm/parser/scssScanner.js +33 -54
- package/lib/esm/services/cssCodeActions.js +36 -40
- package/lib/esm/services/cssCompletion.js +300 -395
- package/lib/esm/services/cssFolding.js +32 -35
- package/lib/esm/services/cssFormatter.js +22 -22
- package/lib/esm/services/cssHover.js +30 -33
- package/lib/esm/services/cssNavigation.js +260 -289
- package/lib/esm/services/cssSelectionRange.js +6 -6
- package/lib/esm/services/cssValidation.js +13 -16
- package/lib/esm/services/lessCompletion.js +351 -370
- package/lib/esm/services/lint.js +161 -175
- package/lib/esm/services/lintRules.js +20 -27
- package/lib/esm/services/lintUtil.js +19 -28
- package/lib/esm/services/pathCompletion.js +84 -158
- package/lib/esm/services/scssCompletion.js +283 -307
- package/lib/esm/services/scssNavigation.js +65 -137
- package/lib/esm/services/selectorPrinting.js +131 -175
- package/lib/esm/utils/arrays.js +6 -12
- package/lib/esm/utils/objects.js +1 -1
- package/lib/esm/utils/resources.js +3 -16
- package/lib/esm/utils/strings.js +10 -12
- package/lib/umd/beautify/beautify-css.js +11 -4
- package/lib/umd/cssLanguageService.d.ts +2 -1
- package/lib/umd/cssLanguageService.js +34 -32
- package/lib/umd/cssLanguageTypes.js +4 -3
- package/lib/umd/data/webCustomData.js +355 -231
- package/lib/umd/languageFacts/colors.js +65 -68
- package/lib/umd/languageFacts/dataManager.js +41 -44
- package/lib/umd/languageFacts/dataProvider.js +17 -22
- package/lib/umd/languageFacts/entry.js +22 -23
- package/lib/umd/languageFacts/facts.js +5 -1
- package/lib/umd/parser/cssErrors.js +5 -6
- package/lib/umd/parser/cssNodes.js +870 -1307
- package/lib/umd/parser/cssParser.js +424 -380
- package/lib/umd/parser/cssScanner.js +168 -173
- package/lib/umd/parser/cssSymbolScope.js +109 -134
- package/lib/umd/parser/lessParser.js +182 -206
- package/lib/umd/parser/lessScanner.js +22 -42
- package/lib/umd/parser/scssErrors.js +5 -6
- package/lib/umd/parser/scssParser.js +202 -213
- package/lib/umd/parser/scssScanner.js +25 -45
- package/lib/umd/services/cssCodeActions.js +41 -44
- package/lib/umd/services/cssCompletion.js +308 -402
- package/lib/umd/services/cssFolding.js +35 -38
- package/lib/umd/services/cssFormatter.js +25 -25
- package/lib/umd/services/cssHover.js +36 -38
- package/lib/umd/services/cssNavigation.js +267 -295
- package/lib/umd/services/cssSelectionRange.js +8 -8
- package/lib/umd/services/cssValidation.js +17 -19
- package/lib/umd/services/lessCompletion.js +354 -372
- package/lib/umd/services/lint.js +167 -180
- package/lib/umd/services/lintRules.js +20 -24
- package/lib/umd/services/lintUtil.js +20 -28
- package/lib/umd/services/pathCompletion.js +87 -160
- package/lib/umd/services/scssCompletion.js +287 -310
- package/lib/umd/services/scssNavigation.js +69 -140
- package/lib/umd/services/selectorPrinting.js +134 -174
- package/lib/umd/utils/arrays.js +6 -12
- package/lib/umd/utils/objects.js +1 -1
- package/lib/umd/utils/resources.js +4 -17
- package/lib/umd/utils/strings.js +10 -12
- package/package.json +16 -15
|
@@ -3,42 +3,6 @@
|
|
|
3
3
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
'use strict';
|
|
6
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
7
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
8
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
9
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
10
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
11
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
12
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13
|
-
});
|
|
14
|
-
};
|
|
15
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
16
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
17
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
18
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
19
|
-
function step(op) {
|
|
20
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
21
|
-
while (_) try {
|
|
22
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
23
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
24
|
-
switch (op[0]) {
|
|
25
|
-
case 0: case 1: t = op; break;
|
|
26
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
27
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
28
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
29
|
-
default:
|
|
30
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
31
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
32
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
33
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
34
|
-
if (t[2]) _.ops.pop();
|
|
35
|
-
_.trys.pop(); continue;
|
|
36
|
-
}
|
|
37
|
-
op = body.call(thisArg, _);
|
|
38
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
39
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
6
|
import { DocumentHighlightKind, Location, Range, SymbolKind, TextEdit, FileType } from '../cssLanguageTypes';
|
|
43
7
|
import * as nls from 'vscode-nls';
|
|
44
8
|
import * as nodes from '../parser/cssNodes';
|
|
@@ -46,22 +10,22 @@ import { Symbols } from '../parser/cssSymbolScope';
|
|
|
46
10
|
import { getColorValue, hslFromColor, hwbFromColor } from '../languageFacts/facts';
|
|
47
11
|
import { startsWith } from '../utils/strings';
|
|
48
12
|
import { dirname, joinPath } from '../utils/resources';
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
13
|
+
const localize = nls.loadMessageBundle();
|
|
14
|
+
const startsWithSchemeRegex = /^\w+:\/\//;
|
|
15
|
+
const startsWithData = /^data:/;
|
|
16
|
+
export class CSSNavigation {
|
|
17
|
+
constructor(fileSystemProvider, resolveModuleReferences) {
|
|
54
18
|
this.fileSystemProvider = fileSystemProvider;
|
|
55
19
|
this.resolveModuleReferences = resolveModuleReferences;
|
|
56
20
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
21
|
+
findDefinition(document, position, stylesheet) {
|
|
22
|
+
const symbols = new Symbols(stylesheet);
|
|
23
|
+
const offset = document.offsetAt(position);
|
|
24
|
+
const node = nodes.getNodeAtOffset(stylesheet, offset);
|
|
61
25
|
if (!node) {
|
|
62
26
|
return null;
|
|
63
27
|
}
|
|
64
|
-
|
|
28
|
+
const symbol = symbols.findSymbolFromNode(node);
|
|
65
29
|
if (!symbol) {
|
|
66
30
|
return null;
|
|
67
31
|
}
|
|
@@ -69,30 +33,30 @@ var CSSNavigation = /** @class */ (function () {
|
|
|
69
33
|
uri: document.uri,
|
|
70
34
|
range: getRange(symbol.node, document)
|
|
71
35
|
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return highlights.map(
|
|
36
|
+
}
|
|
37
|
+
findReferences(document, position, stylesheet) {
|
|
38
|
+
const highlights = this.findDocumentHighlights(document, position, stylesheet);
|
|
39
|
+
return highlights.map(h => {
|
|
76
40
|
return {
|
|
77
41
|
uri: document.uri,
|
|
78
42
|
range: h.range
|
|
79
43
|
};
|
|
80
44
|
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
45
|
+
}
|
|
46
|
+
findDocumentHighlights(document, position, stylesheet) {
|
|
47
|
+
const result = [];
|
|
48
|
+
const offset = document.offsetAt(position);
|
|
49
|
+
let node = nodes.getNodeAtOffset(stylesheet, offset);
|
|
86
50
|
if (!node || node.type === nodes.NodeType.Stylesheet || node.type === nodes.NodeType.Declarations) {
|
|
87
51
|
return result;
|
|
88
52
|
}
|
|
89
53
|
if (node.type === nodes.NodeType.Identifier && node.parent && node.parent.type === nodes.NodeType.ClassSelector) {
|
|
90
54
|
node = node.parent;
|
|
91
55
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
stylesheet.accept(
|
|
56
|
+
const symbols = new Symbols(stylesheet);
|
|
57
|
+
const symbol = symbols.findSymbolFromNode(node);
|
|
58
|
+
const name = node.getText();
|
|
59
|
+
stylesheet.accept(candidate => {
|
|
96
60
|
if (symbol) {
|
|
97
61
|
if (symbols.matchesSymbol(candidate, symbol)) {
|
|
98
62
|
result.push({
|
|
@@ -112,17 +76,16 @@ var CSSNavigation = /** @class */ (function () {
|
|
|
112
76
|
return true;
|
|
113
77
|
});
|
|
114
78
|
return result;
|
|
115
|
-
}
|
|
116
|
-
|
|
79
|
+
}
|
|
80
|
+
isRawStringDocumentLinkNode(node) {
|
|
117
81
|
return node.type === nodes.NodeType.Import;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
for (
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
var target = link.target;
|
|
82
|
+
}
|
|
83
|
+
findDocumentLinks(document, stylesheet, documentContext) {
|
|
84
|
+
const linkData = this.findUnresolvedLinks(document, stylesheet);
|
|
85
|
+
const resolvedLinks = [];
|
|
86
|
+
for (let data of linkData) {
|
|
87
|
+
const link = data.link;
|
|
88
|
+
const target = link.target;
|
|
126
89
|
if (!target || startsWithData.test(target)) {
|
|
127
90
|
// no links for data:
|
|
128
91
|
}
|
|
@@ -130,7 +93,7 @@ var CSSNavigation = /** @class */ (function () {
|
|
|
130
93
|
resolvedLinks.push(link);
|
|
131
94
|
}
|
|
132
95
|
else {
|
|
133
|
-
|
|
96
|
+
const resolved = documentContext.resolveReference(target, document.uri);
|
|
134
97
|
if (resolved) {
|
|
135
98
|
link.target = resolved;
|
|
136
99
|
}
|
|
@@ -138,63 +101,47 @@ var CSSNavigation = /** @class */ (function () {
|
|
|
138
101
|
}
|
|
139
102
|
}
|
|
140
103
|
return resolvedLinks;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
case 2:
|
|
160
|
-
if (!startsWithSchemeRegex.test(target)) return [3 /*break*/, 3];
|
|
161
|
-
resolvedLinks.push(link);
|
|
162
|
-
return [3 /*break*/, 5];
|
|
163
|
-
case 3: return [4 /*yield*/, this.resolveRelativeReference(target, document.uri, documentContext, data.isRawLink)];
|
|
164
|
-
case 4:
|
|
165
|
-
resolvedTarget = _a.sent();
|
|
166
|
-
if (resolvedTarget !== undefined) {
|
|
167
|
-
link.target = resolvedTarget;
|
|
168
|
-
resolvedLinks.push(link);
|
|
169
|
-
}
|
|
170
|
-
_a.label = 5;
|
|
171
|
-
case 5:
|
|
172
|
-
_i++;
|
|
173
|
-
return [3 /*break*/, 1];
|
|
174
|
-
case 6: return [2 /*return*/, resolvedLinks];
|
|
104
|
+
}
|
|
105
|
+
async findDocumentLinks2(document, stylesheet, documentContext) {
|
|
106
|
+
const linkData = this.findUnresolvedLinks(document, stylesheet);
|
|
107
|
+
const resolvedLinks = [];
|
|
108
|
+
for (let data of linkData) {
|
|
109
|
+
const link = data.link;
|
|
110
|
+
const target = link.target;
|
|
111
|
+
if (!target || startsWithData.test(target)) {
|
|
112
|
+
// no links for data:
|
|
113
|
+
}
|
|
114
|
+
else if (startsWithSchemeRegex.test(target)) {
|
|
115
|
+
resolvedLinks.push(link);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const resolvedTarget = await this.resolveRelativeReference(target, document.uri, documentContext, data.isRawLink);
|
|
119
|
+
if (resolvedTarget !== undefined) {
|
|
120
|
+
link.target = resolvedTarget;
|
|
121
|
+
resolvedLinks.push(link);
|
|
175
122
|
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return resolvedLinks;
|
|
126
|
+
}
|
|
127
|
+
findUnresolvedLinks(document, stylesheet) {
|
|
128
|
+
const result = [];
|
|
129
|
+
const collect = (uriStringNode) => {
|
|
130
|
+
let rawUri = uriStringNode.getText();
|
|
131
|
+
const range = getRange(uriStringNode, document);
|
|
185
132
|
// Make sure the range is not empty
|
|
186
133
|
if (range.start.line === range.end.line && range.start.character === range.end.character) {
|
|
187
134
|
return;
|
|
188
135
|
}
|
|
189
|
-
if (startsWith(rawUri,
|
|
136
|
+
if (startsWith(rawUri, `'`) || startsWith(rawUri, `"`)) {
|
|
190
137
|
rawUri = rawUri.slice(1, -1);
|
|
191
138
|
}
|
|
192
|
-
|
|
193
|
-
result.push({ link: { target: rawUri, range
|
|
139
|
+
const isRawLink = uriStringNode.parent ? this.isRawStringDocumentLinkNode(uriStringNode.parent) : false;
|
|
140
|
+
result.push({ link: { target: rawUri, range }, isRawLink });
|
|
194
141
|
};
|
|
195
|
-
stylesheet.accept(
|
|
142
|
+
stylesheet.accept(candidate => {
|
|
196
143
|
if (candidate.type === nodes.NodeType.URILiteral) {
|
|
197
|
-
|
|
144
|
+
const first = candidate.getChild(0);
|
|
198
145
|
if (first) {
|
|
199
146
|
collect(first);
|
|
200
147
|
}
|
|
@@ -204,9 +151,9 @@ var CSSNavigation = /** @class */ (function () {
|
|
|
204
151
|
* In @import, it is possible to include links that do not use `url()`
|
|
205
152
|
* For example, `@import 'foo.css';`
|
|
206
153
|
*/
|
|
207
|
-
if (candidate.parent &&
|
|
208
|
-
|
|
209
|
-
if (startsWith(rawText,
|
|
154
|
+
if (candidate.parent && this.isRawStringDocumentLinkNode(candidate.parent)) {
|
|
155
|
+
const rawText = candidate.getText();
|
|
156
|
+
if (startsWith(rawText, `'`) || startsWith(rawText, `"`)) {
|
|
210
157
|
collect(candidate);
|
|
211
158
|
}
|
|
212
159
|
return false;
|
|
@@ -214,226 +161,241 @@ var CSSNavigation = /** @class */ (function () {
|
|
|
214
161
|
return true;
|
|
215
162
|
});
|
|
216
163
|
return result;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
164
|
+
}
|
|
165
|
+
findSymbolInformations(document, stylesheet) {
|
|
166
|
+
const result = [];
|
|
167
|
+
const addSymbolInformation = (name, kind, symbolNodeOrRange) => {
|
|
168
|
+
const range = symbolNodeOrRange instanceof nodes.Node ? getRange(symbolNodeOrRange, document) : symbolNodeOrRange;
|
|
169
|
+
const entry = {
|
|
170
|
+
name,
|
|
171
|
+
kind,
|
|
172
|
+
location: Location.create(document.uri, range)
|
|
225
173
|
};
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
174
|
+
result.push(entry);
|
|
175
|
+
};
|
|
176
|
+
this.collectDocumentSymbols(document, stylesheet, addSymbolInformation);
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
findDocumentSymbols(document, stylesheet) {
|
|
180
|
+
const result = [];
|
|
181
|
+
const parents = [];
|
|
182
|
+
const addDocumentSymbol = (name, kind, symbolNodeOrRange, nameNodeOrRange, bodyNode) => {
|
|
183
|
+
const range = symbolNodeOrRange instanceof nodes.Node ? getRange(symbolNodeOrRange, document) : symbolNodeOrRange;
|
|
184
|
+
const selectionRange = (nameNodeOrRange instanceof nodes.Node ? getRange(nameNodeOrRange, document) : nameNodeOrRange) ?? Range.create(range.start, range.start);
|
|
185
|
+
const entry = {
|
|
186
|
+
name,
|
|
187
|
+
kind,
|
|
188
|
+
range,
|
|
189
|
+
selectionRange
|
|
190
|
+
};
|
|
191
|
+
let top = parents.pop();
|
|
192
|
+
while (top && !containsRange(top[1], range)) {
|
|
193
|
+
top = parents.pop();
|
|
194
|
+
}
|
|
195
|
+
if (top) {
|
|
196
|
+
const topSymbol = top[0];
|
|
197
|
+
if (!topSymbol.children) {
|
|
198
|
+
topSymbol.children = [];
|
|
199
|
+
}
|
|
200
|
+
topSymbol.children.push(entry);
|
|
201
|
+
parents.push(top); // put back top
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
result.push(entry);
|
|
205
|
+
}
|
|
206
|
+
if (bodyNode) {
|
|
207
|
+
parents.push([entry, getRange(bodyNode, document)]);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
this.collectDocumentSymbols(document, stylesheet, addDocumentSymbol);
|
|
211
|
+
return result;
|
|
212
|
+
}
|
|
213
|
+
collectDocumentSymbols(document, stylesheet, collect) {
|
|
214
|
+
stylesheet.accept(node => {
|
|
215
|
+
if (node instanceof nodes.RuleSet) {
|
|
216
|
+
for (const selector of node.getSelectors().getChildren()) {
|
|
217
|
+
if (selector instanceof nodes.Selector) {
|
|
218
|
+
const range = Range.create(document.positionAt(selector.offset), document.positionAt(node.end));
|
|
219
|
+
collect(selector.getText(), SymbolKind.Class, range, selector, node.getDeclarations());
|
|
220
|
+
}
|
|
233
221
|
}
|
|
234
|
-
return false;
|
|
235
222
|
}
|
|
236
223
|
else if (node instanceof nodes.VariableDeclaration) {
|
|
237
|
-
|
|
238
|
-
entry.kind = SymbolKind.Variable;
|
|
224
|
+
collect(node.getName(), SymbolKind.Variable, node, node.getVariable(), undefined);
|
|
239
225
|
}
|
|
240
226
|
else if (node instanceof nodes.MixinDeclaration) {
|
|
241
|
-
|
|
242
|
-
entry.kind = SymbolKind.Method;
|
|
227
|
+
collect(node.getName(), SymbolKind.Method, node, node.getIdentifier(), node.getDeclarations());
|
|
243
228
|
}
|
|
244
229
|
else if (node instanceof nodes.FunctionDeclaration) {
|
|
245
|
-
|
|
246
|
-
entry.kind = SymbolKind.Function;
|
|
230
|
+
collect(node.getName(), SymbolKind.Function, node, node.getIdentifier(), node.getDeclarations());
|
|
247
231
|
}
|
|
248
232
|
else if (node instanceof nodes.Keyframe) {
|
|
249
|
-
|
|
233
|
+
const name = localize('literal.keyframes', "@keyframes {0}", node.getName());
|
|
234
|
+
collect(name, SymbolKind.Class, node, node.getIdentifier(), node.getDeclarations());
|
|
250
235
|
}
|
|
251
236
|
else if (node instanceof nodes.FontFace) {
|
|
252
|
-
|
|
237
|
+
const name = localize('literal.fontface', "@font-face");
|
|
238
|
+
collect(name, SymbolKind.Class, node, undefined, node.getDeclarations());
|
|
253
239
|
}
|
|
254
240
|
else if (node instanceof nodes.Media) {
|
|
255
|
-
|
|
241
|
+
const mediaList = node.getChild(0);
|
|
256
242
|
if (mediaList instanceof nodes.Medialist) {
|
|
257
|
-
|
|
258
|
-
|
|
243
|
+
const name = '@media ' + mediaList.getText();
|
|
244
|
+
collect(name, SymbolKind.Module, node, mediaList, node.getDeclarations());
|
|
259
245
|
}
|
|
260
246
|
}
|
|
261
|
-
if (entry.name) {
|
|
262
|
-
entry.location = Location.create(document.uri, getRange(locationNode, document));
|
|
263
|
-
result.push(entry);
|
|
264
|
-
}
|
|
265
247
|
return true;
|
|
266
248
|
});
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
var colorInfo = getColorInformation(node, document);
|
|
249
|
+
}
|
|
250
|
+
findDocumentColors(document, stylesheet) {
|
|
251
|
+
const result = [];
|
|
252
|
+
stylesheet.accept((node) => {
|
|
253
|
+
const colorInfo = getColorInformation(node, document);
|
|
273
254
|
if (colorInfo) {
|
|
274
255
|
result.push(colorInfo);
|
|
275
256
|
}
|
|
276
257
|
return true;
|
|
277
258
|
});
|
|
278
259
|
return result;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
260
|
+
}
|
|
261
|
+
getColorPresentations(document, stylesheet, color, range) {
|
|
262
|
+
const result = [];
|
|
263
|
+
const red256 = Math.round(color.red * 255), green256 = Math.round(color.green * 255), blue256 = Math.round(color.blue * 255);
|
|
264
|
+
let label;
|
|
284
265
|
if (color.alpha === 1) {
|
|
285
|
-
label =
|
|
266
|
+
label = `rgb(${red256}, ${green256}, ${blue256})`;
|
|
286
267
|
}
|
|
287
268
|
else {
|
|
288
|
-
label =
|
|
269
|
+
label = `rgba(${red256}, ${green256}, ${blue256}, ${color.alpha})`;
|
|
289
270
|
}
|
|
290
271
|
result.push({ label: label, textEdit: TextEdit.replace(range, label) });
|
|
291
272
|
if (color.alpha === 1) {
|
|
292
|
-
label =
|
|
273
|
+
label = `#${toTwoDigitHex(red256)}${toTwoDigitHex(green256)}${toTwoDigitHex(blue256)}`;
|
|
293
274
|
}
|
|
294
275
|
else {
|
|
295
|
-
label =
|
|
276
|
+
label = `#${toTwoDigitHex(red256)}${toTwoDigitHex(green256)}${toTwoDigitHex(blue256)}${toTwoDigitHex(Math.round(color.alpha * 255))}`;
|
|
296
277
|
}
|
|
297
278
|
result.push({ label: label, textEdit: TextEdit.replace(range, label) });
|
|
298
|
-
|
|
279
|
+
const hsl = hslFromColor(color);
|
|
299
280
|
if (hsl.a === 1) {
|
|
300
|
-
label =
|
|
281
|
+
label = `hsl(${hsl.h}, ${Math.round(hsl.s * 100)}%, ${Math.round(hsl.l * 100)}%)`;
|
|
301
282
|
}
|
|
302
283
|
else {
|
|
303
|
-
label =
|
|
284
|
+
label = `hsla(${hsl.h}, ${Math.round(hsl.s * 100)}%, ${Math.round(hsl.l * 100)}%, ${hsl.a})`;
|
|
304
285
|
}
|
|
305
286
|
result.push({ label: label, textEdit: TextEdit.replace(range, label) });
|
|
306
|
-
|
|
287
|
+
const hwb = hwbFromColor(color);
|
|
307
288
|
if (hwb.a === 1) {
|
|
308
|
-
label =
|
|
289
|
+
label = `hwb(${hwb.h} ${Math.round(hwb.w * 100)}% ${Math.round(hwb.b * 100)}%)`;
|
|
309
290
|
}
|
|
310
291
|
else {
|
|
311
|
-
label =
|
|
292
|
+
label = `hwb(${hwb.h} ${Math.round(hwb.w * 100)}% ${Math.round(hwb.b * 100)}% / ${hwb.a})`;
|
|
312
293
|
}
|
|
313
294
|
result.push({ label: label, textEdit: TextEdit.replace(range, label) });
|
|
314
295
|
return result;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
var edits = highlights.map(function (h) { return TextEdit.replace(h.range, newName); });
|
|
296
|
+
}
|
|
297
|
+
doRename(document, position, newName, stylesheet) {
|
|
298
|
+
const highlights = this.findDocumentHighlights(document, position, stylesheet);
|
|
299
|
+
const edits = highlights.map(h => TextEdit.replace(h.range, newName));
|
|
320
300
|
return {
|
|
321
|
-
changes:
|
|
301
|
+
changes: { [document.uri]: edits }
|
|
322
302
|
};
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
else if (rootFolderUri && documentFolderUri.startsWith(rootFolderUri) && (documentFolderUri.length !== rootFolderUri.length)) {
|
|
389
|
-
return [2 /*return*/, this.resolvePathToModule(_moduleName, dirname(documentFolderUri), rootFolderUri)];
|
|
390
|
-
}
|
|
391
|
-
return [2 /*return*/, undefined];
|
|
392
|
-
}
|
|
393
|
-
});
|
|
394
|
-
});
|
|
395
|
-
};
|
|
396
|
-
CSSNavigation.prototype.fileExists = function (uri) {
|
|
397
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
398
|
-
var stat, err_1;
|
|
399
|
-
return __generator(this, function (_a) {
|
|
400
|
-
switch (_a.label) {
|
|
401
|
-
case 0:
|
|
402
|
-
if (!this.fileSystemProvider) {
|
|
403
|
-
return [2 /*return*/, false];
|
|
404
|
-
}
|
|
405
|
-
_a.label = 1;
|
|
406
|
-
case 1:
|
|
407
|
-
_a.trys.push([1, 3, , 4]);
|
|
408
|
-
return [4 /*yield*/, this.fileSystemProvider.stat(uri)];
|
|
409
|
-
case 2:
|
|
410
|
-
stat = _a.sent();
|
|
411
|
-
if (stat.type === FileType.Unknown && stat.size === -1) {
|
|
412
|
-
return [2 /*return*/, false];
|
|
413
|
-
}
|
|
414
|
-
return [2 /*return*/, true];
|
|
415
|
-
case 3:
|
|
416
|
-
err_1 = _a.sent();
|
|
417
|
-
return [2 /*return*/, false];
|
|
418
|
-
case 4: return [2 /*return*/];
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
|
-
});
|
|
422
|
-
};
|
|
423
|
-
return CSSNavigation;
|
|
424
|
-
}());
|
|
425
|
-
export { CSSNavigation };
|
|
303
|
+
}
|
|
304
|
+
async resolveModuleReference(ref, documentUri, documentContext) {
|
|
305
|
+
if (startsWith(documentUri, 'file://')) {
|
|
306
|
+
const moduleName = getModuleNameFromPath(ref);
|
|
307
|
+
const rootFolderUri = documentContext.resolveReference('/', documentUri);
|
|
308
|
+
const documentFolderUri = dirname(documentUri);
|
|
309
|
+
const modulePath = await this.resolvePathToModule(moduleName, documentFolderUri, rootFolderUri);
|
|
310
|
+
if (modulePath) {
|
|
311
|
+
const pathWithinModule = ref.substring(moduleName.length + 1);
|
|
312
|
+
return joinPath(modulePath, pathWithinModule);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return undefined;
|
|
316
|
+
}
|
|
317
|
+
async resolveRelativeReference(ref, documentUri, documentContext, isRawLink) {
|
|
318
|
+
const relativeReference = documentContext.resolveReference(ref, documentUri);
|
|
319
|
+
// Following [css-loader](https://github.com/webpack-contrib/css-loader#url)
|
|
320
|
+
// and [sass-loader's](https://github.com/webpack-contrib/sass-loader#imports)
|
|
321
|
+
// convention, if an import path starts with ~ then use node module resolution
|
|
322
|
+
// *unless* it starts with "~/" as this refers to the user's home directory.
|
|
323
|
+
if (ref[0] === '~' && ref[1] !== '/' && this.fileSystemProvider) {
|
|
324
|
+
ref = ref.substring(1);
|
|
325
|
+
return await this.resolveModuleReference(ref, documentUri, documentContext) || relativeReference;
|
|
326
|
+
}
|
|
327
|
+
// Following [less-loader](https://github.com/webpack-contrib/less-loader#imports)
|
|
328
|
+
// and [sass-loader's](https://github.com/webpack-contrib/sass-loader#resolving-import-at-rules)
|
|
329
|
+
// new resolving import at-rules (~ is deprecated). The loader will first try to resolve @import as a relative path. If it cannot be resolved,
|
|
330
|
+
// then the loader will try to resolve @import inside node_modules.
|
|
331
|
+
if (this.resolveModuleReferences) {
|
|
332
|
+
if (relativeReference && await this.fileExists(relativeReference)) {
|
|
333
|
+
return relativeReference;
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
return await this.resolveModuleReference(ref, documentUri, documentContext) || relativeReference;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return relativeReference;
|
|
340
|
+
}
|
|
341
|
+
async resolvePathToModule(_moduleName, documentFolderUri, rootFolderUri) {
|
|
342
|
+
// resolve the module relative to the document. We can't use `require` here as the code is webpacked.
|
|
343
|
+
const packPath = joinPath(documentFolderUri, 'node_modules', _moduleName, 'package.json');
|
|
344
|
+
if (await this.fileExists(packPath)) {
|
|
345
|
+
return dirname(packPath);
|
|
346
|
+
}
|
|
347
|
+
else if (rootFolderUri && documentFolderUri.startsWith(rootFolderUri) && (documentFolderUri.length !== rootFolderUri.length)) {
|
|
348
|
+
return this.resolvePathToModule(_moduleName, dirname(documentFolderUri), rootFolderUri);
|
|
349
|
+
}
|
|
350
|
+
return undefined;
|
|
351
|
+
}
|
|
352
|
+
async fileExists(uri) {
|
|
353
|
+
if (!this.fileSystemProvider) {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
try {
|
|
357
|
+
const stat = await this.fileSystemProvider.stat(uri);
|
|
358
|
+
if (stat.type === FileType.Unknown && stat.size === -1) {
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
catch (err) {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
426
368
|
function getColorInformation(node, document) {
|
|
427
|
-
|
|
369
|
+
const color = getColorValue(node);
|
|
428
370
|
if (color) {
|
|
429
|
-
|
|
430
|
-
return { color
|
|
371
|
+
const range = getRange(node, document);
|
|
372
|
+
return { color, range };
|
|
431
373
|
}
|
|
432
374
|
return null;
|
|
433
375
|
}
|
|
434
376
|
function getRange(node, document) {
|
|
435
377
|
return Range.create(document.positionAt(node.offset), document.positionAt(node.end));
|
|
436
378
|
}
|
|
379
|
+
/**
|
|
380
|
+
* Test if `otherRange` is in `range`. If the ranges are equal, will return true.
|
|
381
|
+
*/
|
|
382
|
+
function containsRange(range, otherRange) {
|
|
383
|
+
const otherStartLine = otherRange.start.line, otherEndLine = otherRange.end.line;
|
|
384
|
+
const rangeStartLine = range.start.line, rangeEndLine = range.end.line;
|
|
385
|
+
if (otherStartLine < rangeStartLine || otherEndLine < rangeStartLine) {
|
|
386
|
+
return false;
|
|
387
|
+
}
|
|
388
|
+
if (otherStartLine > rangeEndLine || otherEndLine > rangeEndLine) {
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
if (otherStartLine === rangeStartLine && otherRange.start.character < range.start.character) {
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
394
|
+
if (otherEndLine === rangeEndLine && otherRange.end.character > range.end.character) {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
437
399
|
function getHighlightKind(node) {
|
|
438
400
|
if (node.type === nodes.NodeType.Selector) {
|
|
439
401
|
return DocumentHighlightKind.Write;
|
|
@@ -458,13 +420,22 @@ function getHighlightKind(node) {
|
|
|
458
420
|
return DocumentHighlightKind.Read;
|
|
459
421
|
}
|
|
460
422
|
function toTwoDigitHex(n) {
|
|
461
|
-
|
|
423
|
+
const r = n.toString(16);
|
|
462
424
|
return r.length !== 2 ? '0' + r : r;
|
|
463
425
|
}
|
|
464
426
|
function getModuleNameFromPath(path) {
|
|
465
|
-
|
|
427
|
+
const firstSlash = path.indexOf('/');
|
|
428
|
+
if (firstSlash === -1) {
|
|
429
|
+
return '';
|
|
430
|
+
}
|
|
431
|
+
// If a scoped module (starts with @) then get up until second instance of '/', or to the end of the string for root-level imports.
|
|
466
432
|
if (path[0] === '@') {
|
|
467
|
-
|
|
433
|
+
const secondSlash = path.indexOf('/', firstSlash + 1);
|
|
434
|
+
if (secondSlash === -1) {
|
|
435
|
+
return path;
|
|
436
|
+
}
|
|
437
|
+
return path.substring(0, secondSlash);
|
|
468
438
|
}
|
|
469
|
-
|
|
439
|
+
// Otherwise get until first instance of '/'
|
|
440
|
+
return path.substring(0, firstSlash);
|
|
470
441
|
}
|