vscode-css-languageservice 5.4.1 → 6.0.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 (87) hide show
  1. package/CHANGELOG.md +5 -1
  2. package/README.md +1 -0
  3. package/lib/esm/beautify/beautify-css.js +50 -8
  4. package/lib/esm/cssLanguageService.d.ts +37 -37
  5. package/lib/esm/cssLanguageService.js +72 -75
  6. package/lib/esm/cssLanguageTypes.d.ts +238 -238
  7. package/lib/esm/cssLanguageTypes.js +42 -42
  8. package/lib/esm/data/webCustomData.js +21959 -21965
  9. package/lib/esm/languageFacts/builtinData.js +142 -142
  10. package/lib/esm/languageFacts/colors.js +469 -472
  11. package/lib/esm/languageFacts/dataManager.js +88 -92
  12. package/lib/esm/languageFacts/dataProvider.js +73 -79
  13. package/lib/esm/languageFacts/entry.js +137 -138
  14. package/lib/esm/languageFacts/facts.js +8 -8
  15. package/lib/esm/parser/cssErrors.js +48 -50
  16. package/lib/esm/parser/cssNodes.js +1502 -2019
  17. package/lib/esm/parser/cssParser.js +1534 -1566
  18. package/lib/esm/parser/cssScanner.js +592 -599
  19. package/lib/esm/parser/cssSymbolScope.js +311 -341
  20. package/lib/esm/parser/lessParser.js +714 -740
  21. package/lib/esm/parser/lessScanner.js +57 -78
  22. package/lib/esm/parser/scssErrors.js +18 -20
  23. package/lib/esm/parser/scssParser.js +796 -818
  24. package/lib/esm/parser/scssScanner.js +95 -116
  25. package/lib/esm/services/cssCodeActions.js +77 -81
  26. package/lib/esm/services/cssCompletion.js +1054 -1149
  27. package/lib/esm/services/cssFolding.js +190 -193
  28. package/lib/esm/services/cssFormatter.js +136 -136
  29. package/lib/esm/services/cssHover.js +148 -151
  30. package/lib/esm/services/cssNavigation.js +378 -470
  31. package/lib/esm/services/cssSelectionRange.js +47 -47
  32. package/lib/esm/services/cssValidation.js +41 -44
  33. package/lib/esm/services/lessCompletion.js +378 -397
  34. package/lib/esm/services/lint.js +518 -532
  35. package/lib/esm/services/lintRules.js +76 -83
  36. package/lib/esm/services/lintUtil.js +196 -205
  37. package/lib/esm/services/pathCompletion.js +157 -231
  38. package/lib/esm/services/scssCompletion.js +354 -378
  39. package/lib/esm/services/scssNavigation.js +82 -154
  40. package/lib/esm/services/selectorPrinting.js +492 -536
  41. package/lib/esm/utils/arrays.js +40 -46
  42. package/lib/esm/utils/objects.js +11 -11
  43. package/lib/esm/utils/resources.js +11 -24
  44. package/lib/esm/utils/strings.js +102 -104
  45. package/lib/umd/beautify/beautify-css.js +50 -8
  46. package/lib/umd/cssLanguageService.d.ts +37 -37
  47. package/lib/umd/cssLanguageService.js +99 -102
  48. package/lib/umd/cssLanguageTypes.d.ts +238 -238
  49. package/lib/umd/cssLanguageTypes.js +89 -88
  50. package/lib/umd/data/webCustomData.js +21972 -21978
  51. package/lib/umd/languageFacts/builtinData.js +154 -154
  52. package/lib/umd/languageFacts/colors.js +492 -495
  53. package/lib/umd/languageFacts/dataManager.js +101 -104
  54. package/lib/umd/languageFacts/dataProvider.js +86 -91
  55. package/lib/umd/languageFacts/entry.js +152 -153
  56. package/lib/umd/languageFacts/facts.js +29 -29
  57. package/lib/umd/parser/cssErrors.js +61 -62
  58. package/lib/umd/parser/cssNodes.js +1587 -2034
  59. package/lib/umd/parser/cssParser.js +1547 -1578
  60. package/lib/umd/parser/cssScanner.js +606 -611
  61. package/lib/umd/parser/cssSymbolScope.js +328 -353
  62. package/lib/umd/parser/lessParser.js +727 -752
  63. package/lib/umd/parser/lessScanner.js +70 -90
  64. package/lib/umd/parser/scssErrors.js +31 -32
  65. package/lib/umd/parser/scssParser.js +809 -830
  66. package/lib/umd/parser/scssScanner.js +108 -128
  67. package/lib/umd/services/cssCodeActions.js +90 -93
  68. package/lib/umd/services/cssCompletion.js +1067 -1161
  69. package/lib/umd/services/cssFolding.js +203 -206
  70. package/lib/umd/services/cssFormatter.js +150 -150
  71. package/lib/umd/services/cssHover.js +161 -163
  72. package/lib/umd/services/cssNavigation.js +391 -482
  73. package/lib/umd/services/cssSelectionRange.js +60 -60
  74. package/lib/umd/services/cssValidation.js +54 -56
  75. package/lib/umd/services/lessCompletion.js +391 -409
  76. package/lib/umd/services/lint.js +531 -544
  77. package/lib/umd/services/lintRules.js +91 -95
  78. package/lib/umd/services/lintUtil.js +210 -218
  79. package/lib/umd/services/pathCompletion.js +171 -244
  80. package/lib/umd/services/scssCompletion.js +367 -390
  81. package/lib/umd/services/scssNavigation.js +95 -166
  82. package/lib/umd/services/selectorPrinting.js +510 -550
  83. package/lib/umd/utils/arrays.js +55 -61
  84. package/lib/umd/utils/objects.js +25 -25
  85. package/lib/umd/utils/resources.js +26 -39
  86. package/lib/umd/utils/strings.js +120 -122
  87. package/package.json +11 -11
