diff --git a/src/css-node.ts b/src/css-node.ts index db80a7d..b4a4613 100644 --- a/src/css-node.ts +++ b/src/css-node.ts @@ -40,12 +40,11 @@ import { FLAG_IMPORTANT, FLAG_HAS_ERROR, FLAG_HAS_BLOCK, - FLAG_VENDOR_PREFIXED, FLAG_HAS_DECLARATIONS, FLAG_HAS_PARENS, } from './arena' -import { CHAR_MINUS_HYPHEN, CHAR_PLUS, is_whitespace, str_starts_with } from './string-utils' +import { CHAR_MINUS_HYPHEN, CHAR_PLUS, is_whitespace, is_vendor_prefixed, str_starts_with } from './string-utils' import { parse_dimension } from './parse-utils' // Type name lookup table - maps numeric type to CSSTree-compatible strings @@ -312,9 +311,28 @@ export class CSSNode { return this.arena.has_flag(this.index, FLAG_IMPORTANT) } - // Check if this has a vendor prefix (flag-based for performance) + // Check if this has a vendor prefix (computed on-demand) get is_vendor_prefixed(): boolean { - return this.arena.has_flag(this.index, FLAG_VENDOR_PREFIXED) + switch (this.type) { + case DECLARATION: + // Check property name (e.g., -webkit-transform) + return is_vendor_prefixed(this.name) + case PSEUDO_CLASS_SELECTOR: + case PSEUDO_ELEMENT_SELECTOR: + // Check pseudo-class/element name without colons (e.g., -webkit-autofill, -webkit-scrollbar) + return is_vendor_prefixed(this.name) + case AT_RULE: + // Check at-rule name (e.g., -webkit-keyframes from @-webkit-keyframes) + return is_vendor_prefixed(this.name) + case FUNCTION: + // Check function name (e.g., -webkit-gradient from -webkit-gradient()) + return is_vendor_prefixed(this.name) + case IDENTIFIER: + // Check identifier value (e.g., -webkit-sticky) + return is_vendor_prefixed(this.text) + default: + return false + } } // Check if this node has an error diff --git a/src/parse-selector.ts b/src/parse-selector.ts index bc1d5b3..afc47f8 100644 --- a/src/parse-selector.ts +++ b/src/parse-selector.ts @@ -15,7 +15,6 @@ import { NESTING_SELECTOR, NTH_OF_SELECTOR, LANG_SELECTOR, - FLAG_VENDOR_PREFIXED, FLAG_HAS_PARENS, ATTR_OPERATOR_NONE, ATTR_OPERATOR_EQUAL, @@ -46,7 +45,6 @@ import { import { skip_whitespace_forward, skip_whitespace_and_comments_forward, skip_whitespace_and_comments_backward } from './parse-utils' import { is_whitespace, - is_vendor_prefixed, str_equals, CHAR_PLUS, CHAR_TILDE, @@ -686,10 +684,6 @@ export class SelectorParser { // Content is the pseudo name (without colons) this.arena.set_content_start_delta(node, this.lexer.token_start - start) this.arena.set_content_length(node, this.lexer.token_end - this.lexer.token_start) - // Check for vendor prefix and set flag if detected - if (is_vendor_prefixed(this.source, this.lexer.token_start, this.lexer.token_end)) { - this.arena.set_flag(node, FLAG_VENDOR_PREFIXED) - } return node } else if (token_type === TOKEN_FUNCTION) { // Pseudo-class function like :nth-child() @@ -744,11 +738,6 @@ export class SelectorParser { // This allows formatters to distinguish :lang() from :hover this.arena.set_flag(node, FLAG_HAS_PARENS) - // Check for vendor prefix and set flag if detected - if (is_vendor_prefixed(this.source, func_name_start, func_name_end)) { - this.arena.set_flag(node, FLAG_VENDOR_PREFIXED) - } - // Parse the content inside the parentheses if (content_end > content_start) { // Check if this is an nth-* pseudo-class diff --git a/src/parse.ts b/src/parse.ts index f68966d..b375d65 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -10,7 +10,6 @@ import { BLOCK, FLAG_IMPORTANT, FLAG_HAS_BLOCK, - FLAG_VENDOR_PREFIXED, FLAG_HAS_DECLARATIONS, } from './arena' import { CSSNode } from './css-node' @@ -27,7 +26,6 @@ import { TOKEN_DELIM, TOKEN_AT_KEYWORD, } from './token-types' -import { is_vendor_prefixed } from './string-utils' import { trim_boundaries } from './parse-utils' export interface ParserOptions { @@ -322,11 +320,6 @@ export class Parser { this.arena.set_content_start_delta(declaration, 0) this.arena.set_content_length(declaration, prop_end - prop_start) - // Check for vendor prefix and set flag if detected - if (is_vendor_prefixed(this.source, prop_start, prop_end)) { - this.arena.set_flag(declaration, FLAG_VENDOR_PREFIXED) - } - // Track value start (after colon, skipping whitespace) let value_start = this.lexer.token_start let value_end = value_start diff --git a/src/string-utils.ts b/src/string-utils.ts index 9cdb383..8b63643 100644 --- a/src/string-utils.ts +++ b/src/string-utils.ts @@ -162,7 +162,17 @@ export function str_index_of(str: string, searchChar: string): number { * - `--custom-property` → false (CSS custom property) * - `border-radius` → false (doesn't start with hyphen) */ -export function is_vendor_prefixed(source: string, start: number, end: number): boolean { +// Overload signatures +export function is_vendor_prefixed(text: string): boolean +export function is_vendor_prefixed(source: string, start: number, end: number): boolean +// Implementation +export function is_vendor_prefixed(source: string, start?: number, end?: number): boolean { + // Handle string-only overload + if (start === undefined || end === undefined) { + start = 0 + end = source.length + } + // Must start with a hyphen if (source.charCodeAt(start) !== CHAR_MINUS_HYPHEN) { return false