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.
Files changed (83) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/SECURITY.md +41 -0
  3. package/lib/esm/beautify/beautify-css.js +11 -4
  4. package/lib/esm/cssLanguageService.d.ts +2 -1
  5. package/lib/esm/cssLanguageService.js +15 -17
  6. package/lib/esm/cssLanguageTypes.js +2 -2
  7. package/lib/esm/data/webCustomData.js +356 -232
  8. package/lib/esm/languageFacts/builtinData.js +15 -15
  9. package/lib/esm/languageFacts/colors.js +66 -69
  10. package/lib/esm/languageFacts/dataManager.js +38 -42
  11. package/lib/esm/languageFacts/dataProvider.js +17 -23
  12. package/lib/esm/languageFacts/entry.js +22 -23
  13. package/lib/esm/parser/cssErrors.js +5 -7
  14. package/lib/esm/parser/cssNodes.js +869 -1377
  15. package/lib/esm/parser/cssParser.js +419 -376
  16. package/lib/esm/parser/cssScanner.js +168 -175
  17. package/lib/esm/parser/cssSymbolScope.js +107 -137
  18. package/lib/esm/parser/lessParser.js +177 -202
  19. package/lib/esm/parser/lessScanner.js +22 -43
  20. package/lib/esm/parser/scssErrors.js +5 -7
  21. package/lib/esm/parser/scssParser.js +196 -208
  22. package/lib/esm/parser/scssScanner.js +33 -54
  23. package/lib/esm/services/cssCodeActions.js +36 -40
  24. package/lib/esm/services/cssCompletion.js +300 -395
  25. package/lib/esm/services/cssFolding.js +32 -35
  26. package/lib/esm/services/cssFormatter.js +22 -22
  27. package/lib/esm/services/cssHover.js +30 -33
  28. package/lib/esm/services/cssNavigation.js +260 -289
  29. package/lib/esm/services/cssSelectionRange.js +6 -6
  30. package/lib/esm/services/cssValidation.js +13 -16
  31. package/lib/esm/services/lessCompletion.js +351 -370
  32. package/lib/esm/services/lint.js +161 -175
  33. package/lib/esm/services/lintRules.js +20 -27
  34. package/lib/esm/services/lintUtil.js +19 -28
  35. package/lib/esm/services/pathCompletion.js +84 -158
  36. package/lib/esm/services/scssCompletion.js +283 -307
  37. package/lib/esm/services/scssNavigation.js +65 -137
  38. package/lib/esm/services/selectorPrinting.js +131 -175
  39. package/lib/esm/utils/arrays.js +6 -12
  40. package/lib/esm/utils/objects.js +1 -1
  41. package/lib/esm/utils/resources.js +3 -16
  42. package/lib/esm/utils/strings.js +10 -12
  43. package/lib/umd/beautify/beautify-css.js +11 -4
  44. package/lib/umd/cssLanguageService.d.ts +2 -1
  45. package/lib/umd/cssLanguageService.js +34 -32
  46. package/lib/umd/cssLanguageTypes.js +4 -3
  47. package/lib/umd/data/webCustomData.js +355 -231
  48. package/lib/umd/languageFacts/colors.js +65 -68
  49. package/lib/umd/languageFacts/dataManager.js +41 -44
  50. package/lib/umd/languageFacts/dataProvider.js +17 -22
  51. package/lib/umd/languageFacts/entry.js +22 -23
  52. package/lib/umd/languageFacts/facts.js +5 -1
  53. package/lib/umd/parser/cssErrors.js +5 -6
  54. package/lib/umd/parser/cssNodes.js +870 -1307
  55. package/lib/umd/parser/cssParser.js +424 -380
  56. package/lib/umd/parser/cssScanner.js +168 -173
  57. package/lib/umd/parser/cssSymbolScope.js +109 -134
  58. package/lib/umd/parser/lessParser.js +182 -206
  59. package/lib/umd/parser/lessScanner.js +22 -42
  60. package/lib/umd/parser/scssErrors.js +5 -6
  61. package/lib/umd/parser/scssParser.js +202 -213
  62. package/lib/umd/parser/scssScanner.js +25 -45
  63. package/lib/umd/services/cssCodeActions.js +41 -44
  64. package/lib/umd/services/cssCompletion.js +308 -402
  65. package/lib/umd/services/cssFolding.js +35 -38
  66. package/lib/umd/services/cssFormatter.js +25 -25
  67. package/lib/umd/services/cssHover.js +36 -38
  68. package/lib/umd/services/cssNavigation.js +267 -295
  69. package/lib/umd/services/cssSelectionRange.js +8 -8
  70. package/lib/umd/services/cssValidation.js +17 -19
  71. package/lib/umd/services/lessCompletion.js +354 -372
  72. package/lib/umd/services/lint.js +167 -180
  73. package/lib/umd/services/lintRules.js +20 -24
  74. package/lib/umd/services/lintUtil.js +20 -28
  75. package/lib/umd/services/pathCompletion.js +87 -160
  76. package/lib/umd/services/scssCompletion.js +287 -310
  77. package/lib/umd/services/scssNavigation.js +69 -140
  78. package/lib/umd/services/selectorPrinting.js +134 -174
  79. package/lib/umd/utils/arrays.js +6 -12
  80. package/lib/umd/utils/objects.js +1 -1
  81. package/lib/umd/utils/resources.js +4 -17
  82. package/lib/umd/utils/strings.js +10 -12
  83. package/package.json +16 -15
