Skip to content

Commit

Permalink
Improve inspect() output for complex units
Browse files Browse the repository at this point in the history
Closes #2070
  • Loading branch information
nex3 committed Dec 5, 2023
1 parent cd3b0cc commit 9d32a0c
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 25 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.69.6

* Produce better output for numbers with complex units in `meta.inspect()` and
debugging messages.

## 1.69.5

### JS API
Expand Down
59 changes: 38 additions & 21 deletions lib/src/visitor/serialize.dart
Original file line number Diff line number Diff line change
Expand Up @@ -489,13 +489,8 @@ final class _SerializeVisitor

void _writeCalculationValue(Object value) {
switch (value) {
case SassNumber(value: double(isFinite: false), hasComplexUnits: true):
if (!_inspect) {
throw SassScriptException("$value isn't a valid CSS value.");
}

_writeNumber(value.value);
_buffer.write(value.unitString);
case SassNumber(hasComplexUnits: true) when !_inspect:
throw SassScriptException("$value isn't a valid CSS value.");

case SassNumber(value: double(isFinite: false)):
switch (value.value) {
Expand All @@ -507,12 +502,15 @@ final class _SerializeVisitor
_buffer.write('NaN');
}

if (value.numeratorUnits.firstOrNull case var unit?) {
_writeOptionalSpace();
_buffer.writeCharCode($asterisk);
_writeOptionalSpace();
_buffer.writeCharCode($1);
_buffer.write(unit);
_writeCalculationUnits(value.numeratorUnits, value.denominatorUnits);

case SassNumber(hasComplexUnits: true):
_writeNumber(value.value);
if (value.numeratorUnits case [var first, ...var rest]) {
_buffer.write(first);
_writeCalculationUnits(rest, value.denominatorUnits);
} else {
_writeCalculationUnits([], value.denominatorUnits);
}

case Value():
Expand All @@ -534,14 +532,34 @@ final class _SerializeVisitor
_parenthesizeCalculationRhs(operator, right.operator)) ||
(operator == CalculationOperator.dividedBy &&
right is SassNumber &&
!right.value.isFinite &&
right.hasUnits);
(right.value.isFinite ? right.hasComplexUnits : right.hasUnits));
if (parenthesizeRight) _buffer.writeCharCode($lparen);
_writeCalculationValue(right);
if (parenthesizeRight) _buffer.writeCharCode($rparen);
}
}

/// Writes the complex numerator and denominator units beyond the first
/// numerator unit for a number as they appear in a calculation.
void _writeCalculationUnits(
List<String> numeratorUnits, List<String> denominatorUnits) {
for (var unit in numeratorUnits) {
_writeOptionalSpace();
_buffer.writeCharCode($asterisk);
_writeOptionalSpace();
_buffer.writeCharCode($1);
_buffer.write(unit);
}

for (var unit in denominatorUnits) {
_writeOptionalSpace();
_buffer.writeCharCode($slash);
_writeOptionalSpace();
_buffer.writeCharCode($1);
_buffer.write(unit);
}
}

/// Returns whether the right-hand operation of a calculation should be
/// parenthesized.
///
Expand Down Expand Up @@ -787,16 +805,15 @@ final class _SerializeVisitor
return;
}

_writeNumber(value.value);

if (!_inspect) {
if (value.hasComplexUnits) {
if (value.hasComplexUnits) {
if (!_inspect) {
throw SassScriptException("$value isn't a valid CSS value.");
}

if (value.numeratorUnits case [var first]) _buffer.write(first);
visitCalculation(SassCalculation.unsimplified('calc', [value]));
} else {
_buffer.write(value.unitString);
_writeNumber(value.value);
if (value.numeratorUnits case [var first]) _buffer.write(first);
}
}

Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: sass
version: 1.69.5
version: 1.69.6-dev
description: A Sass implementation in Dart.
homepage: https://github.com/sass/dart-sass

Expand Down
51 changes: 48 additions & 3 deletions test/output_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,55 @@ void main() {
});
});

// Tests for sass/dart-sass#417.
// Tests for sass/dart-sass#2070.
//
// Note there's no need for "in Sass" cases as it's not possible to have
// trailing loud comments in the Sass syntax.
// These aren't covered by sass-spec because the inspect format for
// non-literal values isn't covered by the spec.
group("uses a nice format to inspect numbers with complex units", () {
group("finite", () {
test("top-level", () {
expect(compileString("""
@use 'sass:meta';
a {b: meta.inspect(1px * 1em)};
"""), equalsIgnoringWhitespace('a { b: calc(1px * 1em); }'));
});

test("in calc", () {
expect(compileString("""
@use 'sass:meta';
a {b: meta.inspect(calc(1px * 1em))};
"""), equalsIgnoringWhitespace('a { b: calc(1px * 1em); }'));
});

test("nested in calc", () {
expect(compileString("""
@use 'sass:meta';
a {b: meta.inspect(calc(c / (1px * 1em)))};
"""), equalsIgnoringWhitespace('a { b: calc(c / (1px * 1em)); }'));
});

test("numerator and denominator", () {
expect(compileString("""
@use 'sass:math';
@use 'sass:meta';
a {b: meta.inspect(1px * math.div(math.div(1em, 1s), 1x))};
"""), equalsIgnoringWhitespace('a { b: calc(1px * 1em / 1s / 1x); }'));
});

test("denominator only", () {
expect(compileString("""
@use 'sass:math';
@use 'sass:meta';
a {b: meta.inspect(math.div(math.div(1, 1s), 1x))};
"""), equalsIgnoringWhitespace('a { b: calc(1 / 1s / 1x); }'));
});
});
});

// Tests for sass/dart-sass#417.
//
// Note there's no need for "in Sass" cases as it's not possible to have
// trailing loud comments in the Sass syntax.
group("preserve trailing loud comments in SCSS", () {
test("after open block", () {
expect(compileString("""
Expand Down

0 comments on commit 9d32a0c

Please sign in to comment.