fixed CssPrinter pretty print indent levels (#169)
* fixed CssPrinter pretty print indent levels
* review comments
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92dacab..75c5158 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
- Fixed a regression parsing declaration values containing spaces.
- Add support for `lh` and `rlh` units.
- Refactor the package example.
+- Addressed an issue with the indent level of the `CssPrinter` output.
## 0.17.2
diff --git a/lib/src/css_printer.dart b/lib/src/css_printer.dart
index 85e7978..e0507d1 100644
--- a/lib/src/css_printer.dart
+++ b/lib/src/css_printer.dart
@@ -7,35 +7,91 @@
/// Visitor that produces a formatted string representation of the CSS tree.
class CssPrinter extends Visitor {
StringBuffer _buff = StringBuffer();
- bool prettyPrint = true;
+ bool _prettyPrint = true;
bool _isInKeyframes = false;
+ int _indent = 0;
+ bool _startOfLine = true;
/// Walk the [tree] Stylesheet. [pretty] if true emits line breaks, extra
/// spaces, friendly property values, etc., if false emits compacted output.
@override
void visitTree(StyleSheet tree, {bool pretty = false}) {
- prettyPrint = pretty;
+ _prettyPrint = pretty;
_buff = StringBuffer();
+ _indent = 0;
+ _startOfLine = true;
+
visitStyleSheet(tree);
}
/// Appends [str] to the output buffer.
void emit(String str) {
- _buff.write(str);
+ if (_prettyPrint) {
+ if (_startOfLine) {
+ _startOfLine = false;
+ _buff.write(' ' * _indent);
+ }
+ _buff.write(str);
+ } else {
+ _buff.write(str);
+ }
+ }
+
+ void _emitLBrace() {
+ _indent += 2;
+ _buff.write('{');
+
+ if (_prettyPrint) {
+ _buff.writeln();
+ _startOfLine = true;
+ }
+ }
+
+ void _emitRBrace() {
+ _indent -= 2;
+
+ if (_prettyPrint) {
+ if (!_startOfLine) _buff.write('\n');
+ _buff.write('${' ' * _indent}}\n');
+ _startOfLine = true;
+ } else {
+ _buff.write('}');
+ if (_indent == 0) {
+ _buff.writeln();
+ }
+ }
+ }
+
+ void _emitSemicolon({bool forceLf = false}) {
+ if (_prettyPrint) {
+ _buff.write(';\n');
+ _startOfLine = true;
+ } else {
+ _buff.write(';');
+ if (forceLf) _buff.write('\n');
+ }
+ }
+
+ void _emitLf({bool force = false}) {
+ if (_prettyPrint) {
+ _buff.write('\n');
+ _startOfLine = true;
+ } else if (force) {
+ _buff.write('\n');
+ }
}
/// Returns the output buffer.
@override
String toString() => _buff.toString().trim();
- String get _newLine => prettyPrint ? '\n' : '';
- String get _sp => prettyPrint ? ' ' : '';
+ String get _sp => _prettyPrint ? ' ' : '';
// TODO(terry): When adding obfuscation we'll need isOptimized (compact w/
// obfuscation) and have isTesting (compact no obfuscation) and
// isCompact would be !prettyPrint. We'll need another boolean
// flag for obfuscation.
- bool get _isTesting => !prettyPrint;
+ bool get _isTesting => !_prettyPrint;
@override
void visitCalcTerm(CalcTerm node) {
@@ -86,28 +142,30 @@
@override
void visitDocumentDirective(DocumentDirective node) {
- emit('$_newLine@-moz-document ');
+ emit('@-moz-document ');
node.functions.first.visit(this);
for (var function in node.functions.skip(1)) {
emit(',$_sp');
function.visit(this);
}
- emit('$_sp{');
+ emit(_sp);
+ _emitLBrace();
for (var ruleSet in node.groupRuleBody) {
ruleSet.visit(this);
}
- emit('$_newLine}');
+ _emitRBrace();
}
@override
void visitSupportsDirective(SupportsDirective node) {
- emit('$_newLine@supports ');
+ emit('@supports ');
node.condition!.visit(this);
- emit('$_sp{');
+ emit(_sp);
+ _emitLBrace();
for (var rule in node.groupRuleBody) {
rule.visit(this);
}
- emit('$_newLine}');
+ _emitRBrace();
}
@override
@@ -143,29 +201,32 @@
@override
void visitViewportDirective(ViewportDirective node) {
- emit('@${node.name}$_sp{$_newLine');
+ emit('@${node.name}$_sp');
+ _emitLBrace();
node.declarations.visit(this);
- emit('}');
+ _emitRBrace();
}
@override
void visitMediaDirective(MediaDirective node) {
- emit('$_newLine@media');
+ emit('@media');
emitMediaQueries(node.mediaQueries.cast<MediaQuery>());
- emit('$_sp{');
+ emit(_sp);
+ _emitLBrace();
for (var ruleset in node.rules) {
ruleset.visit(this);
}
- emit('$_newLine}');
+ _emitRBrace();
}
@override
void visitHostDirective(HostDirective node) {
- emit('$_newLine@host$_sp{');
+ emit('@host$_sp');
+ _emitLBrace();
for (var ruleset in node.rules) {
ruleset.visit(this);
}
- emit('$_newLine}');
+ _emitRBrace();
}
/// @page : pseudoPage {
@@ -173,7 +234,7 @@
/// }
@override
void visitPageDirective(PageDirective node) {
- emit('$_newLine@page');
+ emit('@page');
if (node.hasIdent || node.hasPseudoPage) {
if (node.hasIdent) emit(' ');
emit(node._ident!);
@@ -182,17 +243,19 @@
var declsMargin = node._declsMargin;
var declsMarginLength = declsMargin.length;
- emit('$_sp{$_newLine');
+ emit(_sp);
+ _emitLBrace();
for (var i = 0; i < declsMarginLength; i++) {
declsMargin[i].visit(this);
}
- emit('}');
+ _emitRBrace();
}
/// @charset "charset encoding"
@override
void visitCharsetDirective(CharsetDirective node) {
- emit('$_newLine@charset "${node.charEncoding}";');
+ emit('@charset "${node.charEncoding}"');
+ _emitSemicolon(forceLf: true);
}
@override
@@ -201,51 +264,54 @@
if (_isTesting) {
// Emit assuming url() was parsed; most suite tests use url function.
- emit(' @import url(${node.import})');
+ emit('@import url(${node.import})');
} else if (isStartingQuote(node.import)) {
- emit(' @import ${node.import}');
+ emit('@import ${node.import}');
} else {
// url(...) isn't needed only a URI can follow an @import directive; emit
// url as a string.
- emit(' @import "${node.import}"');
+ emit('@import "${node.import}"');
}
emitMediaQueries(node.mediaQueries);
- emit(';');
+ _emitSemicolon(forceLf: true);
}
@override
void visitKeyFrameDirective(KeyFrameDirective node) {
- emit('$_newLine${node.keyFrameName} ');
+ emit('${node.keyFrameName} ');
node.name!.visit(this);
- emit('$_sp{$_newLine');
+ emit(_sp);
+ _emitLBrace();
_isInKeyframes = true;
for (final block in node._blocks) {
block.visit(this);
}
_isInKeyframes = false;
- emit('}');
+ _emitRBrace();
}
@override
void visitFontFaceDirective(FontFaceDirective node) {
- emit('$_newLine@font-face ');
- emit('$_sp{$_newLine');
+ emit('@font-face');
+ emit(_sp);
+ _emitLBrace();
node._declarations.visit(this);
- emit('}');
+ _emitRBrace();
}
@override
void visitKeyFrameBlock(KeyFrameBlock node) {
- emit('$_sp$_sp');
node._blockSelectors.visit(this);
- emit('$_sp{$_newLine');
+ emit(_sp);
+ _emitLBrace();
node._declarations.visit(this);
- emit('$_sp$_sp}$_newLine');
+ _emitRBrace();
}
@override
void visitStyletDirective(StyletDirective node) {
- emit('/* @stylet export as ${node.dartClassName} */\n');
+ emit('/* @stylet export as ${node.dartClassName} */');
+ _emitLf(force: true);
}
@override
@@ -253,49 +319,51 @@
bool isStartingQuote(String ch) => '\'"'.contains(ch);
if (isStartingQuote(node._uri!)) {
- emit(' @namespace ${node.prefix}"${node._uri}"');
+ emit('@namespace ${node.prefix}"${node._uri}"');
} else {
if (_isTesting) {
// Emit exactly was we parsed.
- emit(' @namespace ${node.prefix}url(${node._uri})');
+ emit('@namespace ${node.prefix}url(${node._uri})');
} else {
// url(...) isn't needed only a URI can follow a:
// @namespace prefix directive.
- emit(' @namespace ${node.prefix}${node._uri}');
+ emit('@namespace ${node.prefix}${node._uri}');
}
}
- emit(';');
+ _emitSemicolon(forceLf: true);
}
@override
void visitVarDefinitionDirective(VarDefinitionDirective node) {
visitVarDefinition(node.def);
- emit(';$_newLine');
+ _emitSemicolon();
}
@override
void visitMixinRulesetDirective(MixinRulesetDirective node) {
- emit('@mixin ${node.name} {');
+ emit('@mixin ${node.name} ');
+ _emitLBrace();
for (var ruleset in node.rulesets) {
ruleset.visit(this);
}
- emit('}');
+ _emitRBrace();
}
@override
void visitMixinDeclarationDirective(MixinDeclarationDirective node) {
- emit('@mixin ${node.name} {\n');
+ emit('@mixin ${node.name}$_sp');
+ _emitLBrace();
visitDeclarationGroup(node.declarations);
- emit('}');
+ _emitRBrace();
}
/// Added optional newLine for handling @include at top-level vs/ inside of
/// a declaration group.
@override
void visitIncludeDirective(IncludeDirective node, [bool topLevel = true]) {
- if (topLevel) emit(_newLine);
+ if (topLevel) _emitLf();
emit('@include ${node.name}');
- emit(';');
+ _emitSemicolon(forceLf: true);
}
@override
@@ -305,11 +373,11 @@
@override
void visitRuleSet(RuleSet node) {
- emit(_newLine);
node.selectorGroup!.visit(this);
- emit('$_sp{$_newLine');
+ emit(_sp);
+ _emitLBrace();
node.declarationGroup.visit(this);
- emit('}');
+ _emitRBrace();
}
@override
@@ -317,15 +385,12 @@
var declarations = node.declarations;
var declarationsLength = declarations.length;
for (var i = 0; i < declarationsLength; i++) {
- if (i > 0) emit(_newLine);
- emit('$_sp$_sp');
declarations[i].visit(this);
// Don't emit the last semicolon in compact mode.
- if (prettyPrint || i < declarationsLength - 1) {
- emit(';');
+ if (_prettyPrint || i < declarationsLength - 1) {
+ _emitSemicolon();
}
}
- if (declarationsLength > 0) emit(_newLine);
}
@override
@@ -333,11 +398,10 @@
var marginSymName =
TokenKind.idToValue(TokenKind.MARGIN_DIRECTIVES, node.margin_sym);
- emit('@$marginSymName$_sp{$_newLine');
-
+ emit('@$marginSymName$_sp');
+ _emitLBrace();
visitDeclarationGroup(node);
-
- emit('}$_newLine');
+ _emitRBrace();
}
@override
@@ -619,6 +683,7 @@
void visitExpressions(Expressions node) {
var expressions = node.expressions;
var expressionsLength = expressions.length;
+
for (var i = 0; i < expressionsLength; i++) {
// Add space seperator between terms without an operator.
// TODO(terry): Should have a BinaryExpression to solve this problem.
diff --git a/lib/src/tree_printer.dart b/lib/src/tree_printer.dart
index 0398226..4b6fbf8 100644
--- a/lib/src/tree_printer.dart
+++ b/lib/src/tree_printer.dart
@@ -17,6 +17,7 @@
class _TreePrinter extends Visitor {
final TreeOutput output;
final bool useSpan;
+
_TreePrinter(this.output, this.useSpan) {
output.printer = this;
}
diff --git a/test/compiler_test.dart b/test/compiler_test.dart
index ad0bfd3..2879040 100644
--- a/test/compiler_test.dart
+++ b/test/compiler_test.dart
@@ -653,20 +653,20 @@
expect(errors.isEmpty, true, reason: errors.toString());
expect(prettyPrint(stylesheet), r'''
@host {
-:scope {
- white-space: nowrap;
- overflow-style: marquee-line;
- overflow-x: marquee;
-}
-* {
- color: #f00;
-}
-*:hover {
- font-weight: bold;
-}
-:nth-child(odd) {
- color: #00f;
-}
+ :scope {
+ white-space: nowrap;
+ overflow-style: marquee-line;
+ overflow-x: marquee;
+ }
+ * {
+ color: #f00;
+ }
+ *:hover {
+ font-weight: bold;
+ }
+ :nth-child(odd) {
+ color: #00f;
+ }
}''');
}
diff --git a/test/declaration_test.dart b/test/declaration_test.dart
index ba94c73..0a1b91c 100644
--- a/test/declaration_test.dart
+++ b/test/declaration_test.dart
@@ -166,7 +166,7 @@
}
@-webkit-keyframes pulsate {
0% {
- -webkit-transform: translate3d(0, 0, 0) scale(1.0);
+ -webkit-transform: translate3d(0, 0, 0) scale(1.0);
}
}''';
@@ -311,9 +311,9 @@
final generated = r'''
@media screen, print {
-.foobar_screen {
- width: 10px;
-}
+ .foobar_screen {
+ width: 10px;
+ }
}
@page {
height: 22px;
@@ -323,14 +323,14 @@
width: 10px;
}
@page bar:left {
-@top-left {
- margin: 8px;
-}
+ @top-left {
+ margin: 8px;
+ }
}
@page {
-@top-left {
- margin: 8px;
-}
+ @top-left {
+ margin: 8px;
+ }
width: 10px;
}
@charset "ISO-8859-1";
@@ -355,12 +355,12 @@
}''';
var generated = '''
@media screen AND (-webkit-min-device-pixel-ratio:0) {
-.todo-item .toggle {
- background: none;
-}
-#todo-item .toggle {
- height: 40px;
-}
+ .todo-item .toggle {
+ background: none;
+ }
+ #todo-item .toggle {
+ height: 40px;
+ }
}''';
var stylesheet = parseCss(input, errors: errors, opts: simpleOptions);
@@ -386,27 +386,27 @@
border: 20px;
}
}''';
- generated =
- '''@media handheld AND (min-width:20em), screen AND (min-width:20em) {
-#id {
- color: #f00;
-}
-.myclass {
- height: 20px;
-}
+ generated = '''
+@media handheld AND (min-width:20em), screen AND (min-width:20em) {
+ #id {
+ color: #f00;
+ }
+ .myclass {
+ height: 20px;
+ }
}
@media print AND (min-resolution:300dpi) {
-#anotherId {
- color: #fff;
-}
+ #anotherId {
+ color: #fff;
+ }
}
@media print AND (min-resolution:280dpcm) {
-#finalId {
- color: #aaa;
-}
-.class2 {
- border: 20px;
-}
+ #finalId {
+ color: #aaa;
+ }
+ .class2 {
+ border: 20px;
+ }
}''';
stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions);
@@ -421,9 +421,12 @@
font-size: 10em;
}
}''';
- generated = '@media ONLY screen AND (min-device-width:4000px) '
- 'AND (min-device-height:2000px), screen AND (another:100px) {\n'
- 'html {\n font-size: 10em;\n}\n}';
+ generated = '''
+@media ONLY screen AND (min-device-width:4000px) AND (min-device-height:2000px), screen AND (another:100px) {
+ html {
+ font-size: 10em;
+ }
+}''';
stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions);
@@ -439,7 +442,7 @@
}''';
generated = '@media screen, print AND (min-device-width:4000px) AND '
'(min-device-height:2000px), screen AND (another:100px) {\n'
- 'html {\n font-size: 10em;\n}\n}';
+ ' html {\n font-size: 10em;\n }\n}';
stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions);
@@ -482,15 +485,16 @@
}
}
}''';
- generated = '''@media (min-width:840px) {
-.cell {
- width: calc(33% - 16px);
-}
-@supports (display: grid) {
-.cell {
- grid-column-end: span 4;
-}
-}
+ generated = '''
+@media (min-width:840px) {
+ .cell {
+ width: calc(33% - 16px);
+ }
+ @supports (display: grid) {
+ .cell {
+ grid-column-end: span 4;
+ }
+ }
}''';
expectCss(input, generated);
}
@@ -504,10 +508,11 @@
color: #000;
}
}''';
- var expected = '''@-moz-document url-prefix() {
-div {
- color: #000;
-}
+ var expected = '''
+@-moz-document url-prefix() {
+ div {
+ color: #000;
+ }
}''';
var styleSheet = parseCss(css, errors: errors);
expect(styleSheet, isNotNull);
@@ -521,10 +526,11 @@
color: #000;
}
}''';
- expected = '''@-moz-document url-prefix("http://www.w3.org/Style/") {
-div {
- color: #000;
-}
+ expected = '''
+@-moz-document url-prefix("http://www.w3.org/Style/") {
+ div {
+ color: #000;
+ }
}''';
styleSheet = parseCss(css, errors: errors);
expect(styleSheet, isNotNull);
@@ -538,10 +544,11 @@
color: #000;
}
}''';
- expected = '''@-moz-document domain("google.com") {
-div {
- color: #000;
-}
+ expected = '''
+@-moz-document domain("google.com") {
+ div {
+ color: #000;
+ }
}''';
styleSheet = parseCss(css, errors: errors);
expect(styleSheet, isNotNull);
@@ -558,7 +565,7 @@
'url("http://www.w3.org/"), '
'url-prefix("http://www.w3.org/Style/"), '
'domain("google.com"), '
- 'regexp("https:.*") {\ndiv {\n color: #000;\n}\n}';
+ 'regexp("https:.*") {\n div {\n color: #000;\n }\n}';
styleSheet = parseCss(css, errors: errors);
expect(styleSheet, isNotNull);
expect(errors, isEmpty);
@@ -573,10 +580,11 @@
-webkit-appearance: none;
}
}''';
- var expected = '''@supports (-webkit-appearance: none) {
-div {
- -webkit-appearance: none;
-}
+ var expected = '''
+@supports (-webkit-appearance: none) {
+ div {
+ -webkit-appearance: none;
+ }
}''';
expectCss(css, expected);
@@ -585,10 +593,11 @@
@supports not ( display: flex ) {
body { width: 100%; }
}''';
- expected = '''@supports not (display: flex) {
-body {
- width: 100%;
-}
+ expected = '''
+@supports not (display: flex) {
+ body {
+ width: 100%;
+ }
}''';
expectCss(css, expected);
@@ -606,9 +615,9 @@
'(-moz-box-shadow: 0 0 2px #000 inset) or '
'(-webkit-box-shadow: 0 0 2px #000 inset) or '
'(-o-box-shadow: 0 0 2px #000 inset) {\n'
- '.box {\n'
- ' box-shadow: 0 0 2px #000 inset;\n'
- '}\n'
+ ' .box {\n'
+ ' box-shadow: 0 0 2px #000 inset;\n'
+ ' }\n'
'}';
expectCss(css, expected);
@@ -625,10 +634,10 @@
expected = '@supports '
'((transition-property: color) or (animation-name: foo)) and '
'(transform: rotate(10deg)) {\n'
- 'div {\n'
- ' transition-property: color;\n'
- ' transform: rotate(10deg);\n'
- '}\n'
+ ' div {\n'
+ ' transition-property: color;\n'
+ ' transform: rotate(10deg);\n'
+ ' }\n'
'}';
expectCss(css, expected);
@@ -682,7 +691,7 @@
src: url(fonts/BBCBengali.ttf) format("opentype");
unicode-range: U+0A-FF, U+980-9FF, U+????, U+3???;
}''';
- final generated = '''@font-face {
+ final generated = '''@font-face {
font-family: BBCBengali;
src: url("fonts/BBCBengali.ttf") format("opentype");
unicode-range: U+0A-FF, U+980-9FF, U+????, U+3???;
@@ -698,7 +707,7 @@
src: url(http://example.com/fonts/Gentium.ttf);
src: url(http://example.com/fonts/Gentium.ttf);
}''';
- final generated1 = '''@font-face {
+ final generated1 = '''@font-face {
font-family: Gentium;
src: url("http://example.com/fonts/Gentium.ttf");
src: url("http://example.com/fonts/Gentium.ttf");
@@ -715,7 +724,7 @@
url(basic-sans-serif.ttf) format("opentype"),
local(Gentium Bold);
}''';
- final generated2 = '@font-face {\n'
+ final generated2 = '@font-face {\n'
' src: url("ideal-sans-serif.woff") '
'format("woff"), url("basic-sans-serif.ttf") '
'format("opentype"), local(Gentium Bold);\n}';
@@ -734,7 +743,7 @@
font-weight: bold;
}''';
final generated3 = '''
-@font-face {
+@font-face {
font-family: MyGentium Text Ornaments;
src: local(Gentium Bold), local(Gentium-Bold), url("GentiumBold.ttf");
font-weight: bold;
@@ -751,7 +760,7 @@
src: local(STIXGeneral), url(/stixfonts/STIXGeneral.otf);
unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF;
}''';
- final generated4 = '''@font-face {
+ final generated4 = '''@font-face {
font-family: STIXGeneral;
src: local(STIXGeneral), url("/stixfonts/STIXGeneral.otf");
unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF;
@@ -799,33 +808,34 @@
}
''';
- final generated = '@import "simple.css"; '
- '@import "test.css" print; '
- '@import "test.css" screen, print; '
- '@import "http://google.com/maps/maps.css";\n'
- 'div[href^="test"] {\n'
- ' height: 10px;\n'
- '}\n'
- '@-webkit-keyframes pulsate {\n'
- ' from {\n'
- ' -webkit-transform: translate3d(0, 0, 0) scale(1.0);\n'
- ' }\n'
- ' 10% {\n'
- ' -webkit-transform: translate3d(0, 0, 0) scale(1.0);\n'
- ' }\n'
- ' 30% {\n'
- ' -webkit-transform: translate3d(0, 2, 0) scale(1.0);\n'
- ' }\n'
- '}\n'
- '.foobar {\n'
- ' grid-columns: 10px ("content" 1fr 10px) [4];\n'
- '}\n'
- '.test-background {\n'
- ' background: url("http://www.foo.com/bar.png");\n'
- '}\n'
- '.test-background-with-multiple-properties {\n'
- ' background: #000 url("http://www.foo.com/bar.png");\n'
- '}';
+ final generated = '''
+@import "simple.css";
+@import "test.css" print;
+@import "test.css" screen, print;
+@import "http://google.com/maps/maps.css";
+div[href^="test"] {
+ height: 10px;
+}
+@-webkit-keyframes pulsate {
+ from {
+ -webkit-transform: translate3d(0, 0, 0) scale(1.0);
+ }
+ 10% {
+ -webkit-transform: translate3d(0, 0, 0) scale(1.0);
+ }
+ 30% {
+ -webkit-transform: translate3d(0, 2, 0) scale(1.0);
+ }
+}
+.foobar {
+ grid-columns: 10px ("content" 1fr 10px) [4];
+}
+.test-background {
+ background: url("http://www.foo.com/bar.png");
+}
+.test-background-with-multiple-properties {
+ background: #000 url("http://www.foo.com/bar.png");
+}''';
var stylesheet = parseCss(input, errors: errors);
expect(errors.isEmpty, true, reason: errors.toString());
@@ -865,14 +875,15 @@
color: rgba(0, 0, 0, 0.2);
}
''';
- final generated = 'div{color:green!important;background:red blue green}'
- '.foo p[bar]{color:blue}'
- '@page{@top-left{color:red}}'
- '@page:first{}'
- '@page foo:first{}'
- '@media screen AND (max-width:800px){div{font-size:24px}}'
- '@keyframes foo{0%{transform:scaleX(0)}}'
- 'div{color:rgba(0,0,0,0.2)}';
+ final generated = '''
+div{color:green!important;background:red blue green}
+.foo p[bar]{color:blue}
+@page{@top-left{color:red}}
+@page:first{}
+@page foo:first{}
+@media screen AND (max-width:800px){div{font-size:24px}}
+@keyframes foo{0%{transform:scaleX(0)}}
+div{color:rgba(0,0,0,0.2)}''';
var stylesheet = parseCss(input, errors: errors);
@@ -1145,7 +1156,8 @@
}
}''';
- final generated = '''.testIE-6 {
+ final generated = '''
+.testIE-6 {
_zoom: 5;
}
.clearfix {
@@ -1180,42 +1192,42 @@
}
@-webkit-keyframes progress-bar-stripes {
from {
- background-position: 40px 0;
+ background-position: 40px 0;
}
to {
- background-position: 0 0;
+ background-position: 0 0;
}
}
@-moz-keyframes progress-bar-stripes {
from {
- background-position: 40px 0;
+ background-position: 40px 0;
}
to {
- background-position: 0 0;
+ background-position: 0 0;
}
}
@keyframes progress-bar-stripes {
from {
- background-position: 40px 0;
+ background-position: 40px 0;
}
to {
- background-position: 0 0;
+ background-position: 0 0;
}
}
@-o-keyframes progress-bar-stripes {
from {
- background-position: 40px 0;
+ background-position: 40px 0;
}
to {
- background-position: 0 0;
+ background-position: 0 0;
}
}
@keyframes progress-bar-stripes {
from {
- background-position: 40px 0;
+ background-position: 40px 0;
}
to {
- background-position: 0 0;
+ background-position: 0 0;
}
}''';
diff --git a/test/keyframes_test.dart b/test/keyframes_test.dart
index 0c9456f..3560c0d 100644
--- a/test/keyframes_test.dart
+++ b/test/keyframes_test.dart
@@ -17,8 +17,8 @@
final expected = r'''
@keyframes ping {
75%, 100% {
- transform: scale(2);
- opacity: 0;
+ transform: scale(2);
+ opacity: 0;
}
}''';
expect(prettyPrint(stylesheet), expected);
diff --git a/test/mixin_test.dart b/test/mixin_test.dart
index 0432b1c..a60674a 100644
--- a/test/mixin_test.dart
+++ b/test/mixin_test.dart
@@ -397,7 +397,6 @@
}
''', r'''
var-values: #f00, #0f0, #00f;
-
.primary {
color: #f00;
background-color: #0f0;
diff --git a/test/nested_test.dart b/test/nested_test.dart
index a594969..a579868 100644
--- a/test/nested_test.dart
+++ b/test/nested_test.dart
@@ -238,7 +238,7 @@
void complexNest() {
final input = '''
-@font-face { font-family: arial; }
+@font-face { font-family: arial; }
div { color: #f0f0f0; }
#header + div {
color: url(abc.png);
@@ -276,7 +276,7 @@
span { color: #1f1f2f; }
''';
- final generated = r'''@font-face {
+ final generated = r'''@font-face {
font-family: arial;
}
div {
@@ -353,17 +353,18 @@
}
}
''';
- final generated = r'''@media screen AND (-webkit-min-device-pixel-ratio:0) {
-#toggle-all {
- image: url("test.jpb");
- color: #f00;
-}
-#toggle-all div, #toggle-all table {
- background: none;
-}
-#toggle-all div a, #toggle-all table a {
- width: 100px;
-}
+ final generated = r'''
+@media screen AND (-webkit-min-device-pixel-ratio:0) {
+ #toggle-all {
+ image: url("test.jpb");
+ color: #f00;
+ }
+ #toggle-all div, #toggle-all table {
+ background: none;
+ }
+ #toggle-all div a, #toggle-all table a {
+ width: 100px;
+ }
}''';
compileAndValidate(input, generated);
diff --git a/test/testing.dart b/test/testing.dart
index d93c4a3..00e6ce7 100644
--- a/test/testing.dart
+++ b/test/testing.dart
@@ -10,16 +10,18 @@
export 'package:csslib/src/preprocessor_options.dart';
-const simpleOptionsWithCheckedAndWarningsAsErrors = PreprocessorOptions(
- useColors: false,
- checked: true,
- warningsAsErrors: true,
- inputFile: 'memory');
+const PreprocessorOptions simpleOptionsWithCheckedAndWarningsAsErrors =
+ PreprocessorOptions(
+ useColors: false,
+ checked: true,
+ warningsAsErrors: true,
+ inputFile: 'memory',
+);
-const simpleOptions =
+const PreprocessorOptions simpleOptions =
PreprocessorOptions(useColors: false, inputFile: 'memory');
-const options = PreprocessorOptions(
+const PreprocessorOptions options = PreprocessorOptions(
useColors: false, warningsAsErrors: true, inputFile: 'memory');
/// Spin-up CSS parser in checked mode to detect any problematic CSS. Normally,
@@ -49,17 +51,11 @@
{List<Message>? errors, PreprocessorOptions? opts}) =>
compileCss(input, errors: errors, polyfill: true, opts: opts);
-/// CSS emitter walks the style sheet tree and emits readable CSS.
-final _emitCss = CssPrinter();
-
-/// Simple Visitor does nothing but walk tree.
-final _cssVisitor = Visitor();
-
/// Pretty printer for CSS.
String prettyPrint(StyleSheet ss) {
// Walk the tree testing basic Visitor class.
walkTree(ss);
- return (_emitCss..visitTree(ss, pretty: true)).toString();
+ return (CssPrinter()..visitTree(ss, pretty: true)).toString();
}
/// Helper function to emit compact (non-pretty printed) CSS for suite test
@@ -67,12 +63,12 @@
/// expected suite test results.
String compactOutput(StyleSheet ss) {
walkTree(ss);
- return (_emitCss..visitTree(ss, pretty: false)).toString();
+ return (CssPrinter()..visitTree(ss, pretty: false)).toString();
}
/// Walks the style sheet tree does nothing; insures the basic walker works.
void walkTree(StyleSheet ss) {
- _cssVisitor.visitTree(ss);
+ Visitor().visitTree(ss);
}
String dumpTree(StyleSheet ss) => treeToDebugString(ss);
diff --git a/test/var_test.dart b/test/var_test.dart
index 079955f..482fda9 100644
--- a/test/var_test.dart
+++ b/test/var_test.dart
@@ -179,12 +179,12 @@
content: var(content);
text-shadow: var(text-shadow);
}
-@font-face {
+@font-face {
font-family: var(font-family);
src: var(src);
unicode-range: var(unicode-range);
}
-@font-face {
+@font-face {
font-family: var(font-family);
src: var(src-1);
unicode-range: var(unicode-range-1);
@@ -214,12 +214,12 @@
content: "✔";
text-shadow: 0 -1px 0 #bfbfbf;
}
-@font-face {
+@font-face {
font-family: Gentium;
src: url("http://example.com/fonts/Gentium.ttf");
unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF;
}
-@font-face {
+@font-face {
font-family: Gentium;
src: local(Gentium Bold), local(Gentium-Bold), url("GentiumBold.ttf");
unicode-range: U+0A-FF, U+980-9FF, U+????, U+3???;
@@ -602,12 +602,12 @@
content: var(content);
text-shadow: var(text-shadow);
}
-@font-face {
+@font-face {
font-family: var(font-family);
src: var(src);
unicode-range: var(unicode-range);
}
-@font-face {
+@font-face {
font-family: var(font-family);
src: var(src-1);
unicode-range: var(unicode-range-1);
@@ -637,12 +637,12 @@
content: "✔";
text-shadow: 0 -1px 0 #bfbfbf;
}
-@font-face {
+@font-face {
font-family: Gentium;
src: url("http://example.com/fonts/Gentium.ttf");
unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF;
}
-@font-face {
+@font-face {
font-family: Gentium;
src: local(Gentium Bold), local(Gentium-Bold), url("GentiumBold.ttf");
unicode-range: U+0A-FF, U+980-9FF, U+????, U+3???;
@@ -667,7 +667,6 @@
final generated = '''
var-color-background: #f00;
var-color-foreground: #00f;
-
.test {
background-color: var(color-background);
color: var(color-foreground);
@@ -692,7 +691,6 @@
final generated2 = '''
var-color-background: #f00;
var-color-foreground: #00f;
-
.test {
background-color: var(color-background);
color: var(color-foreground);
@@ -720,7 +718,6 @@
final generated = '''
var-color-background: #f00;
var-color-foreground: #00f;
-
.test {
background-color: var(color-background);
color: var(color-foreground);
@@ -745,7 +742,6 @@
final generated2 = '''
var-color-background: #f00;
var-color-foreground: #00f;
-
.test {
background-color: var(color-background);
color: var(color-foreground);
diff --git a/test/visitor_test.dart b/test/visitor_test.dart
index f845993..a70f91f 100644
--- a/test/visitor_test.dart
+++ b/test/visitor_test.dart
@@ -109,4 +109,34 @@
void main() {
test('Class Visitors', testClassVisitors);
test('Polyfill', testPolyFill);
+ test('pretty-print', testPrettyPrint);
+}
+
+void testPrettyPrint() {
+ final input = '''
+.good { color: red; }
+@media screen { .better { color: blue; } }
+.best { color: green }''';
+
+ var styleSheet = parseCss(input);
+
+ // pretty print
+ expect(prettyPrint(styleSheet), '''
+.good {
+ color: #f00;
+}
+@media screen {
+ .better {
+ color: #00f;
+ }
+}
+.best {
+ color: #008000;
+}''');
+
+ // compact output
+ expect(compactOutput(styleSheet), '''
+.good{color:red}
+@media screen{.better{color:blue}}
+.best{color:green}''');
}