more correctly emit newlines around
This commit is contained in:
parent
be9eb8e0b0
commit
1a660c7aa8
@ -30,8 +30,15 @@ enum Toplevel {
|
|||||||
UnknownAtRule(Box<ToplevelUnknownAtRule>),
|
UnknownAtRule(Box<ToplevelUnknownAtRule>),
|
||||||
Keyframes(Box<Keyframes>),
|
Keyframes(Box<Keyframes>),
|
||||||
KeyframesRuleSet(Vec<KeyframesSelector>, Vec<BlockEntry>),
|
KeyframesRuleSet(Vec<KeyframesSelector>, Vec<BlockEntry>),
|
||||||
Media { query: String, body: Vec<Stmt> },
|
Media {
|
||||||
Supports { params: String, body: Vec<Stmt> },
|
query: String,
|
||||||
|
body: Vec<Stmt>,
|
||||||
|
inside_rule: bool,
|
||||||
|
},
|
||||||
|
Supports {
|
||||||
|
params: String,
|
||||||
|
body: Vec<Stmt>,
|
||||||
|
},
|
||||||
Newline,
|
Newline,
|
||||||
// todo: do we actually need a toplevel style variant?
|
// todo: do we actually need a toplevel style variant?
|
||||||
Style(Style),
|
Style(Style),
|
||||||
@ -114,11 +121,15 @@ impl Css {
|
|||||||
if body.is_empty() {
|
if body.is_empty() {
|
||||||
return Ok(Vec::new());
|
return Ok(Vec::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
let selector = selector.into_selector().remove_placeholders();
|
let selector = selector.into_selector().remove_placeholders();
|
||||||
|
|
||||||
if selector.is_empty() {
|
if selector.is_empty() {
|
||||||
return Ok(Vec::new());
|
return Ok(Vec::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut vals = vec![Toplevel::new_rule(selector)];
|
let mut vals = vec![Toplevel::new_rule(selector)];
|
||||||
|
|
||||||
for rule in body {
|
for rule in body {
|
||||||
match rule {
|
match rule {
|
||||||
Stmt::RuleSet { .. } => vals.extend(self.parse_stmt(rule)?),
|
Stmt::RuleSet { .. } => vals.extend(self.parse_stmt(rule)?),
|
||||||
@ -126,7 +137,11 @@ impl Css {
|
|||||||
Stmt::Comment(s) => vals.first_mut().unwrap().push_comment(s),
|
Stmt::Comment(s) => vals.first_mut().unwrap().push_comment(s),
|
||||||
Stmt::Media(m) => {
|
Stmt::Media(m) => {
|
||||||
let MediaRule { query, body, .. } = *m;
|
let MediaRule { query, body, .. } = *m;
|
||||||
vals.push(Toplevel::Media { query, body });
|
vals.push(Toplevel::Media {
|
||||||
|
query,
|
||||||
|
body,
|
||||||
|
inside_rule: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Stmt::Supports(s) => {
|
Stmt::Supports(s) => {
|
||||||
let SupportsRule { params, body } = *s;
|
let SupportsRule { params, body } = *s;
|
||||||
@ -173,7 +188,11 @@ impl Css {
|
|||||||
Stmt::Style(s) => vec![Toplevel::Style(s)],
|
Stmt::Style(s) => vec![Toplevel::Style(s)],
|
||||||
Stmt::Media(m) => {
|
Stmt::Media(m) => {
|
||||||
let MediaRule { query, body, .. } = *m;
|
let MediaRule { query, body, .. } = *m;
|
||||||
vec![Toplevel::Media { query, body }]
|
vec![Toplevel::Media {
|
||||||
|
query,
|
||||||
|
body,
|
||||||
|
inside_rule: false,
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
Stmt::Supports(s) => {
|
Stmt::Supports(s) => {
|
||||||
let SupportsRule { params, body } = *s;
|
let SupportsRule { params, body } = *s;
|
||||||
@ -265,8 +284,8 @@ trait Formatter {
|
|||||||
struct CompressedFormatter {}
|
struct CompressedFormatter {}
|
||||||
|
|
||||||
impl Formatter for CompressedFormatter {
|
impl Formatter for CompressedFormatter {
|
||||||
fn write_css(&mut self, buf: &mut Vec<u8>, mut css: Css, map: &CodeMap) -> SassResult<()> {
|
fn write_css(&mut self, buf: &mut Vec<u8>, css: Css, map: &CodeMap) -> SassResult<()> {
|
||||||
for block in mem::take(&mut css.blocks) {
|
for block in css.blocks {
|
||||||
match block {
|
match block {
|
||||||
Toplevel::RuleSet(selector, styles) => {
|
Toplevel::RuleSet(selector, styles) => {
|
||||||
if styles.is_empty() {
|
if styles.is_empty() {
|
||||||
@ -362,7 +381,7 @@ impl Formatter for CompressedFormatter {
|
|||||||
self.write_css(buf, css, map)?;
|
self.write_css(buf, css, map)?;
|
||||||
write!(buf, "}}")?;
|
write!(buf, "}}")?;
|
||||||
}
|
}
|
||||||
Toplevel::Media { query, body } => {
|
Toplevel::Media { query, body, .. } => {
|
||||||
if body.is_empty() {
|
if body.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -433,32 +452,38 @@ struct ExpandedFormatter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Formatter for ExpandedFormatter {
|
impl Formatter for ExpandedFormatter {
|
||||||
fn write_css(&mut self, buf: &mut Vec<u8>, mut css: Css, map: &CodeMap) -> SassResult<()> {
|
fn write_css(&mut self, buf: &mut Vec<u8>, css: Css, map: &CodeMap) -> SassResult<()> {
|
||||||
let mut has_written = false;
|
let mut has_written = false;
|
||||||
let padding = " ".repeat(self.nesting);
|
let padding = " ".repeat(self.nesting);
|
||||||
let mut should_emit_newline = false;
|
let mut should_emit_newline = false;
|
||||||
self.nesting += 1;
|
self.nesting += 1;
|
||||||
for block in mem::take(&mut css.blocks) {
|
|
||||||
|
for block in css.blocks {
|
||||||
match block {
|
match block {
|
||||||
Toplevel::RuleSet(selector, styles) => {
|
Toplevel::RuleSet(selector, styles) => {
|
||||||
if styles.is_empty() {
|
if styles.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
has_written = true;
|
has_written = true;
|
||||||
if should_emit_newline && !css.in_at_rule {
|
if should_emit_newline && !css.in_at_rule {
|
||||||
should_emit_newline = false;
|
should_emit_newline = false;
|
||||||
writeln!(buf)?;
|
writeln!(buf)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(buf, "{}{} {{", padding, selector)?;
|
writeln!(buf, "{}{} {{", padding, selector)?;
|
||||||
|
|
||||||
for style in styles {
|
for style in styles {
|
||||||
writeln!(buf, "{} {}", padding, style.to_string()?)?;
|
writeln!(buf, "{} {}", padding, style.to_string()?)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(buf, "{}}}", padding)?;
|
writeln!(buf, "{}}}", padding)?;
|
||||||
}
|
}
|
||||||
Toplevel::KeyframesRuleSet(selector, body) => {
|
Toplevel::KeyframesRuleSet(selector, body) => {
|
||||||
if body.is_empty() {
|
if body.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
has_written = true;
|
has_written = true;
|
||||||
|
|
||||||
writeln!(
|
writeln!(
|
||||||
@ -552,13 +577,22 @@ impl Formatter for ExpandedFormatter {
|
|||||||
self.write_css(buf, css, map)?;
|
self.write_css(buf, css, map)?;
|
||||||
writeln!(buf, "{}}}", padding)?;
|
writeln!(buf, "{}}}", padding)?;
|
||||||
}
|
}
|
||||||
Toplevel::Media { query, body } => {
|
Toplevel::Media {
|
||||||
|
query,
|
||||||
|
body,
|
||||||
|
inside_rule,
|
||||||
|
} => {
|
||||||
if body.is_empty() {
|
if body.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if should_emit_newline {
|
||||||
|
should_emit_newline = false;
|
||||||
|
writeln!(buf)?;
|
||||||
|
}
|
||||||
|
|
||||||
writeln!(buf, "{}@media {} {{", padding, query)?;
|
writeln!(buf, "{}@media {} {{", padding, query)?;
|
||||||
let css = Css::from_stmts(body, true, css.allows_charset)?;
|
let css = Css::from_stmts(body, inside_rule, css.allows_charset)?;
|
||||||
self.write_css(buf, css, map)?;
|
self.write_css(buf, css, map)?;
|
||||||
writeln!(buf, "{}}}", padding)?;
|
writeln!(buf, "{}}}", padding)?;
|
||||||
}
|
}
|
||||||
@ -573,7 +607,9 @@ impl Formatter for ExpandedFormatter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.nesting -= 1;
|
self.nesting -= 1;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ impl IsWhitespace for Token {
|
|||||||
if self.kind.is_whitespace() {
|
if self.kind.is_whitespace() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,59 @@ test!(
|
|||||||
",
|
",
|
||||||
"@media (false) {\n a {\n b: c;\n }\n}\n"
|
"@media (false) {\n a {\n b: c;\n }\n}\n"
|
||||||
);
|
);
|
||||||
|
test!(
|
||||||
|
newline_emitted_for_different_toplevel_rulesets,
|
||||||
|
"@media print {
|
||||||
|
a {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
b {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
}",
|
||||||
|
"@media print {\n a {\n color: red;\n }\n\n b {\n color: green;\n }\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
newline_emitted_before_media_when_following_ruleset,
|
||||||
|
"a {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
@media print {
|
||||||
|
a {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
}",
|
||||||
|
"a {\n color: red;\n}\n\n@media print {\n a {\n color: red;\n }\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
no_newline_emitted_between_two_media_rules,
|
||||||
|
"@media print {
|
||||||
|
a {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media print {
|
||||||
|
a {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
}",
|
||||||
|
"@media print {\n a {\n color: red;\n }\n}\n@media print {\n a {\n color: red;\n }\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
no_newline_emitted_between_two_media_rules_when_in_same_ruleset,
|
||||||
|
"a {
|
||||||
|
@media foo {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media bar {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
}",
|
||||||
|
"@media foo {\n a {\n color: red;\n }\n}\n@media bar {\n a {\n color: green;\n }\n}\n"
|
||||||
|
);
|
||||||
|
|
||||||
error!(
|
error!(
|
||||||
media_feature_missing_closing_paren,
|
media_feature_missing_closing_paren,
|
||||||
"@media foo and (bar:a", "Error: expected \")\"."
|
"@media foo and (bar:a", "Error: expected \")\"."
|
||||||
|
Loading…
x
Reference in New Issue
Block a user