@tbela99/css-parser 1.2.0 → 1.3.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.
- package/CHANGELOG.md +5 -0
- package/README.md +2 -2
- package/dist/index-umd-web.js +483 -849
- package/dist/index.cjs +483 -849
- package/dist/index.d.ts +107 -11
- package/dist/lib/ast/features/calc.js +1 -25
- package/dist/lib/ast/features/inlinecssvariables.js +0 -19
- package/dist/lib/ast/features/transform.js +2 -2
- package/dist/lib/ast/math/expression.js +26 -149
- package/dist/lib/ast/math/math.js +8 -8
- package/dist/lib/ast/transform/compute.js +4 -37
- package/dist/lib/ast/transform/matrix.js +33 -34
- package/dist/lib/ast/transform/minify.js +32 -51
- package/dist/lib/ast/transform/perspective.js +1 -1
- package/dist/lib/ast/transform/rotate.js +13 -13
- package/dist/lib/ast/transform/scale.js +8 -8
- package/dist/lib/ast/transform/skew.js +4 -4
- package/dist/lib/ast/transform/translate.js +8 -8
- package/dist/lib/ast/transform/utils.js +31 -39
- package/dist/lib/ast/types.js +91 -2
- package/dist/lib/parser/declaration/set.js +2 -2
- package/dist/lib/parser/parse.js +34 -12
- package/dist/lib/parser/tokenize.js +28 -40
- package/dist/lib/parser/utils/type.js +1 -1
- package/dist/lib/renderer/render.js +36 -27
- package/dist/lib/syntax/color/cmyk.js +2 -2
- package/dist/lib/syntax/color/color-mix.js +11 -12
- package/dist/lib/syntax/color/color.js +7 -7
- package/dist/lib/syntax/color/hsl.js +4 -4
- package/dist/lib/syntax/color/hwb.js +27 -8
- package/dist/lib/syntax/color/lab.js +4 -4
- package/dist/lib/syntax/color/lch.js +4 -4
- package/dist/lib/syntax/color/oklab.js +4 -4
- package/dist/lib/syntax/color/oklch.js +4 -4
- package/dist/lib/syntax/color/relativecolor.js +1 -1
- package/dist/lib/syntax/color/rgb.js +4 -4
- package/dist/lib/syntax/color/utils/components.js +15 -3
- package/dist/lib/syntax/color/utils/distance.js +11 -1
- package/dist/lib/syntax/syntax.js +8 -17
- package/dist/lib/syntax/utils.js +1 -1
- package/dist/lib/validation/at-rules/document.js +1 -1
- package/dist/lib/validation/at-rules/import.js +4 -4
- package/dist/lib/validation/at-rules/keyframes.js +0 -11
- package/dist/lib/validation/at-rules/supports.js +6 -6
- package/dist/lib/validation/config.js +0 -4
- package/dist/lib/validation/parser/parse.js +0 -8
- package/dist/lib/validation/selector.js +0 -9
- package/dist/lib/validation/syntax.js +14 -134
- package/dist/lib/validation/syntaxes/complex-selector-list.js +0 -11
- package/dist/lib/validation/syntaxes/family-name.js +0 -32
- package/dist/lib/validation/syntaxes/keyframe-selector.js +0 -11
- package/dist/lib/validation/syntaxes/relative-selector-list.js +0 -26
- package/dist/lib/validation/syntaxes/url.js +0 -33
- package/dist/lib/validation/utils/list.js +0 -8
- package/package.json +1 -1
|
@@ -74,12 +74,12 @@ function color2RgbToken(token) {
|
|
|
74
74
|
}
|
|
75
75
|
function rgb2RgbToken(values) {
|
|
76
76
|
const chi = [
|
|
77
|
-
{ typ: EnumToken.NumberTokenType, val:
|
|
78
|
-
{ typ: EnumToken.NumberTokenType, val:
|
|
79
|
-
{ typ: EnumToken.NumberTokenType, val:
|
|
77
|
+
{ typ: EnumToken.NumberTokenType, val: values[0] },
|
|
78
|
+
{ typ: EnumToken.NumberTokenType, val: values[1] },
|
|
79
|
+
{ typ: EnumToken.NumberTokenType, val: values[2] },
|
|
80
80
|
];
|
|
81
81
|
if (values.length == 4) {
|
|
82
|
-
chi.push({ typ: EnumToken.PercentageTokenType, val:
|
|
82
|
+
chi.push({ typ: EnumToken.PercentageTokenType, val: values[3] * 100 });
|
|
83
83
|
}
|
|
84
84
|
return {
|
|
85
85
|
typ: EnumToken.ColorTokenType,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ColorType, EnumToken } from '../../../ast/types.js';
|
|
2
2
|
import '../../../ast/minify.js';
|
|
3
|
-
import '../../../ast/walk.js';
|
|
3
|
+
import { walkValues } from '../../../ast/walk.js';
|
|
4
4
|
import '../../../parser/parse.js';
|
|
5
5
|
import '../../../parser/tokenize.js';
|
|
6
6
|
import '../../../parser/utils/config.js';
|
|
@@ -13,7 +13,7 @@ function getComponents(token) {
|
|
|
13
13
|
const value = expandHexValue(token.kin == ColorType.LIT ? COLORS_NAMES[token.val.toLowerCase()] : token.val);
|
|
14
14
|
// @ts-ignore
|
|
15
15
|
return value.slice(1).match(/([a-fA-F0-9]{2})/g).map((t, index) => {
|
|
16
|
-
return { typ: EnumToken.Number, val:
|
|
16
|
+
return { typ: EnumToken.Number, val: index < 3 ? parseInt(t, 16) : parseInt(t, 16) / 255 };
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
const result = [];
|
|
@@ -23,7 +23,19 @@ function getComponents(token) {
|
|
|
23
23
|
].includes(child.typ)) {
|
|
24
24
|
continue;
|
|
25
25
|
}
|
|
26
|
-
if (child.typ == EnumToken.
|
|
26
|
+
if (child.typ == EnumToken.FunctionTokenType) {
|
|
27
|
+
if ('var' == child.val.toLowerCase()) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
for (const { value } of walkValues(child.chi)) {
|
|
32
|
+
if (value.typ == EnumToken.FunctionTokenType && 'var' === value.val.toLowerCase()) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (child.typ == EnumToken.ColorTokenType && 'currentcolor' === child.val.toLowerCase()) {
|
|
27
39
|
return null;
|
|
28
40
|
}
|
|
29
41
|
result.push(child);
|
|
@@ -9,13 +9,23 @@ import '../../../parser/utils/config.js';
|
|
|
9
9
|
import './constants.js';
|
|
10
10
|
import '../../../renderer/sourcemap/lib/encode.js';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Calculate the distance between two okLab colors.
|
|
14
|
+
* @param okLab1
|
|
15
|
+
* @param okLab2
|
|
16
|
+
*/
|
|
12
17
|
function okLabDistance(okLab1, okLab2) {
|
|
13
18
|
return Math.sqrt(Math.pow(okLab1[0] - okLab2[0], 2) + Math.pow(okLab1[1] - okLab2[1], 2) + Math.pow(okLab1[2] - okLab2[2], 2));
|
|
14
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Check if two colors are close.
|
|
22
|
+
* @param color1
|
|
23
|
+
* @param color2
|
|
24
|
+
* @param threshold
|
|
25
|
+
*/
|
|
15
26
|
function isOkLabClose(color1, color2, threshold = .01) {
|
|
16
27
|
color1 = convertColor(color1, ColorType.OKLAB);
|
|
17
28
|
color2 = convertColor(color2, ColorType.OKLAB);
|
|
18
|
-
// console.error(JSON.stringify({color1, color2}, null, 1));
|
|
19
29
|
if (color1 == null || color2 == null) {
|
|
20
30
|
return false;
|
|
21
31
|
}
|
|
@@ -499,18 +499,18 @@ function isPolarColorspace(token) {
|
|
|
499
499
|
}
|
|
500
500
|
function isHueInterpolationMethod(token) {
|
|
501
501
|
if (!Array.isArray(token)) {
|
|
502
|
-
return token.typ == EnumToken.IdenTokenType && 'hue'
|
|
502
|
+
return token.typ == EnumToken.IdenTokenType && 'hue' === token.val?.toLowerCase?.();
|
|
503
503
|
}
|
|
504
504
|
if (token.length != 2 || token[0].typ != EnumToken.IdenTokenType || token[1].typ != EnumToken.IdenTokenType) {
|
|
505
505
|
return false;
|
|
506
506
|
}
|
|
507
|
-
return ['shorter', 'longer', 'increasing', 'decreasing'].includes(token[0].val) && 'hue'
|
|
507
|
+
return ['shorter', 'longer', 'increasing', 'decreasing'].includes(token[0].val?.toLowerCase?.()) && 'hue' === token[1].val?.toLowerCase?.();
|
|
508
508
|
}
|
|
509
509
|
function isIdentColor(token) {
|
|
510
510
|
return token.typ == EnumToken.ColorTokenType && [ColorType.SYS, ColorType.DPSYS, ColorType.LIT].includes(token.kin) && isIdent(token.val);
|
|
511
511
|
}
|
|
512
512
|
function isPercentageToken(token) {
|
|
513
|
-
return token.typ == EnumToken.PercentageTokenType || (token.typ == EnumToken.NumberTokenType && token.val ==
|
|
513
|
+
return token.typ == EnumToken.PercentageTokenType || (token.typ == EnumToken.NumberTokenType && token.val == 0);
|
|
514
514
|
}
|
|
515
515
|
function isColor(token) {
|
|
516
516
|
if (token.typ == EnumToken.ColorTokenType) {
|
|
@@ -621,7 +621,7 @@ function isColor(token) {
|
|
|
621
621
|
if (children.length == 3) {
|
|
622
622
|
if (children[0].length > 4 ||
|
|
623
623
|
children[0][0].typ != EnumToken.IdenTokenType ||
|
|
624
|
-
'in'
|
|
624
|
+
'in' !== children[0][0].val?.toLowerCase?.() ||
|
|
625
625
|
!isColorspace(children[0][1]) ||
|
|
626
626
|
(children[0].length >= 3 && !isHueInterpolationMethod(children[0].slice(2))) ||
|
|
627
627
|
children[1].length > 2 ||
|
|
@@ -633,12 +633,12 @@ function isColor(token) {
|
|
|
633
633
|
return false;
|
|
634
634
|
}
|
|
635
635
|
if (children[1].length == 2) {
|
|
636
|
-
if (!(children[1][1].typ == EnumToken.PercentageTokenType || (children[1][1].typ == EnumToken.NumberTokenType && children[1][1].val ==
|
|
636
|
+
if (!(children[1][1].typ == EnumToken.PercentageTokenType || (children[1][1].typ == EnumToken.NumberTokenType && children[1][1].val == 0))) {
|
|
637
637
|
return false;
|
|
638
638
|
}
|
|
639
639
|
}
|
|
640
640
|
if (children[2].length == 2) {
|
|
641
|
-
if (!(children[2][1].typ == EnumToken.PercentageTokenType || (children[2][1].typ == EnumToken.NumberTokenType && children[2][1].val ==
|
|
641
|
+
if (!(children[2][1].typ == EnumToken.PercentageTokenType || (children[2][1].typ == EnumToken.NumberTokenType && children[2][1].val == 0))) {
|
|
642
642
|
return false;
|
|
643
643
|
}
|
|
644
644
|
}
|
|
@@ -782,15 +782,6 @@ function isIdent(name) {
|
|
|
782
782
|
}
|
|
783
783
|
return true;
|
|
784
784
|
}
|
|
785
|
-
function isNonPrintable(codepoint) {
|
|
786
|
-
// null -> backspace
|
|
787
|
-
return (codepoint >= 0 && codepoint <= 0x8) ||
|
|
788
|
-
// tab
|
|
789
|
-
codepoint == 0xb ||
|
|
790
|
-
// delete
|
|
791
|
-
codepoint == 0x7f ||
|
|
792
|
-
(codepoint >= 0xe && codepoint <= 0x1f);
|
|
793
|
-
}
|
|
794
785
|
function isPseudo(name) {
|
|
795
786
|
return name.charAt(0) == ':' &&
|
|
796
787
|
((name.endsWith('(') && isIdent(name.charAt(1) == ':' ? name.slice(2, -1) : name.slice(1, -1))) ||
|
|
@@ -897,7 +888,7 @@ function parseDimension(name) {
|
|
|
897
888
|
}
|
|
898
889
|
const dimension = {
|
|
899
890
|
typ: EnumToken.DimensionTokenType,
|
|
900
|
-
val: name.slice(0, index),
|
|
891
|
+
val: +name.slice(0, index),
|
|
901
892
|
unit: name.slice(index)
|
|
902
893
|
};
|
|
903
894
|
if (isAngle(dimension)) {
|
|
@@ -957,4 +948,4 @@ function isWhiteSpace(codepoint) {
|
|
|
957
948
|
codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
|
|
958
949
|
}
|
|
959
950
|
|
|
960
|
-
export { colorFontTech, fontFeaturesTech, fontFormat, isAngle, isAtKeyword, isColor, isColorspace, isDigit, isDimension, isFlex, isFrequency, isFunction, isHash, isHexColor, isHueInterpolationMethod, isIdent, isIdentCodepoint, isIdentColor, isIdentStart, isLength, isNewLine,
|
|
951
|
+
export { colorFontTech, fontFeaturesTech, fontFormat, isAngle, isAtKeyword, isColor, isColorspace, isDigit, isDimension, isFlex, isFrequency, isFunction, isHash, isHexColor, isHueInterpolationMethod, isIdent, isIdentCodepoint, isIdentColor, isIdentStart, isLength, isNewLine, isNumber, isPercentage, isPercentageToken, isPolarColorspace, isPseudo, isRectangularOrthogonalColorspace, isResolution, isTime, isWhiteSpace, mathFuncs, mediaTypes, mozExtensions, parseColor, parseDimension, pseudoAliasMap, pseudoElements, transformFunctions, webkitExtensions, wildCardFuncs };
|
package/dist/lib/syntax/utils.js
CHANGED
|
@@ -45,7 +45,7 @@ function validateAtRuleDocument(atRule, options, root) {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
// @ts-ignore
|
|
48
|
-
if ((t[0].typ != EnumToken.FunctionTokenType && t[0].typ != EnumToken.UrlFunctionTokenType) || !['url', 'url-prefix', 'domain', 'media-document', 'regexp'].
|
|
48
|
+
if ((t[0].typ != EnumToken.FunctionTokenType && t[0].typ != EnumToken.UrlFunctionTokenType) || !['url', 'url-prefix', 'domain', 'media-document', 'regexp'].includes(t[0].val?.toLowerCase?.())) {
|
|
49
49
|
return {
|
|
50
50
|
valid: SyntaxValidationResult.Drop,
|
|
51
51
|
context: [],
|
|
@@ -94,8 +94,7 @@ function validateAtRuleImport(atRule, options, root) {
|
|
|
94
94
|
if (tokens.length > 0) {
|
|
95
95
|
// @ts-ignore
|
|
96
96
|
if (tokens[0].typ == EnumToken.IdenTokenType) {
|
|
97
|
-
|
|
98
|
-
if ('layer'.localeCompare(tokens[0].val, undefined, { sensitivity: 'base' }) == 0) {
|
|
97
|
+
if ('layer' === tokens[0].val.toLowerCase()) {
|
|
99
98
|
tokens.shift();
|
|
100
99
|
// @ts-ignore
|
|
101
100
|
if (!consumeWhitespace(tokens)) {
|
|
@@ -113,7 +112,7 @@ function validateAtRuleImport(atRule, options, root) {
|
|
|
113
112
|
// @ts-ignore
|
|
114
113
|
else if (tokens[0].typ == EnumToken.FunctionTokenType) {
|
|
115
114
|
// @ts-ignore
|
|
116
|
-
if ('layer'
|
|
115
|
+
if ('layer' === tokens[0].val.toLowerCase()) {
|
|
117
116
|
const result = validateLayerName(tokens[0].chi);
|
|
118
117
|
if (result.valid == SyntaxValidationResult.Drop) {
|
|
119
118
|
return result;
|
|
@@ -122,8 +121,9 @@ function validateAtRuleImport(atRule, options, root) {
|
|
|
122
121
|
// @ts-ignore
|
|
123
122
|
consumeWhitespace(tokens);
|
|
124
123
|
}
|
|
124
|
+
// tokens[0]?.val
|
|
125
125
|
// @ts-ignore
|
|
126
|
-
if ('supports'
|
|
126
|
+
if ('supports' === tokens[0]?.val?.toLowerCase?.()) {
|
|
127
127
|
const result = validateAtRuleSupportsConditions(atRule, tokens[0].chi);
|
|
128
128
|
if (result.valid == SyntaxValidationResult.Drop) {
|
|
129
129
|
return result;
|
|
@@ -21,17 +21,6 @@ function validateAtRuleKeyframes(atRule, options, root) {
|
|
|
21
21
|
}
|
|
22
22
|
const tokens = atRule.tokens.filter((t) => t.typ != EnumToken.CommentTokenType).slice();
|
|
23
23
|
consumeWhitespace(tokens);
|
|
24
|
-
// if (tokens.length == 0) {
|
|
25
|
-
//
|
|
26
|
-
// // @ts-ignore
|
|
27
|
-
// return {
|
|
28
|
-
// valid: SyntaxValidationResult.Drop,
|
|
29
|
-
// context: [],
|
|
30
|
-
// node: atRule,
|
|
31
|
-
// syntax: '@keyframes',
|
|
32
|
-
// error: 'expecting at-rule prelude'
|
|
33
|
-
// } as ValidationSyntaxResult;
|
|
34
|
-
// }
|
|
35
24
|
if (tokens.length == 0 || ![EnumToken.StringTokenType, EnumToken.IdenTokenType].includes(tokens[0].typ)) {
|
|
36
25
|
// @ts-ignore
|
|
37
26
|
return {
|
|
@@ -166,7 +166,7 @@ function validateSupportCondition(atRule, token) {
|
|
|
166
166
|
if (token.typ == EnumToken.MediaFeatureNotTokenType) {
|
|
167
167
|
return validateSupportCondition(atRule, token.val);
|
|
168
168
|
}
|
|
169
|
-
if (token.typ == EnumToken.FunctionTokenType && token.val.
|
|
169
|
+
if (token.typ == EnumToken.FunctionTokenType && 'selector' === token.val.toLowerCase()) {
|
|
170
170
|
return {
|
|
171
171
|
valid: SyntaxValidationResult.Valid,
|
|
172
172
|
context: [],
|
|
@@ -223,7 +223,7 @@ function validateSupportFeature(token) {
|
|
|
223
223
|
return validateSupportFeature(token.val);
|
|
224
224
|
}
|
|
225
225
|
if (token.typ == EnumToken.FunctionTokenType) {
|
|
226
|
-
if (token.val.
|
|
226
|
+
if ('selector' === token.val.toLowerCase()) {
|
|
227
227
|
return {
|
|
228
228
|
valid: SyntaxValidationResult.Valid,
|
|
229
229
|
context: [],
|
|
@@ -232,10 +232,10 @@ function validateSupportFeature(token) {
|
|
|
232
232
|
error: ''
|
|
233
233
|
};
|
|
234
234
|
}
|
|
235
|
-
if (
|
|
235
|
+
if ('font-tech' === token.val.toLowerCase()) {
|
|
236
236
|
const chi = token.chi.filter((t) => ![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ));
|
|
237
237
|
// @ts-ignore
|
|
238
|
-
return chi.length == 1 && chi[0].typ == EnumToken.IdenTokenType && colorFontTech.concat(fontFeaturesTech).
|
|
238
|
+
return chi.length == 1 && chi[0].typ == EnumToken.IdenTokenType && colorFontTech.concat(fontFeaturesTech).includes(chi[0].val.toLowerCase()) ?
|
|
239
239
|
{
|
|
240
240
|
valid: SyntaxValidationResult.Valid,
|
|
241
241
|
context: [],
|
|
@@ -251,10 +251,10 @@ function validateSupportFeature(token) {
|
|
|
251
251
|
error: 'expected font-tech'
|
|
252
252
|
};
|
|
253
253
|
}
|
|
254
|
-
if (
|
|
254
|
+
if ('font-format' === token.val.toLowerCase()) {
|
|
255
255
|
const chi = token.chi.filter((t) => ![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ));
|
|
256
256
|
// @ts-ignore
|
|
257
|
-
return chi.length == 1 && chi[0].typ == EnumToken.IdenTokenType && fontFormat.
|
|
257
|
+
return chi.length == 1 && chi[0].typ == EnumToken.IdenTokenType && fontFormat.includes(chi[0].val, toLowerCase()) ?
|
|
258
258
|
{
|
|
259
259
|
valid: SyntaxValidationResult.Valid,
|
|
260
260
|
context: [],
|
|
@@ -175,7 +175,6 @@ function parseSyntax(syntax) {
|
|
|
175
175
|
typ: ValidationTokenEnum.Root,
|
|
176
176
|
chi: []
|
|
177
177
|
}, 'pos', { ...objectProperties, value: { ind: 0, lin: 1, col: 0 } });
|
|
178
|
-
// return minify(doParseSyntax(syntaxes, tokenize(syntaxes), root)) as ValidationRootToken;
|
|
179
178
|
return minify(doParseSyntax(syntax, tokenize(syntax), root));
|
|
180
179
|
}
|
|
181
180
|
function matchParens(syntax, iterator) {
|
|
@@ -351,10 +350,6 @@ function matchAtRule(syntax, iterator) {
|
|
|
351
350
|
token.typ = ValidationTokenEnum.AtRule;
|
|
352
351
|
break;
|
|
353
352
|
}
|
|
354
|
-
// if (item.value.typ != ValidationTokenEnum.Whitespace) {
|
|
355
|
-
//
|
|
356
|
-
// console.error('unexpected token', item.value);
|
|
357
|
-
// }
|
|
358
353
|
item = iterator.next();
|
|
359
354
|
if (item.done) {
|
|
360
355
|
break;
|
|
@@ -971,9 +966,6 @@ function renderSyntax(token, parent) {
|
|
|
971
966
|
return '{' + token.chi.reduce((acc, t) => acc + renderSyntax(t), '') + '}';
|
|
972
967
|
case ValidationTokenEnum.DeclarationDefinitionToken:
|
|
973
968
|
return token.nam + ': ' + renderSyntax(token.val);
|
|
974
|
-
// case ValidationTokenEnum.ColumnArrayToken:
|
|
975
|
-
//
|
|
976
|
-
// return (token as ValidationColumnArrayToken).chi.reduce((acc: string, curr: ValidationToken) => acc + (acc.trim().length > 0 ? '||' : '') + renderSyntax(curr), '');
|
|
977
969
|
default:
|
|
978
970
|
throw new Error('Unhandled token: ' + JSON.stringify({ token }, null, 1));
|
|
979
971
|
}
|
|
@@ -13,15 +13,6 @@ import './config.js';
|
|
|
13
13
|
import { validateSelectorList } from './syntaxes/selector-list.js';
|
|
14
14
|
|
|
15
15
|
function validateSelector(selector, options, root) {
|
|
16
|
-
// if (root == null) {
|
|
17
|
-
//
|
|
18
|
-
// return validateSelectorList(selector, root, options);
|
|
19
|
-
// }
|
|
20
|
-
// @ts-ignore
|
|
21
|
-
// if (root.typ == EnumToken.AtRuleNodeType && root.nam.match(/^(-[a-z]+-)?keyframes$/)) {
|
|
22
|
-
//
|
|
23
|
-
// return validateKeyframeBlockList(selector, root as AstAtRule, options);
|
|
24
|
-
// }
|
|
25
16
|
let isNested = root.typ == EnumToken.RuleNodeType ? 1 : 0;
|
|
26
17
|
let currentRoot = root.parent;
|
|
27
18
|
while (currentRoot != null && isNested == 0) {
|