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.
- package/CHANGELOG.md +5 -1
- package/README.md +1 -0
- package/lib/esm/beautify/beautify-css.js +50 -8
- package/lib/esm/cssLanguageService.d.ts +37 -37
- package/lib/esm/cssLanguageService.js +72 -75
- package/lib/esm/cssLanguageTypes.d.ts +238 -238
- package/lib/esm/cssLanguageTypes.js +42 -42
- package/lib/esm/data/webCustomData.js +21959 -21965
- package/lib/esm/languageFacts/builtinData.js +142 -142
- package/lib/esm/languageFacts/colors.js +469 -472
- package/lib/esm/languageFacts/dataManager.js +88 -92
- package/lib/esm/languageFacts/dataProvider.js +73 -79
- package/lib/esm/languageFacts/entry.js +137 -138
- package/lib/esm/languageFacts/facts.js +8 -8
- package/lib/esm/parser/cssErrors.js +48 -50
- package/lib/esm/parser/cssNodes.js +1502 -2019
- package/lib/esm/parser/cssParser.js +1534 -1566
- package/lib/esm/parser/cssScanner.js +592 -599
- package/lib/esm/parser/cssSymbolScope.js +311 -341
- package/lib/esm/parser/lessParser.js +714 -740
- package/lib/esm/parser/lessScanner.js +57 -78
- package/lib/esm/parser/scssErrors.js +18 -20
- package/lib/esm/parser/scssParser.js +796 -818
- package/lib/esm/parser/scssScanner.js +95 -116
- package/lib/esm/services/cssCodeActions.js +77 -81
- package/lib/esm/services/cssCompletion.js +1054 -1149
- package/lib/esm/services/cssFolding.js +190 -193
- package/lib/esm/services/cssFormatter.js +136 -136
- package/lib/esm/services/cssHover.js +148 -151
- package/lib/esm/services/cssNavigation.js +378 -470
- package/lib/esm/services/cssSelectionRange.js +47 -47
- package/lib/esm/services/cssValidation.js +41 -44
- package/lib/esm/services/lessCompletion.js +378 -397
- package/lib/esm/services/lint.js +518 -532
- package/lib/esm/services/lintRules.js +76 -83
- package/lib/esm/services/lintUtil.js +196 -205
- package/lib/esm/services/pathCompletion.js +157 -231
- package/lib/esm/services/scssCompletion.js +354 -378
- package/lib/esm/services/scssNavigation.js +82 -154
- package/lib/esm/services/selectorPrinting.js +492 -536
- package/lib/esm/utils/arrays.js +40 -46
- package/lib/esm/utils/objects.js +11 -11
- package/lib/esm/utils/resources.js +11 -24
- package/lib/esm/utils/strings.js +102 -104
- package/lib/umd/beautify/beautify-css.js +50 -8
- package/lib/umd/cssLanguageService.d.ts +37 -37
- package/lib/umd/cssLanguageService.js +99 -102
- package/lib/umd/cssLanguageTypes.d.ts +238 -238
- package/lib/umd/cssLanguageTypes.js +89 -88
- package/lib/umd/data/webCustomData.js +21972 -21978
- package/lib/umd/languageFacts/builtinData.js +154 -154
- package/lib/umd/languageFacts/colors.js +492 -495
- package/lib/umd/languageFacts/dataManager.js +101 -104
- package/lib/umd/languageFacts/dataProvider.js +86 -91
- package/lib/umd/languageFacts/entry.js +152 -153
- package/lib/umd/languageFacts/facts.js +29 -29
- package/lib/umd/parser/cssErrors.js +61 -62
- package/lib/umd/parser/cssNodes.js +1587 -2034
- package/lib/umd/parser/cssParser.js +1547 -1578
- package/lib/umd/parser/cssScanner.js +606 -611
- package/lib/umd/parser/cssSymbolScope.js +328 -353
- package/lib/umd/parser/lessParser.js +727 -752
- package/lib/umd/parser/lessScanner.js +70 -90
- package/lib/umd/parser/scssErrors.js +31 -32
- package/lib/umd/parser/scssParser.js +809 -830
- package/lib/umd/parser/scssScanner.js +108 -128
- package/lib/umd/services/cssCodeActions.js +90 -93
- package/lib/umd/services/cssCompletion.js +1067 -1161
- package/lib/umd/services/cssFolding.js +203 -206
- package/lib/umd/services/cssFormatter.js +150 -150
- package/lib/umd/services/cssHover.js +161 -163
- package/lib/umd/services/cssNavigation.js +391 -482
- package/lib/umd/services/cssSelectionRange.js +60 -60
- package/lib/umd/services/cssValidation.js +54 -56
- package/lib/umd/services/lessCompletion.js +391 -409
- package/lib/umd/services/lint.js +531 -544
- package/lib/umd/services/lintRules.js +91 -95
- package/lib/umd/services/lintUtil.js +210 -218
- package/lib/umd/services/pathCompletion.js +171 -244
- package/lib/umd/services/scssCompletion.js +367 -390
- package/lib/umd/services/scssNavigation.js +95 -166
- package/lib/umd/services/selectorPrinting.js +510 -550
- package/lib/umd/utils/arrays.js +55 -61
- package/lib/umd/utils/objects.js +25 -25
- package/lib/umd/utils/resources.js +26 -39
- package/lib/umd/utils/strings.js +120 -122
- 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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
this.id = id;
|
|
15
|
-
this.message = message;
|
|
16
|
-
this.defaultValue = defaultValue;
|
|
17
|
-
// nothing to do
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
this.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
this.fullPropertyName = decl.getFullPropertyName().toLowerCase();
|
|
10
|
-
this.node = decl;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
setSide(model, '
|
|
26
|
-
setSide(model, '
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
updateModelWithValue(model, '
|
|
46
|
-
updateModelWithValue(model, '
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
updateModelWithValue(model, '
|
|
52
|
-
updateModelWithValue(model, '
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
updateModelWithValue(model, '
|
|
58
|
-
updateModelWithValue(model, '
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
+
}
|