Skip to content

Commit 4520b8b

Browse files
authored
Don't trim escaped whitespace (#523)
Related to sass/ruby-sass#96
1 parent 1206761 commit 4520b8b

File tree

5 files changed

+44
-15
lines changed

5 files changed

+44
-15
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
command-line interface, Dart API, and JS API. These load paths are checked
1111
just after the load paths explicitly passed by the user.
1212

13+
* Properly compile selectors that end in escaped whitespace.
14+
1315
[content-args]: https://github.com/sass/language/blob/master/accepted/content-args.md
1416
[at-rule-interpolation]: https://github.com/sass/language/blob/master/accepted/at-rule-interpolation.md
1517

lib/src/utils.dart

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,15 @@ int countOccurrences(String string, int codeUnit) {
4848
}
4949

5050
/// Like [String.trim], but only trims ASCII whitespace.
51-
String trimAscii(String string) {
51+
///
52+
/// If [excludeEscape] is `true`, this doesn't trim whitespace included in a CSS
53+
/// escape.
54+
String trimAscii(String string, {bool excludeEscape: false}) {
5255
var start = _firstNonWhitespace(string);
5356
return start == null
5457
? ""
55-
: string.substring(start, _lastNonWhitespace(string) + 1);
58+
: string.substring(
59+
start, _lastNonWhitespace(string, excludeEscape: excludeEscape) + 1);
5660
}
5761

5862
/// Like [String.trimLeft], but only trims ASCII whitespace.
@@ -62,13 +66,16 @@ String trimAsciiLeft(String string) {
6266
}
6367

6468
/// Like [String.trimRight], but only trims ASCII whitespace.
65-
String trimAsciiRight(String string) {
66-
var end = _lastNonWhitespace(string);
69+
///
70+
/// If [excludeEscape] is `true`, this doesn't trim whitespace included in a CSS
71+
/// escape.
72+
String trimAsciiRight(String string, {bool excludeEscape: false}) {
73+
var end = _lastNonWhitespace(string, excludeEscape: excludeEscape);
6774
return end == null ? "" : string.substring(0, end + 1);
6875
}
6976

7077
/// Returns the index of the first character in [string] that's not ASCII
71-
/// whitepsace, or [null] if [string] is entirely spaces.
78+
/// whitespace, or [null] if [string] is entirely spaces.
7279
int _firstNonWhitespace(String string) {
7380
for (var i = 0; i < string.length; i++) {
7481
if (!isWhitespace(string.codeUnitAt(i))) return i;
@@ -78,9 +85,22 @@ int _firstNonWhitespace(String string) {
7885

7986
/// Returns the index of the last character in [string] that's not ASCII
8087
/// whitespace, or [null] if [string] is entirely spaces.
81-
int _lastNonWhitespace(String string) {
88+
///
89+
/// If [excludeEscape] is `true`, this doesn't move past whitespace that's
90+
/// included in a CSS escape.
91+
int _lastNonWhitespace(String string, {bool excludeEscape: false}) {
8292
for (var i = string.length - 1; i >= 0; i--) {
83-
if (!isWhitespace(string.codeUnitAt(i))) return i;
93+
var codeUnit = string.codeUnitAt(i);
94+
if (!isWhitespace(codeUnit)) {
95+
if (excludeEscape &&
96+
i != 0 &&
97+
i != string.length &&
98+
codeUnit == $backslash) {
99+
return i + 1;
100+
} else {
101+
return i;
102+
}
103+
}
84104
}
85105
return null;
86106
}

lib/src/visitor/async_evaluate.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -584,8 +584,10 @@ class _EvaluateVisitor
584584

585585
var list = _adjustParseError(
586586
targetText.span,
587-
() => new SelectorList.parse(targetText.value.trim(),
588-
logger: _logger, allowParent: false));
587+
() => new SelectorList.parse(
588+
trimAscii(targetText.value, excludeEscape: true),
589+
logger: _logger,
590+
allowParent: false));
589591

590592
for (var complex in list.components) {
591593
if (complex.components.length != 1 ||
@@ -1687,7 +1689,8 @@ class _EvaluateVisitor
16871689
{bool trim: false, bool warnForColor: false}) async {
16881690
var result =
16891691
await _performInterpolation(interpolation, warnForColor: warnForColor);
1690-
return new CssValue(trim ? result.trim() : result, interpolation.span);
1692+
return new CssValue(trim ? trimAscii(result, excludeEscape: true) : result,
1693+
interpolation.span);
16911694
}
16921695

16931696
/// Evaluates [interpolation].

lib/src/visitor/evaluate.dart

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// DO NOT EDIT. This file was generated from async_evaluate.dart.
66
// See tool/synchronize.dart for details.
77
//
8-
// Checksum: 0dc10210feef4db5d092a631d32ee93dd5a12907
8+
// Checksum: abeba8d186777d0dc1eedf9f9d29e4514bcd7619
99

1010
import 'async_evaluate.dart' show EvaluateResult;
1111
export 'async_evaluate.dart' show EvaluateResult;
@@ -585,8 +585,10 @@ class _EvaluateVisitor
585585

586586
var list = _adjustParseError(
587587
targetText.span,
588-
() => new SelectorList.parse(targetText.value.trim(),
589-
logger: _logger, allowParent: false));
588+
() => new SelectorList.parse(
589+
trimAscii(targetText.value, excludeEscape: true),
590+
logger: _logger,
591+
allowParent: false));
590592

591593
for (var complex in list.components) {
592594
if (complex.components.length != 1 ||
@@ -1664,7 +1666,8 @@ class _EvaluateVisitor
16641666
{bool trim: false, bool warnForColor: false}) {
16651667
var result =
16661668
_performInterpolation(interpolation, warnForColor: warnForColor);
1667-
return new CssValue(trim ? result.trim() : result, interpolation.span);
1669+
return new CssValue(trim ? trimAscii(result, excludeEscape: true) : result,
1670+
interpolation.span);
16681671
}
16691672

16701673
/// Evaluates [interpolation].

lib/src/visitor/serialize.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import '../ast/node.dart';
1515
import '../ast/selector.dart';
1616
import '../color_names.dart';
1717
import '../exception.dart';
18+
import '../utils.dart';
1819
import '../util/character.dart';
1920
import '../util/no_source_map_buffer.dart';
2021
import '../util/number.dart';
@@ -396,7 +397,7 @@ class _SerializeVisitor implements CssVisitor, ValueVisitor, SelectorVisitor {
396397
_buffer.write(value);
397398
return;
398399
} else if (minimumIndentation == -1) {
399-
_buffer.write(value.trimRight());
400+
_buffer.write(trimAsciiRight(value, excludeEscape: true));
400401
_buffer.writeCharCode($space);
401402
return;
402403
}

0 commit comments

Comments
 (0)