diff --git a/CHANGELOG.md b/CHANGELOG.md
index ab6796d6b..539705f1e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.80.4
+
+* No user-visible changes.
+
## 1.80.3
* Fix a bug where `@import url("...")` would crash in plain CSS files.
diff --git a/pkg/sass-parser/CHANGELOG.md b/pkg/sass-parser/CHANGELOG.md
index 968d6d72b..eae5707f7 100644
--- a/pkg/sass-parser/CHANGELOG.md
+++ b/pkg/sass-parser/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.4.1
+
+* Add `BooleanExpression` and `NumberExpression`.
+
## 0.4.0
* **Breaking change:** Warnings are no longer emitted during parsing, so the
diff --git a/pkg/sass-parser/README.md b/pkg/sass-parser/README.md
index 89908a492..bfb2b3520 100644
--- a/pkg/sass-parser/README.md
+++ b/pkg/sass-parser/README.md
@@ -257,3 +257,17 @@ There are a few cases where an operation that's valid in PostCSS won't work with
* Trying to add child nodes to a Sass statement that doesn't support children
like `@use` or `@error` is not supported.
+
+## Contributing
+
+Before sending out a pull request, please run the following commands from the
+`pkg/sass-parser` directory:
+
+* `npm run check` - Runs `eslint`, and then tries to compile the package with
+ `tsc`.
+
+* `npm run test` - Runs all the tests in the package.
+
+Note: You should run `dart run grinder before-test` from the `dart-sass`
+directory beforehand to ensure you're running `sass-parser` against the latest
+version of `dart-sass` JavaScript API.
diff --git a/pkg/sass-parser/lib/index.ts b/pkg/sass-parser/lib/index.ts
index 5746f98e4..11f9e3bd1 100644
--- a/pkg/sass-parser/lib/index.ts
+++ b/pkg/sass-parser/lib/index.ts
@@ -3,7 +3,6 @@
// https://opensource.org/licenses/MIT.
import * as postcss from 'postcss';
-import * as sassApi from 'sass';
import {Root} from './src/statement/root';
import * as sassInternal from './src/sass-internal';
@@ -27,6 +26,16 @@ export {
StringExpressionProps,
StringExpressionRaws,
} from './src/expression/string';
+export {
+ BooleanExpression,
+ BooleanExpressionProps,
+ BooleanExpressionRaws,
+} from './src/expression/boolean';
+export {
+ NumberExpression,
+ NumberExpressionProps,
+ NumberExpressionRaws,
+} from './src/expression/number';
export {
Interpolation,
InterpolationProps,
diff --git a/pkg/sass-parser/lib/src/expression/__snapshots__/boolean.test.ts.snap b/pkg/sass-parser/lib/src/expression/__snapshots__/boolean.test.ts.snap
new file mode 100644
index 000000000..1b68fedcf
--- /dev/null
+++ b/pkg/sass-parser/lib/src/expression/__snapshots__/boolean.test.ts.snap
@@ -0,0 +1,17 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`a boolean expression toJSON 1`] = `
+{
+ "inputs": [
+ {
+ "css": "@#{true}",
+ "hasBOM": false,
+ "id": "",
+ },
+ ],
+ "raws": {},
+ "sassType": "boolean",
+ "source": <1:4-1:8 in 0>,
+ "value": true,
+}
+`;
diff --git a/pkg/sass-parser/lib/src/expression/__snapshots__/number.test.ts.snap b/pkg/sass-parser/lib/src/expression/__snapshots__/number.test.ts.snap
new file mode 100644
index 000000000..6af882031
--- /dev/null
+++ b/pkg/sass-parser/lib/src/expression/__snapshots__/number.test.ts.snap
@@ -0,0 +1,18 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`a number expression toJSON 1`] = `
+{
+ "inputs": [
+ {
+ "css": "@#{123%}",
+ "hasBOM": false,
+ "id": "",
+ },
+ ],
+ "raws": {},
+ "sassType": "number",
+ "source": <1:4-1:8 in 0>,
+ "unit": "%",
+ "value": 123,
+}
+`;
diff --git a/pkg/sass-parser/lib/src/expression/boolean.test.ts b/pkg/sass-parser/lib/src/expression/boolean.test.ts
new file mode 100644
index 000000000..ca9f64f1b
--- /dev/null
+++ b/pkg/sass-parser/lib/src/expression/boolean.test.ts
@@ -0,0 +1,122 @@
+// Copyright 2024 Google Inc. Use of this source code is governed by an
+// MIT-style license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT.
+
+import {BooleanExpression} from '../..';
+import * as utils from '../../../test/utils';
+
+describe('a boolean expression', () => {
+ let node: BooleanExpression;
+
+ describe('true', () => {
+ function describeNode(
+ description: string,
+ create: () => BooleanExpression
+ ): void {
+ describe(description, () => {
+ beforeEach(() => void (node = create()));
+
+ it('has sassType boolean', () => expect(node.sassType).toBe('boolean'));
+
+ it('is true', () => expect(node.value).toBe(true));
+ });
+ }
+
+ describeNode('parsed', () => utils.parseExpression('true'));
+
+ describeNode(
+ 'constructed manually',
+ () => new BooleanExpression({value: true})
+ );
+
+ describeNode('constructed from ExpressionProps', () =>
+ utils.fromExpressionProps({value: true})
+ );
+ });
+
+ describe('false', () => {
+ function describeNode(
+ description: string,
+ create: () => BooleanExpression
+ ): void {
+ describe(description, () => {
+ beforeEach(() => void (node = create()));
+
+ it('has sassType boolean', () => expect(node.sassType).toBe('boolean'));
+
+ it('is false', () => expect(node.value).toBe(false));
+ });
+ }
+
+ describeNode('parsed', () => utils.parseExpression('false'));
+
+ describeNode(
+ 'constructed manually',
+ () => new BooleanExpression({value: false})
+ );
+
+ describeNode('constructed from ExpressionProps', () =>
+ utils.fromExpressionProps({value: false})
+ );
+ });
+
+ it('assigned new value', () => {
+ node = utils.parseExpression('true');
+ node.value = false;
+ expect(node.value).toBe(false);
+ });
+
+ describe('stringifies', () => {
+ it('true', () => {
+ expect(utils.parseExpression('true').toString()).toBe('true');
+ });
+
+ it('false', () => {
+ expect(utils.parseExpression('false').toString()).toBe('false');
+ });
+ });
+
+ describe('clone', () => {
+ let original: BooleanExpression;
+
+ beforeEach(() => {
+ original = utils.parseExpression('true');
+ });
+
+ describe('with no overrides', () => {
+ let clone: BooleanExpression;
+
+ beforeEach(() => void (clone = original.clone()));
+
+ describe('has the same properties:', () => {
+ it('value', () => expect(clone.value).toBe(true));
+
+ it('raws', () => expect(clone.raws).toEqual({}));
+
+ it('source', () => expect(clone.source).toBe(original.source));
+ });
+
+ it('creates a new self', () => expect(clone).not.toBe(original));
+ });
+
+ describe('overrides', () => {
+ describe('value', () => {
+ it('defined', () =>
+ expect(original.clone({value: false}).value).toBe(false));
+
+ it('undefined', () =>
+ expect(original.clone({value: undefined}).value).toBe(true));
+ });
+
+ describe('raws', () => {
+ it('defined', () =>
+ expect(original.clone({raws: {}}).raws).toEqual({}));
+
+ it('undefined', () =>
+ expect(original.clone({raws: undefined}).raws).toEqual({}));
+ });
+ });
+ });
+
+ it('toJSON', () => expect(utils.parseExpression('true')).toMatchSnapshot());
+});
diff --git a/pkg/sass-parser/lib/src/expression/boolean.ts b/pkg/sass-parser/lib/src/expression/boolean.ts
new file mode 100644
index 000000000..a75c567ed
--- /dev/null
+++ b/pkg/sass-parser/lib/src/expression/boolean.ts
@@ -0,0 +1,82 @@
+// Copyright 2024 Google Inc. Use of this source code is governed by an
+// MIT-style license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT.
+
+import * as postcss from 'postcss';
+
+import {LazySource} from '../lazy-source';
+import type * as sassInternal from '../sass-internal';
+import * as utils from '../utils';
+import {Expression} from '.';
+
+/**
+ * The initializer properties for {@link BooleanExpression}.
+ *
+ * @category Expression
+ */
+export interface BooleanExpressionProps {
+ value: boolean;
+ raws?: BooleanExpressionRaws;
+}
+
+/**
+ * Raws indicating how to precisely serialize a {@link BooleanExpression}.
+ *
+ * @category Expression
+ */
+// eslint-disable-next-line @typescript-eslint/no-empty-interface -- No raws for a boolean expression yet.
+export interface BooleanExpressionRaws {}
+
+/**
+ * An expression representing a boolean literal in Sass.
+ *
+ * @category Expression
+ */
+export class BooleanExpression extends Expression {
+ readonly sassType = 'boolean' as const;
+ declare raws: BooleanExpressionRaws;
+
+ /** The boolean value of this expression. */
+ get value(): boolean {
+ return this._value;
+ }
+ set value(value: boolean) {
+ // TODO - postcss/postcss#1957: Mark this as dirty
+ this._value = value;
+ }
+ private _value!: boolean;
+
+ constructor(defaults: BooleanExpressionProps);
+ /** @hidden */
+ constructor(_: undefined, inner: sassInternal.BooleanExpression);
+ constructor(defaults?: object, inner?: sassInternal.BooleanExpression) {
+ super(defaults);
+ if (inner) {
+ this.source = new LazySource(inner);
+ this.value = inner.value;
+ } else {
+ this.value ??= false;
+ }
+ }
+
+ clone(overrides?: Partial): this {
+ return utils.cloneNode(this, overrides, ['raws', 'value']);
+ }
+
+ toJSON(): object;
+ /** @hidden */
+ toJSON(_: string, inputs: Map): object;
+ toJSON(_?: string, inputs?: Map): object {
+ return utils.toJSON(this, ['value'], inputs);
+ }
+
+ /** @hidden */
+ toString(): string {
+ return this.value ? 'true' : 'false';
+ }
+
+ /** @hidden */
+ get nonStatementChildren(): ReadonlyArray {
+ return [];
+ }
+}
diff --git a/pkg/sass-parser/lib/src/expression/convert.ts b/pkg/sass-parser/lib/src/expression/convert.ts
index 792a74b11..52cbb2363 100644
--- a/pkg/sass-parser/lib/src/expression/convert.ts
+++ b/pkg/sass-parser/lib/src/expression/convert.ts
@@ -7,12 +7,16 @@ import * as sassInternal from '../sass-internal';
import {BinaryOperationExpression} from './binary-operation';
import {StringExpression} from './string';
import {Expression} from '.';
+import {BooleanExpression} from './boolean';
+import {NumberExpression} from './number';
/** The visitor to use to convert internal Sass nodes to JS. */
const visitor = sassInternal.createExpressionVisitor({
visitBinaryOperationExpression: inner =>
new BinaryOperationExpression(undefined, inner),
visitStringExpression: inner => new StringExpression(undefined, inner),
+ visitBooleanExpression: inner => new BooleanExpression(undefined, inner),
+ visitNumberExpression: inner => new NumberExpression(undefined, inner),
});
/** Converts an internal expression AST node into an external one. */
diff --git a/pkg/sass-parser/lib/src/expression/from-props.ts b/pkg/sass-parser/lib/src/expression/from-props.ts
index 030684e52..d74450813 100644
--- a/pkg/sass-parser/lib/src/expression/from-props.ts
+++ b/pkg/sass-parser/lib/src/expression/from-props.ts
@@ -5,10 +5,17 @@
import {BinaryOperationExpression} from './binary-operation';
import {Expression, ExpressionProps} from '.';
import {StringExpression} from './string';
+import {BooleanExpression} from './boolean';
+import {NumberExpression} from './number';
/** Constructs an expression from {@link ExpressionProps}. */
export function fromProps(props: ExpressionProps): Expression {
if ('text' in props) return new StringExpression(props);
if ('left' in props) return new BinaryOperationExpression(props);
+ if ('value' in props) {
+ if (typeof props.value === 'boolean') return new BooleanExpression(props);
+ if (typeof props.value === 'number') return new NumberExpression(props);
+ }
+
throw new Error(`Unknown node type: ${props}`);
}
diff --git a/pkg/sass-parser/lib/src/expression/index.ts b/pkg/sass-parser/lib/src/expression/index.ts
index a5f599133..ac1d37671 100644
--- a/pkg/sass-parser/lib/src/expression/index.ts
+++ b/pkg/sass-parser/lib/src/expression/index.ts
@@ -7,6 +7,8 @@ import type {
BinaryOperationExpression,
BinaryOperationExpressionProps,
} from './binary-operation';
+import {BooleanExpression, BooleanExpressionProps} from './boolean';
+import {NumberExpression, NumberExpressionProps} from './number';
import type {StringExpression, StringExpressionProps} from './string';
/**
@@ -14,14 +16,22 @@ import type {StringExpression, StringExpressionProps} from './string';
*
* @category Expression
*/
-export type AnyExpression = BinaryOperationExpression | StringExpression;
+export type AnyExpression =
+ | BinaryOperationExpression
+ | StringExpression
+ | BooleanExpression
+ | NumberExpression;
/**
* Sass expression types.
*
* @category Expression
*/
-export type ExpressionType = 'binary-operation' | 'string';
+export type ExpressionType =
+ | 'binary-operation'
+ | 'string'
+ | 'boolean'
+ | 'number';
/**
* The union type of all properties that can be used to construct Sass
@@ -31,7 +41,9 @@ export type ExpressionType = 'binary-operation' | 'string';
*/
export type ExpressionProps =
| BinaryOperationExpressionProps
- | StringExpressionProps;
+ | StringExpressionProps
+ | BooleanExpressionProps
+ | NumberExpressionProps;
/**
* The superclass of Sass expression nodes.
diff --git a/pkg/sass-parser/lib/src/expression/number.test.ts b/pkg/sass-parser/lib/src/expression/number.test.ts
new file mode 100644
index 000000000..7a3fe7671
--- /dev/null
+++ b/pkg/sass-parser/lib/src/expression/number.test.ts
@@ -0,0 +1,197 @@
+// Copyright 2024 Google Inc. Use of this source code is governed by an
+// MIT-style license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT.
+
+import {NumberExpression} from '../..';
+import * as utils from '../../../test/utils';
+
+describe('a number expression', () => {
+ let node: NumberExpression;
+
+ describe('unitless', () => {
+ function describeNode(
+ description: string,
+ create: () => NumberExpression
+ ): void {
+ describe(description, () => {
+ beforeEach(() => void (node = create()));
+
+ it('has sassType number', () => expect(node.sassType).toBe('number'));
+
+ it('is a number', () => expect(node.value).toBe(123));
+
+ it('has no unit', () => expect(node.unit).toBeNull());
+ });
+ }
+
+ describeNode('parsed', () => utils.parseExpression('123'));
+
+ describeNode(
+ 'constructed manually',
+ () => new NumberExpression({value: 123})
+ );
+
+ describeNode('constructed from ExpressionProps', () =>
+ utils.fromExpressionProps({value: 123})
+ );
+ });
+
+ describe('with a unit', () => {
+ function describeNode(
+ description: string,
+ create: () => NumberExpression
+ ): void {
+ describe(description, () => {
+ beforeEach(() => void (node = create()));
+
+ it('has sassType number', () => expect(node.sassType).toBe('number'));
+
+ it('is a number', () => expect(node.value).toBe(123));
+
+ it('has a unit', () => expect(node.unit).toBe('px'));
+ });
+ }
+
+ describeNode('parsed', () => utils.parseExpression('123px'));
+
+ describeNode(
+ 'constructed manually',
+ () =>
+ new NumberExpression({
+ value: 123,
+ unit: 'px',
+ })
+ );
+
+ describeNode('constructed from ExpressionProps', () =>
+ utils.fromExpressionProps({
+ value: 123,
+ unit: 'px',
+ })
+ );
+ });
+
+ describe('floating-point number', () => {
+ describe('unitless', () => {
+ beforeEach(() => void (node = utils.parseExpression('3.14')));
+
+ it('value', () => expect(node.value).toBe(3.14));
+
+ it('unit', () => expect(node.unit).toBeNull());
+ });
+
+ describe('with a unit', () => {
+ beforeEach(() => void (node = utils.parseExpression('1.618px')));
+
+ it('value', () => expect(node.value).toBe(1.618));
+
+ it('unit', () => expect(node.unit).toBe('px'));
+ });
+ });
+
+ describe('assigned new', () => {
+ beforeEach(() => void (node = utils.parseExpression('123')));
+
+ it('value', () => {
+ node.value = 456;
+ expect(node.value).toBe(456);
+ });
+
+ it('unit', () => {
+ node.unit = 'px';
+ expect(node.unit).toBe('px');
+ });
+ });
+
+ describe('stringifies', () => {
+ it('unitless', () =>
+ expect(utils.parseExpression('123').toString()).toBe('123'));
+
+ it('with a unit', () =>
+ expect(utils.parseExpression('123px').toString()).toBe('123px'));
+
+ it('floating-point number', () =>
+ expect(utils.parseExpression('3.14').toString()).toBe('3.14'));
+
+ describe('raws', () => {
+ it('with the same raw value as the expression', () =>
+ expect(
+ new NumberExpression({
+ value: 123,
+ raws: {value: {raw: 'hello', value: 123}},
+ }).toString()
+ ).toBe('hello'));
+
+ it('with a different raw value than the expression', () =>
+ expect(
+ new NumberExpression({
+ value: 123,
+ raws: {value: {raw: 'hello', value: 234}},
+ }).toString()
+ ).toBe('123'));
+ });
+ });
+
+ describe('clone', () => {
+ let original: NumberExpression;
+
+ beforeEach(() => {
+ original = utils.parseExpression('123');
+ // TODO: remove this once raws are properly parsed.
+ original.raws.value = {raw: '0123.0', value: 123};
+ });
+
+ describe('with no overrides', () => {
+ let clone: NumberExpression;
+
+ beforeEach(() => void (clone = original.clone()));
+
+ describe('has the same properties:', () => {
+ it('value', () => expect(clone.value).toBe(123));
+
+ it('unit', () => expect(clone.unit).toBeNull());
+
+ it('raws', () =>
+ expect(clone.raws).toEqual({value: {raw: '0123.0', value: 123}}));
+
+ it('source', () => expect(clone.source).toBe(original.source));
+ });
+
+ it('creates a new self', () => expect(clone).not.toBe(original));
+ });
+
+ describe('overrides', () => {
+ describe('value', () => {
+ it('defined', () =>
+ expect(original.clone({value: 123}).value).toBe(123));
+
+ it('undefined', () =>
+ expect(original.clone({value: undefined}).value).toBe(123));
+ });
+
+ describe('unit', () => {
+ it('defined', () =>
+ expect(original.clone({unit: 'px'}).unit).toBe('px'));
+
+ it('undefined', () =>
+ expect(original.clone({unit: undefined}).unit).toBeNull());
+ });
+
+ describe('raws', () => {
+ it('defined', () =>
+ expect(
+ original.clone({raws: {value: {raw: '1e3', value: 1e3}}}).raws
+ ).toEqual({
+ value: {raw: '1e3', value: 1e3},
+ }));
+
+ it('undefined', () =>
+ expect(original.clone({raws: undefined}).raws).toEqual({
+ value: {raw: '0123.0', value: 123},
+ }));
+ });
+ });
+ });
+
+ it('toJSON', () => expect(utils.parseExpression('123%')).toMatchSnapshot());
+});
diff --git a/pkg/sass-parser/lib/src/expression/number.ts b/pkg/sass-parser/lib/src/expression/number.ts
new file mode 100644
index 000000000..0a5efbebb
--- /dev/null
+++ b/pkg/sass-parser/lib/src/expression/number.ts
@@ -0,0 +1,112 @@
+// Copyright 2024 Google Inc. Use of this source code is governed by an
+// MIT-style license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT.
+
+import * as postcss from 'postcss';
+
+import {LazySource} from '../lazy-source';
+import type * as sassInternal from '../sass-internal';
+import * as utils from '../utils';
+import {Expression} from '.';
+
+/**
+ * The initializer properties for {@link NumberExpression}.
+ *
+ * @category Expression
+ */
+export interface NumberExpressionProps {
+ value: number;
+ unit?: string;
+ raws?: NumberExpressionRaws;
+}
+
+/**
+ * Raws indicating how to precisely serialize a {@link NumberExpression}.
+ *
+ * @category Expression
+ */
+export interface NumberExpressionRaws {
+ /**
+ * The raw string representation of the number.
+ *
+ * Numbers can be represented with or without leading and trailing zeroes, and
+ * use scientific notation. For example, the following number representations
+ * have the same value: `1e3`, `1000`, `01000.0`.
+ */
+ // TODO: Replace with RawWithValue when #2389 lands.
+ value?: {raw: string; value: number};
+}
+
+/**
+ * An expression representing a number literal in Sass.
+ *
+ * @category Expression
+ */
+export class NumberExpression extends Expression {
+ readonly sassType = 'number' as const;
+ declare raws: NumberExpressionRaws;
+
+ /** The numeric value of this expression. */
+ get value(): number {
+ return this._value;
+ }
+ set value(value: number) {
+ // TODO - postcss/postcss#1957: Mark this as dirty
+ this._value = value;
+ }
+ private _value!: number;
+
+ /** The denominator units of this number. */
+ get unit(): string | null {
+ return this._unit;
+ }
+ set unit(unit: string | null) {
+ // TODO - postcss/postcss#1957: Mark this as dirty
+ this._unit = unit;
+ }
+ private _unit!: string | null;
+
+ /** Whether the number is unitless. */
+ isUnitless(): boolean {
+ return this.unit === null;
+ }
+
+ constructor(defaults: NumberExpressionProps);
+ /** @hidden */
+ constructor(_: undefined, inner: sassInternal.NumberExpression);
+ constructor(defaults?: object, inner?: sassInternal.NumberExpression) {
+ super(defaults);
+ if (inner) {
+ this.source = new LazySource(inner);
+ this.value = inner.value;
+ this.unit = inner.unit;
+ } else {
+ this.value ??= 0;
+ this.unit ??= null;
+ }
+ }
+
+ clone(overrides?: Partial): this {
+ return utils.cloneNode(this, overrides, ['raws', 'value', 'unit']);
+ }
+
+ toJSON(): object;
+ /** @hidden */
+ toJSON(_: string, inputs: Map): object;
+ toJSON(_?: string, inputs?: Map): object {
+ return utils.toJSON(this, ['value', 'unit'], inputs);
+ }
+
+ /** @hidden */
+ toString(): string {
+ if (this.raws?.value?.value === this.value) {
+ return this.raws.value.raw + (this.unit ?? '');
+ }
+ return this.value + (this.unit ?? '');
+ }
+
+ /** @hidden */
+ get nonStatementChildren(): ReadonlyArray {
+ return [];
+ }
+}
diff --git a/pkg/sass-parser/lib/src/sass-internal.ts b/pkg/sass-parser/lib/src/sass-internal.ts
index 3ae2064ba..b0b42c1a5 100644
--- a/pkg/sass-parser/lib/src/sass-internal.ts
+++ b/pkg/sass-parser/lib/src/sass-internal.ts
@@ -186,6 +186,15 @@ declare namespace SassInternal {
readonly text: Interpolation;
readonly hasQuotes: boolean;
}
+
+ class BooleanExpression extends Expression {
+ readonly value: boolean;
+ }
+
+ class NumberExpression extends Expression {
+ readonly value: number;
+ readonly unit: string;
+ }
}
const sassInternal = (
@@ -213,6 +222,8 @@ export type Interpolation = SassInternal.Interpolation;
export type Expression = SassInternal.Expression;
export type BinaryOperationExpression = SassInternal.BinaryOperationExpression;
export type StringExpression = SassInternal.StringExpression;
+export type BooleanExpression = SassInternal.BooleanExpression;
+export type NumberExpression = SassInternal.NumberExpression;
export interface StatementVisitorObject {
visitAtRootRule(node: AtRootRule): T;
@@ -232,6 +243,8 @@ export interface StatementVisitorObject {
export interface ExpressionVisitorObject {
visitBinaryOperationExpression(node: BinaryOperationExpression): T;
visitStringExpression(node: StringExpression): T;
+ visitBooleanExpression(node: BooleanExpression): T;
+ visitNumberExpression(node: NumberExpression): T;
}
export const parse = sassInternal.parse;
diff --git a/pkg/sass-parser/package.json b/pkg/sass-parser/package.json
index f3c720e27..878a800bb 100644
--- a/pkg/sass-parser/package.json
+++ b/pkg/sass-parser/package.json
@@ -1,6 +1,6 @@
{
"name": "sass-parser",
- "version": "0.4.0",
+ "version": "0.4.1-dev",
"description": "A PostCSS-compatible wrapper of the official Sass parser",
"repository": "sass/sass",
"author": "Google Inc.",
diff --git a/pkg/sass_api/CHANGELOG.md b/pkg/sass_api/CHANGELOG.md
index 0621a0d79..e5f3333ab 100644
--- a/pkg/sass_api/CHANGELOG.md
+++ b/pkg/sass_api/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 14.0.1
+
+* No user-visible changes.
+
## 14.0.0
* **Breaking change:** Warnings are no longer emitted during parsing, so the
diff --git a/pkg/sass_api/pubspec.yaml b/pkg/sass_api/pubspec.yaml
index 653bdb91f..eaeb53b09 100644
--- a/pkg/sass_api/pubspec.yaml
+++ b/pkg/sass_api/pubspec.yaml
@@ -2,7 +2,7 @@ name: sass_api
# Note: Every time we add a new Sass AST node, we need to bump the *major*
# version because it's a breaking change for anyone who's implementing the
# visitor interface(s).
-version: 14.0.0
+version: 14.0.1-dev
description: Additional APIs for Dart Sass.
homepage: https://github.com/sass/dart-sass
@@ -10,7 +10,7 @@ environment:
sdk: ">=3.0.0 <4.0.0"
dependencies:
- sass: 1.80.3
+ sass: 1.80.4-dev
dev_dependencies:
dartdoc: ^8.0.14
diff --git a/pubspec.yaml b/pubspec.yaml
index d3ed7ffac..a3726492f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: sass
-version: 1.80.3
+version: 1.80.4-dev
description: A Sass implementation in Dart.
homepage: https://github.com/sass/dart-sass