added comma separated imports
This commit is contained in:
parent
741f560e90
commit
be4d02490c
@ -1,9 +1,15 @@
|
|||||||
use std::{ffi::OsStr, fs, path::Path, path::PathBuf};
|
use std::{ffi::OsStr, fs, path::Path, path::PathBuf};
|
||||||
|
|
||||||
use codemap::Spanned;
|
use codemap::{Span, Spanned};
|
||||||
use peekmore::PeekMore;
|
use peekmore::PeekMore;
|
||||||
|
|
||||||
use crate::{common::QuoteKind, error::SassResult, lexer::Lexer, value::Value, Token};
|
use crate::{
|
||||||
|
common::{ListSeparator::Comma, QuoteKind},
|
||||||
|
error::SassResult,
|
||||||
|
lexer::Lexer,
|
||||||
|
value::Value,
|
||||||
|
Token,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{Parser, Stmt};
|
use super::{Parser, Stmt};
|
||||||
|
|
||||||
@ -58,41 +64,7 @@ fn find_import(file_path: &PathBuf, name: &OsStr, load_paths: &[&Path]) -> Optio
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
pub(super) fn import(&mut self) -> SassResult<Vec<Stmt>> {
|
pub fn _parse_single_import(&mut self, file_name: &str, span: Span) -> SassResult<Vec<Stmt>> {
|
||||||
self.whitespace();
|
|
||||||
|
|
||||||
match self.toks.peek() {
|
|
||||||
Some(Token { kind: '\'', .. })
|
|
||||||
| Some(Token { kind: '"', .. })
|
|
||||||
| Some(Token { kind: 'u', .. }) => {}
|
|
||||||
Some(Token { pos, .. }) => return Err(("Expected string.", *pos).into()),
|
|
||||||
None => return Err(("expected more input.", self.span_before).into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let Spanned {
|
|
||||||
node: file_name_as_value,
|
|
||||||
span,
|
|
||||||
} = self.parse_value(true)?;
|
|
||||||
let file_name = match file_name_as_value {
|
|
||||||
Value::String(s, QuoteKind::Quoted) => {
|
|
||||||
if s.ends_with(".css") || s.starts_with("http://") || s.starts_with("https://") {
|
|
||||||
return Ok(vec![Stmt::Import(format!("\"{}\"", s))]);
|
|
||||||
} else {
|
|
||||||
s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Value::String(s, QuoteKind::None) => {
|
|
||||||
if s.starts_with("url(") {
|
|
||||||
return Ok(vec![Stmt::Import(s)]);
|
|
||||||
} else {
|
|
||||||
s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => return Err(("Expected string.", span).into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.whitespace();
|
|
||||||
|
|
||||||
let path: &Path = file_name.as_ref();
|
let path: &Path = file_name.as_ref();
|
||||||
|
|
||||||
let path_buf = if path.is_absolute() {
|
let path_buf = if path.is_absolute() {
|
||||||
@ -104,7 +76,6 @@ impl<'a> Parser<'a> {
|
|||||||
.unwrap_or_else(|| Path::new(""))
|
.unwrap_or_else(|| Path::new(""))
|
||||||
.join(path)
|
.join(path)
|
||||||
};
|
};
|
||||||
|
|
||||||
let name = path_buf.file_name().unwrap_or_else(|| OsStr::new(".."));
|
let name = path_buf.file_name().unwrap_or_else(|| OsStr::new(".."));
|
||||||
|
|
||||||
if let Some(name) = find_import(&path_buf, name, &self.options.load_paths) {
|
if let Some(name) = find_import(&path_buf, name, &self.options.load_paths) {
|
||||||
@ -112,7 +83,6 @@ impl<'a> Parser<'a> {
|
|||||||
name.to_string_lossy().into(),
|
name.to_string_lossy().into(),
|
||||||
String::from_utf8(fs::read(&name)?)?,
|
String::from_utf8(fs::read(&name)?)?,
|
||||||
);
|
);
|
||||||
|
|
||||||
return Parser {
|
return Parser {
|
||||||
toks: &mut Lexer::new(&file)
|
toks: &mut Lexer::new(&file)
|
||||||
.collect::<Vec<Token>>()
|
.collect::<Vec<Token>>()
|
||||||
@ -134,7 +104,67 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
.parse();
|
.parse();
|
||||||
}
|
}
|
||||||
|
self.whitespace();
|
||||||
|
|
||||||
Err(("Can't find stylesheet to import.", span).into())
|
Err(("Can't find stylesheet to import.", span).into())
|
||||||
}
|
}
|
||||||
|
pub(super) fn import(&mut self) -> SassResult<Vec<Stmt>> {
|
||||||
|
self.whitespace();
|
||||||
|
match self.toks.peek() {
|
||||||
|
Some(Token { kind: '\'', .. })
|
||||||
|
| Some(Token { kind: '"', .. })
|
||||||
|
| Some(Token { kind: 'u', .. }) => {}
|
||||||
|
Some(Token { pos, .. }) => return Err(("Expected string.", *pos).into()),
|
||||||
|
None => return Err(("expected more input.", self.span_before).into()),
|
||||||
|
};
|
||||||
|
let Spanned {
|
||||||
|
node: file_name_as_value,
|
||||||
|
span,
|
||||||
|
} = self.parse_value(true)?;
|
||||||
|
|
||||||
|
match file_name_as_value {
|
||||||
|
Value::String(s, QuoteKind::Quoted) => {
|
||||||
|
if s.ends_with(".css") || s.starts_with("http://") || s.starts_with("https://") {
|
||||||
|
Ok(vec![Stmt::Import(format!("\"{}\"", s))])
|
||||||
|
} else {
|
||||||
|
self._parse_single_import(&s, span)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::String(s, QuoteKind::None) => {
|
||||||
|
if s.starts_with("url(") {
|
||||||
|
Ok(vec![Stmt::Import(s)])
|
||||||
|
} else {
|
||||||
|
self._parse_single_import(&s, span)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::List(v, Comma, _) => {
|
||||||
|
let mut list_of_imports: Vec<Stmt> = Vec::new();
|
||||||
|
for file_name_element in v {
|
||||||
|
match file_name_element {
|
||||||
|
Value::String(s, QuoteKind::Quoted) => {
|
||||||
|
if s.ends_with(".css")
|
||||||
|
|| s.starts_with("http://")
|
||||||
|
|| s.starts_with("https://")
|
||||||
|
{
|
||||||
|
list_of_imports.push(Stmt::Import(format!("\"{}\"", s)));
|
||||||
|
} else {
|
||||||
|
list_of_imports.append(&mut self._parse_single_import(&s, span)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::String(s, QuoteKind::None) => {
|
||||||
|
if s.starts_with("url(") {
|
||||||
|
list_of_imports.push(Stmt::Import(s));
|
||||||
|
} else {
|
||||||
|
list_of_imports.append(&mut self._parse_single_import(&s, span)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Err(("Expected string.", span).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(list_of_imports)
|
||||||
|
}
|
||||||
|
_ => Err(("Expected string.", span).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,28 @@ fn single_quotes_import() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn comma_seperated_import() {
|
||||||
|
let input = "@import 'firsta', 'seconda';\na {\n color: $a;\n}";
|
||||||
|
tempfile!("firsta", "$a: red;");
|
||||||
|
tempfile!("seconda", "p { color: blue; }");
|
||||||
|
assert_eq!(
|
||||||
|
"p {\n color: blue;\n}\n\na {\n color: red;\n}\n",
|
||||||
|
&grass::from_string(input.to_string(), &grass::Options::default()).expect(input)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn comma_seperated_import_order() {
|
||||||
|
let input = "@import 'firstb', 'secondb', url(third);";
|
||||||
|
tempfile!("firstb", "p { color: red; }");
|
||||||
|
tempfile!("secondb", "p { color: blue; }");
|
||||||
|
assert_eq!(
|
||||||
|
"p {\n color: red;\n}\n\np {\n color: blue;\n}\n@import url(third);\n",
|
||||||
|
&grass::from_string(input.to_string(), &grass::Options::default()).expect(input)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn finds_name_scss() {
|
fn finds_name_scss() {
|
||||||
let input = "@import \"finds_name_scss\";\na {\n color: $a;\n}";
|
let input = "@import \"finds_name_scss\";\na {\n color: $a;\n}";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user