From 421f5a580c225d4257a9cedb41feff7c2ec3b45c Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 18 Oct 2026 09:19:38 +0000 Subject: [PATCH 1/2] fix: add WithChildren to MediaFeature type and narrow its value Fixes #249 --- src/node-types.test.ts | 11 +++++++++++ src/node-types.ts | 19 ++++++++++--------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/node-types.test.ts b/src/node-types.test.ts index 44f34fb..3df968f 100644 --- a/src/node-types.test.ts +++ b/src/node-types.test.ts @@ -40,6 +40,7 @@ import type { PseudoElementSelector, NthSelector, MediaFeature, + MediaQuery, LayerName, Combinator, Identifier, @@ -341,6 +342,16 @@ describe('type narrowing — compile-time', () => { expect(dim.type_name).toBe('Dimension') }) + test('MediaFeature exposes children, including extra hack nodes like 0\\0', () => { + const atrule = parse('@media (min-width:0\\0) {}').first_child! as Atrule + const query = atrule.prelude!.first_child! as MediaQuery + const feature = query.first_child as MediaFeature + expect(feature.has_children).toBe(true) + expect(feature.child_count).toBe(2) + expect([...feature].map((c) => c.type_name)).toEqual(['Number', 'Identifier']) + expect(feature.value?.type_name).toBe('Number') + }) + test('ContainerQuery children include PreludeOperator for and/or/not, without casting', () => { const atrule = parse('@container style(a: 1) and style(b: 2) {}').first_child! as Atrule const containerQuery = atrule.prelude!.first_child! as ContainerQuery diff --git a/src/node-types.ts b/src/node-types.ts index 7a553ff..3d34052 100644 --- a/src/node-types.ts +++ b/src/node-types.ts @@ -543,15 +543,16 @@ export type MediaQuery = WithClone< } > -export type MediaFeature = Leaf< - typeof MEDIA_FEATURE, - 'Feature', - { - /** Feature name, e.g. "min-width" */ - readonly property: string - /** Feature value node (e.g. Dimension, Number, Identifier, Ratio), or null for boolean features like (hover) */ - readonly value: CSSNode | null - } +export type MediaFeature = WithClone< + CSSNode & + WithChildren & { + readonly type: typeof MEDIA_FEATURE + readonly type_name: 'Feature' + /** Feature name, e.g. "min-width" */ + readonly property: string + /** Feature value node (Dimension, Number, Identifier or Ratio), or null for boolean features like (hover). Hacks like `0\0` add further children after it. */ + readonly value: Identifier | Number | Dimension | Ratio | null + } > export type MediaType = Leaf< From 7697d71abc4d03659e16843ed2f801bea85282e1 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 18 Oct 2026 09:34:13 +0000 Subject: [PATCH 2/2] test: add toBeTypeOf assertions to MediaFeature children test --- src/node-types.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/node-types.test.ts b/src/node-types.test.ts index 3df968f..f19740e 100644 --- a/src/node-types.test.ts +++ b/src/node-types.test.ts @@ -346,6 +346,8 @@ describe('type narrowing — compile-time', () => { const atrule = parse('@media (min-width:0\\0) {}').first_child! as Atrule const query = atrule.prelude!.first_child! as MediaQuery const feature = query.first_child as MediaFeature + expect(feature.has_children).toBeTypeOf('boolean') + expect(feature.child_count).toBeTypeOf('number') expect(feature.has_children).toBe(true) expect(feature.child_count).toBe(2) expect([...feature].map((c) => c.type_name)).toEqual(['Number', 'Identifier'])