Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.17.4

* Consistently parse U+000C FORM FEED, U+000D CARRIAGE RETURN, and sequences of
U+000D CARRIAGE RETURN followed by U+000A LINE FEED as individual newlines.

## 1.17.3

* Fix an edge case where slash-separated numbers were written to the stylesheet
Expand Down
25 changes: 23 additions & 2 deletions lib/src/parse/sass.dart
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class SassParser extends StylesheetParser {
// Ignore empty lines.
case $cr:
case $lf:
case $ff:
return null;

case $dollar:
Expand Down Expand Up @@ -282,8 +283,8 @@ class SassParser extends StylesheetParser {
if (_peekIndentation() <= parentIndentation) break;

// Preserve empty lines.
while (isNewline(scanner.peekChar(1))) {
scanner.readChar();
while (_lookingAtDoubleNewline()) {
_expectNewline();
buffer.writeln();
buffer.write(" *");
}
Expand Down Expand Up @@ -315,14 +316,34 @@ class SassParser extends StylesheetParser {
case $semicolon:
scanner.error("semicolons aren't allowed in the indented syntax.");
return;
case $cr:
scanner.readChar();
if (scanner.peekChar() == $lf) scanner.readChar();
return;
case $lf:
case $ff:
scanner.readChar();
return;
default:
scanner.error("expected newline.");
}
}

/// Returns whether the scanner is immediately before *two* newlines.
bool _lookingAtDoubleNewline() {
switch (scanner.peekChar()) {
case $cr:
var nextChar = scanner.peekChar(1);
if (nextChar == $lf) return isNewline(scanner.peekChar(2));
return nextChar == $cr || nextChar == $ff;
case $lf:
case $ff:
return isNewline(scanner.peekChar(1));
default:
return false;
}
}

/// As long as the scanner's position is indented beneath the starting line,
/// runs [body] to consume the next statement.
void _whileIndentedLower(void body()) {
Expand Down
10 changes: 10 additions & 0 deletions lib/src/parse/scss.dart
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ class ScssParser extends StylesheetParser {
buffer.writeCharCode(scanner.readChar());
return LoudComment(buffer.interpolation(scanner.spanFrom(start)));

case $cr:
scanner.readChar();
if (scanner.peekChar() != $lf) buffer.writeCharCode($lf);
break;

case $ff:
scanner.readChar();
buffer.writeCharCode($lf);
break;

default:
buffer.writeCharCode(scanner.readChar());
break;
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.17.3
version: 1.17.4-dev
description: A Sass implementation in Dart.
author: Dart Team <[email protected]>
homepage: https://github.com/sass/dart-sass
Expand Down
26 changes: 26 additions & 0 deletions test/output_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2019 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.

// Almost all CSS output tests should go in sass-spec rather than here. This
// just covers tests that explicitly validate out that's considered too
// implementation-specific to verify in sass-spec.

import 'package:test/test.dart';

import 'package:sass/sass.dart';

void main() {
// Regression test for sass/dart-sass#623. This needs to be tested here
// because sass-spec normalizes CR LF newlines.
group("normalizes newlines in a loud comment", () {
test("in SCSS", () {
expect(compileString("/* foo\r\n * bar */"), equals("/* foo\n * bar */"));
});

test("in Sass", () {
expect(compileString("/*\r\n foo\r\n bar", syntax: Syntax.sass),
equals("/* foo\n * bar */"));
});
});
}