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.
Files changed (74) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/lib/esm/beautify/beautify-css.js +1437 -1606
  3. package/lib/esm/cssLanguageService.d.ts +2 -2
  4. package/lib/esm/cssLanguageService.js +18 -18
  5. package/lib/esm/languageFacts/colors.js +1 -1
  6. package/lib/esm/languageFacts/dataManager.js +3 -3
  7. package/lib/esm/languageFacts/entry.js +1 -1
  8. package/lib/esm/languageFacts/facts.js +3 -3
  9. package/lib/esm/parser/cssNodes.js +1 -1
  10. package/lib/esm/parser/cssParser.js +5 -5
  11. package/lib/esm/parser/cssSymbolScope.js +2 -2
  12. package/lib/esm/parser/lessParser.js +5 -5
  13. package/lib/esm/parser/lessScanner.js +1 -1
  14. package/lib/esm/parser/scssParser.js +6 -6
  15. package/lib/esm/parser/scssScanner.js +1 -1
  16. package/lib/esm/services/cssCodeActions.js +4 -4
  17. package/lib/esm/services/cssCompletion.js +7 -7
  18. package/lib/esm/services/cssFolding.js +3 -3
  19. package/lib/esm/services/cssFormatter.js +3 -3
  20. package/lib/esm/services/cssHover.js +6 -6
  21. package/lib/esm/services/cssNavigation.js +6 -6
  22. package/lib/esm/services/cssSelectionRange.js +2 -2
  23. package/lib/esm/services/cssValidation.js +4 -4
  24. package/lib/esm/services/lessCompletion.js +2 -2
  25. package/lib/esm/services/lint.js +5 -5
  26. package/lib/esm/services/lintRules.js +1 -1
  27. package/lib/esm/services/lintUtil.js +1 -1
  28. package/lib/esm/services/pathCompletion.js +3 -3
  29. package/lib/esm/services/scssCompletion.js +3 -3
  30. package/lib/esm/services/scssNavigation.js +4 -4
  31. package/lib/esm/services/selectorPrinting.js +3 -3
  32. package/package.json +15 -15
  33. package/lib/umd/beautify/beautify-css.js +0 -1695
  34. package/lib/umd/cssLanguageService.d.ts +0 -39
  35. package/lib/umd/cssLanguageService.js +0 -105
  36. package/lib/umd/cssLanguageTypes.d.ts +0 -267
  37. package/lib/umd/cssLanguageTypes.js +0 -89
  38. package/lib/umd/data/webCustomData.js +0 -44613
  39. package/lib/umd/languageFacts/builtinData.js +0 -155
  40. package/lib/umd/languageFacts/colors.js +0 -949
  41. package/lib/umd/languageFacts/dataManager.js +0 -101
  42. package/lib/umd/languageFacts/dataProvider.js +0 -86
  43. package/lib/umd/languageFacts/entry.js +0 -217
  44. package/lib/umd/languageFacts/facts.js +0 -33
  45. package/lib/umd/parser/cssErrors.js +0 -61
  46. package/lib/umd/parser/cssNodes.js +0 -1676
  47. package/lib/umd/parser/cssParser.js +0 -2035
  48. package/lib/umd/parser/cssScanner.js +0 -619
  49. package/lib/umd/parser/cssSymbolScope.js +0 -328
  50. package/lib/umd/parser/lessParser.js +0 -732
  51. package/lib/umd/parser/lessScanner.js +0 -70
  52. package/lib/umd/parser/scssErrors.js +0 -30
  53. package/lib/umd/parser/scssParser.js +0 -874
  54. package/lib/umd/parser/scssScanner.js +0 -108
  55. package/lib/umd/services/cssCodeActions.js +0 -89
  56. package/lib/umd/services/cssCompletion.js +0 -1109
  57. package/lib/umd/services/cssFolding.js +0 -202
  58. package/lib/umd/services/cssFormatter.js +0 -149
  59. package/lib/umd/services/cssHover.js +0 -174
  60. package/lib/umd/services/cssNavigation.js +0 -539
  61. package/lib/umd/services/cssSelectionRange.js +0 -59
  62. package/lib/umd/services/cssValidation.js +0 -54
  63. package/lib/umd/services/lessCompletion.js +0 -390
  64. package/lib/umd/services/lint.js +0 -577
  65. package/lib/umd/services/lintRules.js +0 -90
  66. package/lib/umd/services/lintUtil.js +0 -210
  67. package/lib/umd/services/pathCompletion.js +0 -171
  68. package/lib/umd/services/scssCompletion.js +0 -367
  69. package/lib/umd/services/scssNavigation.js +0 -169
  70. package/lib/umd/services/selectorPrinting.js +0 -575
  71. package/lib/umd/utils/arrays.js +0 -54
  72. package/lib/umd/utils/objects.js +0 -24
  73. package/lib/umd/utils/resources.js +0 -25
  74. package/lib/umd/utils/strings.js +0 -123
