@projectwallace/css-parser 0.8.6 → 0.8.7
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/dist/arena.d.ts +1 -0
- package/dist/arena.js +2 -1
- package/dist/css-node.d.ts +3 -0
- package/dist/css-node.js +10 -2
- package/dist/parse-declaration.js +49 -6
- package/dist/parse.js +13 -4
- package/package.json +1 -1
package/dist/arena.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ export declare const FLAG_HAS_BLOCK: number;
|
|
|
41
41
|
export declare const FLAG_VENDOR_PREFIXED: number;
|
|
42
42
|
export declare const FLAG_HAS_DECLARATIONS: number;
|
|
43
43
|
export declare const FLAG_HAS_PARENS: number;
|
|
44
|
+
export declare const FLAG_BROWSERHACK: number;
|
|
44
45
|
export declare const ATTR_OPERATOR_NONE = 0;
|
|
45
46
|
export declare const ATTR_OPERATOR_EQUAL = 1;
|
|
46
47
|
export declare const ATTR_OPERATOR_TILDE_EQUAL = 2;
|
package/dist/arena.js
CHANGED
|
@@ -41,6 +41,7 @@ const FLAG_LENGTH_OVERFLOW = 1 << 2;
|
|
|
41
41
|
const FLAG_HAS_BLOCK = 1 << 3;
|
|
42
42
|
const FLAG_HAS_DECLARATIONS = 1 << 5;
|
|
43
43
|
const FLAG_HAS_PARENS = 1 << 6;
|
|
44
|
+
const FLAG_BROWSERHACK = 1 << 7;
|
|
44
45
|
const ATTR_OPERATOR_NONE = 0;
|
|
45
46
|
const ATTR_OPERATOR_EQUAL = 1;
|
|
46
47
|
const ATTR_OPERATOR_TILDE_EQUAL = 2;
|
|
@@ -279,4 +280,4 @@ class CSSDataArena {
|
|
|
279
280
|
}
|
|
280
281
|
}
|
|
281
282
|
|
|
282
|
-
export { ATTRIBUTE_SELECTOR, ATTR_FLAG_CASE_INSENSITIVE, ATTR_FLAG_CASE_SENSITIVE, ATTR_FLAG_NONE, ATTR_OPERATOR_CARET_EQUAL, ATTR_OPERATOR_DOLLAR_EQUAL, ATTR_OPERATOR_EQUAL, ATTR_OPERATOR_NONE, ATTR_OPERATOR_PIPE_EQUAL, ATTR_OPERATOR_STAR_EQUAL, ATTR_OPERATOR_TILDE_EQUAL, AT_RULE, BLOCK, CLASS_SELECTOR, COMBINATOR, COMMENT, CONTAINER_QUERY, CSSDataArena, DECLARATION, DIMENSION, FLAG_HAS_BLOCK, FLAG_HAS_DECLARATIONS, FLAG_HAS_ERROR, FLAG_HAS_PARENS, FLAG_IMPORTANT, FLAG_LENGTH_OVERFLOW, FUNCTION, HASH, IDENTIFIER, ID_SELECTOR, LANG_SELECTOR, LAYER_NAME, MEDIA_FEATURE, MEDIA_QUERY, MEDIA_TYPE, NESTING_SELECTOR, NTH_OF_SELECTOR, NTH_SELECTOR, NUMBER, OPERATOR, PARENTHESIS, PRELUDE_OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, SELECTOR, SELECTOR_LIST, STRING, STYLESHEET, STYLE_RULE, SUPPORTS_QUERY, TYPE_SELECTOR, UNIVERSAL_SELECTOR, URL };
|
|
283
|
+
export { ATTRIBUTE_SELECTOR, ATTR_FLAG_CASE_INSENSITIVE, ATTR_FLAG_CASE_SENSITIVE, ATTR_FLAG_NONE, ATTR_OPERATOR_CARET_EQUAL, ATTR_OPERATOR_DOLLAR_EQUAL, ATTR_OPERATOR_EQUAL, ATTR_OPERATOR_NONE, ATTR_OPERATOR_PIPE_EQUAL, ATTR_OPERATOR_STAR_EQUAL, ATTR_OPERATOR_TILDE_EQUAL, AT_RULE, BLOCK, CLASS_SELECTOR, COMBINATOR, COMMENT, CONTAINER_QUERY, CSSDataArena, DECLARATION, DIMENSION, FLAG_BROWSERHACK, FLAG_HAS_BLOCK, FLAG_HAS_DECLARATIONS, FLAG_HAS_ERROR, FLAG_HAS_PARENS, FLAG_IMPORTANT, FLAG_LENGTH_OVERFLOW, FUNCTION, HASH, IDENTIFIER, ID_SELECTOR, LANG_SELECTOR, LAYER_NAME, MEDIA_FEATURE, MEDIA_QUERY, MEDIA_TYPE, NESTING_SELECTOR, NTH_OF_SELECTOR, NTH_SELECTOR, NUMBER, OPERATOR, PARENTHESIS, PRELUDE_OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, SELECTOR, SELECTOR_LIST, STRING, STYLESHEET, STYLE_RULE, SUPPORTS_QUERY, TYPE_SELECTOR, UNIVERSAL_SELECTOR, URL };
|
package/dist/css-node.d.ts
CHANGED
|
@@ -64,6 +64,7 @@ export type PlainCSSNode = {
|
|
|
64
64
|
prelude?: string;
|
|
65
65
|
is_important?: boolean;
|
|
66
66
|
is_vendor_prefixed?: boolean;
|
|
67
|
+
is_browserhack?: boolean;
|
|
67
68
|
has_error?: boolean;
|
|
68
69
|
attr_operator?: number;
|
|
69
70
|
attr_flags?: number;
|
|
@@ -124,6 +125,8 @@ export declare class CSSNode {
|
|
|
124
125
|
get unit(): string | null;
|
|
125
126
|
/** Check if this declaration has !important */
|
|
126
127
|
get is_important(): boolean | null;
|
|
128
|
+
/** Check if this declaration has a browser hack prefix */
|
|
129
|
+
get is_browserhack(): boolean | null;
|
|
127
130
|
/** Check if this has a vendor prefix (computed on-demand) */
|
|
128
131
|
get is_vendor_prefixed(): boolean;
|
|
129
132
|
/** Check if this node has an error */
|
package/dist/css-node.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DIMENSION, NUMBER, URL, STRING, DECLARATION, FLAG_IMPORTANT, IDENTIFIER, FUNCTION, AT_RULE, PSEUDO_ELEMENT_SELECTOR, PSEUDO_CLASS_SELECTOR, FLAG_HAS_ERROR, FLAG_HAS_BLOCK, FLAG_HAS_DECLARATIONS, STYLE_RULE, BLOCK, COMMENT, FLAG_HAS_PARENS, NTH_SELECTOR, NTH_OF_SELECTOR, SELECTOR_LIST, SELECTOR, COMBINATOR, ATTRIBUTE_SELECTOR, PRELUDE_OPERATOR, LAYER_NAME, SUPPORTS_QUERY, CONTAINER_QUERY, MEDIA_TYPE, MEDIA_FEATURE, MEDIA_QUERY, LANG_SELECTOR, NESTING_SELECTOR, UNIVERSAL_SELECTOR, ID_SELECTOR, CLASS_SELECTOR, TYPE_SELECTOR, PARENTHESIS, OPERATOR, HASH, STYLESHEET } from './arena.js';
|
|
1
|
+
import { DIMENSION, NUMBER, URL, STRING, DECLARATION, FLAG_IMPORTANT, FLAG_BROWSERHACK, IDENTIFIER, FUNCTION, AT_RULE, PSEUDO_ELEMENT_SELECTOR, PSEUDO_CLASS_SELECTOR, FLAG_HAS_ERROR, FLAG_HAS_BLOCK, FLAG_HAS_DECLARATIONS, STYLE_RULE, BLOCK, COMMENT, FLAG_HAS_PARENS, NTH_SELECTOR, NTH_OF_SELECTOR, SELECTOR_LIST, SELECTOR, COMBINATOR, ATTRIBUTE_SELECTOR, PRELUDE_OPERATOR, LAYER_NAME, SUPPORTS_QUERY, CONTAINER_QUERY, MEDIA_TYPE, MEDIA_FEATURE, MEDIA_QUERY, LANG_SELECTOR, NESTING_SELECTOR, UNIVERSAL_SELECTOR, ID_SELECTOR, CLASS_SELECTOR, TYPE_SELECTOR, PARENTHESIS, OPERATOR, HASH, STYLESHEET } from './arena.js';
|
|
2
2
|
import { str_starts_with, is_vendor_prefixed, is_whitespace, CHAR_MINUS_HYPHEN, CHAR_PLUS } from './string-utils.js';
|
|
3
3
|
import { parse_dimension } from './parse-utils.js';
|
|
4
4
|
|
|
@@ -160,6 +160,11 @@ class CSSNode {
|
|
|
160
160
|
if (this.type !== DECLARATION) return null;
|
|
161
161
|
return this.arena.has_flag(this.index, FLAG_IMPORTANT);
|
|
162
162
|
}
|
|
163
|
+
/** Check if this declaration has a browser hack prefix */
|
|
164
|
+
get is_browserhack() {
|
|
165
|
+
if (this.type !== DECLARATION) return null;
|
|
166
|
+
return this.arena.has_flag(this.index, FLAG_BROWSERHACK);
|
|
167
|
+
}
|
|
163
168
|
/** Check if this has a vendor prefix (computed on-demand) */
|
|
164
169
|
get is_vendor_prefixed() {
|
|
165
170
|
switch (this.type) {
|
|
@@ -478,7 +483,10 @@ class CSSNode {
|
|
|
478
483
|
if (this.type === AT_RULE && this.prelude) {
|
|
479
484
|
plain.prelude = this.prelude;
|
|
480
485
|
}
|
|
481
|
-
if (this.type === DECLARATION)
|
|
486
|
+
if (this.type === DECLARATION) {
|
|
487
|
+
plain.is_important = this.is_important;
|
|
488
|
+
plain.is_browserhack = this.is_browserhack;
|
|
489
|
+
}
|
|
482
490
|
plain.is_vendor_prefixed = this.is_vendor_prefixed;
|
|
483
491
|
plain.has_error = this.has_error;
|
|
484
492
|
if (this.type === ATTRIBUTE_SELECTOR) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Lexer } from './tokenize.js';
|
|
2
|
-
import { CSSDataArena, DECLARATION, FLAG_IMPORTANT } from './arena.js';
|
|
2
|
+
import { CSSDataArena, DECLARATION, FLAG_IMPORTANT, FLAG_BROWSERHACK } from './arena.js';
|
|
3
3
|
import { ValueParser } from './parse-value.js';
|
|
4
|
-
import {
|
|
4
|
+
import { is_vendor_prefixed } from './string-utils.js';
|
|
5
|
+
import { TOKEN_AT_KEYWORD, TOKEN_HASH, TOKEN_IDENT, TOKEN_DELIM, TOKEN_LEFT_PAREN, TOKEN_RIGHT_PAREN, TOKEN_LEFT_BRACKET, TOKEN_RIGHT_BRACKET, TOKEN_COMMA, TOKEN_COLON, TOKEN_EOF, TOKEN_SEMICOLON, TOKEN_RIGHT_BRACE, TOKEN_LEFT_BRACE } from './token-types.js';
|
|
5
6
|
import { trim_boundaries } from './parse-utils.js';
|
|
6
7
|
import { CSSNode } from './css-node.js';
|
|
7
8
|
|
|
@@ -25,13 +26,52 @@ class DeclarationParser {
|
|
|
25
26
|
}
|
|
26
27
|
// Parse a declaration using a provided lexer (used by Parser to avoid re-tokenization)
|
|
27
28
|
parse_declaration_with_lexer(lexer, end) {
|
|
28
|
-
|
|
29
|
+
let has_browser_hack = false;
|
|
30
|
+
let browser_hack_start = 0;
|
|
31
|
+
let browser_hack_line = 1;
|
|
32
|
+
let browser_hack_column = 1;
|
|
33
|
+
if (lexer.token_type === TOKEN_AT_KEYWORD || lexer.token_type === TOKEN_HASH) {
|
|
34
|
+
has_browser_hack = true;
|
|
35
|
+
browser_hack_start = lexer.token_start;
|
|
36
|
+
browser_hack_line = lexer.token_line;
|
|
37
|
+
browser_hack_column = lexer.token_column;
|
|
38
|
+
} else if (lexer.token_type === TOKEN_IDENT) {
|
|
39
|
+
const first_char = this.source.charCodeAt(lexer.token_start);
|
|
40
|
+
if (first_char === 95) {
|
|
41
|
+
has_browser_hack = true;
|
|
42
|
+
browser_hack_start = lexer.token_start;
|
|
43
|
+
browser_hack_line = lexer.token_line;
|
|
44
|
+
browser_hack_column = lexer.token_column;
|
|
45
|
+
} else if (first_char === 45) {
|
|
46
|
+
if (!is_vendor_prefixed(this.source, lexer.token_start, lexer.token_end)) {
|
|
47
|
+
has_browser_hack = true;
|
|
48
|
+
browser_hack_start = lexer.token_start;
|
|
49
|
+
browser_hack_line = lexer.token_line;
|
|
50
|
+
browser_hack_column = lexer.token_column;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
const is_browser_hack_token = lexer.token_type === TOKEN_DELIM || lexer.token_type === TOKEN_LEFT_PAREN || lexer.token_type === TOKEN_RIGHT_PAREN || lexer.token_type === TOKEN_LEFT_BRACKET || lexer.token_type === TOKEN_RIGHT_BRACKET || lexer.token_type === TOKEN_COMMA || lexer.token_type === TOKEN_COLON;
|
|
55
|
+
if (is_browser_hack_token) {
|
|
56
|
+
const delim_saved = lexer.save_position();
|
|
57
|
+
browser_hack_start = lexer.token_start;
|
|
58
|
+
browser_hack_line = lexer.token_line;
|
|
59
|
+
browser_hack_column = lexer.token_column;
|
|
60
|
+
lexer.next_token_fast(true);
|
|
61
|
+
if (lexer.token_type === TOKEN_IDENT) {
|
|
62
|
+
has_browser_hack = true;
|
|
63
|
+
} else {
|
|
64
|
+
lexer.restore_position(delim_saved);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (lexer.token_type !== TOKEN_IDENT && lexer.token_type !== TOKEN_AT_KEYWORD && lexer.token_type !== TOKEN_HASH) {
|
|
29
69
|
return null;
|
|
30
70
|
}
|
|
31
|
-
let prop_start = lexer.token_start;
|
|
71
|
+
let prop_start = has_browser_hack ? browser_hack_start : lexer.token_start;
|
|
32
72
|
let prop_end = lexer.token_end;
|
|
33
|
-
let decl_line = lexer.token_line;
|
|
34
|
-
let decl_column = lexer.token_column;
|
|
73
|
+
let decl_line = has_browser_hack ? browser_hack_line : lexer.token_line;
|
|
74
|
+
let decl_column = has_browser_hack ? browser_hack_column : lexer.token_column;
|
|
35
75
|
const saved = lexer.save_position();
|
|
36
76
|
lexer.next_token_fast(true);
|
|
37
77
|
if (lexer.token_type !== TOKEN_COLON) {
|
|
@@ -92,6 +132,9 @@ class DeclarationParser {
|
|
|
92
132
|
if (has_important) {
|
|
93
133
|
this.arena.set_flag(declaration, FLAG_IMPORTANT);
|
|
94
134
|
}
|
|
135
|
+
if (has_browser_hack) {
|
|
136
|
+
this.arena.set_flag(declaration, FLAG_BROWSERHACK);
|
|
137
|
+
}
|
|
95
138
|
if (lexer.token_type === TOKEN_SEMICOLON) {
|
|
96
139
|
last_end = lexer.token_end;
|
|
97
140
|
lexer.next_token_fast(true);
|
package/dist/parse.js
CHANGED
|
@@ -4,8 +4,9 @@ import { CSSNode } from './css-node.js';
|
|
|
4
4
|
import { SelectorParser } from './parse-selector.js';
|
|
5
5
|
import { AtRulePreludeParser } from './parse-atrule-prelude.js';
|
|
6
6
|
import { DeclarationParser } from './parse-declaration.js';
|
|
7
|
-
import { TOKEN_EOF, TOKEN_AT_KEYWORD, TOKEN_LEFT_BRACE, TOKEN_RIGHT_BRACE, TOKEN_IDENT, TOKEN_SEMICOLON } from './token-types.js';
|
|
7
|
+
import { TOKEN_EOF, TOKEN_AT_KEYWORD, TOKEN_LEFT_BRACE, TOKEN_RIGHT_BRACE, TOKEN_IDENT, TOKEN_HASH, TOKEN_DELIM, TOKEN_LEFT_PAREN, TOKEN_RIGHT_PAREN, TOKEN_LEFT_BRACKET, TOKEN_RIGHT_BRACKET, TOKEN_COMMA, TOKEN_COLON, TOKEN_SEMICOLON } from './token-types.js';
|
|
8
8
|
import { trim_boundaries } from './parse-utils.js';
|
|
9
|
+
import { CHAR_PERIOD, CHAR_GREATER_THAN, CHAR_PLUS, CHAR_TILDE, CHAR_AMPERSAND } from './string-utils.js';
|
|
9
10
|
|
|
10
11
|
let DECLARATION_AT_RULES = /* @__PURE__ */ new Set(["font-face", "font-feature-values", "page", "property", "counter-style"]);
|
|
11
12
|
let CONDITIONAL_AT_RULES = /* @__PURE__ */ new Set(["media", "supports", "container", "layer", "nest"]);
|
|
@@ -176,10 +177,18 @@ class Parser {
|
|
|
176
177
|
}
|
|
177
178
|
// Parse a declaration: property: value;
|
|
178
179
|
parse_declaration() {
|
|
179
|
-
|
|
180
|
-
|
|
180
|
+
const token_type = this.peek_type();
|
|
181
|
+
if (token_type === TOKEN_IDENT || token_type === TOKEN_AT_KEYWORD || token_type === TOKEN_HASH) {
|
|
182
|
+
return this.declaration_parser.parse_declaration_with_lexer(this.lexer, this.source.length);
|
|
183
|
+
}
|
|
184
|
+
if (token_type === TOKEN_DELIM || token_type === TOKEN_LEFT_PAREN || token_type === TOKEN_RIGHT_PAREN || token_type === TOKEN_LEFT_BRACKET || token_type === TOKEN_RIGHT_BRACKET || token_type === TOKEN_COMMA || token_type === TOKEN_COLON) {
|
|
185
|
+
const char_code = this.source.charCodeAt(this.lexer.token_start);
|
|
186
|
+
if (char_code === CHAR_PERIOD || char_code === CHAR_GREATER_THAN || char_code === CHAR_PLUS || char_code === CHAR_TILDE || char_code === CHAR_AMPERSAND) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
return this.declaration_parser.parse_declaration_with_lexer(this.lexer, this.source.length);
|
|
181
190
|
}
|
|
182
|
-
return
|
|
191
|
+
return null;
|
|
183
192
|
}
|
|
184
193
|
// Parse an at-rule: @media, @import, @font-face, etc.
|
|
185
194
|
parse_atrule() {
|
package/package.json
CHANGED