Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions src/css-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
11 changes: 0 additions & 11 deletions src/parse-selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
NESTING_SELECTOR,
NTH_OF_SELECTOR,
LANG_SELECTOR,
FLAG_VENDOR_PREFIXED,
FLAG_HAS_PARENS,
ATTR_OPERATOR_NONE,
ATTR_OPERATOR_EQUAL,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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
Expand Down
7 changes: 0 additions & 7 deletions src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
BLOCK,
FLAG_IMPORTANT,
FLAG_HAS_BLOCK,
FLAG_VENDOR_PREFIXED,
FLAG_HAS_DECLARATIONS,
} from './arena'
import { CSSNode } from './css-node'
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
12 changes: 11 additions & 1 deletion src/string-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down