@projectwallace/css-parser 0.13.5 → 0.13.6
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/css-node-2ejJUrIw.js +645 -0
- package/dist/css-node-DqyvMXBN.d.ts +313 -0
- package/dist/index.d.ts +150 -16
- package/dist/index.js +103 -13
- package/dist/parse-anplusb.d.ts +26 -2
- package/dist/parse-anplusb.js +191 -207
- package/dist/parse-atrule-prelude.d.ts +40 -2
- package/dist/parse-atrule-prelude.js +556 -652
- package/dist/parse-declaration.d.ts +16 -2
- package/dist/parse-declaration.js +140 -167
- package/dist/parse-dimension-CCn_XRDe.js +177 -0
- package/dist/parse-dimension.d.ts +6 -3
- package/dist/parse-dimension.js +1 -35
- package/dist/parse-selector.d.ts +37 -2
- package/dist/parse-selector.js +508 -635
- package/dist/parse-utils-DnsZRpfd.js +98 -0
- package/dist/parse-value.d.ts +23 -2
- package/dist/parse-value.js +176 -224
- package/dist/parse.d.ts +38 -8
- package/dist/parse.js +274 -353
- package/dist/tokenize-BQFB1jXg.js +540 -0
- package/dist/tokenize-odLrcjj2.d.ts +110 -0
- package/dist/tokenize.d.ts +2 -26
- package/dist/tokenize.js +1 -545
- package/package.json +20 -26
- package/dist/arena.d.ts +0 -60
- package/dist/arena.js +0 -291
- package/dist/char-types.d.ts +0 -14
- package/dist/char-types.js +0 -53
- package/dist/constants.d.ts +0 -44
- package/dist/constants.js +0 -51
- package/dist/css-node.d.ts +0 -203
- package/dist/css-node.js +0 -498
- package/dist/parse-utils.d.ts +0 -1
- package/dist/parse-utils.js +0 -60
- package/dist/string-utils.d.ts +0 -99
- package/dist/string-utils.js +0 -129
- package/dist/token-types.d.ts +0 -35
- package/dist/token-types.js +0 -29
- package/dist/walk.d.ts +0 -28
- package/dist/walk.js +0 -51
|
@@ -1,7 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as Lexer } from "./tokenize-odLrcjj2.js";
|
|
2
|
+
import { E as CSSDataArena, r as CSSNode } from "./css-node-DqyvMXBN.js";
|
|
3
|
+
|
|
4
|
+
//#region src/parse-declaration.d.ts
|
|
5
|
+
/** @internal */
|
|
6
|
+
declare class DeclarationParser {
|
|
7
|
+
private arena;
|
|
8
|
+
private source;
|
|
9
|
+
private value_parser;
|
|
10
|
+
constructor(arena: CSSDataArena, source: string, parse_values?: boolean);
|
|
11
|
+
parse_declaration(start: number, end: number, line?: number, column?: number): number | null;
|
|
12
|
+
parse_declaration_with_lexer(lexer: Lexer, end: number): number | null;
|
|
13
|
+
}
|
|
2
14
|
/**
|
|
3
15
|
* Parse a CSS declaration string and return an AST
|
|
4
16
|
* @param source - The CSS declaration to parse (e.g., "color: red", "margin: 10px !important")
|
|
5
17
|
* @returns The DECLARATION CSSNode
|
|
6
18
|
*/
|
|
7
|
-
|
|
19
|
+
declare function parse_declaration(source: string): CSSNode;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { DeclarationParser, parse_declaration };
|
|
@@ -1,170 +1,143 @@
|
|
|
1
|
-
import { Lexer } from
|
|
2
|
-
import { CSSDataArena,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
} else {
|
|
138
|
-
this.arena.set_value_start_delta(declaration, value_start - prop_start);
|
|
139
|
-
this.arena.set_value_length(declaration, 0);
|
|
140
|
-
if (this.value_parser) {
|
|
141
|
-
let valueNode = this.value_parser.parse_value(value_start, value_start, value_start_line, value_start_column);
|
|
142
|
-
this.arena.append_children(declaration, [valueNode]);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
if (has_important) {
|
|
146
|
-
this.arena.set_flag(declaration, FLAG_IMPORTANT);
|
|
147
|
-
}
|
|
148
|
-
if (has_browser_hack) {
|
|
149
|
-
this.arena.set_flag(declaration, FLAG_BROWSERHACK);
|
|
150
|
-
}
|
|
151
|
-
if (lexer.token_type === TOKEN_SEMICOLON) {
|
|
152
|
-
last_end = lexer.token_end;
|
|
153
|
-
lexer.next_token_fast(true);
|
|
154
|
-
}
|
|
155
|
-
this.arena.set_length(declaration, last_end - prop_start);
|
|
156
|
-
return declaration;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
1
|
+
import { t as Lexer } from "./tokenize-BQFB1jXg.js";
|
|
2
|
+
import { C as CSSDataArena, r as CSSNode } from "./css-node-2ejJUrIw.js";
|
|
3
|
+
import { i as is_vendor_prefixed } from "./parse-dimension-CCn_XRDe.js";
|
|
4
|
+
import { i as trim_boundaries } from "./parse-utils-DnsZRpfd.js";
|
|
5
|
+
import { ValueParser } from "./parse-value.js";
|
|
6
|
+
//#region src/parse-declaration.ts
|
|
7
|
+
/** @internal */
|
|
8
|
+
var DeclarationParser = class {
|
|
9
|
+
arena;
|
|
10
|
+
source;
|
|
11
|
+
value_parser;
|
|
12
|
+
constructor(arena, source, parse_values = true) {
|
|
13
|
+
this.arena = arena;
|
|
14
|
+
this.source = source;
|
|
15
|
+
this.value_parser = parse_values ? new ValueParser(arena, source) : null;
|
|
16
|
+
}
|
|
17
|
+
parse_declaration(start, end, line = 1, column = 1) {
|
|
18
|
+
const lexer = new Lexer(this.source);
|
|
19
|
+
lexer.seek(start, line, column);
|
|
20
|
+
lexer.next_token_fast(true);
|
|
21
|
+
return this.parse_declaration_with_lexer(lexer, end);
|
|
22
|
+
}
|
|
23
|
+
parse_declaration_with_lexer(lexer, end) {
|
|
24
|
+
let has_browser_hack = false;
|
|
25
|
+
let browser_hack_start = 0;
|
|
26
|
+
let browser_hack_line = 1;
|
|
27
|
+
let browser_hack_column = 1;
|
|
28
|
+
if (lexer.token_type === 1) {
|
|
29
|
+
const first_char = this.source.charCodeAt(lexer.token_start);
|
|
30
|
+
if (first_char === 95) {
|
|
31
|
+
has_browser_hack = true;
|
|
32
|
+
browser_hack_start = lexer.token_start;
|
|
33
|
+
browser_hack_line = lexer.token_line;
|
|
34
|
+
browser_hack_column = lexer.token_column;
|
|
35
|
+
} else if (first_char === 45) {
|
|
36
|
+
if (this.source.charCodeAt(lexer.token_start + 1) !== 45 && !is_vendor_prefixed(this.source, lexer.token_start, lexer.token_end)) {
|
|
37
|
+
has_browser_hack = true;
|
|
38
|
+
browser_hack_start = lexer.token_start;
|
|
39
|
+
browser_hack_line = lexer.token_line;
|
|
40
|
+
browser_hack_column = lexer.token_column;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
} else if (lexer.token_type === 3 || lexer.token_type === 4) {
|
|
44
|
+
has_browser_hack = true;
|
|
45
|
+
browser_hack_start = lexer.token_start;
|
|
46
|
+
browser_hack_line = lexer.token_line;
|
|
47
|
+
browser_hack_column = lexer.token_column;
|
|
48
|
+
} else if (lexer.token_type === 9 || lexer.token_type === 21 || lexer.token_type === 22 || lexer.token_type === 19 || lexer.token_type === 20 || lexer.token_type === 18 || lexer.token_type === 16) {
|
|
49
|
+
const delim_saved = lexer.save_position();
|
|
50
|
+
browser_hack_start = lexer.token_start;
|
|
51
|
+
browser_hack_line = lexer.token_line;
|
|
52
|
+
browser_hack_column = lexer.token_column;
|
|
53
|
+
lexer.next_token_fast(true);
|
|
54
|
+
if (lexer.token_type === 1) has_browser_hack = true;
|
|
55
|
+
else lexer.restore_position(delim_saved);
|
|
56
|
+
}
|
|
57
|
+
if (lexer.token_type !== 1 && lexer.token_type !== 3 && lexer.token_type !== 4) return null;
|
|
58
|
+
let prop_start = has_browser_hack ? browser_hack_start : lexer.token_start;
|
|
59
|
+
let prop_end = lexer.token_end;
|
|
60
|
+
let decl_line = has_browser_hack ? browser_hack_line : lexer.token_line;
|
|
61
|
+
let decl_column = has_browser_hack ? browser_hack_column : lexer.token_column;
|
|
62
|
+
const saved = lexer.save_position();
|
|
63
|
+
lexer.next_token_fast(true);
|
|
64
|
+
if (lexer.token_type !== 16) {
|
|
65
|
+
lexer.restore_position(saved);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
lexer.next_token_fast(true);
|
|
69
|
+
let declaration = this.arena.create_node(4, prop_start, 0, decl_line, decl_column);
|
|
70
|
+
this.arena.set_content_start_delta(declaration, 0);
|
|
71
|
+
this.arena.set_content_length(declaration, prop_end - prop_start);
|
|
72
|
+
let value_start = lexer.token_start;
|
|
73
|
+
let value_start_line = lexer.token_line;
|
|
74
|
+
let value_start_column = lexer.token_column;
|
|
75
|
+
let value_end = value_start;
|
|
76
|
+
let has_important = false;
|
|
77
|
+
let last_end = lexer.token_end;
|
|
78
|
+
let paren_depth = 0;
|
|
79
|
+
while (lexer.token_type !== 26 && lexer.token_start < end) {
|
|
80
|
+
let token_type = lexer.token_type;
|
|
81
|
+
if (token_type === 21 || token_type === 2) paren_depth++;
|
|
82
|
+
else if (token_type === 22) paren_depth--;
|
|
83
|
+
if (token_type === 17 && paren_depth === 0) break;
|
|
84
|
+
if (token_type === 24 && paren_depth === 0) break;
|
|
85
|
+
if (token_type === 23) {
|
|
86
|
+
lexer.restore_position(saved);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
if (token_type === 9 && this.source[lexer.token_start] === "!") {
|
|
90
|
+
value_end = lexer.token_start;
|
|
91
|
+
if (lexer.next_token_fast(true) === 1) {
|
|
92
|
+
has_important = true;
|
|
93
|
+
last_end = lexer.token_end;
|
|
94
|
+
lexer.next_token_fast(true);
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
last_end = lexer.token_end;
|
|
99
|
+
value_end = last_end;
|
|
100
|
+
lexer.next_token_fast(true);
|
|
101
|
+
}
|
|
102
|
+
let trimmed = trim_boundaries(this.source, value_start, value_end);
|
|
103
|
+
if (trimmed) {
|
|
104
|
+
this.arena.set_value_start_delta(declaration, trimmed[0] - prop_start);
|
|
105
|
+
this.arena.set_value_length(declaration, trimmed[1] - trimmed[0]);
|
|
106
|
+
if (this.value_parser) {
|
|
107
|
+
let valueNode = this.value_parser.parse_value(value_start, trimmed[1], value_start_line, value_start_column);
|
|
108
|
+
this.arena.append_children(declaration, [valueNode]);
|
|
109
|
+
} else {
|
|
110
|
+
let rawNode = this.arena.create_node(8, trimmed[0], trimmed[1] - trimmed[0], value_start_line, value_start_column);
|
|
111
|
+
this.arena.append_children(declaration, [rawNode]);
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
this.arena.set_value_start_delta(declaration, value_start - prop_start);
|
|
115
|
+
this.arena.set_value_length(declaration, 0);
|
|
116
|
+
if (this.value_parser) {
|
|
117
|
+
let valueNode = this.value_parser.parse_value(value_start, value_start, value_start_line, value_start_column);
|
|
118
|
+
this.arena.append_children(declaration, [valueNode]);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (has_important) this.arena.set_flag(declaration, 1);
|
|
122
|
+
if (has_browser_hack) this.arena.set_flag(declaration, 128);
|
|
123
|
+
if (lexer.token_type === 17) {
|
|
124
|
+
last_end = lexer.token_end;
|
|
125
|
+
lexer.next_token_fast(true);
|
|
126
|
+
}
|
|
127
|
+
this.arena.set_length(declaration, last_end - prop_start);
|
|
128
|
+
return declaration;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Parse a CSS declaration string and return an AST
|
|
133
|
+
* @param source - The CSS declaration to parse (e.g., "color: red", "margin: 10px !important")
|
|
134
|
+
* @returns The DECLARATION CSSNode
|
|
135
|
+
*/
|
|
159
136
|
function parse_declaration(source) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const empty = arena.create_node(DECLARATION, 0, 0, 1, 1);
|
|
165
|
-
return new CSSNode(arena, source, empty);
|
|
166
|
-
}
|
|
167
|
-
return new CSSNode(arena, source, decl_index);
|
|
137
|
+
const arena = new CSSDataArena(CSSDataArena.capacity_for_source(source.length));
|
|
138
|
+
const decl_index = new DeclarationParser(arena, source).parse_declaration(0, source.length);
|
|
139
|
+
if (decl_index === null) return new CSSNode(arena, source, arena.create_node(4, 0, 0, 1, 1));
|
|
140
|
+
return new CSSNode(arena, source, decl_index);
|
|
168
141
|
}
|
|
169
|
-
|
|
142
|
+
//#endregion
|
|
170
143
|
export { DeclarationParser, parse_declaration };
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if a character code is whitespace (space, tab, newline, CR, or FF)
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
function is_whitespace(ch) {
|
|
6
|
+
return ch === 32 || ch === 9 || ch === 10 || ch === 13 || ch === 12;
|
|
7
|
+
}
|
|
8
|
+
/** @internal */
|
|
9
|
+
function is_combinator(ch) {
|
|
10
|
+
return ch === 62 || ch === 43 || ch === 126;
|
|
11
|
+
}
|
|
12
|
+
/** @internal */
|
|
13
|
+
function is_digit(ch) {
|
|
14
|
+
return ch >= 48 && ch <= 57;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* @param a Base string, MUST be lowercase!
|
|
18
|
+
* @param b Compare string
|
|
19
|
+
*/
|
|
20
|
+
function str_equals(a, b) {
|
|
21
|
+
if (a.length !== b.length) return false;
|
|
22
|
+
for (let i = 0; i < a.length; i++) {
|
|
23
|
+
let ca = a.charCodeAt(i);
|
|
24
|
+
let cb = b.charCodeAt(i);
|
|
25
|
+
cb |= 32;
|
|
26
|
+
if (ca !== cb) return false;
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Case-insensitive ASCII prefix check without allocations
|
|
32
|
+
* Returns true if string `str` starts with prefix (case-insensitive)
|
|
33
|
+
*
|
|
34
|
+
* IMPORTANT: prefix MUST be lowercase for correct comparison
|
|
35
|
+
*
|
|
36
|
+
* @param str - The string to check
|
|
37
|
+
* @param prefix - The lowercase prefix to match against
|
|
38
|
+
*/
|
|
39
|
+
function str_starts_with(str, prefix) {
|
|
40
|
+
if (str.length < prefix.length) return false;
|
|
41
|
+
for (let i = 0; i < prefix.length; i++) {
|
|
42
|
+
let ca = str.charCodeAt(i);
|
|
43
|
+
let cb = prefix.charCodeAt(i);
|
|
44
|
+
if (ca >= 65 && ca <= 90) ca |= 32;
|
|
45
|
+
if (ca !== cb) return false;
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Case-insensitive character/substring search without allocations
|
|
51
|
+
* Returns the index of the first occurrence of searchChar (case-insensitive)
|
|
52
|
+
*
|
|
53
|
+
* IMPORTANT: searchChar MUST be lowercase for correct comparison
|
|
54
|
+
*
|
|
55
|
+
* @param str - The string to search in
|
|
56
|
+
* @param searchChar - The lowercase character/substring to find
|
|
57
|
+
* @returns The index of the first match, or -1 if not found
|
|
58
|
+
*/
|
|
59
|
+
function str_index_of(str, searchChar) {
|
|
60
|
+
if (searchChar.length === 0) return -1;
|
|
61
|
+
if (searchChar.length === 1) {
|
|
62
|
+
const searchCode = searchChar.charCodeAt(0);
|
|
63
|
+
for (let i = 0; i < str.length; i++) {
|
|
64
|
+
let ca = str.charCodeAt(i);
|
|
65
|
+
if (ca >= 65 && ca <= 90) ca |= 32;
|
|
66
|
+
if (ca === searchCode) return i;
|
|
67
|
+
}
|
|
68
|
+
return -1;
|
|
69
|
+
}
|
|
70
|
+
for (let i = 0; i <= str.length - searchChar.length; i++) {
|
|
71
|
+
let match = true;
|
|
72
|
+
for (let j = 0; j < searchChar.length; j++) {
|
|
73
|
+
let ca = str.charCodeAt(i + j);
|
|
74
|
+
let cb = searchChar.charCodeAt(j);
|
|
75
|
+
if (ca >= 65 && ca <= 90) ca |= 32;
|
|
76
|
+
if (ca !== cb) {
|
|
77
|
+
match = false;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (match) return i;
|
|
82
|
+
}
|
|
83
|
+
return -1;
|
|
84
|
+
}
|
|
85
|
+
function is_vendor_prefixed(source, start, end) {
|
|
86
|
+
if (start === void 0 || end === void 0) {
|
|
87
|
+
start = 0;
|
|
88
|
+
end = source.length;
|
|
89
|
+
}
|
|
90
|
+
if (source.charCodeAt(start) !== 45) return false;
|
|
91
|
+
if (source.charCodeAt(start + 1) === 45) return false;
|
|
92
|
+
if (end - start < 3) return false;
|
|
93
|
+
for (let i = start + 2; i < end; i++) if (source.charCodeAt(i) === 45) return true;
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check if a string is a CSS custom property (starts with --)
|
|
98
|
+
*
|
|
99
|
+
* @param str - The string to check
|
|
100
|
+
* @returns true if the string starts with -- (custom property)
|
|
101
|
+
*
|
|
102
|
+
* Examples:
|
|
103
|
+
* - `--primary-color` → true
|
|
104
|
+
* - `--my-var` → true
|
|
105
|
+
* - `-webkit-transform` → false (vendor prefix, not custom)
|
|
106
|
+
* - `border-radius` → false (standard property)
|
|
107
|
+
* - `color` → false
|
|
108
|
+
*/
|
|
109
|
+
function is_custom(str) {
|
|
110
|
+
if (str.length < 3) return false;
|
|
111
|
+
return str.charCodeAt(0) === 45 && str.charCodeAt(1) === 45;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Strip vendor prefix from a string
|
|
115
|
+
*
|
|
116
|
+
* @param str - The string to strip vendor prefix from
|
|
117
|
+
* @returns The string without vendor prefix, or original string if no prefix found
|
|
118
|
+
*
|
|
119
|
+
* Examples:
|
|
120
|
+
* - `-webkit-keyframes` → `keyframes`
|
|
121
|
+
* - `-moz-appearance` → `appearance`
|
|
122
|
+
* - `-ms-filter` → `filter`
|
|
123
|
+
* - `-o-border-image` → `border-image`
|
|
124
|
+
* - `keyframes` → `keyframes` (no change)
|
|
125
|
+
* - `--custom-property` → `--custom-property` (custom property, not vendor prefix)
|
|
126
|
+
*/
|
|
127
|
+
function strip_vendor_prefix(str) {
|
|
128
|
+
if (!is_vendor_prefixed(str)) return str;
|
|
129
|
+
for (let i = 2; i < str.length; i++) if (str.charCodeAt(i) === 45) return str.substring(i + 1);
|
|
130
|
+
return str;
|
|
131
|
+
}
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/parse-dimension.ts
|
|
134
|
+
/**
|
|
135
|
+
* Parse a dimension string into numeric value and unit
|
|
136
|
+
*
|
|
137
|
+
* @param text - Dimension text like "100px", "50%", "1.5em"
|
|
138
|
+
* @returns Object with value (number) and unit (string)
|
|
139
|
+
*
|
|
140
|
+
* Examples:
|
|
141
|
+
* - "100px" → { value: 100, unit: "px" }
|
|
142
|
+
* - "50%" → { value: 50, unit: "%" }
|
|
143
|
+
* - "1.5em" → { value: 1.5, unit: "em" }
|
|
144
|
+
* - "-10rem" → { value: -10, unit: "rem" }
|
|
145
|
+
*/
|
|
146
|
+
function parse_dimension(text) {
|
|
147
|
+
let num_end = 0;
|
|
148
|
+
for (let i = 0; i < text.length; i++) {
|
|
149
|
+
let ch = text.charCodeAt(i);
|
|
150
|
+
if (ch === 101 || ch === 69) {
|
|
151
|
+
if (i + 1 < text.length) {
|
|
152
|
+
let next_ch = text.charCodeAt(i + 1);
|
|
153
|
+
if (is_digit(next_ch)) {
|
|
154
|
+
num_end = i + 1;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if ((next_ch === 43 || next_ch === 45) && i + 2 < text.length) {
|
|
158
|
+
if (is_digit(text.charCodeAt(i + 2))) {
|
|
159
|
+
num_end = i + 1;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
if (is_digit(ch) || ch === 46 || ch === 45 || ch === 43) num_end = i + 1;
|
|
167
|
+
else break;
|
|
168
|
+
}
|
|
169
|
+
let num_str = text.substring(0, num_end);
|
|
170
|
+
let unit = text.substring(num_end);
|
|
171
|
+
return {
|
|
172
|
+
value: num_str ? parseFloat(num_str) : 0,
|
|
173
|
+
unit
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
//#endregion
|
|
177
|
+
export { is_whitespace as a, str_starts_with as c, is_vendor_prefixed as i, strip_vendor_prefix as l, is_combinator as n, str_equals as o, is_custom as r, str_index_of as s, parse_dimension as t };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//#region src/parse-dimension.d.ts
|
|
1
2
|
/**
|
|
2
3
|
* Parse a dimension string into numeric value and unit
|
|
3
4
|
*
|
|
@@ -10,7 +11,9 @@
|
|
|
10
11
|
* - "1.5em" → { value: 1.5, unit: "em" }
|
|
11
12
|
* - "-10rem" → { value: -10, unit: "rem" }
|
|
12
13
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
declare function parse_dimension(text: string): {
|
|
15
|
+
value: number;
|
|
16
|
+
unit: string;
|
|
16
17
|
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { parse_dimension };
|
package/dist/parse-dimension.js
CHANGED
|
@@ -1,36 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
function parse_dimension(text) {
|
|
4
|
-
let num_end = 0;
|
|
5
|
-
for (let i = 0; i < text.length; i++) {
|
|
6
|
-
let ch = text.charCodeAt(i);
|
|
7
|
-
if (ch === 101 || ch === 69) {
|
|
8
|
-
if (i + 1 < text.length) {
|
|
9
|
-
let next_ch = text.charCodeAt(i + 1);
|
|
10
|
-
if (is_digit(next_ch)) {
|
|
11
|
-
num_end = i + 1;
|
|
12
|
-
continue;
|
|
13
|
-
}
|
|
14
|
-
if ((next_ch === 43 || next_ch === 45) && i + 2 < text.length) {
|
|
15
|
-
let afterSign = text.charCodeAt(i + 2);
|
|
16
|
-
if (is_digit(afterSign)) {
|
|
17
|
-
num_end = i + 1;
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
break;
|
|
23
|
-
}
|
|
24
|
-
if (is_digit(ch) || ch === CHAR_PERIOD || ch === CHAR_MINUS_HYPHEN || ch === CHAR_PLUS) {
|
|
25
|
-
num_end = i + 1;
|
|
26
|
-
} else {
|
|
27
|
-
break;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
let num_str = text.substring(0, num_end);
|
|
31
|
-
let unit = text.substring(num_end);
|
|
32
|
-
let value = num_str ? parseFloat(num_str) : 0;
|
|
33
|
-
return { value, unit };
|
|
34
|
-
}
|
|
35
|
-
|
|
1
|
+
import { t as parse_dimension } from "./parse-dimension-CCn_XRDe.js";
|
|
36
2
|
export { parse_dimension };
|
package/dist/parse-selector.d.ts
CHANGED
|
@@ -1,7 +1,42 @@
|
|
|
1
|
-
import { CSSNode } from
|
|
1
|
+
import { E as CSSDataArena, r as CSSNode } from "./css-node-DqyvMXBN.js";
|
|
2
|
+
|
|
3
|
+
//#region src/parse-selector.d.ts
|
|
4
|
+
/** @internal */
|
|
5
|
+
declare class SelectorParser {
|
|
6
|
+
private lexer;
|
|
7
|
+
private arena;
|
|
8
|
+
private source;
|
|
9
|
+
private selector_end;
|
|
10
|
+
constructor(arena: CSSDataArena, source: string);
|
|
11
|
+
parse_selector(start: number, end: number, line?: number, column?: number, allow_relative?: boolean): number | null;
|
|
12
|
+
private parse_selector_list;
|
|
13
|
+
private parse_complex_selector;
|
|
14
|
+
private parse_compound_selector;
|
|
15
|
+
private parse_simple_selector;
|
|
16
|
+
private parse_namespace_local_part;
|
|
17
|
+
private parse_type_or_namespace_selector;
|
|
18
|
+
private parse_universal_or_namespace_selector;
|
|
19
|
+
private parse_empty_namespace_selector;
|
|
20
|
+
private try_parse_combinator;
|
|
21
|
+
private parse_class_selector;
|
|
22
|
+
private parse_attribute_selector;
|
|
23
|
+
private parse_attribute_content;
|
|
24
|
+
private parse_pseudo;
|
|
25
|
+
private parse_pseudo_function;
|
|
26
|
+
private parse_pseudo_function_after_colon;
|
|
27
|
+
private is_nth_pseudo;
|
|
28
|
+
private parse_lang_identifiers;
|
|
29
|
+
private parse_nth_expression;
|
|
30
|
+
private find_of_keyword;
|
|
31
|
+
private create_node;
|
|
32
|
+
private create_node_at;
|
|
33
|
+
private skip_whitespace;
|
|
34
|
+
}
|
|
2
35
|
/**
|
|
3
36
|
* Parse a CSS selector string and return an AST
|
|
4
37
|
* @param source - The CSS selector to parse (e.g., "div.class > p#id")
|
|
5
38
|
* @returns The root CSSNode of the selector AST
|
|
6
39
|
*/
|
|
7
|
-
|
|
40
|
+
declare function parse_selector(source: string): CSSNode;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { SelectorParser, parse_selector };
|