@@ -1,577 +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", "@vscode/l10n", "../languageFacts/facts", "../parser/cssNodes", "../utils/arrays", "./lintRules", "./lintUtil"], 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.LintVisitor = void 0;
17
- const l10n = require("@vscode/l10n");
18
- const languageFacts = require("../languageFacts/facts");
19
- const nodes = require("../parser/cssNodes");
20
- const arrays_1 = require("../utils/arrays");
21
- const lintRules_1 = require("./lintRules");
22
- const lintUtil_1 = require("./lintUtil");
23
- class NodesByRootMap {
24
- constructor() {
25
- this.data = {};
26
- }
27
- add(root, name, node) {
28
- let entry = this.data[root];
29
- if (!entry) {
30
- entry = { nodes: [], names: [] };
31
- this.data[root] = entry;
32
- }
33
- entry.names.push(name);
34
- if (node) {
35
- entry.nodes.push(node);
36
- }
37
- }
38
- }
39
- class LintVisitor {
40
- static entries(node, document, settings, cssDataManager, entryFilter) {
41
- const visitor = new LintVisitor(document, settings, cssDataManager);
42
- node.acceptVisitor(visitor);
43
- visitor.completeValidations();
44
- return visitor.getEntries(entryFilter);
45
- }
46
- constructor(document, settings, cssDataManager) {
47
- this.cssDataManager = cssDataManager;
48
- this.warnings = [];
49
- this.settings = settings;
50
- this.documentText = document.getText();
51
- this.keyframes = new NodesByRootMap();
52
- this.validProperties = {};
53
- const properties = settings.getSetting(lintRules_1.Settings.ValidProperties);
54
- if (Array.isArray(properties)) {
55
- properties.forEach((p) => {
56
- if (typeof p === 'string') {
57
- const name = p.trim().toLowerCase();
58
- if (name.length) {
59
- this.validProperties[name] = true;
60
- }
61
- }
62
- });
63
- }
64
- }
65
- isValidPropertyDeclaration(element) {
66
- const propertyName = element.fullPropertyName;
67
- return this.validProperties[propertyName];
68
- }
69
- fetch(input, s) {
70
- const elements = [];
71
- for (const curr of input) {
72
- if (curr.fullPropertyName === s) {
73
- elements.push(curr);
74
- }
75
- }
76
- return elements;
77
- }
78
- fetchWithValue(input, s, v) {
79
- const elements = [];
80
- for (const inputElement of input) {
81
- if (inputElement.fullPropertyName === s) {
82
- const expression = inputElement.node.getValue();
83
- if (expression && this.findValueInExpression(expression, v)) {
84
- elements.push(inputElement);
85
- }
86
- }
87
- }
88
- return elements;
89
- }
90
- findValueInExpression(expression, v) {
91
- let found = false;
92
- expression.accept(node => {
93
- if (node.type === nodes.NodeType.Identifier && node.matches(v)) {
94
- found = true;
95
- }
96
- return !found;
97
- });
98
- return found;
99
- }
100
- getEntries(filter = (nodes.Level.Warning | nodes.Level.Error)) {
101
- return this.warnings.filter(entry => {
102
- return (entry.getLevel() & filter) !== 0;
103
- });
104
- }
105
- addEntry(node, rule, details) {
106
- const entry = new nodes.Marker(node, rule, this.settings.getRule(rule), details);
107
- this.warnings.push(entry);
108
- }
109
- getMissingNames(expected, actual) {
110
- const expectedClone = expected.slice(0); // clone
111
- for (let i = 0; i < actual.length; i++) {
112
- const k = expectedClone.indexOf(actual[i]);
113
- if (k !== -1) {
114
- expectedClone[k] = null;
115
- }
116
- }
117
- let result = null;
118
- for (let i = 0; i < expectedClone.length; i++) {
119
- const curr = expectedClone[i];
120
- if (curr) {
121
- if (result === null) {
122
- result = l10n.t("'{0}'", curr);
123
- }
124
- else {
125
- result = l10n.t("{0}, '{1}'", result, curr);
126
- }
127
- }
128
- }
129
- return result;
130
- }
131
- visitNode(node) {
132
- switch (node.type) {
133
- case nodes.NodeType.UnknownAtRule:
134
- return this.visitUnknownAtRule(node);
135
- case nodes.NodeType.Keyframe:
136
- return this.visitKeyframe(node);
137
- case nodes.NodeType.FontFace:
138
- return this.visitFontFace(node);
139
- case nodes.NodeType.Ruleset:
140
- return this.visitRuleSet(node);
141
- case nodes.NodeType.SimpleSelector:
142
- return this.visitSimpleSelector(node);
143
- case nodes.NodeType.Function:
144
- return this.visitFunction(node);
145
- case nodes.NodeType.NumericValue:
146
- return this.visitNumericValue(node);
147
- case nodes.NodeType.Import:
148
- return this.visitImport(node);
149
- case nodes.NodeType.HexColorValue:
150
- return this.visitHexColorValue(node);
151
- case nodes.NodeType.Prio:
152
- return this.visitPrio(node);
153
- case nodes.NodeType.IdentifierSelector:
154
- return this.visitIdentifierSelector(node);
155
- }
156
- return true;
157
- }
158
- completeValidations() {
159
- this.validateKeyframes();
160
- }
161
- visitUnknownAtRule(node) {
162
- const atRuleName = node.getChild(0);
163
- if (!atRuleName) {
164
- return false;
165
- }
166
- const atDirective = this.cssDataManager.getAtDirective(atRuleName.getText());
167
- if (atDirective) {
168
- return false;
169
- }
170
- this.addEntry(atRuleName, lintRules_1.Rules.UnknownAtRules, `Unknown at rule ${atRuleName.getText()}`);
171
- return true;
172
- }
173
- visitKeyframe(node) {
174
- const keyword = node.getKeyword();
175
- if (!keyword) {
176
- return false;
177
- }
178
- const text = keyword.getText();
179
- this.keyframes.add(node.getName(), text, (text !== '@keyframes') ? keyword : null);
180
- return true;
181
- }
182
- validateKeyframes() {
183
- // @keyframe and it's vendor specific alternatives
184
- // @keyframe should be included
185
- const expected = ['@-webkit-keyframes', '@-moz-keyframes', '@-o-keyframes'];
186
- for (const name in this.keyframes.data) {
187
- const actual = this.keyframes.data[name].names;
188
- const needsStandard = (actual.indexOf('@keyframes') === -1);
189
- if (!needsStandard && actual.length === 1) {
190
- continue; // only the non-vendor specific keyword is used, that's fine, no warning
191
- }
192
- const missingVendorSpecific = this.getMissingNames(expected, actual);
193
- if (missingVendorSpecific || needsStandard) {
194
- for (const node of this.keyframes.data[name].nodes) {
195
- if (needsStandard) {
196
- const message = l10n.t("Always define standard rule '@keyframes' when defining keyframes.");
197
- this.addEntry(node, lintRules_1.Rules.IncludeStandardPropertyWhenUsingVendorPrefix, message);
198
- }
199
- if (missingVendorSpecific) {
200
- const message = l10n.t("Always include all vendor specific rules: Missing: {0}", missingVendorSpecific);
201
- this.addEntry(node, lintRules_1.Rules.AllVendorPrefixes, message);
202
- }
203
- }
204
- }
205
- }
206
- return true;
207
- }
208
- visitSimpleSelector(node) {
209
- /////////////////////////////////////////////////////////////
210
- // Lint - The universal selector (*) is known to be slow.
211
- /////////////////////////////////////////////////////////////
212
- const firstChar = this.documentText.charAt(node.offset);
213
- if (node.length === 1 && firstChar === '*') {
214
- this.addEntry(node, lintRules_1.Rules.UniversalSelector);
215
- }
216
- return true;
217
- }
218
- visitIdentifierSelector(node) {
219
- /////////////////////////////////////////////////////////////
220
- // Lint - Avoid id selectors
221
- /////////////////////////////////////////////////////////////
222
- this.addEntry(node, lintRules_1.Rules.AvoidIdSelector);
223
- return true;
224
- }
225
- visitImport(node) {
226
- /////////////////////////////////////////////////////////////
227
- // Lint - Import statements shouldn't be used, because they aren't offering parallel downloads.
228
- /////////////////////////////////////////////////////////////
229
- this.addEntry(node, lintRules_1.Rules.ImportStatemement);
230
- return true;
231
- }
232
- visitRuleSet(node) {
233
- /////////////////////////////////////////////////////////////
234
- // Lint - Don't use empty rulesets.
235
- /////////////////////////////////////////////////////////////
236
- const declarations = node.getDeclarations();
237
- if (!declarations) {
238
- // syntax error
239
- return false;
240
- }
241
- if (!declarations.hasChildren()) {
242
- this.addEntry(node.getSelectors(), lintRules_1.Rules.EmptyRuleSet);
243
- }
244
- const propertyTable = [];
245
- for (const element of declarations.getChildren()) {
246
- if (element instanceof nodes.Declaration) {
247
- propertyTable.push(new lintUtil_1.Element(element));
248
- }
249
- }
250
- /////////////////////////////////////////////////////////////
251
- // the rule warns when it finds:
252
- // width being used with border, border-left, border-right, padding, padding-left, or padding-right
253
- // height being used with border, border-top, border-bottom, padding, padding-top, or padding-bottom
254
- // No error when box-sizing property is specified, as it assumes the user knows what he's doing.
255
- // see https://github.com/CSSLint/csslint/wiki/Beware-of-box-model-size
256
- /////////////////////////////////////////////////////////////
257
- const boxModel = (0, lintUtil_1.default)(propertyTable);
258
- if (boxModel.width) {
259
- let properties = [];
260
- if (boxModel.right.value) {
261
- properties = (0, arrays_1.union)(properties, boxModel.right.properties);
262
- }
263
- if (boxModel.left.value) {
264
- properties = (0, arrays_1.union)(properties, boxModel.left.properties);
265
- }
266
- if (properties.length !== 0) {
267
- for (const item of properties) {
268
- this.addEntry(item.node, lintRules_1.Rules.BewareOfBoxModelSize);
269
- }
270
- this.addEntry(boxModel.width.node, lintRules_1.Rules.BewareOfBoxModelSize);
271
- }
272
- }
273
- if (boxModel.height) {
274
- let properties = [];
275
- if (boxModel.top.value) {
276
- properties = (0, arrays_1.union)(properties, boxModel.top.properties);
277
- }
278
- if (boxModel.bottom.value) {
279
- properties = (0, arrays_1.union)(properties, boxModel.bottom.properties);
280
- }
281
- if (properties.length !== 0) {
282
- for (const item of properties) {
283
- this.addEntry(item.node, lintRules_1.Rules.BewareOfBoxModelSize);
284
- }
285
- this.addEntry(boxModel.height.node, lintRules_1.Rules.BewareOfBoxModelSize);
286
- }
287
- }
288
- /////////////////////////////////////////////////////////////
289
- // Properties ignored due to display
290
- /////////////////////////////////////////////////////////////
291
- // With 'display: inline-block', 'float' has no effect
292
- let displayElems = this.fetchWithValue(propertyTable, 'display', 'inline-block');
293
- if (displayElems.length > 0) {
294
- const elem = this.fetch(propertyTable, 'float');
295
- for (let index = 0; index < elem.length; index++) {
296
- const node = elem[index].node;
297
- const value = node.getValue();
298
- if (value && !value.matches('none')) {
299
- this.addEntry(node, lintRules_1.Rules.PropertyIgnoredDueToDisplay, l10n.t("inline-block is ignored due to the float. If 'float' has a value other than 'none', the box is floated and 'display' is treated as 'block'"));
300
- }
301
- }
302
- }
303
- // With 'display: block', 'vertical-align' has no effect
304
- displayElems = this.fetchWithValue(propertyTable, 'display', 'block');
305
- if (displayElems.length > 0) {
306
- const elem = this.fetch(propertyTable, 'vertical-align');
307
- for (let index = 0; index < elem.length; index++) {
308
- this.addEntry(elem[index].node, lintRules_1.Rules.PropertyIgnoredDueToDisplay, l10n.t("Property is ignored due to the display. With 'display: block', vertical-align should not be used."));
309
- }
310
- }
311
- /////////////////////////////////////////////////////////////
312
- // Avoid 'float'
313
- /////////////////////////////////////////////////////////////
314
- const elements = this.fetch(propertyTable, 'float');
315
- for (let index = 0; index < elements.length; index++) {
316
- const element = elements[index];
317
- if (!this.isValidPropertyDeclaration(element)) {
318
- this.addEntry(element.node, lintRules_1.Rules.AvoidFloat);
319
- }
320
- }
321
- /////////////////////////////////////////////////////////////
322
- // Don't use duplicate declarations.
323
- /////////////////////////////////////////////////////////////
324
- for (let i = 0; i < propertyTable.length; i++) {
325
- const element = propertyTable[i];
326
- if (element.fullPropertyName !== 'background' && !this.validProperties[element.fullPropertyName]) {
327
- const value = element.node.getValue();
328
- if (value && this.documentText.charAt(value.offset) !== '-') {
329
- const elements = this.fetch(propertyTable, element.fullPropertyName);
330
- if (elements.length > 1) {
331
- for (let k = 0; k < elements.length; k++) {
332
- const value = elements[k].node.getValue();
333
- if (value && this.documentText.charAt(value.offset) !== '-' && elements[k] !== element) {
334
- this.addEntry(element.node, lintRules_1.Rules.DuplicateDeclarations);
335
- }
336
- }
337
- }
338
- }
339
- }
340
- }
341
- /////////////////////////////////////////////////////////////
342
- // Unknown propery & When using a vendor-prefixed gradient, make sure to use them all.
343
- /////////////////////////////////////////////////////////////
344
- const isExportBlock = node.getSelectors().matches(":export");
345
- if (!isExportBlock) {
346
- const propertiesBySuffix = new NodesByRootMap();
347
- let containsUnknowns = false;
348
- for (const element of propertyTable) {
349
- const decl = element.node;
350
- if (this.isCSSDeclaration(decl)) {
351
- let name = element.fullPropertyName;
352
- const firstChar = name.charAt(0);
353
- if (firstChar === '-') {
354
- if (name.charAt(1) !== '-') { // avoid css variables
355
- if (!this.cssDataManager.isKnownProperty(name) && !this.validProperties[name]) {
356
- this.addEntry(decl.getProperty(), lintRules_1.Rules.UnknownVendorSpecificProperty);
357
- }
358
- const nonPrefixedName = decl.getNonPrefixedPropertyName();
359
- propertiesBySuffix.add(nonPrefixedName, name, decl.getProperty());
360
- }
361
- }
362
- else {
363
- const fullName = name;
364
- if (firstChar === '*' || firstChar === '_') {
365
- this.addEntry(decl.getProperty(), lintRules_1.Rules.IEStarHack);
366
- name = name.substr(1);
367
- }
368
- // _property and *property might be contributed via custom data
369
- if (!this.cssDataManager.isKnownProperty(fullName) && !this.cssDataManager.isKnownProperty(name)) {
370
- if (!this.validProperties[name]) {
371
- this.addEntry(decl.getProperty(), lintRules_1.Rules.UnknownProperty, l10n.t("Unknown property: '{0}'", decl.getFullPropertyName()));
372
- }
373
- }
374
- propertiesBySuffix.add(name, name, null); // don't pass the node as we don't show errors on the standard
375
- }
376
- }
377
- else {
378
- containsUnknowns = true;
379
- }
380
- }
381
- if (!containsUnknowns) { // don't perform this test if there are
382
- for (const suffix in propertiesBySuffix.data) {
383
- const entry = propertiesBySuffix.data[suffix];
384
- const actual = entry.names;
385
- const needsStandard = this.cssDataManager.isStandardProperty(suffix) && (actual.indexOf(suffix) === -1);
386
- if (!needsStandard && actual.length === 1) {
387
- continue; // only the non-vendor specific rule is used, that's fine, no warning
388
- }
389
- /**
390
- * We should ignore missing standard properties, if there's an explicit contextual reference to a
391
- * vendor specific pseudo-element selector with the same vendor (prefix)
392
- *
393
- * (See https://github.com/microsoft/vscode/issues/164350)
394
- */
395
- const entriesThatNeedStandard = new Set(needsStandard ? entry.nodes : []);
396
- if (needsStandard) {
397
- const pseudoElements = this.getContextualVendorSpecificPseudoElements(node);
398
- for (const node of entry.nodes) {
399
- const propertyName = node.getName();
400
- const prefix = propertyName.substring(0, propertyName.length - suffix.length);
401
- if (pseudoElements.some(x => x.startsWith(prefix))) {
402
- entriesThatNeedStandard.delete(node);
403
- }
404
- }
405
- }
406
- const expected = [];
407
- for (let i = 0, len = LintVisitor.prefixes.length; i < len; i++) {
408
- const prefix = LintVisitor.prefixes[i];
409
- if (this.cssDataManager.isStandardProperty(prefix + suffix)) {
410
- expected.push(prefix + suffix);
411
- }
412
- }
413
- const missingVendorSpecific = this.getMissingNames(expected, actual);
414
- if (missingVendorSpecific || needsStandard) {
415
- for (const node of entry.nodes) {
416
- if (needsStandard && entriesThatNeedStandard.has(node)) {
417
- const message = l10n.t("Also define the standard property '{0}' for compatibility", suffix);
418
- this.addEntry(node, lintRules_1.Rules.IncludeStandardPropertyWhenUsingVendorPrefix, message);
419
- }
420
- if (missingVendorSpecific) {
421
- const message = l10n.t("Always include all vendor specific properties: Missing: {0}", missingVendorSpecific);
422
- this.addEntry(node, lintRules_1.Rules.AllVendorPrefixes, message);
423
- }
424
- }
425
- }
426
- }
427
- }
428
- }
429
- return true;
430
- }
431
- /**
432
- * Walks up the syntax tree (starting from given `node`) and captures vendor
433
- * specific pseudo-element selectors.
434
- * @returns An array of vendor specific pseudo-elements; or empty if none
435
- * was found.
436
- */
437
- getContextualVendorSpecificPseudoElements(node) {
438
- function walkDown(s, n) {
439
- for (const child of n.getChildren()) {
440
- if (child.type === nodes.NodeType.PseudoSelector) {
441
- const pseudoElement = child.getChildren()[0]?.getText();
442
- if (pseudoElement) {
443
- s.add(pseudoElement);
444
- }
445
- }
446
- walkDown(s, child);
447
- }
448
- }
449
- function walkUp(s, n) {
450
- if (n.type === nodes.NodeType.Ruleset) {
451
- for (const selector of n.getSelectors().getChildren()) {
452
- walkDown(s, selector);
453
- }
454
- }
455
- return n.parent ? walkUp(s, n.parent) : undefined;
456
- }
457
- const result = new Set();
458
- walkUp(result, node);
459
- return Array.from(result);
460
- }
461
- visitPrio(node) {
462
- /////////////////////////////////////////////////////////////
463
- // Don't use !important
464
- /////////////////////////////////////////////////////////////
465
- this.addEntry(node, lintRules_1.Rules.AvoidImportant);
466
- return true;
467
- }
468
- visitNumericValue(node) {
469
- /////////////////////////////////////////////////////////////
470
- // 0 has no following unit
471
- /////////////////////////////////////////////////////////////
472
- const funcDecl = node.findParent(nodes.NodeType.Function);
473
- if (funcDecl && funcDecl.getName() === 'calc') {
474
- return true;
475
- }
476
- const decl = node.findParent(nodes.NodeType.Declaration);
477
- if (decl) {
478
- const declValue = decl.getValue();
479
- if (declValue) {
480
- const value = node.getValue();
481
- if (!value.unit || languageFacts.units.length.indexOf(value.unit.toLowerCase()) === -1) {
482
- return true;
483
- }
484
- if (parseFloat(value.value) === 0.0 && !!value.unit && !this.validProperties[decl.getFullPropertyName()]) {
485
- this.addEntry(node, lintRules_1.Rules.ZeroWithUnit);
486
- }
487
- }
488
- }
489
- return true;
490
- }
491
- visitFontFace(node) {
492
- const declarations = node.getDeclarations();
493
- if (!declarations) {
494
- // syntax error
495
- return false;
496
- }
497
- let definesSrc = false, definesFontFamily = false;
498
- let containsUnknowns = false;
499
- for (const node of declarations.getChildren()) {
500
- if (this.isCSSDeclaration(node)) {
501
- const name = node.getProperty().getName().toLowerCase();
502
- if (name === 'src') {
503
- definesSrc = true;
504
- }
505
- if (name === 'font-family') {
506
- definesFontFamily = true;
507
- }
508
- }
509
- else {
510
- containsUnknowns = true;
511
- }
512
- }
513
- if (!containsUnknowns && (!definesSrc || !definesFontFamily)) {
514
- this.addEntry(node, lintRules_1.Rules.RequiredPropertiesForFontFace);
515
- }
516
- return true;
517
- }
518
- isCSSDeclaration(node) {
519
- if (node instanceof nodes.Declaration) {
520
- if (!node.getValue()) {
521
- return false;
522
- }
523
- const property = node.getProperty();
524
- if (!property) {
525
- return false;
526
- }
527
- const identifier = property.getIdentifier();
528
- if (!identifier || identifier.containsInterpolation()) {
529
- return false;
530
- }
531
- return true;
532
- }
533
- return false;
534
- }
535
- visitHexColorValue(node) {
536
- // Rule: #eeff0011 or #eeff00 or #ef01 or #ef0
537
- const length = node.length;
538
- if (length !== 9 && length !== 7 && length !== 5 && length !== 4) {
539
- this.addEntry(node, lintRules_1.Rules.HexColorLength);
540
- }
541
- return false;
542
- }
543
- visitFunction(node) {
544
- const fnName = node.getName().toLowerCase();
545
- let expectedAttrCount = -1;
546
- let actualAttrCount = 0;
547
- switch (fnName) {
548
- case 'rgb(':
549
- case 'hsl(':
550
- expectedAttrCount = 3;
551
- break;
552
- case 'rgba(':
553
- case 'hsla(':
554
- expectedAttrCount = 4;
555
- break;
556
- }
557
- if (expectedAttrCount !== -1) {
558
- node.getArguments().accept(n => {
559
- if (n instanceof nodes.BinaryExpression) {
560
- actualAttrCount += 1;
561
- return false;
562
- }
563
- return true;
564
- });
565
- if (actualAttrCount !== expectedAttrCount) {
566
- this.addEntry(node, lintRules_1.Rules.ArgsInColorFunction);
567
- }
568
- }
569
- return true;
570
- }
571
- }
572
- exports.LintVisitor = LintVisitor;
573
- LintVisitor.prefixes = [
574
- '-ms-', '-moz-', '-o-', '-webkit-', // Quite common
575
- // '-xv-', '-atsc-', '-wap-', '-khtml-', 'mso-', 'prince-', '-ah-', '-hp-', '-ro-', '-rim-', '-tc-' // Quite un-common
576
- ];
577
- });