2020-01-25 12:43:07 -05:00
|
|
|
use std::fmt::{self, Display};
|
2020-01-25 20:55:44 -05:00
|
|
|
use std::iter::Peekable;
|
2020-01-25 12:43:07 -05:00
|
|
|
|
2020-02-29 11:45:36 -05:00
|
|
|
use num_traits::cast::ToPrimitive;
|
|
|
|
|
|
|
|
use crate::common::{Keyword, Pos, Scope, Symbol};
|
2020-02-17 09:22:41 -05:00
|
|
|
use crate::error::SassResult;
|
2020-01-25 13:05:40 -05:00
|
|
|
use crate::function::Function;
|
|
|
|
use crate::mixin::Mixin;
|
2020-02-22 11:58:30 -05:00
|
|
|
use crate::selector::Selector;
|
2020-02-29 11:45:36 -05:00
|
|
|
use crate::units::Unit;
|
|
|
|
use crate::utils::{devour_whitespace, devour_whitespace_or_comment, parse_interpolation};
|
|
|
|
use crate::value::{Number, Value};
|
2020-02-29 16:45:00 -05:00
|
|
|
use crate::{eat_expr, Expr, RuleSet, Stmt, Token, TokenKind};
|
2020-01-25 13:05:40 -05:00
|
|
|
|
2020-01-25 13:19:32 -05:00
|
|
|
#[derive(Debug, Clone)]
|
2020-01-25 13:05:40 -05:00
|
|
|
pub(crate) enum AtRule {
|
|
|
|
Error(Pos, String),
|
|
|
|
Warn(Pos, String),
|
|
|
|
Debug(Pos, String),
|
2020-01-25 13:49:25 -05:00
|
|
|
Mixin(String, Box<Mixin>),
|
|
|
|
Function(String, Box<Function>),
|
2020-01-25 20:55:44 -05:00
|
|
|
Return(Vec<Token>),
|
2020-02-28 18:27:32 -05:00
|
|
|
Charset,
|
2020-02-22 11:58:30 -05:00
|
|
|
Unknown(UnknownAtRule),
|
2020-02-29 11:45:36 -05:00
|
|
|
For(Vec<Stmt>),
|
2020-01-26 15:27:38 -05:00
|
|
|
}
|
|
|
|
|
2020-02-22 11:58:30 -05:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub(crate) struct UnknownAtRule {
|
|
|
|
pub name: String,
|
|
|
|
pub super_selector: Selector,
|
|
|
|
pub params: String,
|
|
|
|
pub body: Vec<Stmt>,
|
2020-01-25 13:49:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl AtRule {
|
|
|
|
pub fn from_tokens<I: Iterator<Item = Token>>(
|
|
|
|
rule: &AtRuleKind,
|
|
|
|
pos: Pos,
|
|
|
|
toks: &mut Peekable<I>,
|
|
|
|
scope: &Scope,
|
2020-02-22 15:34:32 -05:00
|
|
|
super_selector: &Selector,
|
2020-02-17 09:22:41 -05:00
|
|
|
) -> SassResult<AtRule> {
|
2020-01-25 13:49:25 -05:00
|
|
|
devour_whitespace(toks);
|
2020-02-22 11:58:30 -05:00
|
|
|
Ok(match rule {
|
2020-01-25 13:49:25 -05:00
|
|
|
AtRuleKind::Error => {
|
|
|
|
let message = toks
|
|
|
|
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
|
|
|
|
.map(|x| x.kind.to_string())
|
|
|
|
.collect::<String>();
|
2020-02-22 11:58:30 -05:00
|
|
|
AtRule::Error(pos, message)
|
2020-01-25 13:49:25 -05:00
|
|
|
}
|
|
|
|
AtRuleKind::Warn => {
|
|
|
|
let message = toks
|
|
|
|
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
|
|
|
|
.map(|x| x.kind.to_string())
|
|
|
|
.collect::<String>();
|
|
|
|
devour_whitespace(toks);
|
2020-02-22 11:58:30 -05:00
|
|
|
AtRule::Warn(pos, message)
|
2020-01-25 13:49:25 -05:00
|
|
|
}
|
|
|
|
AtRuleKind::Debug => {
|
|
|
|
let message = toks
|
|
|
|
.by_ref()
|
|
|
|
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
|
|
|
|
.map(|x| x.kind.to_string())
|
|
|
|
.collect::<String>();
|
|
|
|
devour_whitespace(toks);
|
2020-02-22 11:58:30 -05:00
|
|
|
AtRule::Debug(pos, message)
|
2020-01-25 13:49:25 -05:00
|
|
|
}
|
|
|
|
AtRuleKind::Mixin => {
|
2020-02-17 09:22:41 -05:00
|
|
|
let (name, mixin) = Mixin::decl_from_tokens(toks, scope)?;
|
2020-02-22 11:58:30 -05:00
|
|
|
AtRule::Mixin(name, Box::new(mixin))
|
2020-01-25 13:49:25 -05:00
|
|
|
}
|
|
|
|
AtRuleKind::Function => {
|
2020-02-17 09:22:41 -05:00
|
|
|
let (name, func) = Function::decl_from_tokens(toks, scope)?;
|
2020-02-22 11:58:30 -05:00
|
|
|
AtRule::Function(name, Box::new(func))
|
2020-01-25 13:49:25 -05:00
|
|
|
}
|
2020-02-28 01:02:11 -05:00
|
|
|
AtRuleKind::Return => {
|
|
|
|
let mut t = Vec::new();
|
|
|
|
let mut n = 0;
|
|
|
|
while let Some(tok) = toks.peek() {
|
|
|
|
match tok.kind {
|
|
|
|
TokenKind::Symbol(Symbol::OpenCurlyBrace) => n += 1,
|
|
|
|
TokenKind::Symbol(Symbol::CloseCurlyBrace) => n -= 1,
|
|
|
|
TokenKind::Interpolation => n += 1,
|
|
|
|
TokenKind::Symbol(Symbol::SemiColon) => break,
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
if n < 0 {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
t.push(toks.next().unwrap());
|
|
|
|
}
|
|
|
|
AtRule::Return(t)
|
2020-02-28 18:32:11 -05:00
|
|
|
}
|
2020-01-25 13:49:25 -05:00
|
|
|
AtRuleKind::Use => todo!("@use not yet implemented"),
|
|
|
|
AtRuleKind::Annotation => todo!("@annotation not yet implemented"),
|
|
|
|
AtRuleKind::AtRoot => todo!("@at-root not yet implemented"),
|
2020-02-28 18:27:32 -05:00
|
|
|
AtRuleKind::Charset => {
|
2020-02-28 18:32:11 -05:00
|
|
|
toks.take_while(|t| t.kind != TokenKind::Symbol(Symbol::SemiColon))
|
|
|
|
.for_each(drop);
|
2020-02-28 18:27:32 -05:00
|
|
|
AtRule::Charset
|
2020-02-28 18:32:11 -05:00
|
|
|
}
|
2020-01-25 13:49:25 -05:00
|
|
|
AtRuleKind::Each => todo!("@each not yet implemented"),
|
|
|
|
AtRuleKind::Extend => todo!("@extend not yet implemented"),
|
|
|
|
AtRuleKind::If => todo!("@if not yet implemented"),
|
|
|
|
AtRuleKind::Else => todo!("@else not yet implemented"),
|
2020-02-29 11:45:36 -05:00
|
|
|
AtRuleKind::For => {
|
|
|
|
let mut stmts = Vec::new();
|
|
|
|
devour_whitespace_or_comment(toks);
|
|
|
|
let var = if let Some(tok) = toks.next() {
|
|
|
|
match tok.kind {
|
|
|
|
TokenKind::Variable(s) => s,
|
|
|
|
_ => return Err("expected \"$\".".into()),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return Err("expected \"$\".".into());
|
|
|
|
};
|
|
|
|
devour_whitespace_or_comment(toks);
|
|
|
|
if let Some(tok) = toks.next() {
|
|
|
|
match tok.kind {
|
2020-02-29 12:11:40 -05:00
|
|
|
TokenKind::Keyword(Keyword::From(..)) => {}
|
2020-02-29 11:45:36 -05:00
|
|
|
_ => return Err("Expected \"from\".".into()),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return Err("Expected \"from\".".into());
|
|
|
|
};
|
|
|
|
devour_whitespace_or_comment(toks);
|
|
|
|
let mut from_toks = Vec::new();
|
|
|
|
let mut through = 0;
|
|
|
|
while let Some(tok) = toks.next() {
|
|
|
|
match tok.kind {
|
2020-02-29 12:11:40 -05:00
|
|
|
TokenKind::Keyword(Keyword::Through(..)) => {
|
2020-02-29 11:45:36 -05:00
|
|
|
through = 1;
|
|
|
|
break;
|
|
|
|
}
|
2020-02-29 12:11:40 -05:00
|
|
|
TokenKind::Keyword(Keyword::To(..)) => break,
|
2020-02-29 11:45:36 -05:00
|
|
|
_ => from_toks.push(tok),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let from = match Value::from_tokens(&mut from_toks.into_iter().peekable(), scope)? {
|
|
|
|
Value::Dimension(n, _) => match n.to_integer().to_usize() {
|
|
|
|
Some(v) => v,
|
2020-02-29 11:54:12 -05:00
|
|
|
None => return Err(format!("{} is not a int.", n).into()),
|
2020-02-29 11:45:36 -05:00
|
|
|
},
|
2020-02-29 17:25:51 -05:00
|
|
|
v => return Err(format!("{} is not an integer.", v).into()),
|
2020-02-29 11:45:36 -05:00
|
|
|
};
|
|
|
|
devour_whitespace_or_comment(toks);
|
|
|
|
let mut to_toks = Vec::new();
|
|
|
|
while let Some(tok) = toks.next() {
|
|
|
|
match tok.kind {
|
|
|
|
TokenKind::Symbol(Symbol::OpenCurlyBrace) => break,
|
|
|
|
_ => to_toks.push(tok),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let to = match Value::from_tokens(&mut to_toks.into_iter().peekable(), scope)? {
|
|
|
|
Value::Dimension(n, _) => match n.to_integer().to_usize() {
|
|
|
|
Some(v) => v,
|
2020-02-29 11:54:12 -05:00
|
|
|
None => return Err(format!("{} is not a int.", n).into()),
|
2020-02-29 11:45:36 -05:00
|
|
|
},
|
2020-02-29 17:25:51 -05:00
|
|
|
v => return Err(format!("{} is not an integer.", v).into()),
|
2020-02-29 11:45:36 -05:00
|
|
|
};
|
|
|
|
let mut body = Vec::new();
|
|
|
|
let mut n = 1;
|
2020-02-29 15:28:48 -05:00
|
|
|
while let Some(tok) = toks.next() {
|
2020-02-29 11:45:36 -05:00
|
|
|
match tok.kind {
|
|
|
|
TokenKind::Symbol(Symbol::OpenCurlyBrace) => n += 1,
|
|
|
|
TokenKind::Symbol(Symbol::CloseCurlyBrace) => n -= 1,
|
|
|
|
TokenKind::Interpolation => n += 1,
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
if n == 0 {
|
|
|
|
break;
|
|
|
|
}
|
2020-02-29 15:28:48 -05:00
|
|
|
body.push(tok);
|
2020-02-29 11:45:36 -05:00
|
|
|
}
|
|
|
|
|
2020-02-29 15:28:48 -05:00
|
|
|
devour_whitespace_or_comment(toks);
|
|
|
|
|
2020-02-29 11:45:36 -05:00
|
|
|
let mut scope = scope.clone();
|
|
|
|
if from < to {
|
|
|
|
for i in from..(to + through) {
|
2020-02-29 20:09:41 -05:00
|
|
|
scope.insert_var(&var, Value::Dimension(Number::from(i), Unit::None))?;
|
2020-02-29 11:45:36 -05:00
|
|
|
stmts.extend(eat_unknown_atrule_body(
|
|
|
|
&mut body.clone().into_iter().peekable(),
|
|
|
|
&scope,
|
|
|
|
super_selector,
|
|
|
|
)?);
|
|
|
|
}
|
|
|
|
} else if from > to {
|
|
|
|
for i in ((to - through)..(from + 1)).skip(1).rev() {
|
2020-02-29 20:09:41 -05:00
|
|
|
scope.insert_var(&var, Value::Dimension(Number::from(i), Unit::None))?;
|
2020-02-29 11:45:36 -05:00
|
|
|
stmts.extend(eat_unknown_atrule_body(
|
|
|
|
&mut body.clone().into_iter().peekable(),
|
|
|
|
&scope,
|
|
|
|
super_selector,
|
|
|
|
)?);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AtRule::For(stmts)
|
|
|
|
}
|
2020-01-25 13:49:25 -05:00
|
|
|
AtRuleKind::While => todo!("@while not yet implemented"),
|
|
|
|
AtRuleKind::Keyframes => todo!("@keyframes not yet implemented"),
|
2020-02-22 11:58:30 -05:00
|
|
|
AtRuleKind::Unknown(name) => {
|
|
|
|
let mut params = String::new();
|
|
|
|
while let Some(tok) = toks.next() {
|
|
|
|
match tok.kind {
|
|
|
|
TokenKind::Symbol(Symbol::OpenCurlyBrace) => break,
|
|
|
|
TokenKind::Interpolation => {
|
|
|
|
params.push_str(
|
|
|
|
&parse_interpolation(toks, scope)?
|
|
|
|
.into_iter()
|
|
|
|
.map(|x| x.kind.to_string())
|
|
|
|
.collect::<String>(),
|
|
|
|
);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TokenKind::Variable(..) => params.push('$'),
|
2020-02-22 12:56:23 -05:00
|
|
|
TokenKind::Whitespace(..) => {
|
|
|
|
devour_whitespace(toks);
|
|
|
|
params.push(' ');
|
|
|
|
continue;
|
|
|
|
}
|
2020-02-22 11:58:30 -05:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
params.push_str(&tok.kind.to_string());
|
|
|
|
}
|
|
|
|
|
2020-02-22 15:34:32 -05:00
|
|
|
let raw_body = eat_unknown_atrule_body(toks, scope, super_selector)?;
|
|
|
|
let mut body = Vec::with_capacity(raw_body.len());
|
|
|
|
body.push(Stmt::RuleSet(RuleSet::new()));
|
|
|
|
let mut rules = Vec::new();
|
|
|
|
for stmt in raw_body {
|
|
|
|
match stmt {
|
|
|
|
s @ Stmt::Style(..) => rules.push(s),
|
|
|
|
s => body.push(s),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
body[0] = Stmt::RuleSet(RuleSet {
|
|
|
|
selector: super_selector.clone(),
|
|
|
|
rules,
|
|
|
|
super_selector: Selector::new(),
|
|
|
|
});
|
2020-02-22 11:58:30 -05:00
|
|
|
|
|
|
|
let u = UnknownAtRule {
|
|
|
|
name: name.clone(),
|
|
|
|
super_selector: Selector::new(),
|
2020-02-22 12:53:58 -05:00
|
|
|
params: params.trim().to_owned(),
|
2020-02-22 11:58:30 -05:00
|
|
|
body,
|
|
|
|
};
|
|
|
|
|
|
|
|
AtRule::Unknown(u)
|
|
|
|
}
|
2020-01-25 13:49:25 -05:00
|
|
|
_ => todo!("encountered unimplemented at rule"),
|
2020-02-22 11:58:30 -05:00
|
|
|
})
|
2020-01-25 13:49:25 -05:00
|
|
|
}
|
2020-01-25 13:05:40 -05:00
|
|
|
}
|
|
|
|
|
2020-02-22 11:58:30 -05:00
|
|
|
fn eat_unknown_atrule_body<I: Iterator<Item = Token>>(
|
|
|
|
toks: &mut Peekable<I>,
|
|
|
|
scope: &Scope,
|
|
|
|
super_selector: &Selector,
|
|
|
|
) -> SassResult<Vec<Stmt>> {
|
|
|
|
let mut stmts = Vec::new();
|
2020-02-29 14:16:26 -05:00
|
|
|
let mut scope = scope.clone();
|
|
|
|
while let Some(expr) = eat_expr(toks, &scope, super_selector)? {
|
2020-02-22 11:58:30 -05:00
|
|
|
match expr {
|
2020-02-22 15:34:32 -05:00
|
|
|
Expr::AtRule(a) => stmts.push(Stmt::AtRule(a)),
|
2020-02-29 16:13:57 -05:00
|
|
|
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
|
|
|
Expr::Styles(s) => stmts.extend(s.into_iter().map(Box::new).map(Stmt::Style)),
|
2020-02-22 11:58:30 -05:00
|
|
|
Expr::Include(s) => stmts.extend(s),
|
|
|
|
Expr::MixinDecl(..) | Expr::FunctionDecl(..) | Expr::Debug(..) | Expr::Warn(..) => {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
Expr::Selector(selector) => {
|
2020-02-29 14:16:26 -05:00
|
|
|
let rules = eat_unknown_atrule_body(toks, &scope, &super_selector.zip(&selector))?;
|
2020-02-22 11:58:30 -05:00
|
|
|
stmts.push(Stmt::RuleSet(RuleSet {
|
|
|
|
super_selector: super_selector.clone(),
|
|
|
|
selector,
|
|
|
|
rules,
|
|
|
|
}));
|
|
|
|
}
|
2020-02-29 14:16:26 -05:00
|
|
|
Expr::VariableDecl(name, val) => {
|
2020-02-29 20:09:41 -05:00
|
|
|
scope.insert_var(&name, *val)?;
|
2020-02-22 11:58:30 -05:00
|
|
|
}
|
|
|
|
Expr::MultilineComment(s) => stmts.push(Stmt::MultilineComment(s)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(stmts)
|
|
|
|
}
|
2020-01-29 20:01:41 -05:00
|
|
|
|
2020-01-25 12:43:07 -05:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
|
|
pub enum AtRuleKind {
|
|
|
|
// SASS specific @rules
|
2020-02-09 19:44:45 -05:00
|
|
|
/// Loads mixins, functions, and variables from other Sass
|
|
|
|
/// stylesheets, and combines CSS from multiple stylesheets together
|
2020-01-25 12:43:07 -05:00
|
|
|
Use,
|
2020-02-09 19:44:45 -05:00
|
|
|
/// Loads a Sass stylesheet and makes its mixins, functions,
|
|
|
|
/// and variables available when your stylesheet is loaded
|
|
|
|
/// with the `@use` rule
|
2020-01-25 12:43:07 -05:00
|
|
|
Forward,
|
2020-02-09 19:44:45 -05:00
|
|
|
/// Extends the CSS at-rule to load styles, mixins, functions,
|
|
|
|
/// and variables from other stylesheets
|
2020-01-25 12:43:07 -05:00
|
|
|
Import,
|
|
|
|
Mixin,
|
|
|
|
Include,
|
2020-02-09 19:44:45 -05:00
|
|
|
/// Defines custom functions that can be used in SassScript
|
|
|
|
/// expressions
|
2020-01-25 12:43:07 -05:00
|
|
|
Function,
|
2020-01-25 13:49:25 -05:00
|
|
|
Return,
|
2020-01-25 12:43:07 -05:00
|
|
|
/// Allows selectors to inherit styles from one another
|
|
|
|
Extend,
|
|
|
|
/// Puts styles within it at the root of the CSS document
|
|
|
|
AtRoot,
|
|
|
|
/// Causes compilation to fail with an error message
|
|
|
|
Error,
|
|
|
|
/// Prints a warning without stopping compilation entirely
|
|
|
|
Warn,
|
|
|
|
/// Prints a message for debugging purposes
|
|
|
|
Debug,
|
|
|
|
If,
|
|
|
|
Else,
|
|
|
|
Each,
|
|
|
|
For,
|
|
|
|
While,
|
|
|
|
|
|
|
|
// CSS @rules
|
|
|
|
/// Defines the character set used by the style sheet
|
|
|
|
Charset,
|
2020-02-09 19:44:45 -05:00
|
|
|
/// Tells the CSS engine that all its content must be considered
|
|
|
|
/// prefixed with an XML namespace
|
2020-01-25 12:43:07 -05:00
|
|
|
Namespace,
|
2020-02-09 19:44:45 -05:00
|
|
|
/// A conditional group rule that will apply its content if the
|
|
|
|
/// browser meets the criteria of the given condition
|
2020-01-25 12:43:07 -05:00
|
|
|
Supports,
|
2020-02-09 19:44:45 -05:00
|
|
|
/// Describes the aspect of layout changes that will be
|
|
|
|
/// applied when printing the document
|
2020-01-25 12:43:07 -05:00
|
|
|
Page,
|
|
|
|
/// Describes the aspect of an external font to be downloaded
|
|
|
|
FontFace,
|
|
|
|
/// Describes the aspect of intermediate steps in a CSS animation sequence
|
|
|
|
Keyframes,
|
|
|
|
|
|
|
|
// @rules related to @font-feature-values
|
|
|
|
FontFeatureValues,
|
|
|
|
Swash,
|
|
|
|
Ornaments,
|
|
|
|
Annotation,
|
|
|
|
Stylistic,
|
|
|
|
Styleset,
|
|
|
|
CharacterVariant,
|
|
|
|
|
|
|
|
// Experimental CSS @rules
|
|
|
|
/// Describes the aspects of the viewport for small screen devices
|
|
|
|
///
|
|
|
|
/// Currently at the Working Draft stage
|
|
|
|
Viewport,
|
2020-02-09 19:44:45 -05:00
|
|
|
/// A conditional group rule that will apply its content if the document in
|
|
|
|
/// which the style sheet is applied meets the criteria of the given condition
|
2020-01-25 12:43:07 -05:00
|
|
|
///
|
|
|
|
/// Deferred to Level 4 of CSS Spec
|
|
|
|
Document,
|
|
|
|
/// Defines specific counter styles that are not part of the predefined set of styles
|
|
|
|
///
|
|
|
|
/// At the Candidate Recommendation stage
|
|
|
|
CounterStyle,
|
|
|
|
|
2020-02-09 19:44:45 -05:00
|
|
|
/// An unknown at rule.
|
2020-02-22 11:58:30 -05:00
|
|
|
/// For forward compatibility, they are parsed the same as @media
|
2020-02-09 19:44:45 -05:00
|
|
|
Unknown(String),
|
|
|
|
}
|
2020-01-25 12:43:07 -05:00
|
|
|
|
2020-02-09 19:44:45 -05:00
|
|
|
impl From<&str> for AtRuleKind {
|
|
|
|
fn from(c: &str) -> Self {
|
|
|
|
match c.to_ascii_lowercase().as_str() {
|
|
|
|
"use" => Self::Use,
|
|
|
|
"forward" => Self::Forward,
|
|
|
|
"import" => Self::Import,
|
|
|
|
"mixin" => Self::Mixin,
|
|
|
|
"include" => Self::Include,
|
|
|
|
"function" => Self::Function,
|
|
|
|
"return" => Self::Return,
|
|
|
|
"extend" => Self::Extend,
|
|
|
|
"at-root" => Self::AtRoot,
|
|
|
|
"error" => Self::Error,
|
|
|
|
"warn" => Self::Warn,
|
|
|
|
"debug" => Self::Debug,
|
|
|
|
"if" => Self::If,
|
|
|
|
"else" => Self::Else,
|
|
|
|
"each" => Self::Each,
|
|
|
|
"for" => Self::For,
|
|
|
|
"while" => Self::While,
|
|
|
|
"charset" => Self::Charset,
|
|
|
|
"namespace" => Self::Namespace,
|
|
|
|
"supports" => Self::Supports,
|
|
|
|
"page" => Self::Page,
|
|
|
|
"fontface" => Self::FontFace,
|
|
|
|
"keyframes" => Self::Keyframes,
|
|
|
|
"fontfeaturevalues" => Self::FontFeatureValues,
|
|
|
|
"swash" => Self::Swash,
|
|
|
|
"ornaments" => Self::Ornaments,
|
|
|
|
"annotation" => Self::Annotation,
|
|
|
|
"stylistic" => Self::Stylistic,
|
|
|
|
"styleset" => Self::Styleset,
|
|
|
|
"charactervariant" => Self::CharacterVariant,
|
|
|
|
"viewport" => Self::Viewport,
|
|
|
|
"document" => Self::Document,
|
|
|
|
"counterstyle" => Self::CounterStyle,
|
|
|
|
s => Self::Unknown(s.to_owned()),
|
2020-01-25 12:43:07 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for AtRuleKind {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
Self::Use => write!(f, "@use"),
|
|
|
|
Self::Forward => write!(f, "@forward"),
|
|
|
|
Self::Import => write!(f, "@import"),
|
|
|
|
Self::Mixin => write!(f, "@mixin"),
|
|
|
|
Self::Include => write!(f, "@include"),
|
|
|
|
Self::Function => write!(f, "@function"),
|
2020-01-25 13:49:25 -05:00
|
|
|
Self::Return => write!(f, "@return"),
|
2020-01-25 12:43:07 -05:00
|
|
|
Self::Extend => write!(f, "@extend"),
|
2020-01-26 10:53:26 -05:00
|
|
|
Self::AtRoot => write!(f, "@at-root"),
|
2020-01-25 12:43:07 -05:00
|
|
|
Self::Error => write!(f, "@error"),
|
|
|
|
Self::Warn => write!(f, "@warn"),
|
|
|
|
Self::Debug => write!(f, "@debug"),
|
|
|
|
Self::If => write!(f, "@if"),
|
|
|
|
Self::Else => write!(f, "@else"),
|
|
|
|
Self::Each => write!(f, "@each"),
|
|
|
|
Self::For => write!(f, "@for"),
|
|
|
|
Self::While => write!(f, "@while"),
|
|
|
|
Self::Charset => write!(f, "@charset"),
|
|
|
|
Self::Namespace => write!(f, "@namespace"),
|
|
|
|
Self::Supports => write!(f, "@supports"),
|
|
|
|
Self::Page => write!(f, "@page"),
|
|
|
|
Self::FontFace => write!(f, "@fontface"),
|
|
|
|
Self::Keyframes => write!(f, "@keyframes"),
|
|
|
|
Self::FontFeatureValues => write!(f, "@fontfeaturevalues"),
|
|
|
|
Self::Swash => write!(f, "@swash"),
|
|
|
|
Self::Ornaments => write!(f, "@ornaments"),
|
|
|
|
Self::Annotation => write!(f, "@annotation"),
|
|
|
|
Self::Stylistic => write!(f, "@stylistic"),
|
|
|
|
Self::Styleset => write!(f, "@styleset"),
|
|
|
|
Self::CharacterVariant => write!(f, "@charactervariant"),
|
|
|
|
Self::Viewport => write!(f, "@viewport"),
|
|
|
|
Self::Document => write!(f, "@document"),
|
|
|
|
Self::CounterStyle => write!(f, "@counterstyle"),
|
2020-02-09 19:44:45 -05:00
|
|
|
Self::Unknown(s) => write!(f, "@{}", s),
|
2020-01-25 12:43:07 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|