vscode-css-languageservice 6.3.10 → 7.0.0-next.1
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 +8 -0
- package/lib/esm/beautify/beautify-css.js +1437 -1606
- package/lib/esm/cssLanguageService.d.ts +2 -2
- package/lib/esm/cssLanguageService.js +18 -18
- package/lib/esm/languageFacts/colors.js +1 -1
- package/lib/esm/languageFacts/dataManager.js +3 -3
- package/lib/esm/languageFacts/entry.js +1 -1
- package/lib/esm/languageFacts/facts.js +3 -3
- package/lib/esm/parser/cssNodes.js +1 -1
- package/lib/esm/parser/cssParser.js +5 -5
- package/lib/esm/parser/cssSymbolScope.js +2 -2
- package/lib/esm/parser/lessParser.js +5 -5
- package/lib/esm/parser/lessScanner.js +1 -1
- package/lib/esm/parser/scssParser.js +6 -6
- package/lib/esm/parser/scssScanner.js +1 -1
- package/lib/esm/services/cssCodeActions.js +4 -4
- package/lib/esm/services/cssCompletion.js +7 -7
- package/lib/esm/services/cssFolding.js +3 -3
- package/lib/esm/services/cssFormatter.js +3 -3
- package/lib/esm/services/cssHover.js +6 -6
- package/lib/esm/services/cssNavigation.js +6 -6
- package/lib/esm/services/cssSelectionRange.js +2 -2
- package/lib/esm/services/cssValidation.js +4 -4
- package/lib/esm/services/lessCompletion.js +2 -2
- package/lib/esm/services/lint.js +5 -5
- package/lib/esm/services/lintRules.js +1 -1
- package/lib/esm/services/lintUtil.js +1 -1
- package/lib/esm/services/pathCompletion.js +3 -3
- package/lib/esm/services/scssCompletion.js +3 -3
- package/lib/esm/services/scssNavigation.js +4 -4
- package/lib/esm/services/selectorPrinting.js +3 -3
- package/package.json +15 -15
- package/lib/umd/beautify/beautify-css.js +0 -1695
- package/lib/umd/cssLanguageService.d.ts +0 -39
- package/lib/umd/cssLanguageService.js +0 -105
- package/lib/umd/cssLanguageTypes.d.ts +0 -267
- package/lib/umd/cssLanguageTypes.js +0 -89
- package/lib/umd/data/webCustomData.js +0 -44613
- package/lib/umd/languageFacts/builtinData.js +0 -155
- package/lib/umd/languageFacts/colors.js +0 -949
- package/lib/umd/languageFacts/dataManager.js +0 -101
- package/lib/umd/languageFacts/dataProvider.js +0 -86
- package/lib/umd/languageFacts/entry.js +0 -217
- package/lib/umd/languageFacts/facts.js +0 -33
- package/lib/umd/parser/cssErrors.js +0 -61
- package/lib/umd/parser/cssNodes.js +0 -1676
- package/lib/umd/parser/cssParser.js +0 -2035
- package/lib/umd/parser/cssScanner.js +0 -619
- package/lib/umd/parser/cssSymbolScope.js +0 -328
- package/lib/umd/parser/lessParser.js +0 -732
- package/lib/umd/parser/lessScanner.js +0 -70
- package/lib/umd/parser/scssErrors.js +0 -30
- package/lib/umd/parser/scssParser.js +0 -874
- package/lib/umd/parser/scssScanner.js +0 -108
- package/lib/umd/services/cssCodeActions.js +0 -89
- package/lib/umd/services/cssCompletion.js +0 -1109
- package/lib/umd/services/cssFolding.js +0 -202
- package/lib/umd/services/cssFormatter.js +0 -149
- package/lib/umd/services/cssHover.js +0 -174
- package/lib/umd/services/cssNavigation.js +0 -539
- package/lib/umd/services/cssSelectionRange.js +0 -59
- package/lib/umd/services/cssValidation.js +0 -54
- package/lib/umd/services/lessCompletion.js +0 -390
- package/lib/umd/services/lint.js +0 -577
- package/lib/umd/services/lintRules.js +0 -90
- package/lib/umd/services/lintUtil.js +0 -210
- package/lib/umd/services/pathCompletion.js +0 -171
- package/lib/umd/services/scssCompletion.js +0 -367
- package/lib/umd/services/scssNavigation.js +0 -169
- package/lib/umd/services/selectorPrinting.js +0 -575
- package/lib/umd/utils/arrays.js +0 -54
- package/lib/umd/utils/objects.js +0 -24
- package/lib/umd/utils/resources.js +0 -25
- package/lib/umd/utils/strings.js +0 -123
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
(function (factory) {
|
|
2
|
-
if (typeof module === "object" && typeof module.exports === "object") {
|
|
3
|
-
var v = factory(require, exports);
|
|
4
|
-
if (v !== undefined) module.exports = v;
|
|
5
|
-
}
|
|
6
|
-
else if (typeof define === "function" && define.amd) {
|
|
7
|
-
define(["require", "exports", "../parser/cssNodes", "@vscode/l10n"], factory);
|
|
8
|
-
}
|
|
9
|
-
})(function (require, exports) {
|
|
10
|
-
/*---------------------------------------------------------------------------------------------
|
|
11
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
12
|
-
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
13
|
-
*--------------------------------------------------------------------------------------------*/
|
|
14
|
-
'use strict';
|
|
15
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.LintConfigurationSettings = exports.Settings = exports.Rules = exports.Setting = exports.Rule = void 0;
|
|
17
|
-
const nodes = require("../parser/cssNodes");
|
|
18
|
-
const l10n = require("@vscode/l10n");
|
|
19
|
-
const Warning = nodes.Level.Warning;
|
|
20
|
-
const Error = nodes.Level.Error;
|
|
21
|
-
const Ignore = nodes.Level.Ignore;
|
|
22
|
-
class Rule {
|
|
23
|
-
constructor(id, message, defaultValue) {
|
|
24
|
-
this.id = id;
|
|
25
|
-
this.message = message;
|
|
26
|
-
this.defaultValue = defaultValue;
|
|
27
|
-
// nothing to do
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
exports.Rule = Rule;
|
|
31
|
-
class Setting {
|
|
32
|
-
constructor(id, message, defaultValue) {
|
|
33
|
-
this.id = id;
|
|
34
|
-
this.message = message;
|
|
35
|
-
this.defaultValue = defaultValue;
|
|
36
|
-
// nothing to do
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
exports.Setting = Setting;
|
|
40
|
-
exports.Rules = {
|
|
41
|
-
AllVendorPrefixes: new Rule('compatibleVendorPrefixes', l10n.t("When using a vendor-specific prefix make sure to also include all other vendor-specific properties"), Ignore),
|
|
42
|
-
IncludeStandardPropertyWhenUsingVendorPrefix: new Rule('vendorPrefix', l10n.t("When using a vendor-specific prefix also include the standard property"), Warning),
|
|
43
|
-
DuplicateDeclarations: new Rule('duplicateProperties', l10n.t("Do not use duplicate style definitions"), Ignore),
|
|
44
|
-
EmptyRuleSet: new Rule('emptyRules', l10n.t("Do not use empty rulesets"), Warning),
|
|
45
|
-
ImportStatemement: new Rule('importStatement', l10n.t("Import statements do not load in parallel"), Ignore),
|
|
46
|
-
BewareOfBoxModelSize: new Rule('boxModel', l10n.t("Do not use width or height when using padding or border"), Ignore),
|
|
47
|
-
UniversalSelector: new Rule('universalSelector', l10n.t("The universal selector (*) is known to be slow"), Ignore),
|
|
48
|
-
ZeroWithUnit: new Rule('zeroUnits', l10n.t("No unit for zero needed"), Ignore),
|
|
49
|
-
RequiredPropertiesForFontFace: new Rule('fontFaceProperties', l10n.t("@font-face rule must define 'src' and 'font-family' properties"), Warning),
|
|
50
|
-
HexColorLength: new Rule('hexColorLength', l10n.t("Hex colors must consist of three, four, six or eight hex numbers"), Error),
|
|
51
|
-
ArgsInColorFunction: new Rule('argumentsInColorFunction', l10n.t("Invalid number of parameters"), Error),
|
|
52
|
-
UnknownProperty: new Rule('unknownProperties', l10n.t("Unknown property."), Warning),
|
|
53
|
-
UnknownAtRules: new Rule('unknownAtRules', l10n.t("Unknown at-rule."), Warning),
|
|
54
|
-
IEStarHack: new Rule('ieHack', l10n.t("IE hacks are only necessary when supporting IE7 and older"), Ignore),
|
|
55
|
-
UnknownVendorSpecificProperty: new Rule('unknownVendorSpecificProperties', l10n.t("Unknown vendor specific property."), Ignore),
|
|
56
|
-
PropertyIgnoredDueToDisplay: new Rule('propertyIgnoredDueToDisplay', l10n.t("Property is ignored due to the display."), Warning),
|
|
57
|
-
AvoidImportant: new Rule('important', l10n.t("Avoid using !important. It is an indication that the specificity of the entire CSS has gotten out of control and needs to be refactored."), Ignore),
|
|
58
|
-
AvoidFloat: new Rule('float', l10n.t("Avoid using 'float'. Floats lead to fragile CSS that is easy to break if one aspect of the layout changes."), Ignore),
|
|
59
|
-
AvoidIdSelector: new Rule('idSelector', l10n.t("Selectors should not contain IDs because these rules are too tightly coupled with the HTML."), Ignore),
|
|
60
|
-
};
|
|
61
|
-
exports.Settings = {
|
|
62
|
-
ValidProperties: new Setting('validProperties', l10n.t("A list of properties that are not validated against the `unknownProperties` rule."), [])
|
|
63
|
-
};
|
|
64
|
-
class LintConfigurationSettings {
|
|
65
|
-
constructor(conf = {}) {
|
|
66
|
-
this.conf = conf;
|
|
67
|
-
}
|
|
68
|
-
getRule(rule) {
|
|
69
|
-
if (this.conf.hasOwnProperty(rule.id)) {
|
|
70
|
-
const level = toLevel(this.conf[rule.id]);
|
|
71
|
-
if (level) {
|
|
72
|
-
return level;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return rule.defaultValue;
|
|
76
|
-
}
|
|
77
|
-
getSetting(setting) {
|
|
78
|
-
return this.conf[setting.id];
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
exports.LintConfigurationSettings = LintConfigurationSettings;
|
|
82
|
-
function toLevel(level) {
|
|
83
|
-
switch (level) {
|
|
84
|
-
case 'ignore': return nodes.Level.Ignore;
|
|
85
|
-
case 'warning': return nodes.Level.Warning;
|
|
86
|
-
case 'error': return nodes.Level.Error;
|
|
87
|
-
}
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
});
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
(function (factory) {
|
|
2
|
-
if (typeof module === "object" && typeof module.exports === "object") {
|
|
3
|
-
var v = factory(require, exports);
|
|
4
|
-
if (v !== undefined) module.exports = v;
|
|
5
|
-
}
|
|
6
|
-
else if (typeof define === "function" && define.amd) {
|
|
7
|
-
define(["require", "exports", "../utils/arrays"], factory);
|
|
8
|
-
}
|
|
9
|
-
})(function (require, exports) {
|
|
10
|
-
/*---------------------------------------------------------------------------------------------
|
|
11
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
12
|
-
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
13
|
-
*--------------------------------------------------------------------------------------------*/
|
|
14
|
-
'use strict';
|
|
15
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.Element = void 0;
|
|
17
|
-
exports.default = calculateBoxModel;
|
|
18
|
-
const arrays_1 = require("../utils/arrays");
|
|
19
|
-
class Element {
|
|
20
|
-
constructor(decl) {
|
|
21
|
-
this.fullPropertyName = decl.getFullPropertyName().toLowerCase();
|
|
22
|
-
this.node = decl;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
exports.Element = Element;
|
|
26
|
-
function setSide(model, side, value, property) {
|
|
27
|
-
const state = model[side];
|
|
28
|
-
state.value = value;
|
|
29
|
-
if (value) {
|
|
30
|
-
if (!(0, arrays_1.includes)(state.properties, property)) {
|
|
31
|
-
state.properties.push(property);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
function setAllSides(model, value, property) {
|
|
36
|
-
setSide(model, 'top', value, property);
|
|
37
|
-
setSide(model, 'right', value, property);
|
|
38
|
-
setSide(model, 'bottom', value, property);
|
|
39
|
-
setSide(model, 'left', value, property);
|
|
40
|
-
}
|
|
41
|
-
function updateModelWithValue(model, side, value, property) {
|
|
42
|
-
if (side === 'top' || side === 'right' ||
|
|
43
|
-
side === 'bottom' || side === 'left') {
|
|
44
|
-
setSide(model, side, value, property);
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
setAllSides(model, value, property);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
function updateModelWithList(model, values, property) {
|
|
51
|
-
switch (values.length) {
|
|
52
|
-
case 1:
|
|
53
|
-
updateModelWithValue(model, undefined, values[0], property);
|
|
54
|
-
break;
|
|
55
|
-
case 2:
|
|
56
|
-
updateModelWithValue(model, 'top', values[0], property);
|
|
57
|
-
updateModelWithValue(model, 'bottom', values[0], property);
|
|
58
|
-
updateModelWithValue(model, 'right', values[1], property);
|
|
59
|
-
updateModelWithValue(model, 'left', values[1], property);
|
|
60
|
-
break;
|
|
61
|
-
case 3:
|
|
62
|
-
updateModelWithValue(model, 'top', values[0], property);
|
|
63
|
-
updateModelWithValue(model, 'right', values[1], property);
|
|
64
|
-
updateModelWithValue(model, 'left', values[1], property);
|
|
65
|
-
updateModelWithValue(model, 'bottom', values[2], property);
|
|
66
|
-
break;
|
|
67
|
-
case 4:
|
|
68
|
-
updateModelWithValue(model, 'top', values[0], property);
|
|
69
|
-
updateModelWithValue(model, 'right', values[1], property);
|
|
70
|
-
updateModelWithValue(model, 'bottom', values[2], property);
|
|
71
|
-
updateModelWithValue(model, 'left', values[3], property);
|
|
72
|
-
break;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
function matches(value, candidates) {
|
|
76
|
-
for (let candidate of candidates) {
|
|
77
|
-
if (value.matches(candidate)) {
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* @param allowsKeywords whether the initial value of property is zero, so keywords `initial` and `unset` count as zero
|
|
85
|
-
* @return `true` if this node represents a non-zero border; otherwise, `false`
|
|
86
|
-
*/
|
|
87
|
-
function checkLineWidth(value, allowsKeywords = true) {
|
|
88
|
-
if (allowsKeywords && matches(value, ['initial', 'unset'])) {
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
// a <length> is a value and a unit
|
|
92
|
-
// so use `parseFloat` to strip the unit
|
|
93
|
-
return parseFloat(value.getText()) !== 0;
|
|
94
|
-
}
|
|
95
|
-
function checkLineWidthList(nodes, allowsKeywords = true) {
|
|
96
|
-
return nodes.map(node => checkLineWidth(node, allowsKeywords));
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* @param allowsKeywords whether keywords `initial` and `unset` count as zero
|
|
100
|
-
* @return `true` if this node represents a non-zero border; otherwise, `false`
|
|
101
|
-
*/
|
|
102
|
-
function checkLineStyle(valueNode, allowsKeywords = true) {
|
|
103
|
-
if (matches(valueNode, ['none', 'hidden'])) {
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
if (allowsKeywords && matches(valueNode, ['initial', 'unset'])) {
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
|
-
return true;
|
|
110
|
-
}
|
|
111
|
-
function checkLineStyleList(nodes, allowsKeywords = true) {
|
|
112
|
-
return nodes.map(node => checkLineStyle(node, allowsKeywords));
|
|
113
|
-
}
|
|
114
|
-
function checkBorderShorthand(node) {
|
|
115
|
-
const children = node.getChildren();
|
|
116
|
-
// the only child can be a keyword, a <line-width>, or a <line-style>
|
|
117
|
-
// if either check returns false, the result is no border
|
|
118
|
-
if (children.length === 1) {
|
|
119
|
-
const value = children[0];
|
|
120
|
-
return checkLineWidth(value) && checkLineStyle(value);
|
|
121
|
-
}
|
|
122
|
-
// multiple children can't contain keywords
|
|
123
|
-
// if any child means no border, the result is no border
|
|
124
|
-
for (const child of children) {
|
|
125
|
-
const value = child;
|
|
126
|
-
if (!checkLineWidth(value, /* allowsKeywords: */ false) ||
|
|
127
|
-
!checkLineStyle(value, /* allowsKeywords: */ false)) {
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return true;
|
|
132
|
-
}
|
|
133
|
-
function calculateBoxModel(propertyTable) {
|
|
134
|
-
const model = {
|
|
135
|
-
top: { value: false, properties: [] },
|
|
136
|
-
right: { value: false, properties: [] },
|
|
137
|
-
bottom: { value: false, properties: [] },
|
|
138
|
-
left: { value: false, properties: [] },
|
|
139
|
-
};
|
|
140
|
-
for (const property of propertyTable) {
|
|
141
|
-
const value = property.node.value;
|
|
142
|
-
if (typeof value === 'undefined') {
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
switch (property.fullPropertyName) {
|
|
146
|
-
case 'box-sizing':
|
|
147
|
-
// has `box-sizing`, bail out
|
|
148
|
-
return {
|
|
149
|
-
top: { value: false, properties: [] },
|
|
150
|
-
right: { value: false, properties: [] },
|
|
151
|
-
bottom: { value: false, properties: [] },
|
|
152
|
-
left: { value: false, properties: [] },
|
|
153
|
-
};
|
|
154
|
-
case 'width':
|
|
155
|
-
model.width = property;
|
|
156
|
-
break;
|
|
157
|
-
case 'height':
|
|
158
|
-
model.height = property;
|
|
159
|
-
break;
|
|
160
|
-
default:
|
|
161
|
-
const segments = property.fullPropertyName.split('-');
|
|
162
|
-
switch (segments[0]) {
|
|
163
|
-
case 'border':
|
|
164
|
-
switch (segments[1]) {
|
|
165
|
-
case undefined:
|
|
166
|
-
case 'top':
|
|
167
|
-
case 'right':
|
|
168
|
-
case 'bottom':
|
|
169
|
-
case 'left':
|
|
170
|
-
switch (segments[2]) {
|
|
171
|
-
case undefined:
|
|
172
|
-
updateModelWithValue(model, segments[1], checkBorderShorthand(value), property);
|
|
173
|
-
break;
|
|
174
|
-
case 'width':
|
|
175
|
-
// the initial value of `border-width` is `medium`, not zero
|
|
176
|
-
updateModelWithValue(model, segments[1], checkLineWidth(value, false), property);
|
|
177
|
-
break;
|
|
178
|
-
case 'style':
|
|
179
|
-
// the initial value of `border-style` is `none`
|
|
180
|
-
updateModelWithValue(model, segments[1], checkLineStyle(value, true), property);
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
break;
|
|
184
|
-
case 'width':
|
|
185
|
-
// the initial value of `border-width` is `medium`, not zero
|
|
186
|
-
updateModelWithList(model, checkLineWidthList(value.getChildren(), false), property);
|
|
187
|
-
break;
|
|
188
|
-
case 'style':
|
|
189
|
-
// the initial value of `border-style` is `none`
|
|
190
|
-
updateModelWithList(model, checkLineStyleList(value.getChildren(), true), property);
|
|
191
|
-
break;
|
|
192
|
-
}
|
|
193
|
-
break;
|
|
194
|
-
case 'padding':
|
|
195
|
-
if (segments.length === 1) {
|
|
196
|
-
// the initial value of `padding` is zero
|
|
197
|
-
updateModelWithList(model, checkLineWidthList(value.getChildren(), true), property);
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
// the initial value of `padding` is zero
|
|
201
|
-
updateModelWithValue(model, segments[1], checkLineWidth(value, true), property);
|
|
202
|
-
}
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
break;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
return model;
|
|
209
|
-
}
|
|
210
|
-
});
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/*---------------------------------------------------------------------------------------------
|
|
2
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
|
-
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
(function (factory) {
|
|
6
|
-
if (typeof module === "object" && typeof module.exports === "object") {
|
|
7
|
-
var v = factory(require, exports);
|
|
8
|
-
if (v !== undefined) module.exports = v;
|
|
9
|
-
}
|
|
10
|
-
else if (typeof define === "function" && define.amd) {
|
|
11
|
-
define(["require", "exports", "../cssLanguageTypes", "../utils/strings", "../utils/resources"], factory);
|
|
12
|
-
}
|
|
13
|
-
})(function (require, exports) {
|
|
14
|
-
"use strict";
|
|
15
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.PathCompletionParticipant = void 0;
|
|
17
|
-
const cssLanguageTypes_1 = require("../cssLanguageTypes");
|
|
18
|
-
const strings_1 = require("../utils/strings");
|
|
19
|
-
const resources_1 = require("../utils/resources");
|
|
20
|
-
class PathCompletionParticipant {
|
|
21
|
-
constructor(readDirectory) {
|
|
22
|
-
this.readDirectory = readDirectory;
|
|
23
|
-
this.literalCompletions = [];
|
|
24
|
-
this.importCompletions = [];
|
|
25
|
-
}
|
|
26
|
-
onCssURILiteralValue(context) {
|
|
27
|
-
this.literalCompletions.push(context);
|
|
28
|
-
}
|
|
29
|
-
onCssImportPath(context) {
|
|
30
|
-
this.importCompletions.push(context);
|
|
31
|
-
}
|
|
32
|
-
async computeCompletions(document, documentContext) {
|
|
33
|
-
const result = { items: [], isIncomplete: false };
|
|
34
|
-
for (const literalCompletion of this.literalCompletions) {
|
|
35
|
-
const uriValue = literalCompletion.uriValue;
|
|
36
|
-
const fullValue = stripQuotes(uriValue);
|
|
37
|
-
if (fullValue === '.' || fullValue === '..') {
|
|
38
|
-
result.isIncomplete = true;
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
const items = await this.providePathSuggestions(uriValue, literalCompletion.position, literalCompletion.range, document, documentContext);
|
|
42
|
-
for (let item of items) {
|
|
43
|
-
result.items.push(item);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
for (const importCompletion of this.importCompletions) {
|
|
48
|
-
const pathValue = importCompletion.pathValue;
|
|
49
|
-
const fullValue = stripQuotes(pathValue);
|
|
50
|
-
if (fullValue === '.' || fullValue === '..') {
|
|
51
|
-
result.isIncomplete = true;
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
let suggestions = await this.providePathSuggestions(pathValue, importCompletion.position, importCompletion.range, document, documentContext);
|
|
55
|
-
if (document.languageId === 'scss') {
|
|
56
|
-
suggestions.forEach(s => {
|
|
57
|
-
if ((0, strings_1.startsWith)(s.label, '_') && (0, strings_1.endsWith)(s.label, '.scss')) {
|
|
58
|
-
if (s.textEdit) {
|
|
59
|
-
s.textEdit.newText = s.label.slice(1, -5);
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
s.label = s.label.slice(1, -5);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
for (let item of suggestions) {
|
|
68
|
-
result.items.push(item);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return result;
|
|
73
|
-
}
|
|
74
|
-
async providePathSuggestions(pathValue, position, range, document, documentContext) {
|
|
75
|
-
const fullValue = stripQuotes(pathValue);
|
|
76
|
-
const isValueQuoted = (0, strings_1.startsWith)(pathValue, `'`) || (0, strings_1.startsWith)(pathValue, `"`);
|
|
77
|
-
const valueBeforeCursor = isValueQuoted
|
|
78
|
-
? fullValue.slice(0, position.character - (range.start.character + 1))
|
|
79
|
-
: fullValue.slice(0, position.character - range.start.character);
|
|
80
|
-
const currentDocUri = document.uri;
|
|
81
|
-
const fullValueRange = isValueQuoted ? shiftRange(range, 1, -1) : range;
|
|
82
|
-
const replaceRange = pathToReplaceRange(valueBeforeCursor, fullValue, fullValueRange);
|
|
83
|
-
const valueBeforeLastSlash = valueBeforeCursor.substring(0, valueBeforeCursor.lastIndexOf('/') + 1); // keep the last slash
|
|
84
|
-
let parentDir = documentContext.resolveReference(valueBeforeLastSlash || '.', currentDocUri);
|
|
85
|
-
if (parentDir) {
|
|
86
|
-
try {
|
|
87
|
-
const result = [];
|
|
88
|
-
const infos = await this.readDirectory(parentDir);
|
|
89
|
-
for (const [name, type] of infos) {
|
|
90
|
-
// Exclude paths that start with `.`
|
|
91
|
-
if (name.charCodeAt(0) !== CharCode_dot && (type === cssLanguageTypes_1.FileType.Directory || (0, resources_1.joinPath)(parentDir, name) !== currentDocUri)) {
|
|
92
|
-
result.push(createCompletionItem(name, type === cssLanguageTypes_1.FileType.Directory, replaceRange));
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return result;
|
|
96
|
-
}
|
|
97
|
-
catch (e) {
|
|
98
|
-
// ignore
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return [];
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
exports.PathCompletionParticipant = PathCompletionParticipant;
|
|
105
|
-
const CharCode_dot = '.'.charCodeAt(0);
|
|
106
|
-
function stripQuotes(fullValue) {
|
|
107
|
-
if ((0, strings_1.startsWith)(fullValue, `'`) || (0, strings_1.startsWith)(fullValue, `"`)) {
|
|
108
|
-
return fullValue.slice(1, -1);
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
return fullValue;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
function pathToReplaceRange(valueBeforeCursor, fullValue, fullValueRange) {
|
|
115
|
-
let replaceRange;
|
|
116
|
-
const lastIndexOfSlash = valueBeforeCursor.lastIndexOf('/');
|
|
117
|
-
if (lastIndexOfSlash === -1) {
|
|
118
|
-
replaceRange = fullValueRange;
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
// For cases where cursor is in the middle of attribute value, like <script src="./s|rc/test.js">
|
|
122
|
-
// Find the last slash before cursor, and calculate the start of replace range from there
|
|
123
|
-
const valueAfterLastSlash = fullValue.slice(lastIndexOfSlash + 1);
|
|
124
|
-
const startPos = shiftPosition(fullValueRange.end, -valueAfterLastSlash.length);
|
|
125
|
-
// If whitespace exists, replace until it
|
|
126
|
-
const whitespaceIndex = valueAfterLastSlash.indexOf(' ');
|
|
127
|
-
let endPos;
|
|
128
|
-
if (whitespaceIndex !== -1) {
|
|
129
|
-
endPos = shiftPosition(startPos, whitespaceIndex);
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
endPos = fullValueRange.end;
|
|
133
|
-
}
|
|
134
|
-
replaceRange = cssLanguageTypes_1.Range.create(startPos, endPos);
|
|
135
|
-
}
|
|
136
|
-
return replaceRange;
|
|
137
|
-
}
|
|
138
|
-
function createCompletionItem(name, isDir, replaceRange) {
|
|
139
|
-
if (isDir) {
|
|
140
|
-
name = name + '/';
|
|
141
|
-
return {
|
|
142
|
-
label: escapePath(name),
|
|
143
|
-
kind: cssLanguageTypes_1.CompletionItemKind.Folder,
|
|
144
|
-
textEdit: cssLanguageTypes_1.TextEdit.replace(replaceRange, escapePath(name)),
|
|
145
|
-
command: {
|
|
146
|
-
title: 'Suggest',
|
|
147
|
-
command: 'editor.action.triggerSuggest'
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
return {
|
|
153
|
-
label: escapePath(name),
|
|
154
|
-
kind: cssLanguageTypes_1.CompletionItemKind.File,
|
|
155
|
-
textEdit: cssLanguageTypes_1.TextEdit.replace(replaceRange, escapePath(name))
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
// Escape https://www.w3.org/TR/CSS1/#url
|
|
160
|
-
function escapePath(p) {
|
|
161
|
-
return p.replace(/(\s|\(|\)|,|"|')/g, '\\$1');
|
|
162
|
-
}
|
|
163
|
-
function shiftPosition(pos, offset) {
|
|
164
|
-
return cssLanguageTypes_1.Position.create(pos.line, pos.character + offset);
|
|
165
|
-
}
|
|
166
|
-
function shiftRange(range, startOffset, endOffset) {
|
|
167
|
-
const start = shiftPosition(range.start, startOffset);
|
|
168
|
-
const end = shiftPosition(range.end, endOffset);
|
|
169
|
-
return cssLanguageTypes_1.Range.create(start, end);
|
|
170
|
-
}
|
|
171
|
-
});
|