@projectwallace/css-parser 0.2.0 → 0.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/README.md +15 -12
- package/dist/arena.d.ts +1 -0
- package/dist/{at-rule-prelude-parser-7_qZ1z7t.js → at-rule-prelude-parser-pzWB6S0z.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/parse-atrule-prelude.js +2 -2
- package/dist/parse-selector.js +2 -2
- package/dist/parse.js +6 -3
- package/dist/{selector-parser-BjdQlGvW.js → selector-parser-CwNLN7Us.js} +7 -1
- package/dist/{string-utils-Bm2l6p1L.js → string-utils-5j619JDp.js} +19 -5
- package/dist/string-utils.d.ts +23 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,18 +13,7 @@ Built for speed and efficiency, this parser handles large CSS files with minimal
|
|
|
13
13
|
- **Error recovery** - Continues parsing on malformed CSS
|
|
14
14
|
- **Comment preservation** - Comments stored as first-class AST nodes
|
|
15
15
|
- **Location tracking** - Line, column, offset, and length for all nodes
|
|
16
|
-
- **
|
|
17
|
-
- **Structured parsing** - Deep parsing of selectors, values, and at-rule preludes
|
|
18
|
-
|
|
19
|
-
## Performance
|
|
20
|
-
|
|
21
|
-
- **Tiny install size**
|
|
22
|
-
- **Zero allocations during parsing** - all memory allocated upfront based on real world heuristics, which also helps prevent garbage collection running often
|
|
23
|
-
- **Cache-friendly data layout** - contiguous memory for sequential access
|
|
24
|
-
- **First-class comment and location support** - while still being performant because analysis requires constant access to lines and columns
|
|
25
|
-
- **No syntax validation** - focusing only on the raw data we can skip expensive syntax files and MDN data syncs
|
|
26
|
-
|
|
27
|
-
This parser was heavily influenced by [CSSTree](https://github.com/csstree/csstree), one of the most robust CSS parsers available.
|
|
16
|
+
- **Built-in vendor prefix detection** - Automatic detection of `-webkit-`, `-moz-`, etc. for selectors, values, properties and more
|
|
28
17
|
|
|
29
18
|
## Installation
|
|
30
19
|
|
|
@@ -66,10 +55,24 @@ for (const rule of ast) {
|
|
|
66
55
|
}
|
|
67
56
|
```
|
|
68
57
|
|
|
58
|
+
## Performance
|
|
59
|
+
|
|
60
|
+
- **Tiny install size**
|
|
61
|
+
- **Zero allocations during parsing** - all memory allocated upfront based on real world heuristics, which also helps prevent garbage collection running often
|
|
62
|
+
- **Cache-friendly data layout** - contiguous memory for sequential access powered by concepts or Data Oriented Design
|
|
63
|
+
- **First-class comment and location support** - while still being performant because analysis requires constant access to lines and columns
|
|
64
|
+
- **No syntax validation** - focusing only on the raw data we can skip expensive syntax files and MDN data syncs
|
|
65
|
+
|
|
66
|
+
This parser was heavily influenced by [CSSTree](https://github.com/csstree/csstree), one of the most robust CSS parsers available.
|
|
67
|
+
|
|
69
68
|
## Documentation
|
|
70
69
|
|
|
71
70
|
See [API.md](./API.md) for complete documentation of all parser functions and options.
|
|
72
71
|
|
|
72
|
+
## Non-goals
|
|
73
|
+
|
|
74
|
+
- **No syntax validation** - this parser does not try to validate your CSS structure. Everything can be anything
|
|
75
|
+
|
|
73
76
|
## License
|
|
74
77
|
|
|
75
78
|
MIT
|
package/dist/arena.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ export declare const FLAG_IMPORTANT: number;
|
|
|
36
36
|
export declare const FLAG_HAS_ERROR: number;
|
|
37
37
|
export declare const FLAG_LENGTH_OVERFLOW: number;
|
|
38
38
|
export declare const FLAG_HAS_BLOCK: number;
|
|
39
|
+
export declare const FLAG_VENDOR_PREFIXED: number;
|
|
39
40
|
export declare class CSSDataArena {
|
|
40
41
|
private buffer;
|
|
41
42
|
private view;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { L as Lexer, q as TOKEN_COMMA, T as TOKEN_IDENT, t as TOKEN_LEFT_PAREN, u as TOKEN_RIGHT_PAREN, l as TOKEN_WHITESPACE, f as TOKEN_URL, a as TOKEN_FUNCTION, d as TOKEN_STRING, y as TOKEN_EOF } from './lexer-DXablYMZ.js';
|
|
2
|
-
import {
|
|
2
|
+
import { Q as str_equals, E as NODE_PRELUDE_OPERATOR, y as NODE_PRELUDE_MEDIA_TYPE, w as NODE_PRELUDE_MEDIA_QUERY, x as NODE_PRELUDE_MEDIA_FEATURE, P as trim_boundaries, D as NODE_PRELUDE_IDENTIFIER, z as NODE_PRELUDE_CONTAINER_QUERY, A as NODE_PRELUDE_SUPPORTS_QUERY, B as NODE_PRELUDE_LAYER_NAME, F as NODE_PRELUDE_IMPORT_URL, G as NODE_PRELUDE_IMPORT_LAYER, H as NODE_PRELUDE_IMPORT_SUPPORTS, R as CHAR_SPACE, S as CHAR_TAB, T as CHAR_NEWLINE, U as CHAR_CARRIAGE_RETURN, V as CHAR_FORM_FEED } from './string-utils-5j619JDp.js';
|
|
3
3
|
|
|
4
4
|
class AtRulePreludeParser {
|
|
5
5
|
lexer;
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { parse } from './parse.js';
|
|
|
2
2
|
export { parse_selector } from './parse-selector.js';
|
|
3
3
|
export { parse_atrule_prelude } from './parse-atrule-prelude.js';
|
|
4
4
|
export { tokenize } from './tokenize.js';
|
|
5
|
-
export { C as CSSNode, I as FLAG_IMPORTANT, a as NODE_AT_RULE, b as NODE_COMMENT, c as NODE_DECLARATION, z as NODE_PRELUDE_CONTAINER_QUERY, D as NODE_PRELUDE_IDENTIFIER, G as NODE_PRELUDE_IMPORT_LAYER, H as NODE_PRELUDE_IMPORT_SUPPORTS, F as NODE_PRELUDE_IMPORT_URL, B as NODE_PRELUDE_LAYER_NAME, x as NODE_PRELUDE_MEDIA_FEATURE, w as NODE_PRELUDE_MEDIA_QUERY, y as NODE_PRELUDE_MEDIA_TYPE, E as NODE_PRELUDE_OPERATOR, A as NODE_PRELUDE_SUPPORTS_QUERY, d as NODE_SELECTOR, q as NODE_SELECTOR_ATTRIBUTE, o as NODE_SELECTOR_CLASS, t as NODE_SELECTOR_COMBINATOR, p as NODE_SELECTOR_ID, m as NODE_SELECTOR_LIST, v as NODE_SELECTOR_NESTING, r as NODE_SELECTOR_PSEUDO_CLASS, s as NODE_SELECTOR_PSEUDO_ELEMENT, n as NODE_SELECTOR_TYPE, u as NODE_SELECTOR_UNIVERSAL, e as NODE_STYLESHEET, N as NODE_STYLE_RULE, j as NODE_VALUE_COLOR, h as NODE_VALUE_DIMENSION, k as NODE_VALUE_FUNCTION, f as NODE_VALUE_KEYWORD, g as NODE_VALUE_NUMBER, l as NODE_VALUE_OPERATOR, i as NODE_VALUE_STRING } from './string-utils-
|
|
5
|
+
export { C as CSSNode, I as FLAG_IMPORTANT, a as NODE_AT_RULE, b as NODE_COMMENT, c as NODE_DECLARATION, z as NODE_PRELUDE_CONTAINER_QUERY, D as NODE_PRELUDE_IDENTIFIER, G as NODE_PRELUDE_IMPORT_LAYER, H as NODE_PRELUDE_IMPORT_SUPPORTS, F as NODE_PRELUDE_IMPORT_URL, B as NODE_PRELUDE_LAYER_NAME, x as NODE_PRELUDE_MEDIA_FEATURE, w as NODE_PRELUDE_MEDIA_QUERY, y as NODE_PRELUDE_MEDIA_TYPE, E as NODE_PRELUDE_OPERATOR, A as NODE_PRELUDE_SUPPORTS_QUERY, d as NODE_SELECTOR, q as NODE_SELECTOR_ATTRIBUTE, o as NODE_SELECTOR_CLASS, t as NODE_SELECTOR_COMBINATOR, p as NODE_SELECTOR_ID, m as NODE_SELECTOR_LIST, v as NODE_SELECTOR_NESTING, r as NODE_SELECTOR_PSEUDO_CLASS, s as NODE_SELECTOR_PSEUDO_ELEMENT, n as NODE_SELECTOR_TYPE, u as NODE_SELECTOR_UNIVERSAL, e as NODE_STYLESHEET, N as NODE_STYLE_RULE, j as NODE_VALUE_COLOR, h as NODE_VALUE_DIMENSION, k as NODE_VALUE_FUNCTION, f as NODE_VALUE_KEYWORD, g as NODE_VALUE_NUMBER, l as NODE_VALUE_OPERATOR, i as NODE_VALUE_STRING } from './string-utils-5j619JDp.js';
|
|
6
6
|
export { b as TOKEN_AT_KEYWORD, e as TOKEN_BAD_STRING, g as TOKEN_BAD_URL, n as TOKEN_CDC, m as TOKEN_CDO, o as TOKEN_COLON, q as TOKEN_COMMA, x as TOKEN_COMMENT, h as TOKEN_DELIM, k as TOKEN_DIMENSION, y as TOKEN_EOF, a as TOKEN_FUNCTION, c as TOKEN_HASH, T as TOKEN_IDENT, v as TOKEN_LEFT_BRACE, r as TOKEN_LEFT_BRACKET, t as TOKEN_LEFT_PAREN, i as TOKEN_NUMBER, j as TOKEN_PERCENTAGE, w as TOKEN_RIGHT_BRACE, s as TOKEN_RIGHT_BRACKET, u as TOKEN_RIGHT_PAREN, p as TOKEN_SEMICOLON, d as TOKEN_STRING, f as TOKEN_URL, l as TOKEN_WHITESPACE } from './lexer-DXablYMZ.js';
|
|
7
7
|
|
|
8
8
|
function walk(node, callback, depth = 0) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { K as CSSDataArena, C as CSSNode } from './string-utils-
|
|
2
|
-
import { A as AtRulePreludeParser } from './at-rule-prelude-parser-
|
|
1
|
+
import { K as CSSDataArena, C as CSSNode } from './string-utils-5j619JDp.js';
|
|
2
|
+
import { A as AtRulePreludeParser } from './at-rule-prelude-parser-pzWB6S0z.js';
|
|
3
3
|
|
|
4
4
|
function parse_atrule_prelude(at_rule_name, prelude) {
|
|
5
5
|
const arena = new CSSDataArena(CSSDataArena.capacity_for_source(prelude.length));
|
package/dist/parse-selector.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { K as CSSDataArena, d as NODE_SELECTOR, C as CSSNode } from './string-utils-
|
|
2
|
-
import { S as SelectorParser } from './selector-parser-
|
|
1
|
+
import { K as CSSDataArena, d as NODE_SELECTOR, C as CSSNode } from './string-utils-5j619JDp.js';
|
|
2
|
+
import { S as SelectorParser } from './selector-parser-CwNLN7Us.js';
|
|
3
3
|
|
|
4
4
|
function parse_selector(source) {
|
|
5
5
|
const arena = new CSSDataArena(CSSDataArena.capacity_for_source(source.length));
|
package/dist/parse.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { L as Lexer, y as TOKEN_EOF, q as TOKEN_COMMA, h as TOKEN_DELIM, a as TOKEN_FUNCTION, c as TOKEN_HASH, d as TOKEN_STRING, k as TOKEN_DIMENSION, j as TOKEN_PERCENTAGE, i as TOKEN_NUMBER, T as TOKEN_IDENT, t as TOKEN_LEFT_PAREN, u as TOKEN_RIGHT_PAREN, b as TOKEN_AT_KEYWORD, v as TOKEN_LEFT_BRACE, w as TOKEN_RIGHT_BRACE, o as TOKEN_COLON, p as TOKEN_SEMICOLON } from './lexer-DXablYMZ.js';
|
|
2
|
-
import { J as is_whitespace, f as NODE_VALUE_KEYWORD, g as NODE_VALUE_NUMBER, h as NODE_VALUE_DIMENSION, i as NODE_VALUE_STRING, j as NODE_VALUE_COLOR, l as NODE_VALUE_OPERATOR, k as NODE_VALUE_FUNCTION, K as CSSDataArena, e as NODE_STYLESHEET, C as CSSNode, N as NODE_STYLE_RULE, L as FLAG_HAS_BLOCK, d as NODE_SELECTOR, c as NODE_DECLARATION, M as trim_boundaries, I as FLAG_IMPORTANT, a as NODE_AT_RULE } from './string-utils-
|
|
3
|
-
import { S as SelectorParser } from './selector-parser-
|
|
4
|
-
import { A as AtRulePreludeParser } from './at-rule-prelude-parser-
|
|
2
|
+
import { J as is_whitespace, f as NODE_VALUE_KEYWORD, g as NODE_VALUE_NUMBER, h as NODE_VALUE_DIMENSION, i as NODE_VALUE_STRING, j as NODE_VALUE_COLOR, l as NODE_VALUE_OPERATOR, k as NODE_VALUE_FUNCTION, K as CSSDataArena, e as NODE_STYLESHEET, C as CSSNode, N as NODE_STYLE_RULE, L as FLAG_HAS_BLOCK, d as NODE_SELECTOR, c as NODE_DECLARATION, M as is_vendor_prefixed, O as FLAG_VENDOR_PREFIXED, P as trim_boundaries, I as FLAG_IMPORTANT, a as NODE_AT_RULE } from './string-utils-5j619JDp.js';
|
|
3
|
+
import { S as SelectorParser } from './selector-parser-CwNLN7Us.js';
|
|
4
|
+
import { A as AtRulePreludeParser } from './at-rule-prelude-parser-pzWB6S0z.js';
|
|
5
5
|
|
|
6
6
|
const CH_PLUS = 43;
|
|
7
7
|
const CH_MINUS = 45;
|
|
@@ -357,6 +357,9 @@ class Parser {
|
|
|
357
357
|
this.arena.set_start_offset(declaration, prop_start);
|
|
358
358
|
this.arena.set_content_start(declaration, prop_start);
|
|
359
359
|
this.arena.set_content_length(declaration, prop_end - prop_start);
|
|
360
|
+
if (is_vendor_prefixed(this.source, prop_start, prop_end)) {
|
|
361
|
+
this.arena.set_flag(declaration, FLAG_VENDOR_PREFIXED);
|
|
362
|
+
}
|
|
360
363
|
let value_start = this.lexer.token_start;
|
|
361
364
|
let value_end = value_start;
|
|
362
365
|
let has_important = false;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { L as Lexer, q as TOKEN_COMMA, y as TOKEN_EOF, l as TOKEN_WHITESPACE, a as TOKEN_FUNCTION, o as TOKEN_COLON, r as TOKEN_LEFT_BRACKET, h as TOKEN_DELIM, c as TOKEN_HASH, T as TOKEN_IDENT, s as TOKEN_RIGHT_BRACKET, t as TOKEN_LEFT_PAREN, u as TOKEN_RIGHT_PAREN } from './lexer-DXablYMZ.js';
|
|
2
|
-
import { d as NODE_SELECTOR, m as NODE_SELECTOR_LIST, J as is_whitespace, o as NODE_SELECTOR_CLASS, q as NODE_SELECTOR_ATTRIBUTE,
|
|
2
|
+
import { d as NODE_SELECTOR, m as NODE_SELECTOR_LIST, J as is_whitespace, o as NODE_SELECTOR_CLASS, q as NODE_SELECTOR_ATTRIBUTE, P as trim_boundaries, s as NODE_SELECTOR_PSEUDO_ELEMENT, r as NODE_SELECTOR_PSEUDO_CLASS, M as is_vendor_prefixed, O as FLAG_VENDOR_PREFIXED, n as NODE_SELECTOR_TYPE, p as NODE_SELECTOR_ID, u as NODE_SELECTOR_UNIVERSAL, v as NODE_SELECTOR_NESTING, t as NODE_SELECTOR_COMBINATOR } from './string-utils-5j619JDp.js';
|
|
3
3
|
|
|
4
4
|
class SelectorParser {
|
|
5
5
|
lexer;
|
|
@@ -266,6 +266,9 @@ class SelectorParser {
|
|
|
266
266
|
this.arena.set_start_column(node, this.lexer.column);
|
|
267
267
|
this.arena.set_content_start(node, this.lexer.token_start);
|
|
268
268
|
this.arena.set_content_length(node, this.lexer.token_end - this.lexer.token_start);
|
|
269
|
+
if (is_vendor_prefixed(this.source, this.lexer.token_start, this.lexer.token_end)) {
|
|
270
|
+
this.arena.set_flag(node, FLAG_VENDOR_PREFIXED);
|
|
271
|
+
}
|
|
269
272
|
return node;
|
|
270
273
|
} else if (token_type === TOKEN_FUNCTION) {
|
|
271
274
|
return this.parse_pseudo_function_after_colon(start, is_pseudo_element);
|
|
@@ -303,6 +306,9 @@ class SelectorParser {
|
|
|
303
306
|
this.arena.set_start_column(node, this.lexer.column);
|
|
304
307
|
this.arena.set_content_start(node, func_name_start);
|
|
305
308
|
this.arena.set_content_length(node, func_name_end - func_name_start);
|
|
309
|
+
if (is_vendor_prefixed(this.source, func_name_start, func_name_end)) {
|
|
310
|
+
this.arena.set_flag(node, FLAG_VENDOR_PREFIXED);
|
|
311
|
+
}
|
|
306
312
|
return node;
|
|
307
313
|
}
|
|
308
314
|
// Create simple selector nodes
|
|
@@ -36,6 +36,7 @@ const NODE_PRELUDE_IMPORT_SUPPORTS = 40;
|
|
|
36
36
|
const FLAG_IMPORTANT = 1 << 0;
|
|
37
37
|
const FLAG_HAS_ERROR = 1 << 1;
|
|
38
38
|
const FLAG_HAS_BLOCK = 1 << 3;
|
|
39
|
+
const FLAG_VENDOR_PREFIXED = 1 << 4;
|
|
39
40
|
class CSSDataArena {
|
|
40
41
|
buffer;
|
|
41
42
|
view;
|
|
@@ -290,11 +291,9 @@ class CSSNode {
|
|
|
290
291
|
get is_important() {
|
|
291
292
|
return this.arena.has_flag(this.index, FLAG_IMPORTANT);
|
|
292
293
|
}
|
|
293
|
-
// Check if this has a vendor prefix (
|
|
294
|
+
// Check if this has a vendor prefix (flag-based for performance)
|
|
294
295
|
get is_vendor_prefixed() {
|
|
295
|
-
|
|
296
|
-
if (!name) return false;
|
|
297
|
-
return name.startsWith("-webkit-") || name.startsWith("-moz-") || name.startsWith("-ms-") || name.startsWith("-o-");
|
|
296
|
+
return this.arena.has_flag(this.index, FLAG_VENDOR_PREFIXED);
|
|
298
297
|
}
|
|
299
298
|
// Check if this node has an error
|
|
300
299
|
get has_error() {
|
|
@@ -389,6 +388,7 @@ const CHAR_CARRIAGE_RETURN = 13;
|
|
|
389
388
|
const CHAR_FORM_FEED = 12;
|
|
390
389
|
const CHAR_FORWARD_SLASH = 47;
|
|
391
390
|
const CHAR_ASTERISK = 42;
|
|
391
|
+
const CHAR_MINUS_HYPHEN = 45;
|
|
392
392
|
function is_whitespace(ch) {
|
|
393
393
|
return ch === CHAR_SPACE || ch === CHAR_TAB || ch === CHAR_NEWLINE || ch === CHAR_CARRIAGE_RETURN || ch === CHAR_FORM_FEED;
|
|
394
394
|
}
|
|
@@ -448,5 +448,19 @@ function str_equals(a, b) {
|
|
|
448
448
|
}
|
|
449
449
|
return true;
|
|
450
450
|
}
|
|
451
|
+
function is_vendor_prefixed(source, start, end) {
|
|
452
|
+
if (source.charCodeAt(start) !== CHAR_MINUS_HYPHEN) {
|
|
453
|
+
return false;
|
|
454
|
+
}
|
|
455
|
+
if (source.charCodeAt(start + 1) === CHAR_MINUS_HYPHEN) {
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
458
|
+
let length = end - start;
|
|
459
|
+
if (length < 3) {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
let secondHyphenPos = source.indexOf("-", start + 2);
|
|
463
|
+
return secondHyphenPos !== -1 && secondHyphenPos < end;
|
|
464
|
+
}
|
|
451
465
|
|
|
452
|
-
export { NODE_PRELUDE_SUPPORTS_QUERY as A, NODE_PRELUDE_LAYER_NAME as B, CSSNode as C, NODE_PRELUDE_IDENTIFIER as D, NODE_PRELUDE_OPERATOR as E, NODE_PRELUDE_IMPORT_URL as F, NODE_PRELUDE_IMPORT_LAYER as G, NODE_PRELUDE_IMPORT_SUPPORTS as H, FLAG_IMPORTANT as I, is_whitespace as J, CSSDataArena as K, FLAG_HAS_BLOCK as L,
|
|
466
|
+
export { NODE_PRELUDE_SUPPORTS_QUERY as A, NODE_PRELUDE_LAYER_NAME as B, CSSNode as C, NODE_PRELUDE_IDENTIFIER as D, NODE_PRELUDE_OPERATOR as E, NODE_PRELUDE_IMPORT_URL as F, NODE_PRELUDE_IMPORT_LAYER as G, NODE_PRELUDE_IMPORT_SUPPORTS as H, FLAG_IMPORTANT as I, is_whitespace as J, CSSDataArena as K, FLAG_HAS_BLOCK as L, is_vendor_prefixed as M, NODE_STYLE_RULE as N, FLAG_VENDOR_PREFIXED as O, trim_boundaries as P, str_equals as Q, CHAR_SPACE as R, CHAR_TAB as S, CHAR_NEWLINE as T, CHAR_CARRIAGE_RETURN as U, CHAR_FORM_FEED as V, NODE_AT_RULE as a, NODE_COMMENT as b, NODE_DECLARATION as c, NODE_SELECTOR as d, NODE_STYLESHEET as e, NODE_VALUE_KEYWORD as f, NODE_VALUE_NUMBER as g, NODE_VALUE_DIMENSION as h, NODE_VALUE_STRING as i, NODE_VALUE_COLOR as j, NODE_VALUE_FUNCTION as k, NODE_VALUE_OPERATOR as l, NODE_SELECTOR_LIST as m, NODE_SELECTOR_TYPE as n, NODE_SELECTOR_CLASS as o, NODE_SELECTOR_ID as p, NODE_SELECTOR_ATTRIBUTE as q, NODE_SELECTOR_PSEUDO_CLASS as r, NODE_SELECTOR_PSEUDO_ELEMENT as s, NODE_SELECTOR_COMBINATOR as t, NODE_SELECTOR_UNIVERSAL as u, NODE_SELECTOR_NESTING as v, NODE_PRELUDE_MEDIA_QUERY as w, NODE_PRELUDE_MEDIA_FEATURE as x, NODE_PRELUDE_MEDIA_TYPE as y, NODE_PRELUDE_CONTAINER_QUERY as z };
|
package/dist/string-utils.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export declare const CHAR_CARRIAGE_RETURN = 13;
|
|
|
5
5
|
export declare const CHAR_FORM_FEED = 12;
|
|
6
6
|
export declare const CHAR_FORWARD_SLASH = 47;
|
|
7
7
|
export declare const CHAR_ASTERISK = 42;
|
|
8
|
+
export declare const CHAR_MINUS_HYPHEN = 45;
|
|
8
9
|
/**
|
|
9
10
|
* Check if a character code is whitespace (space, tab, newline, CR, or FF)
|
|
10
11
|
*/
|
|
@@ -27,3 +28,25 @@ export declare function trim_boundaries(source: string, start: number, end: numb
|
|
|
27
28
|
* @param b Compare string
|
|
28
29
|
*/
|
|
29
30
|
export declare function str_equals(a: string, b: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Check if a string range has a vendor prefix
|
|
33
|
+
*
|
|
34
|
+
* @param source - The source string
|
|
35
|
+
* @param start - Start offset in source
|
|
36
|
+
* @param end - End offset in source
|
|
37
|
+
* @returns true if the range starts with a vendor prefix (-webkit-, -moz-, -ms-, -o-)
|
|
38
|
+
*
|
|
39
|
+
* Detects vendor prefixes by checking:
|
|
40
|
+
* 1. Starts with a single hyphen (not --)
|
|
41
|
+
* 2. Contains at least 3 characters (shortest is -o-)
|
|
42
|
+
* 3. Has a second hyphen after the vendor name
|
|
43
|
+
*
|
|
44
|
+
* Examples:
|
|
45
|
+
* - `-webkit-transform` → true
|
|
46
|
+
* - `-moz-appearance` → true
|
|
47
|
+
* - `-ms-filter` → true
|
|
48
|
+
* - `-o-border-image` → true
|
|
49
|
+
* - `--custom-property` → false (CSS custom property)
|
|
50
|
+
* - `border-radius` → false (doesn't start with hyphen)
|
|
51
|
+
*/
|
|
52
|
+
export declare function is_vendor_prefixed(source: string, start: number, end: number): boolean;
|
package/package.json
CHANGED