@stacksjs/ts-css 0.1.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.
@@ -0,0 +1,54 @@
1
+ declare function createItem<T>(data: T): ListItem<T>;
2
+ /**
3
+ * Convenience constructor matching `csstree.List()` (callable without `new`).
4
+ */
5
+ export declare function makeList<T>(): CssList<T>;
6
+ /**
7
+ * Doubly linked list used as the children container for every CSS AST node.
8
+ *
9
+ * Mirrors css-tree's `List` so `csstree.List` import sites can switch to
10
+ * `import { CssList as List } from '@stacksjs/ts-css/parse'` without changing
11
+ * call sites. The list owns its `ListItem<T>` cells; items can be moved
12
+ * between lists by detach/insert pairs.
13
+ */
14
+ export declare interface ListItem<T> {
15
+ prev: ListItem<T> | null
16
+ next: ListItem<T> | null
17
+ data: T
18
+ }
19
+ export declare class CssList<T> {
20
+ head: ListItem<T> | null;
21
+ tail: ListItem<T> | null;
22
+ static createItem<U>(data: U): ListItem<U>;
23
+ createItem(data: T): ListItem<T>;
24
+ get isEmpty(): boolean;
25
+ get first(): T | null;
26
+ get last(): T | null;
27
+ *[Symbol.iterator](): Iterator<T>;
28
+ fromArray(items: ReadonlyArray<T>): this;
29
+ toArray(): T[];
30
+ toJSON(): T[];
31
+ forEach(fn: (data: T, item: ListItem<T>, list: CssList<T>) => void, thisArg?: any): void;
32
+ forEachRight(fn: (data: T, item: ListItem<T>, list: CssList<T>) => void, thisArg?: any): void;
33
+ reduce<U>(fn: (acc: U, data: T, index: number, list: CssList<T>) => U, initial: U): U;
34
+ some(fn: (item: T, index: number, list: CssList<T>) => boolean): boolean;
35
+ map<U>(fn: (item: T, index: number, list: CssList<T>) => U): CssList<U>;
36
+ filter(fn: (item: T, index: number, list: CssList<T>) => boolean): CssList<T>;
37
+ clear(): void;
38
+ copy(): CssList<T>;
39
+ prepend(item: ListItem<T>): this;
40
+ prependData(data: T): this;
41
+ append(item: ListItem<T>): this;
42
+ appendData(data: T): this;
43
+ insert(item: ListItem<T>, before?: ListItem<T> | null | undefined): this;
44
+ insertData(data: T, before?: ListItem<T> | null): this;
45
+ remove(item: ListItem<T>): ListItem<T>;
46
+ push(data: T): void;
47
+ pop(): ListItem<T> | null;
48
+ unshift(data: T): void;
49
+ shift(): ListItem<T> | null;
50
+ prependList(list: CssList<T>): this;
51
+ appendList(list: CssList<T>): this;
52
+ insertList(list: CssList<T>, before?: ListItem<T> | null): this;
53
+ replace(oldItem: ListItem<T>, newItemOrList: ListItem<T> | CssList<T>): void;
54
+ }
@@ -0,0 +1,6 @@
1
+ import { TokenType } from '../tokenizer';
2
+ import type { CssNode, ParseOptions } from '../types';
3
+ // ----- top-level dispatch -----
4
+ export declare function parse(source: string, options?: ParseOptions): CssNode;
5
+ // expose some helpers for the public surface
6
+ export { TokenType };
@@ -0,0 +1,67 @@
1
+ /** Decode a CSS-escaped name slice (e.g. `\\26 B` → `&B`). */
2
+ /**
3
+ * Decode a CSS string literal slice to its actual character value.
4
+ * `start` / `end` exclude the surrounding quote characters.
5
+ *
6
+ * Handles:
7
+ * - hex escapes (`\26 ` → `&`)
8
+ * - `\"` / `\'` / `\\`
9
+ * - escaped newlines (CSS: backslash followed by newline is removed)
10
+ * - any other `\<char>` → `<char>`
11
+ */
12
+ export declare function decodeString(source: string, start: number, end: number): string;
13
+ export declare function decodeName(source: string, start: number, end: number): string;
14
+ export declare interface Token {
15
+ type: TokenType
16
+ start: number
17
+ end: number
18
+ }
19
+ export declare class Tokenizer {
20
+ source: string;
21
+ offset: number;
22
+ types: Uint8Array;
23
+ starts: Uint32Array;
24
+ ends: Uint32Array;
25
+ count: number;
26
+ constructor(source: string);
27
+ get lineStarts(): number[];
28
+ get tokens(): Token[];
29
+ locate(offset: number): { line: number, column: number };
30
+ }
31
+ /**
32
+ * CSS Syntax Module Level 3 tokenizer.
33
+ *
34
+ * https://www.w3.org/TR/css-syntax-3/#tokenization
35
+ *
36
+ * Produces a flat sequence of token offsets that the parser walks. Tokens
37
+ * are recorded as parallel arrays (type + offset) rather than allocations
38
+ * — every other CSS lib does the same for performance.
39
+ */
40
+ export declare const enum TokenType {
41
+ EOF = 0,
42
+ Ident = 1,
43
+ Function = 2,
44
+ AtKeyword = 3,
45
+ Hash = 4,
46
+ String = 5,
47
+ BadString = 6,
48
+ Url = 7,
49
+ BadUrl = 8,
50
+ Delim = 9,
51
+ Number = 10,
52
+ Percentage = 11,
53
+ Dimension = 12,
54
+ WhiteSpace = 13,
55
+ CDO = 14,
56
+ CDC = 15,
57
+ Colon = 16,
58
+ Semicolon = 17,
59
+ Comma = 18,
60
+ LeftSquareBracket = 19,
61
+ RightSquareBracket = 20,
62
+ LeftParenthesis = 21,
63
+ RightParenthesis = 22,
64
+ LeftCurlyBracket = 23,
65
+ RightCurlyBracket = 24,
66
+ Comment = 25,
67
+ }
@@ -0,0 +1,264 @@
1
+ import type { CssList } from './list';
2
+ export declare interface BaseNode {
3
+ type: CssNodeType
4
+ loc?: CssLocation | null
5
+ }
6
+ export declare interface CssLocation {
7
+ source: string
8
+ start: { offset: number, line: number, column: number }
9
+ end: { offset: number, line: number, column: number }
10
+ }
11
+ // ----- Containers -----
12
+ export declare interface StyleSheet extends BaseNode {
13
+ type: 'StyleSheet'
14
+ children: CssList<CssNode>
15
+ }
16
+ export declare interface Rule extends BaseNode {
17
+ type: 'Rule'
18
+ prelude: SelectorList | Raw
19
+ block: Block
20
+ }
21
+ export declare interface Atrule extends BaseNode {
22
+ type: 'Atrule'
23
+ name: string
24
+ prelude: AtrulePrelude | Raw | null
25
+ block: Block | null
26
+ }
27
+ export declare interface AtrulePrelude extends BaseNode {
28
+ type: 'AtrulePrelude'
29
+ children: CssList<CssNode>
30
+ }
31
+ export declare interface Block extends BaseNode {
32
+ type: 'Block'
33
+ children: CssList<CssNode>
34
+ }
35
+ // ----- Declarations -----
36
+ export declare interface Declaration extends BaseNode {
37
+ type: 'Declaration'
38
+ important: boolean | string
39
+ property: string
40
+ value: Value | Raw
41
+ }
42
+ export declare interface DeclarationList extends BaseNode {
43
+ type: 'DeclarationList'
44
+ children: CssList<CssNode>
45
+ }
46
+ export declare interface Value extends BaseNode {
47
+ type: 'Value'
48
+ children: CssList<CssNode>
49
+ }
50
+ // ----- Selectors -----
51
+ export declare interface SelectorList extends BaseNode {
52
+ type: 'SelectorList'
53
+ children: CssList<CssNode>
54
+ }
55
+ export declare interface Selector extends BaseNode {
56
+ type: 'Selector'
57
+ children: CssList<CssNode>
58
+ }
59
+ export declare interface TypeSelector extends BaseNode {
60
+ type: 'TypeSelector'
61
+ name: string
62
+ }
63
+ export declare interface IdSelector extends BaseNode {
64
+ type: 'IdSelector'
65
+ name: string
66
+ }
67
+ export declare interface ClassSelector extends BaseNode {
68
+ type: 'ClassSelector'
69
+ name: string
70
+ }
71
+ export declare interface AttributeSelector extends BaseNode {
72
+ type: 'AttributeSelector'
73
+ name: Identifier
74
+ matcher: string | null
75
+ value: StringNode | Identifier | null
76
+ flags: string | null
77
+ }
78
+ export declare interface PseudoClassSelector extends BaseNode {
79
+ type: 'PseudoClassSelector'
80
+ name: string
81
+ children: CssList<CssNode> | null
82
+ }
83
+ export declare interface PseudoElementSelector extends BaseNode {
84
+ type: 'PseudoElementSelector'
85
+ name: string
86
+ children: CssList<CssNode> | null
87
+ }
88
+ export declare interface Combinator extends BaseNode {
89
+ type: 'Combinator'
90
+ name: string
91
+ }
92
+ export declare interface NestingSelector extends BaseNode {
93
+ type: 'NestingSelector'
94
+ }
95
+ // ----- Atomic values -----
96
+ export declare interface Identifier extends BaseNode {
97
+ type: 'Identifier'
98
+ name: string
99
+ }
100
+ export declare interface NumberNode extends BaseNode {
101
+ type: 'Number'
102
+ value: string
103
+ }
104
+ export declare interface PercentageNode extends BaseNode {
105
+ type: 'Percentage'
106
+ value: string
107
+ }
108
+ export declare interface DimensionNode extends BaseNode {
109
+ type: 'Dimension'
110
+ value: string
111
+ unit: string
112
+ }
113
+ export declare interface StringNode extends BaseNode {
114
+ type: 'String'
115
+ value: string
116
+ }
117
+ export declare interface UrlNode extends BaseNode {
118
+ type: 'Url'
119
+ value: string
120
+ }
121
+ export declare interface HashNode extends BaseNode {
122
+ type: 'Hash'
123
+ name: string
124
+ }
125
+ export declare interface OperatorNode extends BaseNode {
126
+ type: 'Operator'
127
+ value: string
128
+ }
129
+ export declare interface FunctionNode extends BaseNode {
130
+ type: 'Function'
131
+ name: string
132
+ children: CssList<CssNode>
133
+ }
134
+ export declare interface ParenthesesNode extends BaseNode {
135
+ type: 'Parentheses'
136
+ children: CssList<CssNode>
137
+ }
138
+ export declare interface BracketsNode extends BaseNode {
139
+ type: 'Brackets'
140
+ children: CssList<CssNode>
141
+ }
142
+ export declare interface RawNode extends BaseNode {
143
+ type: 'Raw'
144
+ value: string
145
+ }
146
+ export declare interface CommentNode extends BaseNode {
147
+ type: 'Comment'
148
+ value: string
149
+ }
150
+ export declare interface WhiteSpaceNode extends BaseNode {
151
+ type: 'WhiteSpace'
152
+ value: string
153
+ }
154
+ export declare interface CDONode extends BaseNode { type: 'CDO' }
155
+ export declare interface CDCNode extends BaseNode { type: 'CDC' }
156
+ export declare interface NthNode extends BaseNode {
157
+ type: 'Nth'
158
+ nth: AnPlusBNode | Identifier
159
+ selector: SelectorList | null
160
+ }
161
+ export declare interface AnPlusBNode extends BaseNode {
162
+ type: 'AnPlusB'
163
+ a: string | null
164
+ b: string | null
165
+ }
166
+ export declare interface RatioNode extends BaseNode {
167
+ type: 'Ratio'
168
+ left: NumberNode
169
+ right: NumberNode
170
+ }
171
+ export declare interface UnicodeRangeNode extends BaseNode {
172
+ type: 'UnicodeRange'
173
+ value: string
174
+ }
175
+ export declare interface MediaQueryListNode extends BaseNode {
176
+ type: 'MediaQueryList'
177
+ children: CssList<CssNode>
178
+ }
179
+ export declare interface MediaQueryNode extends BaseNode {
180
+ type: 'MediaQuery'
181
+ children: CssList<CssNode>
182
+ }
183
+ export declare interface MediaFeatureNode extends BaseNode {
184
+ type: 'MediaFeature'
185
+ name: string
186
+ value: NumberNode | DimensionNode | RatioNode | Identifier | null
187
+ }
188
+ export declare interface ParseOptions {
189
+ filename?: string
190
+ positions?: boolean
191
+ context?: ParseContext
192
+ parseValue?: boolean
193
+ parseAtrulePrelude?: boolean
194
+ parseCustomProperty?: boolean
195
+ parseRulePrelude?: boolean
196
+ onParseError?: (error: SyntaxError, fallbackNode: CssNode) => void
197
+ }
198
+ export type CssNodeType = | 'AnPlusB'
199
+ | 'Atrule'
200
+ | 'AtrulePrelude'
201
+ | 'AttributeSelector'
202
+ | 'Block'
203
+ | 'Brackets'
204
+ | 'CDC'
205
+ | 'CDO'
206
+ | 'ClassSelector'
207
+ | 'Combinator'
208
+ | 'Comment'
209
+ | 'Declaration'
210
+ | 'DeclarationList'
211
+ | 'Dimension'
212
+ | 'Function'
213
+ | 'Hash'
214
+ | 'IdSelector'
215
+ | 'Identifier'
216
+ | 'MediaFeature'
217
+ | 'MediaQuery'
218
+ | 'MediaQueryList'
219
+ | 'NestingSelector'
220
+ | 'Nth'
221
+ | 'Number'
222
+ | 'Operator'
223
+ | 'Parentheses'
224
+ | 'Percentage'
225
+ | 'PseudoClassSelector'
226
+ | 'PseudoElementSelector'
227
+ | 'Ratio'
228
+ | 'Raw'
229
+ | 'Rule'
230
+ | 'Selector'
231
+ | 'SelectorList'
232
+ | 'StyleSheet'
233
+ | 'TypeSelector'
234
+ | 'UnicodeRange'
235
+ | 'Url'
236
+ | 'Value'
237
+ | 'WhiteSpace'
238
+ | 'String';
239
+ // ----- Aliases -----
240
+ export type Raw = RawNode;
241
+ export type CssNode = | StyleSheet | Rule | Atrule | AtrulePrelude | Block
242
+ | Declaration | DeclarationList | Value
243
+ | SelectorList | Selector | TypeSelector | IdSelector | ClassSelector
244
+ | AttributeSelector | PseudoClassSelector | PseudoElementSelector
245
+ | Combinator | NestingSelector
246
+ | Identifier | NumberNode | PercentageNode | DimensionNode
247
+ | StringNode | UrlNode | HashNode | OperatorNode
248
+ | FunctionNode | ParenthesesNode | BracketsNode
249
+ | RawNode | CommentNode | WhiteSpaceNode | CDONode | CDCNode
250
+ | NthNode | AnPlusBNode | RatioNode | UnicodeRangeNode
251
+ | MediaQueryListNode | MediaQueryNode | MediaFeatureNode;
252
+ export type ParseContext = | 'stylesheet'
253
+ | 'atrule'
254
+ | 'atrulePrelude'
255
+ | 'mediaQuery'
256
+ | 'mediaQueryList'
257
+ | 'rule'
258
+ | 'selectorList'
259
+ | 'selector'
260
+ | 'block'
261
+ | 'declarationList'
262
+ | 'declaration'
263
+ | 'value'
264
+ | 'raw';
@@ -0,0 +1,55 @@
1
+ import { CssList, type ListItem } from './list';
2
+ import type { Atrule, CssNode, Declaration, Rule } from './types';
3
+ export declare const walk: WalkFn;
4
+ export declare const walkSkip: symbol;
5
+ export declare const walkStop: symbol;
6
+ export declare interface WalkContext {
7
+ root: CssNode
8
+ stylesheet: CssNode | null
9
+ atrule: Atrule | null
10
+ atrulePrelude: CssNode | null
11
+ rule: Rule | null
12
+ selector: CssNode | null
13
+ block: CssNode | null
14
+ declaration: Declaration | null
15
+ function: CssNode | null
16
+ }
17
+ /**
18
+ * Object-form visitor. The `T extends WalkVisit` generic is inferred from
19
+ * the literal value of `visit`, so writing
20
+ *
21
+ * walk(ast, { visit: 'Rule', enter(node) { … } })
22
+ *
23
+ * narrows `node` to `Rule`. Without `visit`, callbacks receive the full
24
+ * `CssNode` union as `enter`/`leave` arguments.
25
+ */
26
+ export declare interface WalkVisitorObject<T extends WalkVisit | undefined = undefined> {
27
+ visit?: T
28
+ reverse?: boolean
29
+ enter?: VisitorCallback<T extends WalkVisit ? CssNodeOfType<T> : CssNode>
30
+ leave?: VisitorCallback<T extends WalkVisit ? CssNodeOfType<T> : CssNode>
31
+ }
32
+ /**
33
+ * Walk every node of `root`, calling `visitor` (or visitor.enter / .leave).
34
+ * Returns:
35
+ * - undefined when traversal completes,
36
+ * - the SKIP / STOP sentinel propagated from a visitor.
37
+ *
38
+ * `walk.skip` / `walk.stop` are exposed as static-symbol sentinels.
39
+ */
40
+ export declare interface WalkFn {
41
+ (root: CssNode, visitor: WalkVisitorFunction): symbol | undefined
42
+ <T extends WalkVisit>(root: CssNode, visitor: WalkVisitorObject<T>): symbol | undefined
43
+ skip: symbol
44
+ stop: symbol
45
+ }
46
+ export type WalkVisit = CssNode['type'];
47
+ // Narrow CssNode by its `type` discriminant — used to type the
48
+ // `visit: 'Rule'` filter so consumer callbacks receive a `Rule`, not the
49
+ // full union.
50
+ export type CssNodeOfType<T extends WalkVisit> = Extract<CssNode, { type: T }>;
51
+ // eslint-disable-next-line pickier/no-unused-vars
52
+ declare type VisitorCallback<N> = (this: WalkContext, node: N, item: ListItem<CssNode> | null, list: CssList<CssNode> | null) => void | symbol;
53
+ /** Plain-function visitor — runs against every node. */
54
+ export type WalkVisitorFunction = VisitorCallback<CssNode>;
55
+ export type WalkVisitor = WalkVisitorFunction | WalkVisitorObject<WalkVisit | undefined>;
@@ -0,0 +1,18 @@
1
+ import { parseAndCompile } from './pseudo-selectors/selectors';
2
+ import type { Adapter, CompiledQuery, Options } from './types';
3
+ import type { Selector } from '../what';
4
+ export type {
5
+ Adapter,
6
+ CompiledQuery,
7
+ Options,
8
+ Predicate,
9
+ } from './types';
10
+ export declare function compile<Node, ElementNode extends Node>(selector: string | Selector[][], options: Options<Node, ElementNode>): CompiledQuery<ElementNode>;
11
+ /** Drop the cached compile of `selector` for `adapter`, or all entries
12
+ * if `selector` is omitted. */
13
+ export declare function clearSelectorCache(adapter: object, selector?: string): void;
14
+ export declare function selectAll<Node, ElementNode extends Node>(selector: string | Selector[][] | CompiledQuery<ElementNode>, root: Node | Node[], options: Options<Node, ElementNode>): ElementNode[];
15
+ export declare function selectOne<Node, ElementNode extends Node>(selector: string | Selector[][] | CompiledQuery<ElementNode>, root: Node | Node[], options: Options<Node, ElementNode>): ElementNode | null;
16
+ export declare function is<Node, ElementNode extends Node>(node: ElementNode, selector: string | Selector[][] | CompiledQuery<ElementNode>, options: Options<Node, ElementNode>): boolean;
17
+ // expose internals for advanced use
18
+ export { parseAndCompile };