@@ -5,31 +5,27 @@
5
5
  'use strict';
6
6
  import * as nodes from '../parser/cssNodes';
7
7
  import * as nls from 'vscode-nls';
8
- var localize = nls.loadMessageBundle();
9
- var Warning = nodes.Level.Warning;
10
- var Error = nodes.Level.Error;
11
- var Ignore = nodes.Level.Ignore;
12
- var Rule = /** @class */ (function () {
13
- function Rule(id, message, defaultValue) {
8
+ const localize = nls.loadMessageBundle();
9
+ const Warning = nodes.Level.Warning;
10
+ const Error = nodes.Level.Error;
11
+ const Ignore = nodes.Level.Ignore;
12
+ export class Rule {
13
+ constructor(id, message, defaultValue) {
14
14
  this.id = id;
15
15
  this.message = message;
16
16
  this.defaultValue = defaultValue;
17
17
  // nothing to do
18
18
  }
19
- return Rule;
20
- }());
21
- export { Rule };
22
- var Setting = /** @class */ (function () {
23
- function Setting(id, message, defaultValue) {
19
+ }
20
+ export class Setting {
21
+ constructor(id, message, defaultValue) {
24
22
  this.id = id;
25
23
  this.message = message;
26
24
  this.defaultValue = defaultValue;
27
25
  // nothing to do
28
26
  }
29
- return Setting;
30
- }());
31
- export { Setting };
32
- export var Rules = {
27
+ }
28
+ export const Rules = {
33
29
  AllVendorPrefixes: new Rule('compatibleVendorPrefixes', localize('rule.vendorprefixes.all', "When using a vendor-specific prefix make sure to also include all other vendor-specific properties"), Ignore),
34
30
  IncludeStandardPropertyWhenUsingVendorPrefix: new Rule('vendorPrefix', localize('rule.standardvendorprefix.all', "When using a vendor-specific prefix also include the standard property"), Warning),
35
31
  DuplicateDeclarations: new Rule('duplicateProperties', localize('rule.duplicateDeclarations', "Do not use duplicate style definitions"), Ignore),
@@ -50,29 +46,26 @@ export var Rules = {
50
46
  AvoidFloat: new Rule('float', localize('rule.avoidFloat', "Avoid using 'float'. Floats lead to fragile CSS that is easy to break if one aspect of the layout changes."), Ignore),
51
47
  AvoidIdSelector: new Rule('idSelector', localize('rule.avoidIdSelector', "Selectors should not contain IDs because these rules are too tightly coupled with the HTML."), Ignore),
52
48
  };
53
- export var Settings = {
49
+ export const Settings = {
54
50
  ValidProperties: new Setting('validProperties', localize('rule.validProperties', "A list of properties that are not validated against the `unknownProperties` rule."), [])
55
51
  };
56
- var LintConfigurationSettings = /** @class */ (function () {
57
- function LintConfigurationSettings(conf) {
58
- if (conf === void 0) { conf = {}; }
52
+ export class LintConfigurationSettings {
53
+ constructor(conf = {}) {
59
54
  this.conf = conf;
60
55
  }
61
- LintConfigurationSettings.prototype.getRule = function (rule) {
56
+ getRule(rule) {
62
57
  if (this.conf.hasOwnProperty(rule.id)) {
63
- var level = toLevel(this.conf[rule.id]);
58
+ const level = toLevel(this.conf[rule.id]);
64
59
  if (level) {
65
60
  return level;
66
61
  }
67
62
  }
68
63
  return rule.defaultValue;
69
- };
70
- LintConfigurationSettings.prototype.getSetting = function (setting) {
64
+ }
65
+ getSetting(setting) {
71
66
  return this.conf[setting.id];
72
- };
73
- return LintConfigurationSettings;
74
- }());
75
- export { LintConfigurationSettings };
67
+ }
68
+ }
76
69
  function toLevel(level) {
77
70
  switch (level) {
78
71
  case 'ignore': return nodes.Level.Ignore;
@@ -4,16 +4,14 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  'use strict';
6
6
  import { includes } from '../utils/arrays';
7
- var Element = /** @class */ (function () {
8
- function Element(decl) {
7
+ export class Element {
8
+ constructor(decl) {
9
9
  this.fullPropertyName = decl.getFullPropertyName().toLowerCase();
10
10
  this.node = decl;
11
11
  }
12
- return Element;
13
- }());
14
- export { Element };
12
+ }
15
13
  function setSide(model, side, value, property) {
16
- var state = model[side];
14
+ const state = model[side];
17
15
  state.value = value;
18
16
  if (value) {
19
17
  if (!includes(state.properties, property)) {
@@ -62,8 +60,7 @@ function updateModelWithList(model, values, property) {
62
60
  }
63
61
  }
64
62
  function matches(value, candidates) {
65
- for (var _i = 0, candidates_1 = candidates; _i < candidates_1.length; _i++) {
66
- var candidate = candidates_1[_i];
63
+ for (let candidate of candidates) {
67
64
  if (value.matches(candidate)) {
68
65
  return true;
69
66
  }
@@ -74,8 +71,7 @@ function matches(value, candidates) {
74
71
  * @param allowsKeywords whether the initial value of property is zero, so keywords `initial` and `unset` count as zero
75
72
  * @return `true` if this node represents a non-zero border; otherwise, `false`
76
73
  */
77
- function checkLineWidth(value, allowsKeywords) {
78
- if (allowsKeywords === void 0) { allowsKeywords = true; }
74
+ function checkLineWidth(value, allowsKeywords = true) {
79
75
  if (allowsKeywords && matches(value, ['initial', 'unset'])) {
80
76
  return false;
81
77
  }
@@ -83,16 +79,14 @@ function checkLineWidth(value, allowsKeywords) {
83
79
  // so use `parseFloat` to strip the unit
84
80
  return parseFloat(value.getText()) !== 0;
85
81
  }
86
- function checkLineWidthList(nodes, allowsKeywords) {
87
- if (allowsKeywords === void 0) { allowsKeywords = true; }
88
- return nodes.map(function (node) { return checkLineWidth(node, allowsKeywords); });
82
+ function checkLineWidthList(nodes, allowsKeywords = true) {
83
+ return nodes.map(node => checkLineWidth(node, allowsKeywords));
89
84
  }
90
85
  /**
91
86
  * @param allowsKeywords whether keywords `initial` and `unset` count as zero
92
87
  * @return `true` if this node represents a non-zero border; otherwise, `false`
93
88
  */
94
- function checkLineStyle(valueNode, allowsKeywords) {
95
- if (allowsKeywords === void 0) { allowsKeywords = true; }
89
+ function checkLineStyle(valueNode, allowsKeywords = true) {
96
90
  if (matches(valueNode, ['none', 'hidden'])) {
97
91
  return false;
98
92
  }
@@ -101,23 +95,21 @@ function checkLineStyle(valueNode, allowsKeywords) {
101
95
  }
102
96
  return true;
103
97
  }
104
- function checkLineStyleList(nodes, allowsKeywords) {
105
- if (allowsKeywords === void 0) { allowsKeywords = true; }
106
- return nodes.map(function (node) { return checkLineStyle(node, allowsKeywords); });
98
+ function checkLineStyleList(nodes, allowsKeywords = true) {
99
+ return nodes.map(node => checkLineStyle(node, allowsKeywords));
107
100
  }
108
101
  function checkBorderShorthand(node) {
109
- var children = node.getChildren();
102
+ const children = node.getChildren();
110
103
  // the only child can be a keyword, a <line-width>, or a <line-style>
111
104
  // if either check returns false, the result is no border
112
105
  if (children.length === 1) {
113
- var value = children[0];
106
+ const value = children[0];
114
107
  return checkLineWidth(value) && checkLineStyle(value);
115
108
  }
116
109
  // multiple children can't contain keywords
117
110
  // if any child means no border, the result is no border
118
- for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
119
- var child = children_1[_i];
120
- var value = child;
111
+ for (const child of children) {
112
+ const value = child;
121
113
  if (!checkLineWidth(value, /* allowsKeywords: */ false) ||
122
114
  !checkLineStyle(value, /* allowsKeywords: */ false)) {
123
115
  return false;
@@ -126,15 +118,14 @@ function checkBorderShorthand(node) {
126
118
  return true;
127
119
  }
128
120
  export default function calculateBoxModel(propertyTable) {
129
- var model = {
121
+ const model = {
130
122
  top: { value: false, properties: [] },
131
123
  right: { value: false, properties: [] },
132
124
  bottom: { value: false, properties: [] },
133
125
  left: { value: false, properties: [] },
134
126
  };
135
- for (var _i = 0, propertyTable_1 = propertyTable; _i < propertyTable_1.length; _i++) {
136
- var property = propertyTable_1[_i];
137
- var value = property.node.value;
127
+ for (const property of propertyTable) {
128
+ const value = property.node.value;
138
129
  if (typeof value === 'undefined') {
139
130
  continue;
140
131
  }
@@ -154,7 +145,7 @@ export default function calculateBoxModel(propertyTable) {
154
145
  model.height = property;
155
146
  break;
156
147
  default:
157
- var segments = property.fullPropertyName.split('-');
148
+ const segments = property.fullPropertyName.split('-');
158
149
  switch (segments[0]) {
159
150
  case 'border':
160
151
  switch (segments[1]) {
@@ -2,170 +2,96 @@
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Licensed under the MIT License. See License.txt in the project root for license information.
4
4
  *--------------------------------------------------------------------------------------------*/
5
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
- return new (P || (P = Promise))(function (resolve, reject) {
8
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
- step((generator = generator.apply(thisArg, _arguments || [])).next());
12
- });
13
- };
14
- var __generator = (this && this.__generator) || function (thisArg, body) {
15
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
16
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
17
- function verb(n) { return function (v) { return step([n, v]); }; }
18
- function step(op) {
19
- if (f) throw new TypeError("Generator is already executing.");
20
- while (_) try {
21
- 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;
22
- if (y = 0, t) op = [op[0] & 2, t.value];
23
- switch (op[0]) {
24
- case 0: case 1: t = op; break;
25
- case 4: _.label++; return { value: op[1], done: false };
26
- case 5: _.label++; y = op[1]; op = [0]; continue;
27
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
28
- default:
29
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
30
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
31
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
32
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
33
- if (t[2]) _.ops.pop();
34
- _.trys.pop(); continue;
35
- }
36
- op = body.call(thisArg, _);
37
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
38
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
39
- }
40
- };
41
5
  import { FileType, CompletionItemKind, TextEdit, Range, Position } from '../cssLanguageTypes';
42
6
  import { startsWith, endsWith } from '../utils/strings';
43
7
  import { joinPath } from '../utils/resources';
44
- var PathCompletionParticipant = /** @class */ (function () {
45
- function PathCompletionParticipant(readDirectory) {
8
+ export class PathCompletionParticipant {
9
+ constructor(readDirectory) {
46
10
  this.readDirectory = readDirectory;
47
11
  this.literalCompletions = [];
48
12
  this.importCompletions = [];
49
13
  }
50
- PathCompletionParticipant.prototype.onCssURILiteralValue = function (context) {
14
+ onCssURILiteralValue(context) {
51
15
  this.literalCompletions.push(context);
52
- };
53
- PathCompletionParticipant.prototype.onCssImportPath = function (context) {
16
+ }
17
+ onCssImportPath(context) {
54
18
  this.importCompletions.push(context);
55
- };
56
- PathCompletionParticipant.prototype.computeCompletions = function (document, documentContext) {
57
- return __awaiter(this, void 0, void 0, function () {
58
- var result, _i, _a, literalCompletion, uriValue, fullValue, items, _b, items_1, item, _c, _d, importCompletion, pathValue, fullValue, suggestions, _e, suggestions_1, item;
59
- return __generator(this, function (_f) {
60
- switch (_f.label) {
61
- case 0:
62
- result = { items: [], isIncomplete: false };
63
- _i = 0, _a = this.literalCompletions;
64
- _f.label = 1;
65
- case 1:
66
- if (!(_i < _a.length)) return [3 /*break*/, 5];
67
- literalCompletion = _a[_i];
68
- uriValue = literalCompletion.uriValue;
69
- fullValue = stripQuotes(uriValue);
70
- if (!(fullValue === '.' || fullValue === '..')) return [3 /*break*/, 2];
71
- result.isIncomplete = true;
72
- return [3 /*break*/, 4];
73
- case 2: return [4 /*yield*/, this.providePathSuggestions(uriValue, literalCompletion.position, literalCompletion.range, document, documentContext)];
74
- case 3:
75
- items = _f.sent();
76
- for (_b = 0, items_1 = items; _b < items_1.length; _b++) {
77
- item = items_1[_b];
78
- result.items.push(item);
79
- }
80
- _f.label = 4;
81
- case 4:
82
- _i++;
83
- return [3 /*break*/, 1];
84
- case 5:
85
- _c = 0, _d = this.importCompletions;
86
- _f.label = 6;
87
- case 6:
88
- if (!(_c < _d.length)) return [3 /*break*/, 10];
89
- importCompletion = _d[_c];
90
- pathValue = importCompletion.pathValue;
91
- fullValue = stripQuotes(pathValue);
92
- if (!(fullValue === '.' || fullValue === '..')) return [3 /*break*/, 7];
93
- result.isIncomplete = true;
94
- return [3 /*break*/, 9];
95
- case 7: return [4 /*yield*/, this.providePathSuggestions(pathValue, importCompletion.position, importCompletion.range, document, documentContext)];
96
- case 8:
97
- suggestions = _f.sent();
98
- if (document.languageId === 'scss') {
99
- suggestions.forEach(function (s) {
100
- if (startsWith(s.label, '_') && endsWith(s.label, '.scss')) {
101
- if (s.textEdit) {
102
- s.textEdit.newText = s.label.slice(1, -5);
103
- }
104
- else {
105
- s.label = s.label.slice(1, -5);
106
- }
107
- }
108
- });
109
- }
110
- for (_e = 0, suggestions_1 = suggestions; _e < suggestions_1.length; _e++) {
111
- item = suggestions_1[_e];
112
- result.items.push(item);
113
- }
114
- _f.label = 9;
115
- case 9:
116
- _c++;
117
- return [3 /*break*/, 6];
118
- case 10: return [2 /*return*/, result];
19
+ }
20
+ async computeCompletions(document, documentContext) {
21
+ const result = { items: [], isIncomplete: false };
22
+ for (const literalCompletion of this.literalCompletions) {
23
+ const uriValue = literalCompletion.uriValue;
24
+ const fullValue = stripQuotes(uriValue);
25
+ if (fullValue === '.' || fullValue === '..') {
26
+ result.isIncomplete = true;
27
+ }
28
+ else {
29
+ const items = await this.providePathSuggestions(uriValue, literalCompletion.position, literalCompletion.range, document, documentContext);
30
+ for (let item of items) {
31
+ result.items.push(item);
119
32
  }
120
- });
121
- });
122
- };
123
- PathCompletionParticipant.prototype.providePathSuggestions = function (pathValue, position, range, document, documentContext) {
124
- return __awaiter(this, void 0, void 0, function () {
125
- var fullValue, isValueQuoted, valueBeforeCursor, currentDocUri, fullValueRange, replaceRange, valueBeforeLastSlash, parentDir, result, infos, _i, infos_1, _a, name, type, e_1;
126
- return __generator(this, function (_b) {
127
- switch (_b.label) {
128
- case 0:
129
- fullValue = stripQuotes(pathValue);
130
- isValueQuoted = startsWith(pathValue, "'") || startsWith(pathValue, "\"");
131
- valueBeforeCursor = isValueQuoted
132
- ? fullValue.slice(0, position.character - (range.start.character + 1))
133
- : fullValue.slice(0, position.character - range.start.character);
134
- currentDocUri = document.uri;
135
- fullValueRange = isValueQuoted ? shiftRange(range, 1, -1) : range;
136
- replaceRange = pathToReplaceRange(valueBeforeCursor, fullValue, fullValueRange);
137
- valueBeforeLastSlash = valueBeforeCursor.substring(0, valueBeforeCursor.lastIndexOf('/') + 1);
138
- parentDir = documentContext.resolveReference(valueBeforeLastSlash || '.', currentDocUri);
139
- if (!parentDir) return [3 /*break*/, 4];
140
- _b.label = 1;
141
- case 1:
142
- _b.trys.push([1, 3, , 4]);
143
- result = [];
144
- return [4 /*yield*/, this.readDirectory(parentDir)];
145
- case 2:
146
- infos = _b.sent();
147
- for (_i = 0, infos_1 = infos; _i < infos_1.length; _i++) {
148
- _a = infos_1[_i], name = _a[0], type = _a[1];
149
- // Exclude paths that start with `.`
150
- if (name.charCodeAt(0) !== CharCode_dot && (type === FileType.Directory || joinPath(parentDir, name) !== currentDocUri)) {
151
- result.push(createCompletionItem(name, type === FileType.Directory, replaceRange));
33
+ }
34
+ }
35
+ for (const importCompletion of this.importCompletions) {
36
+ const pathValue = importCompletion.pathValue;
37
+ const fullValue = stripQuotes(pathValue);
38
+ if (fullValue === '.' || fullValue === '..') {
39
+ result.isIncomplete = true;
40
+ }
41
+ else {
42
+ let suggestions = await this.providePathSuggestions(pathValue, importCompletion.position, importCompletion.range, document, documentContext);
43
+ if (document.languageId === 'scss') {
44
+ suggestions.forEach(s => {
45
+ if (startsWith(s.label, '_') && endsWith(s.label, '.scss')) {
46
+ if (s.textEdit) {
47
+ s.textEdit.newText = s.label.slice(1, -5);
48
+ }
49
+ else {
50
+ s.label = s.label.slice(1, -5);
152
51
  }
153
52
  }
154
- return [2 /*return*/, result];
155
- case 3:
156
- e_1 = _b.sent();
157
- return [3 /*break*/, 4];
158
- case 4: return [2 /*return*/, []];
53
+ });
54
+ }
55
+ for (let item of suggestions) {
56
+ result.items.push(item);
57
+ }
58
+ }
59
+ }
60
+ return result;
61
+ }
62
+ async providePathSuggestions(pathValue, position, range, document, documentContext) {
63
+ const fullValue = stripQuotes(pathValue);
64
+ const isValueQuoted = startsWith(pathValue, `'`) || startsWith(pathValue, `"`);
65
+ const valueBeforeCursor = isValueQuoted
66
+ ? fullValue.slice(0, position.character - (range.start.character + 1))
67
+ : fullValue.slice(0, position.character - range.start.character);
68
+ const currentDocUri = document.uri;
69
+ const fullValueRange = isValueQuoted ? shiftRange(range, 1, -1) : range;
70
+ const replaceRange = pathToReplaceRange(valueBeforeCursor, fullValue, fullValueRange);
71
+ const valueBeforeLastSlash = valueBeforeCursor.substring(0, valueBeforeCursor.lastIndexOf('/') + 1); // keep the last slash
72
+ let parentDir = documentContext.resolveReference(valueBeforeLastSlash || '.', currentDocUri);
73
+ if (parentDir) {
74
+ try {
75
+ const result = [];
76
+ const infos = await this.readDirectory(parentDir);
77
+ for (const [name, type] of infos) {
78
+ // Exclude paths that start with `.`
79
+ if (name.charCodeAt(0) !== CharCode_dot && (type === FileType.Directory || joinPath(parentDir, name) !== currentDocUri)) {
80
+ result.push(createCompletionItem(name, type === FileType.Directory, replaceRange));
81
+ }
159
82
  }
160
- });
161
- });
162
- };
163
- return PathCompletionParticipant;
164
- }());
165
- export { PathCompletionParticipant };
166
- var CharCode_dot = '.'.charCodeAt(0);
83
+ return result;
84
+ }
85
+ catch (e) {
86
+ // ignore
87
+ }
88
+ }
89
+ return [];
90
+ }
91
+ }
92
+ const CharCode_dot = '.'.charCodeAt(0);
167
93
  function stripQuotes(fullValue) {
168
- if (startsWith(fullValue, "'") || startsWith(fullValue, "\"")) {
94
+ if (startsWith(fullValue, `'`) || startsWith(fullValue, `"`)) {
169
95
  return fullValue.slice(1, -1);
170
96
  }
171
97
  else {
@@ -173,19 +99,19 @@ function stripQuotes(fullValue) {
173
99
  }
174
100
  }
175
101
  function pathToReplaceRange(valueBeforeCursor, fullValue, fullValueRange) {
176
- var replaceRange;
177
- var lastIndexOfSlash = valueBeforeCursor.lastIndexOf('/');
102
+ let replaceRange;
103
+ const lastIndexOfSlash = valueBeforeCursor.lastIndexOf('/');
178
104
  if (lastIndexOfSlash === -1) {
179
105
  replaceRange = fullValueRange;
180
106
  }
181
107
  else {
182
108
  // For cases where cursor is in the middle of attribute value, like <script src="./s|rc/test.js">
183
109
  // Find the last slash before cursor, and calculate the start of replace range from there
184
- var valueAfterLastSlash = fullValue.slice(lastIndexOfSlash + 1);
185
- var startPos = shiftPosition(fullValueRange.end, -valueAfterLastSlash.length);
110
+ const valueAfterLastSlash = fullValue.slice(lastIndexOfSlash + 1);
111
+ const startPos = shiftPosition(fullValueRange.end, -valueAfterLastSlash.length);
186
112
  // If whitespace exists, replace until it
187
- var whitespaceIndex = valueAfterLastSlash.indexOf(' ');
188
- var endPos = void 0;
113
+ const whitespaceIndex = valueAfterLastSlash.indexOf(' ');
114
+ let endPos;
189
115
  if (whitespaceIndex !== -1) {
190
116
  endPos = shiftPosition(startPos, whitespaceIndex);
191
117
  }
@@ -225,7 +151,7 @@ function shiftPosition(pos, offset) {
225
151
  return Position.create(pos.line, pos.character + offset);
226
152
  }
227
153
  function shiftRange(range, startOffset, endOffset) {
228
- var start = shiftPosition(range.start, startOffset);
229
- var end = shiftPosition(range.end, endOffset);
154
+ const start = shiftPosition(range.start, startOffset);
155
+ const end = shiftPosition(range.end, endOffset);
230
156
  return Range.create(start, end);
231
157
  }