2020-01-05 12:52:50 -05:00
|
|
|
//! # Convert from SCSS AST to CSS
|
2020-03-01 14:53:52 -05:00
|
|
|
use std::io::Write;
|
|
|
|
|
2020-06-16 19:38:30 -04:00
|
|
|
use codemap::CodeMap;
|
2020-04-24 22:57:39 -04:00
|
|
|
|
2020-06-25 00:27:24 -04:00
|
|
|
use crate::{
|
2020-07-04 20:50:53 -04:00
|
|
|
atrule::{
|
|
|
|
keyframes::{Keyframes, KeyframesRuleSet, KeyframesSelector},
|
|
|
|
media::MediaRule,
|
|
|
|
SupportsRule, UnknownAtRule,
|
|
|
|
},
|
2020-06-25 00:27:24 -04:00
|
|
|
error::SassResult,
|
|
|
|
parse::Stmt,
|
|
|
|
selector::Selector,
|
|
|
|
style::Style,
|
|
|
|
};
|
2020-01-05 12:45:51 -05:00
|
|
|
|
2020-06-26 05:37:57 -04:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
struct ToplevelUnknownAtRule {
|
|
|
|
name: String,
|
|
|
|
params: String,
|
|
|
|
body: Vec<Stmt>,
|
|
|
|
}
|
|
|
|
|
2020-01-05 12:45:51 -05:00
|
|
|
#[derive(Debug, Clone)]
|
2020-01-20 13:15:47 -05:00
|
|
|
enum Toplevel {
|
2020-01-08 20:39:05 -05:00
|
|
|
RuleSet(Selector, Vec<BlockEntry>),
|
|
|
|
MultilineComment(String),
|
2020-06-26 05:37:57 -04:00
|
|
|
UnknownAtRule(Box<ToplevelUnknownAtRule>),
|
2020-07-04 20:50:53 -04:00
|
|
|
Keyframes(Box<Keyframes>),
|
|
|
|
KeyframesRuleSet(Vec<KeyframesSelector>, Vec<BlockEntry>),
|
2020-06-26 05:37:57 -04:00
|
|
|
Media { query: String, body: Vec<Stmt> },
|
|
|
|
Supports { params: String, body: Vec<Stmt> },
|
2020-01-29 21:25:07 -05:00
|
|
|
Newline,
|
2020-07-06 19:47:12 -04:00
|
|
|
// todo: do we actually need a toplevel style variant?
|
2020-06-25 00:27:24 -04:00
|
|
|
Style(Style),
|
2020-07-06 19:47:12 -04:00
|
|
|
Import(String),
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
|
2020-01-08 20:39:05 -05:00
|
|
|
#[derive(Debug, Clone)]
|
2020-01-20 13:15:47 -05:00
|
|
|
enum BlockEntry {
|
2020-07-06 19:47:12 -04:00
|
|
|
Style(Style),
|
2020-01-08 20:39:05 -05:00
|
|
|
MultilineComment(String),
|
2020-07-06 19:47:12 -04:00
|
|
|
Import(String),
|
2020-01-08 20:39:05 -05:00
|
|
|
}
|
|
|
|
|
2020-04-12 19:37:12 -04:00
|
|
|
impl BlockEntry {
|
|
|
|
pub fn to_string(&self) -> SassResult<String> {
|
2020-01-08 20:39:05 -05:00
|
|
|
match self {
|
2020-04-12 19:37:12 -04:00
|
|
|
BlockEntry::Style(s) => s.to_string(),
|
|
|
|
BlockEntry::MultilineComment(s) => Ok(format!("/*{}*/", s)),
|
2020-07-06 19:47:12 -04:00
|
|
|
BlockEntry::Import(s) => Ok(format!("@import {};", s)),
|
2020-01-08 20:39:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Toplevel {
|
|
|
|
const fn new_rule(selector: Selector) -> Self {
|
|
|
|
Toplevel::RuleSet(selector, Vec::new())
|
|
|
|
}
|
|
|
|
|
2020-07-04 20:50:53 -04:00
|
|
|
fn new_keyframes_rule(selector: Vec<KeyframesSelector>) -> Self {
|
|
|
|
Toplevel::KeyframesRuleSet(selector, Vec::new())
|
|
|
|
}
|
|
|
|
|
2020-07-03 12:38:20 -04:00
|
|
|
fn push_style(&mut self, s: Style) {
|
|
|
|
if s.value.is_null() {
|
|
|
|
return;
|
2020-02-15 09:58:41 -05:00
|
|
|
}
|
2020-07-04 20:50:53 -04:00
|
|
|
if let Toplevel::RuleSet(_, entries) | Toplevel::KeyframesRuleSet(_, entries) = self {
|
2020-07-06 19:47:12 -04:00
|
|
|
entries.push(BlockEntry::Style(s));
|
2020-07-04 20:50:53 -04:00
|
|
|
} else {
|
|
|
|
panic!()
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-08 20:39:05 -05:00
|
|
|
fn push_comment(&mut self, s: String) {
|
2020-07-04 20:50:53 -04:00
|
|
|
if let Toplevel::RuleSet(_, entries) | Toplevel::KeyframesRuleSet(_, entries) = self {
|
2020-01-08 20:39:05 -05:00
|
|
|
entries.push(BlockEntry::MultilineComment(s));
|
2020-07-04 20:50:53 -04:00
|
|
|
} else {
|
|
|
|
panic!()
|
2020-01-08 20:39:05 -05:00
|
|
|
}
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
2020-07-06 19:47:12 -04:00
|
|
|
|
|
|
|
fn push_import(&mut self, s: String) {
|
|
|
|
if let Toplevel::RuleSet(_, entries) | Toplevel::KeyframesRuleSet(_, entries) = self {
|
|
|
|
entries.push(BlockEntry::Import(s));
|
|
|
|
} else {
|
|
|
|
panic!()
|
|
|
|
}
|
|
|
|
}
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
2020-06-18 16:56:03 -04:00
|
|
|
pub(crate) struct Css {
|
2020-01-08 20:39:05 -05:00
|
|
|
blocks: Vec<Toplevel>,
|
2020-07-04 22:46:28 -04:00
|
|
|
in_at_rule: bool,
|
2020-07-16 00:02:42 -04:00
|
|
|
allows_charset: bool,
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Css {
|
2020-07-16 00:02:42 -04:00
|
|
|
pub const fn new(in_at_rule: bool, allows_charset: bool) -> Self {
|
2020-07-04 22:46:28 -04:00
|
|
|
Css {
|
|
|
|
blocks: Vec::new(),
|
|
|
|
in_at_rule,
|
2020-07-16 00:02:42 -04:00
|
|
|
allows_charset,
|
2020-07-04 22:46:28 -04:00
|
|
|
}
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
|
2020-07-16 00:02:42 -04:00
|
|
|
pub(crate) fn from_stmts(
|
|
|
|
s: Vec<Stmt>,
|
|
|
|
in_at_rule: bool,
|
|
|
|
allows_charset: bool,
|
|
|
|
) -> SassResult<Self> {
|
|
|
|
Css::new(in_at_rule, allows_charset).parse_stylesheet(s)
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
|
2020-07-04 12:38:09 -04:00
|
|
|
fn parse_stmt(&mut self, stmt: Stmt) -> SassResult<Vec<Toplevel>> {
|
2020-04-01 17:37:07 -04:00
|
|
|
Ok(match stmt {
|
2020-06-23 01:36:22 -04:00
|
|
|
Stmt::RuleSet { selector, body } => {
|
2020-06-18 16:56:03 -04:00
|
|
|
if body.is_empty() {
|
|
|
|
return Ok(Vec::new());
|
|
|
|
}
|
2020-06-23 02:36:30 -04:00
|
|
|
let selector = selector.into_selector().remove_placeholders();
|
2020-02-29 17:23:17 -05:00
|
|
|
if selector.is_empty() {
|
2020-04-01 17:37:07 -04:00
|
|
|
return Ok(Vec::new());
|
2020-02-29 17:23:17 -05:00
|
|
|
}
|
|
|
|
let mut vals = vec![Toplevel::new_rule(selector)];
|
2020-06-16 19:38:30 -04:00
|
|
|
for rule in body {
|
|
|
|
match rule {
|
2020-07-04 12:38:09 -04:00
|
|
|
Stmt::RuleSet { .. } => vals.extend(self.parse_stmt(rule)?),
|
2020-08-05 03:09:10 -04:00
|
|
|
Stmt::Style(s) => vals.first_mut().unwrap().push_style(s),
|
|
|
|
Stmt::Comment(s) => vals.first_mut().unwrap().push_comment(s),
|
2020-06-25 00:27:24 -04:00
|
|
|
Stmt::Media(m) => {
|
|
|
|
let MediaRule { query, body, .. } = *m;
|
2020-06-24 11:39:32 -04:00
|
|
|
vals.push(Toplevel::Media { query, body })
|
2020-06-16 19:38:30 -04:00
|
|
|
}
|
2020-06-25 00:27:24 -04:00
|
|
|
Stmt::Supports(s) => {
|
2020-06-26 06:12:50 -04:00
|
|
|
let SupportsRule { params, body } = *s;
|
2020-06-20 15:52:53 -04:00
|
|
|
vals.push(Toplevel::Supports { params, body })
|
|
|
|
}
|
2020-06-25 00:27:24 -04:00
|
|
|
Stmt::UnknownAtRule(u) => {
|
|
|
|
let UnknownAtRule {
|
|
|
|
params, body, name, ..
|
|
|
|
} = *u;
|
2020-06-26 05:37:57 -04:00
|
|
|
vals.push(Toplevel::UnknownAtRule(Box::new(ToplevelUnknownAtRule {
|
|
|
|
params,
|
|
|
|
body,
|
|
|
|
name,
|
|
|
|
})))
|
2020-06-25 00:27:24 -04:00
|
|
|
}
|
2020-06-16 19:38:30 -04:00
|
|
|
Stmt::Return(..) => unreachable!(),
|
2020-07-03 12:38:20 -04:00
|
|
|
Stmt::AtRoot { body } => {
|
|
|
|
body.into_iter().try_for_each(|r| -> SassResult<()> {
|
2020-07-04 12:38:09 -04:00
|
|
|
vals.append(&mut self.parse_stmt(r)?);
|
2020-07-03 12:38:20 -04:00
|
|
|
Ok(())
|
|
|
|
})?
|
|
|
|
}
|
2020-07-04 20:50:53 -04:00
|
|
|
Stmt::Keyframes(k) => {
|
2020-07-29 07:18:47 -04:00
|
|
|
let Keyframes { rule, name, body } = *k;
|
|
|
|
vals.push(Toplevel::Keyframes(Box::new(Keyframes {
|
|
|
|
rule,
|
|
|
|
name,
|
|
|
|
body,
|
|
|
|
})))
|
2020-07-04 20:50:53 -04:00
|
|
|
}
|
|
|
|
k @ Stmt::KeyframesRuleSet(..) => {
|
|
|
|
unreachable!("@keyframes ruleset {:?}", k)
|
|
|
|
}
|
2020-08-05 03:09:10 -04:00
|
|
|
Stmt::Import(s) => vals.first_mut().unwrap().push_import(s),
|
2020-01-19 19:27:52 -05:00
|
|
|
};
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
2020-01-19 19:27:52 -05:00
|
|
|
vals
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
2020-06-16 19:38:30 -04:00
|
|
|
Stmt::Comment(s) => vec![Toplevel::MultilineComment(s)],
|
2020-07-06 19:47:12 -04:00
|
|
|
Stmt::Import(s) => vec![Toplevel::Import(s)],
|
2020-04-12 21:47:32 -04:00
|
|
|
Stmt::Style(s) => vec![Toplevel::Style(s)],
|
2020-06-25 00:27:24 -04:00
|
|
|
Stmt::Media(m) => {
|
|
|
|
let MediaRule { query, body, .. } = *m;
|
|
|
|
vec![Toplevel::Media { query, body }]
|
|
|
|
}
|
|
|
|
Stmt::Supports(s) => {
|
2020-06-25 01:18:13 -04:00
|
|
|
let SupportsRule { params, body } = *s;
|
2020-06-25 00:27:24 -04:00
|
|
|
vec![Toplevel::Supports { params, body }]
|
|
|
|
}
|
|
|
|
Stmt::UnknownAtRule(u) => {
|
|
|
|
let UnknownAtRule {
|
|
|
|
params, body, name, ..
|
|
|
|
} = *u;
|
2020-06-26 05:37:57 -04:00
|
|
|
vec![Toplevel::UnknownAtRule(Box::new(ToplevelUnknownAtRule {
|
|
|
|
params,
|
|
|
|
name,
|
|
|
|
body,
|
|
|
|
}))]
|
2020-06-25 00:27:24 -04:00
|
|
|
}
|
2020-06-16 22:00:45 -04:00
|
|
|
Stmt::Return(..) => unreachable!("@return: {:?}", stmt),
|
|
|
|
Stmt::AtRoot { .. } => unreachable!("@at-root: {:?}", stmt),
|
2020-07-04 20:50:53 -04:00
|
|
|
Stmt::Keyframes(k) => vec![Toplevel::Keyframes(k)],
|
|
|
|
Stmt::KeyframesRuleSet(k) => {
|
|
|
|
let KeyframesRuleSet { body, selector } = *k;
|
|
|
|
if body.is_empty() {
|
|
|
|
return Ok(Vec::new());
|
|
|
|
}
|
|
|
|
let mut vals = vec![Toplevel::new_keyframes_rule(selector)];
|
|
|
|
for rule in body {
|
|
|
|
match rule {
|
2020-08-05 03:09:10 -04:00
|
|
|
Stmt::Style(s) => vals.first_mut().unwrap().push_style(s),
|
2020-07-04 20:50:53 -04:00
|
|
|
Stmt::KeyframesRuleSet(..) => vals.extend(self.parse_stmt(rule)?),
|
|
|
|
_ => todo!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vals
|
|
|
|
}
|
2020-04-01 17:37:07 -04:00
|
|
|
})
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
|
2020-07-04 12:38:09 -04:00
|
|
|
fn parse_stylesheet(mut self, stmts: Vec<Stmt>) -> SassResult<Css> {
|
2020-01-29 21:25:07 -05:00
|
|
|
let mut is_first = true;
|
2020-06-16 19:38:30 -04:00
|
|
|
for stmt in stmts {
|
2020-07-04 12:38:09 -04:00
|
|
|
let v = self.parse_stmt(stmt)?;
|
2020-01-29 21:25:07 -05:00
|
|
|
// this is how we print newlines between unrelated styles
|
|
|
|
// it could probably be refactored
|
|
|
|
if !v.is_empty() {
|
2020-08-05 03:09:10 -04:00
|
|
|
if let Some(Toplevel::MultilineComment(..)) = v.first() {
|
2020-02-01 19:25:44 -05:00
|
|
|
} else if is_first {
|
2020-01-29 21:25:07 -05:00
|
|
|
is_first = false;
|
|
|
|
} else {
|
|
|
|
self.blocks.push(Toplevel::Newline);
|
|
|
|
}
|
2020-03-01 14:53:52 -05:00
|
|
|
self.blocks.extend(v);
|
2020-01-29 21:25:07 -05:00
|
|
|
}
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
2020-04-01 17:37:07 -04:00
|
|
|
Ok(self)
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
|
2020-07-04 12:38:09 -04:00
|
|
|
pub fn pretty_print(self, map: &CodeMap) -> SassResult<String> {
|
2020-04-05 23:20:47 -04:00
|
|
|
let mut string = Vec::new();
|
2020-07-16 00:02:42 -04:00
|
|
|
let allows_charset = self.allows_charset;
|
2020-07-04 12:38:09 -04:00
|
|
|
self._inner_pretty_print(&mut string, map, 0)?;
|
2020-07-16 00:02:42 -04:00
|
|
|
if allows_charset && string.iter().any(|s| !s.is_ascii()) {
|
2020-05-01 19:24:26 -04:00
|
|
|
return Ok(format!("@charset \"UTF-8\";\n{}", unsafe {
|
|
|
|
String::from_utf8_unchecked(string)
|
|
|
|
}));
|
2020-02-28 18:27:32 -05:00
|
|
|
}
|
2020-05-01 19:24:26 -04:00
|
|
|
Ok(unsafe { String::from_utf8_unchecked(string) })
|
2020-04-05 23:20:47 -04:00
|
|
|
}
|
|
|
|
|
2020-04-24 22:57:39 -04:00
|
|
|
fn _inner_pretty_print(
|
|
|
|
self,
|
|
|
|
buf: &mut Vec<u8>,
|
|
|
|
map: &CodeMap,
|
|
|
|
nesting: usize,
|
|
|
|
) -> SassResult<()> {
|
2020-04-05 23:20:47 -04:00
|
|
|
let mut has_written = false;
|
|
|
|
let padding = vec![' '; nesting * 2].iter().collect::<String>();
|
2020-06-18 16:56:03 -04:00
|
|
|
let mut should_emit_newline = false;
|
2020-01-05 12:45:51 -05:00
|
|
|
for block in self.blocks {
|
2020-01-08 20:39:05 -05:00
|
|
|
match block {
|
|
|
|
Toplevel::RuleSet(selector, styles) => {
|
|
|
|
if styles.is_empty() {
|
|
|
|
continue;
|
|
|
|
}
|
2020-01-29 21:25:07 -05:00
|
|
|
has_written = true;
|
2020-07-04 22:46:28 -04:00
|
|
|
if should_emit_newline && !self.in_at_rule {
|
2020-06-18 16:56:03 -04:00
|
|
|
should_emit_newline = false;
|
|
|
|
writeln!(buf)?;
|
|
|
|
}
|
2020-02-22 11:59:16 -05:00
|
|
|
writeln!(buf, "{}{} {{", padding, selector)?;
|
2020-01-08 20:39:05 -05:00
|
|
|
for style in styles {
|
2020-04-12 19:37:12 -04:00
|
|
|
writeln!(buf, "{} {}", padding, style.to_string()?)?;
|
2020-01-08 20:39:05 -05:00
|
|
|
}
|
2020-02-22 11:59:16 -05:00
|
|
|
writeln!(buf, "{}}}", padding)?;
|
2020-01-08 20:39:05 -05:00
|
|
|
}
|
2020-07-04 20:50:53 -04:00
|
|
|
Toplevel::KeyframesRuleSet(selector, body) => {
|
|
|
|
if body.is_empty() {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
has_written = true;
|
2020-07-04 22:46:28 -04:00
|
|
|
|
2020-07-04 20:50:53 -04:00
|
|
|
writeln!(
|
|
|
|
buf,
|
|
|
|
"{}{} {{",
|
|
|
|
padding,
|
|
|
|
selector
|
|
|
|
.into_iter()
|
|
|
|
.map(|s| s.to_string())
|
|
|
|
.collect::<Vec<String>>()
|
|
|
|
.join(", ")
|
|
|
|
)?;
|
|
|
|
for style in body {
|
|
|
|
writeln!(buf, "{} {}", padding, style.to_string()?)?;
|
|
|
|
}
|
|
|
|
writeln!(buf, "{}}}", padding)?;
|
|
|
|
}
|
2020-01-08 20:39:05 -05:00
|
|
|
Toplevel::MultilineComment(s) => {
|
2020-01-29 21:25:07 -05:00
|
|
|
has_written = true;
|
2020-02-22 11:59:16 -05:00
|
|
|
writeln!(buf, "{}/*{}*/", padding, s)?;
|
2020-01-26 15:27:38 -05:00
|
|
|
}
|
2020-07-06 19:47:12 -04:00
|
|
|
Toplevel::Import(s) => {
|
|
|
|
has_written = true;
|
|
|
|
writeln!(buf, "{}@import {};", padding, s)?;
|
|
|
|
}
|
2020-06-26 05:37:57 -04:00
|
|
|
Toplevel::UnknownAtRule(u) => {
|
|
|
|
let ToplevelUnknownAtRule { params, name, body } = *u;
|
2020-06-18 16:56:03 -04:00
|
|
|
if should_emit_newline {
|
|
|
|
should_emit_newline = false;
|
|
|
|
writeln!(buf)?;
|
|
|
|
}
|
|
|
|
|
2020-06-16 19:38:30 -04:00
|
|
|
if params.is_empty() {
|
|
|
|
write!(buf, "{}@{}", padding, name)?;
|
|
|
|
} else {
|
|
|
|
write!(buf, "{}@{} {}", padding, name, params)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
if body.is_empty() {
|
|
|
|
writeln!(buf, ";")?;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
writeln!(buf, " {{")?;
|
|
|
|
}
|
|
|
|
|
2020-07-16 00:02:42 -04:00
|
|
|
Css::from_stmts(body, true, self.allows_charset)?._inner_pretty_print(
|
|
|
|
buf,
|
|
|
|
map,
|
|
|
|
nesting + 1,
|
|
|
|
)?;
|
2020-06-16 19:38:30 -04:00
|
|
|
writeln!(buf, "{}}}", padding)?;
|
|
|
|
}
|
2020-07-04 20:50:53 -04:00
|
|
|
Toplevel::Keyframes(k) => {
|
2020-07-29 07:18:47 -04:00
|
|
|
let Keyframes { rule, name, body } = *k;
|
2020-07-04 20:50:53 -04:00
|
|
|
if should_emit_newline {
|
|
|
|
should_emit_newline = false;
|
|
|
|
writeln!(buf)?;
|
|
|
|
}
|
|
|
|
|
2020-07-29 07:18:47 -04:00
|
|
|
write!(buf, "{}@{}", padding, rule)?;
|
2020-07-04 20:50:53 -04:00
|
|
|
|
|
|
|
if !name.is_empty() {
|
|
|
|
write!(buf, " {}", name)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
if body.is_empty() {
|
|
|
|
writeln!(buf, " {{}}")?;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
writeln!(buf, " {{")?;
|
|
|
|
}
|
|
|
|
|
2020-07-16 00:02:42 -04:00
|
|
|
Css::from_stmts(body, true, self.allows_charset)?._inner_pretty_print(
|
|
|
|
buf,
|
|
|
|
map,
|
|
|
|
nesting + 1,
|
|
|
|
)?;
|
2020-07-04 20:50:53 -04:00
|
|
|
writeln!(buf, "{}}}", padding)?;
|
|
|
|
}
|
2020-06-20 15:52:53 -04:00
|
|
|
Toplevel::Supports { params, body } => {
|
|
|
|
if should_emit_newline {
|
|
|
|
should_emit_newline = false;
|
|
|
|
writeln!(buf)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
if params.is_empty() {
|
|
|
|
write!(buf, "{}@supports", padding)?;
|
|
|
|
} else {
|
|
|
|
write!(buf, "{}@supports {}", padding, params)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
if body.is_empty() {
|
|
|
|
writeln!(buf, ";")?;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
writeln!(buf, " {{")?;
|
|
|
|
}
|
|
|
|
|
2020-07-16 00:02:42 -04:00
|
|
|
Css::from_stmts(body, true, self.allows_charset)?._inner_pretty_print(
|
|
|
|
buf,
|
|
|
|
map,
|
|
|
|
nesting + 1,
|
|
|
|
)?;
|
2020-06-20 15:52:53 -04:00
|
|
|
writeln!(buf, "{}}}", padding)?;
|
|
|
|
}
|
2020-06-24 11:39:32 -04:00
|
|
|
Toplevel::Media { query, body } => {
|
2020-06-16 19:38:30 -04:00
|
|
|
if body.is_empty() {
|
|
|
|
continue;
|
2020-02-22 11:59:16 -05:00
|
|
|
}
|
2020-07-04 22:46:28 -04:00
|
|
|
|
2020-06-24 11:39:32 -04:00
|
|
|
writeln!(buf, "{}@media {} {{", padding, query)?;
|
2020-07-16 00:02:42 -04:00
|
|
|
Css::from_stmts(body, true, self.allows_charset)?._inner_pretty_print(
|
|
|
|
buf,
|
|
|
|
map,
|
|
|
|
nesting + 1,
|
|
|
|
)?;
|
2020-06-16 19:38:30 -04:00
|
|
|
writeln!(buf, "{}}}", padding)?;
|
2020-04-24 22:57:39 -04:00
|
|
|
}
|
2020-04-12 21:47:32 -04:00
|
|
|
Toplevel::Style(s) => {
|
|
|
|
writeln!(buf, "{}{}", padding, s.to_string()?)?;
|
|
|
|
}
|
2020-02-01 19:25:44 -05:00
|
|
|
Toplevel::Newline => {
|
|
|
|
if has_written {
|
2020-06-18 16:56:03 -04:00
|
|
|
should_emit_newline = true;
|
2020-02-01 19:25:44 -05:00
|
|
|
}
|
2020-06-18 16:56:03 -04:00
|
|
|
continue;
|
2020-01-29 21:25:07 -05:00
|
|
|
}
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-01-05 12:52:50 -05:00
|
|
|
}
|