2020-01-05 12:52:50 -05:00
|
|
|
//! # Convert from SCSS AST to CSS
|
|
|
|
use crate::{RuleSet, Selector, Stmt, Style, StyleSheet};
|
2020-01-08 20:39:05 -05:00
|
|
|
use std::fmt;
|
2020-01-18 18:36:00 -05:00
|
|
|
use std::io::{self, Write};
|
2020-01-05 12:45:51 -05:00
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
2020-01-08 20:39:05 -05:00
|
|
|
pub enum Toplevel {
|
|
|
|
RuleSet(Selector, Vec<BlockEntry>),
|
|
|
|
MultilineComment(String),
|
|
|
|
// AtRule(AtRule),
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
|
2020-01-08 20:39:05 -05:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum BlockEntry {
|
|
|
|
Style(Style),
|
|
|
|
MultilineComment(String),
|
|
|
|
// AtRule(AtRule),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for BlockEntry {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
BlockEntry::Style(s) => writeln!(f, " {}", s),
|
|
|
|
BlockEntry::MultilineComment(s) => writeln!(f, " /*{}*/", s),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Toplevel {
|
|
|
|
const fn new_rule(selector: Selector) -> Self {
|
|
|
|
Toplevel::RuleSet(selector, Vec::new())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn push_style(&mut self, s: Style) {
|
|
|
|
if let Toplevel::RuleSet(_, entries) = self {
|
|
|
|
entries.push(BlockEntry::Style(s));
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-08 20:39:05 -05:00
|
|
|
fn push_comment(&mut self, s: String) {
|
|
|
|
if let Toplevel::RuleSet(_, entries) = self {
|
|
|
|
entries.push(BlockEntry::MultilineComment(s));
|
|
|
|
}
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct Css {
|
2020-01-08 20:39:05 -05:00
|
|
|
blocks: Vec<Toplevel>,
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Css {
|
2020-01-05 12:52:50 -05:00
|
|
|
pub const fn new() -> Self {
|
2020-01-19 19:27:52 -05:00
|
|
|
Css { blocks: Vec::new() }
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn from_stylesheet(s: StyleSheet) -> Self {
|
2020-01-08 20:39:05 -05:00
|
|
|
Css::new().parse_stylesheet(s)
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
|
2020-01-19 19:27:52 -05:00
|
|
|
fn parse_stmt(&mut self, stmt: Stmt) -> Vec<Toplevel> {
|
2020-01-05 12:45:51 -05:00
|
|
|
match stmt {
|
|
|
|
Stmt::RuleSet(RuleSet {
|
|
|
|
selector,
|
|
|
|
super_selector,
|
|
|
|
rules,
|
|
|
|
}) => {
|
2020-01-19 19:27:52 -05:00
|
|
|
let mut vals = vec![Toplevel::new_rule(super_selector.zip(&selector))];
|
|
|
|
for rule in rules {
|
|
|
|
match rule {
|
|
|
|
Stmt::RuleSet(_) => vals.extend(self.parse_stmt(rule)),
|
|
|
|
Stmt::Style(s) => vals
|
|
|
|
.get_mut(0)
|
|
|
|
.expect("expected block to exist")
|
|
|
|
.push_style(s),
|
|
|
|
Stmt::MultilineComment(s) => vals
|
|
|
|
.get_mut(0)
|
|
|
|
.expect("expected block to exist")
|
|
|
|
.push_comment(s),
|
|
|
|
};
|
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-01-19 19:27:52 -05:00
|
|
|
Stmt::MultilineComment(s) => vec![Toplevel::MultilineComment(s)],
|
|
|
|
Stmt::Style(_) => panic!("expected toplevel element, found style"),
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_stylesheet(mut self, s: StyleSheet) -> Css {
|
2020-01-18 14:57:56 -05:00
|
|
|
for stmt in s.0 {
|
2020-01-19 19:27:52 -05:00
|
|
|
let v = self.parse_stmt(stmt);
|
|
|
|
self.blocks.extend(v);
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2020-01-18 18:36:00 -05:00
|
|
|
pub fn pretty_print<W: Write>(self, buf: &mut W) -> io::Result<()> {
|
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;
|
|
|
|
}
|
|
|
|
writeln!(buf, "{} {{", selector)?;
|
|
|
|
for style in styles {
|
|
|
|
write!(buf, "{}", style)?;
|
|
|
|
}
|
|
|
|
writeln!(buf, "}}")?;
|
|
|
|
}
|
|
|
|
Toplevel::MultilineComment(s) => {
|
|
|
|
writeln!(buf, "/*{}*/", s)?;
|
|
|
|
}
|
2020-01-05 12:45:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-01-05 12:52:50 -05:00
|
|
|
}
|