@@ -1,83 +1,76 @@
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
- 'use strict';
6
- import * as nodes from '../parser/cssNodes';
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) {
14
- this.id = id;
15
- this.message = message;
16
- this.defaultValue = defaultValue;
17
- // nothing to do
18
- }
19
- return Rule;
20
- }());
21
- export { Rule };
22
- var Setting = /** @class */ (function () {
23
- function Setting(id, message, defaultValue) {
24
- this.id = id;
25
- this.message = message;
26
- this.defaultValue = defaultValue;
27
- // nothing to do
28
- }
29
- return Setting;
30
- }());
31
- export { Setting };
32
- export var Rules = {
33
- 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
- IncludeStandardPropertyWhenUsingVendorPrefix: new Rule('vendorPrefix', localize('rule.standardvendorprefix.all', "When using a vendor-specific prefix also include the standard property"), Warning),
35
- DuplicateDeclarations: new Rule('duplicateProperties', localize('rule.duplicateDeclarations', "Do not use duplicate style definitions"), Ignore),
36
- EmptyRuleSet: new Rule('emptyRules', localize('rule.emptyRuleSets', "Do not use empty rulesets"), Warning),
37
- ImportStatemement: new Rule('importStatement', localize('rule.importDirective', "Import statements do not load in parallel"), Ignore),
38
- BewareOfBoxModelSize: new Rule('boxModel', localize('rule.bewareOfBoxModelSize', "Do not use width or height when using padding or border"), Ignore),
39
- UniversalSelector: new Rule('universalSelector', localize('rule.universalSelector', "The universal selector (*) is known to be slow"), Ignore),
40
- ZeroWithUnit: new Rule('zeroUnits', localize('rule.zeroWidthUnit', "No unit for zero needed"), Ignore),
41
- RequiredPropertiesForFontFace: new Rule('fontFaceProperties', localize('rule.fontFaceProperties', "@font-face rule must define 'src' and 'font-family' properties"), Warning),
42
- HexColorLength: new Rule('hexColorLength', localize('rule.hexColor', "Hex colors must consist of three, four, six or eight hex numbers"), Error),
43
- ArgsInColorFunction: new Rule('argumentsInColorFunction', localize('rule.colorFunction', "Invalid number of parameters"), Error),
44
- UnknownProperty: new Rule('unknownProperties', localize('rule.unknownProperty', "Unknown property."), Warning),
45
- UnknownAtRules: new Rule('unknownAtRules', localize('rule.unknownAtRules', "Unknown at-rule."), Warning),
46
- IEStarHack: new Rule('ieHack', localize('rule.ieHack', "IE hacks are only necessary when supporting IE7 and older"), Ignore),
47
- UnknownVendorSpecificProperty: new Rule('unknownVendorSpecificProperties', localize('rule.unknownVendorSpecificProperty', "Unknown vendor specific property."), Ignore),
48
- PropertyIgnoredDueToDisplay: new Rule('propertyIgnoredDueToDisplay', localize('rule.propertyIgnoredDueToDisplay', "Property is ignored due to the display."), Warning),
49
- AvoidImportant: new Rule('important', localize('rule.avoidImportant', "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),
50
- 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
- AvoidIdSelector: new Rule('idSelector', localize('rule.avoidIdSelector', "Selectors should not contain IDs because these rules are too tightly coupled with the HTML."), Ignore),
52
- };
53
- export var Settings = {
54
- ValidProperties: new Setting('validProperties', localize('rule.validProperties', "A list of properties that are not validated against the `unknownProperties` rule."), [])
55
- };
56
- var LintConfigurationSettings = /** @class */ (function () {
57
- function LintConfigurationSettings(conf) {
58
- if (conf === void 0) { conf = {}; }
59
- this.conf = conf;
60
- }
61
- LintConfigurationSettings.prototype.getRule = function (rule) {
62
- if (this.conf.hasOwnProperty(rule.id)) {
63
- var level = toLevel(this.conf[rule.id]);
64
- if (level) {
65
- return level;
66
- }
67
- }
68
- return rule.defaultValue;
69
- };
70
- LintConfigurationSettings.prototype.getSetting = function (setting) {
71
- return this.conf[setting.id];
72
- };
73
- return LintConfigurationSettings;
74
- }());
75
- export { LintConfigurationSettings };
76
- function toLevel(level) {
77
- switch (level) {
78
- case 'ignore': return nodes.Level.Ignore;
79
- case 'warning': return nodes.Level.Warning;
80
- case 'error': return nodes.Level.Error;
81
- }
82
- return null;
83
- }
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
+ 'use strict';
6
+ import * as nodes from '../parser/cssNodes';
7
+ import * as nls from 'vscode-nls';
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
+ this.id = id;
15
+ this.message = message;
16
+ this.defaultValue = defaultValue;
17
+ // nothing to do
18
+ }
19
+ }
20
+ export class Setting {
21
+ constructor(id, message, defaultValue) {
22
+ this.id = id;
23
+ this.message = message;
24
+ this.defaultValue = defaultValue;
25
+ // nothing to do
26
+ }
27
+ }
28
+ export const Rules = {
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),
30
+ IncludeStandardPropertyWhenUsingVendorPrefix: new Rule('vendorPrefix', localize('rule.standardvendorprefix.all', "When using a vendor-specific prefix also include the standard property"), Warning),
31
+ DuplicateDeclarations: new Rule('duplicateProperties', localize('rule.duplicateDeclarations', "Do not use duplicate style definitions"), Ignore),
32
+ EmptyRuleSet: new Rule('emptyRules', localize('rule.emptyRuleSets', "Do not use empty rulesets"), Warning),
33
+ ImportStatemement: new Rule('importStatement', localize('rule.importDirective', "Import statements do not load in parallel"), Ignore),
34
+ BewareOfBoxModelSize: new Rule('boxModel', localize('rule.bewareOfBoxModelSize', "Do not use width or height when using padding or border"), Ignore),
35
+ UniversalSelector: new Rule('universalSelector', localize('rule.universalSelector', "The universal selector (*) is known to be slow"), Ignore),
36
+ ZeroWithUnit: new Rule('zeroUnits', localize('rule.zeroWidthUnit', "No unit for zero needed"), Ignore),
37
+ RequiredPropertiesForFontFace: new Rule('fontFaceProperties', localize('rule.fontFaceProperties', "@font-face rule must define 'src' and 'font-family' properties"), Warning),
38
+ HexColorLength: new Rule('hexColorLength', localize('rule.hexColor', "Hex colors must consist of three, four, six or eight hex numbers"), Error),
39
+ ArgsInColorFunction: new Rule('argumentsInColorFunction', localize('rule.colorFunction', "Invalid number of parameters"), Error),
40
+ UnknownProperty: new Rule('unknownProperties', localize('rule.unknownProperty', "Unknown property."), Warning),
41
+ UnknownAtRules: new Rule('unknownAtRules', localize('rule.unknownAtRules', "Unknown at-rule."), Warning),
42
+ IEStarHack: new Rule('ieHack', localize('rule.ieHack', "IE hacks are only necessary when supporting IE7 and older"), Ignore),
43
+ UnknownVendorSpecificProperty: new Rule('unknownVendorSpecificProperties', localize('rule.unknownVendorSpecificProperty', "Unknown vendor specific property."), Ignore),
44
+ PropertyIgnoredDueToDisplay: new Rule('propertyIgnoredDueToDisplay', localize('rule.propertyIgnoredDueToDisplay', "Property is ignored due to the display."), Warning),
45
+ AvoidImportant: new Rule('important', localize('rule.avoidImportant', "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),
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),
47
+ AvoidIdSelector: new Rule('idSelector', localize('rule.avoidIdSelector', "Selectors should not contain IDs because these rules are too tightly coupled with the HTML."), Ignore),
48
+ };
49
+ export const Settings = {
50
+ ValidProperties: new Setting('validProperties', localize('rule.validProperties', "A list of properties that are not validated against the `unknownProperties` rule."), [])
51
+ };
52
+ export class LintConfigurationSettings {
53
+ constructor(conf = {}) {
54
+ this.conf = conf;
55
+ }
56
+ getRule(rule) {
57
+ if (this.conf.hasOwnProperty(rule.id)) {
58
+ const level = toLevel(this.conf[rule.id]);
59
+ if (level) {
60
+ return level;
61
+ }
62
+ }
63
+ return rule.defaultValue;
64
+ }
65
+ getSetting(setting) {
66
+ return this.conf[setting.id];
67
+ }
68
+ }
69
+ function toLevel(level) {
70
+ switch (level) {
71
+ case 'ignore': return nodes.Level.Ignore;
72
+ case 'warning': return nodes.Level.Warning;
73
+ case 'error': return nodes.Level.Error;
74
+ }
75
+ return null;
76
+ }
@@ -1,205 +1,196 @@
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
- 'use strict';
6
- import { includes } from '../utils/arrays';
7
- var Element = /** @class */ (function () {
8
- function Element(decl) {
9
- this.fullPropertyName = decl.getFullPropertyName().toLowerCase();
10
- this.node = decl;
11
- }
12
- return Element;
13
- }());
14
- export { Element };
15
- function setSide(model, side, value, property) {
16
- var state = model[side];
17
- state.value = value;
18
- if (value) {
19
- if (!includes(state.properties, property)) {
20
- state.properties.push(property);
21
- }
22
- }
23
- }
24
- function setAllSides(model, value, property) {
25
- setSide(model, 'top', value, property);
26
- setSide(model, 'right', value, property);
27
- setSide(model, 'bottom', value, property);
28
- setSide(model, 'left', value, property);
29
- }
30
- function updateModelWithValue(model, side, value, property) {
31
- if (side === 'top' || side === 'right' ||
32
- side === 'bottom' || side === 'left') {
33
- setSide(model, side, value, property);
34
- }
35
- else {
36
- setAllSides(model, value, property);
37
- }
38
- }
39
- function updateModelWithList(model, values, property) {
40
- switch (values.length) {
41
- case 1:
42
- updateModelWithValue(model, undefined, values[0], property);
43
- break;
44
- case 2:
45
- updateModelWithValue(model, 'top', values[0], property);
46
- updateModelWithValue(model, 'bottom', values[0], property);
47
- updateModelWithValue(model, 'right', values[1], property);
48
- updateModelWithValue(model, 'left', values[1], property);
49
- break;
50
- case 3:
51
- updateModelWithValue(model, 'top', values[0], property);
52
- updateModelWithValue(model, 'right', values[1], property);
53
- updateModelWithValue(model, 'left', values[1], property);
54
- updateModelWithValue(model, 'bottom', values[2], property);
55
- break;
56
- case 4:
57
- updateModelWithValue(model, 'top', values[0], property);
58
- updateModelWithValue(model, 'right', values[1], property);
59
- updateModelWithValue(model, 'bottom', values[2], property);
60
- updateModelWithValue(model, 'left', values[3], property);
61
- break;
62
- }
63
- }
64
- function matches(value, candidates) {
65
- for (var _i = 0, candidates_1 = candidates; _i < candidates_1.length; _i++) {
66
- var candidate = candidates_1[_i];
67
- if (value.matches(candidate)) {
68
- return true;
69
- }
70
- }
71
- return false;
72
- }
73
- /**
74
- * @param allowsKeywords whether the initial value of property is zero, so keywords `initial` and `unset` count as zero
75
- * @return `true` if this node represents a non-zero border; otherwise, `false`
76
- */
77
- function checkLineWidth(value, allowsKeywords) {
78
- if (allowsKeywords === void 0) { allowsKeywords = true; }
79
- if (allowsKeywords && matches(value, ['initial', 'unset'])) {
80
- return false;
81
- }
82
- // a <length> is a value and a unit
83
- // so use `parseFloat` to strip the unit
84
- return parseFloat(value.getText()) !== 0;
85
- }
86
- function checkLineWidthList(nodes, allowsKeywords) {
87
- if (allowsKeywords === void 0) { allowsKeywords = true; }
88
- return nodes.map(function (node) { return checkLineWidth(node, allowsKeywords); });
89
- }
90
- /**
91
- * @param allowsKeywords whether keywords `initial` and `unset` count as zero
92
- * @return `true` if this node represents a non-zero border; otherwise, `false`
93
- */
94
- function checkLineStyle(valueNode, allowsKeywords) {
95
- if (allowsKeywords === void 0) { allowsKeywords = true; }
96
- if (matches(valueNode, ['none', 'hidden'])) {
97
- return false;
98
- }
99
- if (allowsKeywords && matches(valueNode, ['initial', 'unset'])) {
100
- return false;
101
- }
102
- return true;
103
- }
104
- function checkLineStyleList(nodes, allowsKeywords) {
105
- if (allowsKeywords === void 0) { allowsKeywords = true; }
106
- return nodes.map(function (node) { return checkLineStyle(node, allowsKeywords); });
107
- }
108
- function checkBorderShorthand(node) {
109
- var children = node.getChildren();
110
- // the only child can be a keyword, a <line-width>, or a <line-style>
111
- // if either check returns false, the result is no border
112
- if (children.length === 1) {
113
- var value = children[0];
114
- return checkLineWidth(value) && checkLineStyle(value);
115
- }
116
- // multiple children can't contain keywords
117
- // 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;
121
- if (!checkLineWidth(value, /* allowsKeywords: */ false) ||
122
- !checkLineStyle(value, /* allowsKeywords: */ false)) {
123
- return false;
124
- }
125
- }
126
- return true;
127
- }
128
- export default function calculateBoxModel(propertyTable) {
129
- var model = {
130
- top: { value: false, properties: [] },
131
- right: { value: false, properties: [] },
132
- bottom: { value: false, properties: [] },
133
- left: { value: false, properties: [] },
134
- };
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;
138
- if (typeof value === 'undefined') {
139
- continue;
140
- }
141
- switch (property.fullPropertyName) {
142
- case 'box-sizing':
143
- // has `box-sizing`, bail out
144
- return {
145
- top: { value: false, properties: [] },
146
- right: { value: false, properties: [] },
147
- bottom: { value: false, properties: [] },
148
- left: { value: false, properties: [] },
149
- };
150
- case 'width':
151
- model.width = property;
152
- break;
153
- case 'height':
154
- model.height = property;
155
- break;
156
- default:
157
- var segments = property.fullPropertyName.split('-');
158
- switch (segments[0]) {
159
- case 'border':
160
- switch (segments[1]) {
161
- case undefined:
162
- case 'top':
163
- case 'right':
164
- case 'bottom':
165
- case 'left':
166
- switch (segments[2]) {
167
- case undefined:
168
- updateModelWithValue(model, segments[1], checkBorderShorthand(value), property);
169
- break;
170
- case 'width':
171
- // the initial value of `border-width` is `medium`, not zero
172
- updateModelWithValue(model, segments[1], checkLineWidth(value, false), property);
173
- break;
174
- case 'style':
175
- // the initial value of `border-style` is `none`
176
- updateModelWithValue(model, segments[1], checkLineStyle(value, true), property);
177
- break;
178
- }
179
- break;
180
- case 'width':
181
- // the initial value of `border-width` is `medium`, not zero
182
- updateModelWithList(model, checkLineWidthList(value.getChildren(), false), property);
183
- break;
184
- case 'style':
185
- // the initial value of `border-style` is `none`
186
- updateModelWithList(model, checkLineStyleList(value.getChildren(), true), property);
187
- break;
188
- }
189
- break;
190
- case 'padding':
191
- if (segments.length === 1) {
192
- // the initial value of `padding` is zero
193
- updateModelWithList(model, checkLineWidthList(value.getChildren(), true), property);
194
- }
195
- else {
196
- // the initial value of `padding` is zero
197
- updateModelWithValue(model, segments[1], checkLineWidth(value, true), property);
198
- }
199
- break;
200
- }
201
- break;
202
- }
203
- }
204
- return model;
205
- }
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
+ 'use strict';
6
+ import { includes } from '../utils/arrays';
7
+ export class Element {
8
+ constructor(decl) {
9
+ this.fullPropertyName = decl.getFullPropertyName().toLowerCase();
10
+ this.node = decl;
11
+ }
12
+ }
13
+ function setSide(model, side, value, property) {
14
+ const state = model[side];
15
+ state.value = value;
16
+ if (value) {
17
+ if (!includes(state.properties, property)) {
18
+ state.properties.push(property);
19
+ }
20
+ }
21
+ }
22
+ function setAllSides(model, value, property) {
23
+ setSide(model, 'top', value, property);
24
+ setSide(model, 'right', value, property);
25
+ setSide(model, 'bottom', value, property);
26
+ setSide(model, 'left', value, property);
27
+ }
28
+ function updateModelWithValue(model, side, value, property) {
29
+ if (side === 'top' || side === 'right' ||
30
+ side === 'bottom' || side === 'left') {
31
+ setSide(model, side, value, property);
32
+ }
33
+ else {
34
+ setAllSides(model, value, property);
35
+ }
36
+ }
37
+ function updateModelWithList(model, values, property) {
38
+ switch (values.length) {
39
+ case 1:
40
+ updateModelWithValue(model, undefined, values[0], property);
41
+ break;
42
+ case 2:
43
+ updateModelWithValue(model, 'top', values[0], property);
44
+ updateModelWithValue(model, 'bottom', values[0], property);
45
+ updateModelWithValue(model, 'right', values[1], property);
46
+ updateModelWithValue(model, 'left', values[1], property);
47
+ break;
48
+ case 3:
49
+ updateModelWithValue(model, 'top', values[0], property);
50
+ updateModelWithValue(model, 'right', values[1], property);
51
+ updateModelWithValue(model, 'left', values[1], property);
52
+ updateModelWithValue(model, 'bottom', values[2], property);
53
+ break;
54
+ case 4:
55
+ updateModelWithValue(model, 'top', values[0], property);
56
+ updateModelWithValue(model, 'right', values[1], property);
57
+ updateModelWithValue(model, 'bottom', values[2], property);
58
+ updateModelWithValue(model, 'left', values[3], property);
59
+ break;
60
+ }
61
+ }
62
+ function matches(value, candidates) {
63
+ for (let candidate of candidates) {
64
+ if (value.matches(candidate)) {
65
+ return true;
66
+ }
67
+ }
68
+ return false;
69
+ }
70
+ /**
71
+ * @param allowsKeywords whether the initial value of property is zero, so keywords `initial` and `unset` count as zero
72
+ * @return `true` if this node represents a non-zero border; otherwise, `false`
73
+ */
74
+ function checkLineWidth(value, allowsKeywords = true) {
75
+ if (allowsKeywords && matches(value, ['initial', 'unset'])) {
76
+ return false;
77
+ }
78
+ // a <length> is a value and a unit
79
+ // so use `parseFloat` to strip the unit
80
+ return parseFloat(value.getText()) !== 0;
81
+ }
82
+ function checkLineWidthList(nodes, allowsKeywords = true) {
83
+ return nodes.map(node => checkLineWidth(node, allowsKeywords));
84
+ }
85
+ /**
86
+ * @param allowsKeywords whether keywords `initial` and `unset` count as zero
87
+ * @return `true` if this node represents a non-zero border; otherwise, `false`
88
+ */
89
+ function checkLineStyle(valueNode, allowsKeywords = true) {
90
+ if (matches(valueNode, ['none', 'hidden'])) {
91
+ return false;
92
+ }
93
+ if (allowsKeywords && matches(valueNode, ['initial', 'unset'])) {
94
+ return false;
95
+ }
96
+ return true;
97
+ }
98
+ function checkLineStyleList(nodes, allowsKeywords = true) {
99
+ return nodes.map(node => checkLineStyle(node, allowsKeywords));
100
+ }
101
+ function checkBorderShorthand(node) {
102
+ const children = node.getChildren();
103
+ // the only child can be a keyword, a <line-width>, or a <line-style>
104
+ // if either check returns false, the result is no border
105
+ if (children.length === 1) {
106
+ const value = children[0];
107
+ return checkLineWidth(value) && checkLineStyle(value);
108
+ }
109
+ // multiple children can't contain keywords
110
+ // if any child means no border, the result is no border
111
+ for (const child of children) {
112
+ const value = child;
113
+ if (!checkLineWidth(value, /* allowsKeywords: */ false) ||
114
+ !checkLineStyle(value, /* allowsKeywords: */ false)) {
115
+ return false;
116
+ }
117
+ }
118
+ return true;
119
+ }
120
+ export default function calculateBoxModel(propertyTable) {
121
+ const model = {
122
+ top: { value: false, properties: [] },
123
+ right: { value: false, properties: [] },
124
+ bottom: { value: false, properties: [] },
125
+ left: { value: false, properties: [] },
126
+ };
127
+ for (const property of propertyTable) {
128
+ const value = property.node.value;
129
+ if (typeof value === 'undefined') {
130
+ continue;
131
+ }
132
+ switch (property.fullPropertyName) {
133
+ case 'box-sizing':
134
+ // has `box-sizing`, bail out
135
+ return {
136
+ top: { value: false, properties: [] },
137
+ right: { value: false, properties: [] },
138
+ bottom: { value: false, properties: [] },
139
+ left: { value: false, properties: [] },
140
+ };
141
+ case 'width':
142
+ model.width = property;
143
+ break;
144
+ case 'height':
145
+ model.height = property;
146
+ break;
147
+ default:
148
+ const segments = property.fullPropertyName.split('-');
149
+ switch (segments[0]) {
150
+ case 'border':
151
+ switch (segments[1]) {
152
+ case undefined:
153
+ case 'top':
154
+ case 'right':
155
+ case 'bottom':
156
+ case 'left':
157
+ switch (segments[2]) {
158
+ case undefined:
159
+ updateModelWithValue(model, segments[1], checkBorderShorthand(value), property);
160
+ break;
161
+ case 'width':
162
+ // the initial value of `border-width` is `medium`, not zero
163
+ updateModelWithValue(model, segments[1], checkLineWidth(value, false), property);
164
+ break;
165
+ case 'style':
166
+ // the initial value of `border-style` is `none`
167
+ updateModelWithValue(model, segments[1], checkLineStyle(value, true), property);
168
+ break;
169
+ }
170
+ break;
171
+ case 'width':
172
+ // the initial value of `border-width` is `medium`, not zero
173
+ updateModelWithList(model, checkLineWidthList(value.getChildren(), false), property);
174
+ break;
175
+ case 'style':
176
+ // the initial value of `border-style` is `none`
177
+ updateModelWithList(model, checkLineStyleList(value.getChildren(), true), property);
178
+ break;
179
+ }
180
+ break;
181
+ case 'padding':
182
+ if (segments.length === 1) {
183
+ // the initial value of `padding` is zero
184
+ updateModelWithList(model, checkLineWidthList(value.getChildren(), true), property);
185
+ }
186
+ else {
187
+ // the initial value of `padding` is zero
188
+ updateModelWithValue(model, segments[1], checkLineWidth(value, true), property);
189
+ }
190
+ break;
191
+ }
192
+ break;
193
+ }
194
+ }
195
+ return model;
196
+ }