From 3c6bb6faba559d23dac95eb8cd1d10db190ee4a7 Mon Sep 17 00:00:00 2001 From: Manuel <30698007+manuel3108@users.noreply.github.com> Date: Wed, 11 Feb 2026 21:36:54 +0100 Subject: [PATCH] chore: provide proper public type for `parseCss` result (#17654) Currently, the [newly introduced `parseCss` from `svelte/compiler`](https://github.com/sveltejs/svelte/pull/17496) returns `Omit`. If you try to work with this in external tooling, everywhere where you pass around the result of this method, you need to use that type as well, which is quite cumbersome. (I'm trying to integrate this into `sv` to get rid of a workaround) This creates a new type in the CSS AST to differentiate between one stylesheet only having the roles, and one beeing the full one that is used in `parse` itself. Im 100% open on the name of the new type or any better ideas. ### Before submitting the PR, please make sure you do the following - [ ] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs - [x] Prefix your PR title with `feat:`, `fix:`, `chore:`, or `docs:`. - [x] This message body should clearly illustrate what problems it solves. - [ ] Ideally, include a test that fails without this PR but passes with it. - [x] If this PR changes code within `packages/svelte/src`, add a changeset (`npx changeset`). ### Tests and linting - [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` --------- Co-authored-by: Rich Harris --- .changeset/tender-pugs-hide.md | 5 +++++ packages/svelte/src/compiler/index.js | 4 ++-- packages/svelte/src/compiler/types/css.d.ts | 11 +++++++++-- packages/svelte/tests/css-parse.test.ts | 6 +++--- packages/svelte/types/index.d.ts | 13 ++++++++++--- 5 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 .changeset/tender-pugs-hide.md diff --git a/.changeset/tender-pugs-hide.md b/.changeset/tender-pugs-hide.md new file mode 100644 index 0000000000..260f49614e --- /dev/null +++ b/.changeset/tender-pugs-hide.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +chore: provide proper public type for `parseCss` result diff --git a/packages/svelte/src/compiler/index.js b/packages/svelte/src/compiler/index.js index acfef6a320..e864c4a1f4 100644 --- a/packages/svelte/src/compiler/index.js +++ b/packages/svelte/src/compiler/index.js @@ -123,7 +123,7 @@ export function parse(source, { modern, loose } = {}) { * The parseCss function parses a CSS stylesheet, returning its abstract syntax tree. * * @param {string} source The CSS source code - * @returns {Omit} + * @returns {AST.CSS.StyleSheetFile} */ export function parseCss(source) { source = remove_bom(source); @@ -135,7 +135,7 @@ export function parseCss(source) { const children = parse_stylesheet(parser); return { - type: 'StyleSheet', + type: 'StyleSheetFile', start: 0, end: source.length, children diff --git a/packages/svelte/src/compiler/types/css.d.ts b/packages/svelte/src/compiler/types/css.d.ts index 154a06ffb1..13eb880d83 100644 --- a/packages/svelte/src/compiler/types/css.d.ts +++ b/packages/svelte/src/compiler/types/css.d.ts @@ -6,10 +6,17 @@ export namespace _CSS { end: number; } - export interface StyleSheet extends BaseNode { + export interface StyleSheetBase extends BaseNode { + children: Array; + } + + export interface StyleSheetFile extends StyleSheetBase { + type: 'StyleSheetFile'; + } + + export interface StyleSheet extends StyleSheetBase { type: 'StyleSheet'; attributes: any[]; // TODO - children: Array; content: { start: number; end: number; diff --git a/packages/svelte/tests/css-parse.test.ts b/packages/svelte/tests/css-parse.test.ts index 4d8ef8601b..3a53e97955 100644 --- a/packages/svelte/tests/css-parse.test.ts +++ b/packages/svelte/tests/css-parse.test.ts @@ -4,7 +4,7 @@ import { parseCss } from 'svelte/compiler'; describe('parseCss', () => { it('parses a simple rule', () => { const ast = parseCss('div { color: red; }'); - assert.equal(ast.type, 'StyleSheet'); + assert.equal(ast.type, 'StyleSheetFile'); assert.equal(ast.children.length, 1); assert.equal(ast.children[0].type, 'Rule'); }); @@ -57,7 +57,7 @@ describe('parseCss', () => { it('parses empty stylesheet', () => { const ast = parseCss(''); - assert.equal(ast.type, 'StyleSheet'); + assert.equal(ast.type, 'StyleSheetFile'); assert.equal(ast.children.length, 0); assert.equal(ast.start, 0); assert.equal(ast.end, 0); @@ -138,7 +138,7 @@ describe('parseCss', () => { it('parses escaped characters', () => { const ast = parseCss("div { background: url('./example.png?\\''); }"); - assert.equal(ast.type, 'StyleSheet'); + assert.equal(ast.type, 'StyleSheetFile'); assert.equal(ast.children.length, 1); const rule = ast.children[0]; assert.equal(rule.type, 'Rule'); diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 62c0e210be..e7aa5395b8 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -889,7 +889,7 @@ declare module 'svelte/compiler' { * * @param source The CSS source code * */ - export function parseCss(source: string): Omit; + export function parseCss(source: string): AST.CSS.StyleSheetFile; /** * @deprecated Replace this with `import { walk } from 'estree-walker'` * */ @@ -1673,10 +1673,17 @@ declare module 'svelte/compiler' { end: number; } - export interface StyleSheet extends BaseNode { + export interface StyleSheetBase extends BaseNode { + children: Array; + } + + export interface StyleSheetFile extends StyleSheetBase { + type: 'StyleSheetFile'; + } + + export interface StyleSheet extends StyleSheetBase { type: 'StyleSheet'; attributes: any[]; // TODO - children: Array; content: { start: number; end: number;