Skip to content

Commit 1caaddf

Browse files
authored
fix node type mismatch between parser and type defs (#277)
Found in projectwallace/format-css#230
1 parent 89fd856 commit 1caaddf

2 files changed

Lines changed: 55 additions & 2 deletions

File tree

src/node-types.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ import type {
4545
Identifier,
4646
Operator,
4747
PreludeOperator,
48+
ContainerQuery,
49+
FeatureRange,
50+
String,
4851
} from './node-types'
4952

5053
// ---------------------------------------------------------------------------
@@ -328,6 +331,52 @@ describe('type narrowing — compile-time', () => {
328331
}
329332
})
330333

334+
test('FeatureRange children are typed as Dimension | PreludeOperator, not Operator', () => {
335+
const atrule = parse('@media (width >= 400px) {}').first_child! as Atrule
336+
const range = atrule.prelude!.first_child!.first_child! as FeatureRange
337+
expectTypeOf(range.children).toEqualTypeOf<(Dimension | PreludeOperator)[]>()
338+
339+
const [op, dim] = range.children
340+
expect(op.type_name).toBe('Operator')
341+
expect(dim.type_name).toBe('Dimension')
342+
})
343+
344+
test('ContainerQuery children include PreludeOperator for and/or/not, without casting', () => {
345+
const atrule = parse('@container style(a: 1) and style(b: 2) {}').first_child! as Atrule
346+
const containerQuery = atrule.prelude!.first_child! as ContainerQuery
347+
expectTypeOf(containerQuery.children).toEqualTypeOf<
348+
(Identifier | MediaFeature | Function | PreludeOperator)[]
349+
>()
350+
351+
const [, op] = containerQuery.children
352+
expect(op.type_name).toBe('Operator')
353+
expect((op as PreludeOperator).text).toBe('and')
354+
})
355+
356+
test('AtrulePrelude children include Identifier for @keyframes/@page/@property preludes', () => {
357+
const atrule = parse('@keyframes spin {}').first_child! as Atrule
358+
const prelude = atrule.prelude! as AtrulePrelude
359+
const [ident] = prelude.children
360+
361+
expect(ident.type_name).toBe('Identifier')
362+
if (ident.type_name === 'Identifier') {
363+
expectTypeOf(ident).toExtend<Identifier>()
364+
expect(ident.text).toBe('spin')
365+
}
366+
})
367+
368+
test('AtrulePrelude children include String for @charset', () => {
369+
const root = parse('@charset "UTF-8";')
370+
const atrule = root.first_child! as Atrule
371+
const prelude = atrule.prelude! as AtrulePrelude
372+
const [str] = prelude.children
373+
374+
expect(str.type_name).toBe('String')
375+
if (str.type_name === 'String') {
376+
expectTypeOf(str).toExtend<String>()
377+
}
378+
})
379+
331380
test('AnyCss enables switch narrowing', () => {
332381
// This test verifies the discriminated union works for switch narrowing.
333382
// The function must compile without type errors.

src/node-types.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,10 @@ export type AtrulePrelude = WithClone<
456456
| Url
457457
// `@supports style(...)` / `selector(...)` function conditions
458458
| Function
459+
// `@page`, `@keyframes`, `@property`, etc. (parse_identifier())
460+
| Identifier
461+
// `@charset` (parse_charset_prelude())
462+
| String
459463
> & { readonly type: typeof AT_RULE_PRELUDE; readonly type_name: 'AtrulePrelude' }
460464
>
461465

@@ -489,7 +493,7 @@ export type MediaType = Leaf<
489493

490494
export type ContainerQuery = WithClone<
491495
CSSNode &
492-
WithChildren<Identifier | MediaFeature | Function> & {
496+
WithChildren<Identifier | MediaFeature | Function | PreludeOperator> & {
493497
readonly type: typeof CONTAINER_QUERY
494498
readonly type_name: 'ContainerQuery'
495499
}
@@ -543,7 +547,7 @@ export type PreludeOperator = Leaf<typeof PRELUDE_OPERATOR, 'Operator'>
543547

544548
export type FeatureRange = WithClone<
545549
CSSNode &
546-
WithChildren<Dimension | Operator> & {
550+
WithChildren<Dimension | PreludeOperator> & {
547551
readonly type: typeof FEATURE_RANGE
548552
readonly type_name: 'MediaFeatureRange'
549553
/** The feature name in a range comparison, e.g. "width" from "(width >= 400px)" */

0 commit comments

Comments
 (0)