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
158 changes: 53 additions & 105 deletions src/api.test.ts

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/arena.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export const ATTR_FLAG_NONE = 0 // No flag
export const ATTR_FLAG_CASE_INSENSITIVE = 1 // [attr=value i]
export const ATTR_FLAG_CASE_SENSITIVE = 2 // [attr=value s]

/** @internal */
export class CSSDataArena {
private buffer: ArrayBuffer
private view: DataView
Expand Down
1 change: 1 addition & 0 deletions src/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export interface LexerPosition {
token_column: number
}

/** @internal */
export class Lexer {
source: string
pos: number
Expand Down
1 change: 1 addition & 0 deletions src/parse-anplusb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { CHAR_MINUS_HYPHEN, CHAR_PLUS } from './string-utils'
import { skip_whitespace_forward } from './parse-utils'
import { CSSNode } from './css-node'

/** @internal */
export class ANplusBParser {
private lexer: Lexer
private arena: CSSDataArena
Expand Down
1 change: 1 addition & 0 deletions src/parse-atrule-prelude.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { str_equals } from './string-utils'
import { trim_boundaries, skip_whitespace_forward } from './parse-utils'
import { CSSNode } from './css-node'

/** @internal */
export class AtRulePreludeParser {
private lexer: Lexer
private arena: CSSDataArena
Expand Down
47 changes: 16 additions & 31 deletions src/parse-options.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { describe, it, expect } from 'vitest'
import { Parser } from './parse'
import { parse } from './parse'
import { SELECTOR_LIST, DECLARATION, IDENTIFIER } from './arena'

describe('Parser Options', () => {
const css = 'body { color: red; }'

describe('Default behavior (all parsing enabled)', () => {
it('should parse values and selectors by default', () => {
const parser = new Parser(css)
const root = parser.parse()
const root = parse(css)
const rule = root.first_child

// Check selector is parsed with detailed structure
Expand All @@ -27,8 +26,7 @@ describe('Parser Options', () => {
})

it('should parse values and selectors with explicit options', () => {
const parser = new Parser(css, { parse_values: true, parse_selectors: true })
const root = parser.parse()
const root = parse(css, { parse_values: true, parse_selectors: true })
const rule = root.first_child

// Check selector is parsed
Expand All @@ -46,8 +44,7 @@ describe('Parser Options', () => {

describe('parse_values disabled', () => {
it('should not parse value details when parse_values is false', () => {
const parser = new Parser(css, { parse_values: false })
const root = parser.parse()
const root = parse(css, { parse_values: false })
const rule = root.first_child

// Selector should still be parsed
Expand All @@ -67,8 +64,7 @@ describe('Parser Options', () => {
})

it('should handle complex values without parsing', () => {
const parser = new Parser('div { margin: 10px 20px; }', { parse_values: false })
const root = parser.parse()
const root = parse('div { margin: 10px 20px; }', { parse_values: false })
const rule = root.first_child
const selector = rule?.first_child
const block = selector?.next_sibling
Expand All @@ -80,8 +76,7 @@ describe('Parser Options', () => {
})

it('should handle function values without parsing', () => {
const parser = new Parser('div { color: rgb(255, 0, 0); }', { parse_values: false })
const root = parser.parse()
const root = parse('div { color: rgb(255, 0, 0); }', { parse_values: false })
const rule = root.first_child
const selector = rule?.first_child
const block = selector?.next_sibling
Expand All @@ -95,8 +90,7 @@ describe('Parser Options', () => {

describe('parseSelectors disabled', () => {
it('should not parse selector details when parseSelectors is false', () => {
const parser = new Parser(css, { parse_selectors: false })
const root = parser.parse()
const root = parse(css, { parse_selectors: false })
const rule = root.first_child

// Selector should exist but be simple (just NODE_SELECTOR_LIST, no detailed structure)
Expand All @@ -114,8 +108,7 @@ describe('Parser Options', () => {
})

it('should handle complex selectors without parsing', () => {
const parser = new Parser('div.container#app { color: red; }', { parse_selectors: false })
const root = parser.parse()
const root = parse('div.container#app { color: red; }', { parse_selectors: false })
const rule = root.first_child
const selector = rule?.first_child

Expand All @@ -125,8 +118,7 @@ describe('Parser Options', () => {
})

it('should handle selector lists without parsing', () => {
const parser = new Parser('div, p, span { color: red; }', { parse_selectors: false })
const root = parser.parse()
const root = parse('div, p, span { color: red; }', { parse_selectors: false })
const rule = root.first_child
const selector = rule?.first_child

Expand All @@ -138,8 +130,7 @@ describe('Parser Options', () => {

describe('Both parse_values and parseSelectors disabled', () => {
it('should not parse details for values or selectors', () => {
const parser = new Parser(css, { parse_values: false, parse_selectors: false })
const root = parser.parse()
const root = parse(css, { parse_values: false, parse_selectors: false })
const rule = root.first_child

// Selector should be simple
Expand All @@ -164,8 +155,7 @@ describe('Parser Options', () => {
color: rgb(255, 0, 0);
}
`
const parser = new Parser(css, { parse_values: false, parse_selectors: false })
const root = parser.parse()
const root = parse(css, { parse_values: false, parse_selectors: false })
const rule = root.first_child

const selector = rule?.first_child
Expand Down Expand Up @@ -194,8 +184,7 @@ describe('Parser Options', () => {
margin: 10px 20px 30px 40px;
}
`
const parser = new Parser(css, { parse_values: false })
const root = parser.parse()
const root = parse(css, { parse_values: false })
const rule = root.first_child
const selector = rule?.first_child

Expand All @@ -219,8 +208,7 @@ describe('Parser Options', () => {
.another-complex[data-attr~="value"] { margin: 0; }
#very-specific-id:not(.excluded) { padding: 10px; }
`
const parser = new Parser(css, { parse_selectors: false })
const root = parser.parse()
const root = parse(css, { parse_selectors: false })

// Can quickly count rules without parsing complex selectors
let count = 0
Expand All @@ -236,8 +224,7 @@ describe('Parser Options', () => {

describe('Options validation', () => {
it('should accept empty options object', () => {
const parser = new Parser(css, {})
const root = parser.parse()
const root = parse(css, {})
const rule = root.first_child
const selector = rule?.first_child
const block = selector?.next_sibling
Expand All @@ -249,8 +236,7 @@ describe('Parser Options', () => {
})

it('should accept partial options', () => {
const parser = new Parser(css, { parse_values: false })
const root = parser.parse()
const root = parse(css, { parse_values: false })
const rule = root.first_child
const selector = rule?.first_child
const block = selector?.next_sibling
Expand All @@ -263,11 +249,10 @@ describe('Parser Options', () => {
})

it('should accept skip_comments with parsing options', () => {
const parser = new Parser('/* test */ body { color: red; }', {
const root = parse('/* test */ body { color: red; }', {
skip_comments: true,
parse_values: false,
})
const root = parser.parse()
const rule = root.first_child

// Comment should be skipped
Expand Down
1 change: 1 addition & 0 deletions src/parse-selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import {
import { ANplusBParser } from './parse-anplusb'
import { CSSNode } from './css-node'

/** @internal */
export class SelectorParser {
private lexer: Lexer
private arena: CSSDataArena
Expand Down
4 changes: 4 additions & 0 deletions src/parse-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export function parse_dimension(text: string): { value: number; unit: string } {
* @param pos - Starting position
* @param end - End boundary (exclusive)
* @returns New position after skipping whitespace
* @internal
*/
export function skip_whitespace_forward(source: string, pos: number, end: number): number {
while (pos < end && is_whitespace(source.charCodeAt(pos))) {
Expand All @@ -79,6 +80,7 @@ export function skip_whitespace_forward(source: string, pos: number, end: number
* @param pos - Starting position
* @param end - End boundary (exclusive)
* @returns New position after skipping whitespace/comments
* @internal
*/
export function skip_whitespace_and_comments_forward(source: string, pos: number, end: number): number {
while (pos < end) {
Expand Down Expand Up @@ -115,6 +117,7 @@ export function skip_whitespace_and_comments_forward(source: string, pos: number
* @param pos - Starting position (exclusive, scanning backward from pos-1)
* @param start - Start boundary (inclusive, won't go before this)
* @returns New position after skipping whitespace/comments backward
* @internal
*/
export function skip_whitespace_and_comments_backward(source: string, pos: number, start: number): number {
while (pos > start) {
Expand Down Expand Up @@ -151,6 +154,7 @@ export function skip_whitespace_and_comments_backward(source: string, pos: numbe
* @param start - Start offset in source
* @param end - End offset in source
* @returns [trimmed_start, trimmed_end] or null if all whitespace/comments
* @internal
*
* Skips whitespace (space, tab, newline, CR, FF) and CSS comments from both ends
* of the specified range. Returns the trimmed boundaries or null if the range
Expand Down
Loading
Loading