feat(css/modules): Implement css modules (#6000)

This commit is contained in:
Donny/강동윤 2022-10-05 14:48:28 +09:00 committed by GitHub
parent 37286e369e
commit 2cce1c82b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
568 changed files with 7819 additions and 32 deletions

View File

@ -275,6 +275,9 @@ jobs:
- crate: swc_css_minifier
os: ubuntu-latest
runner: ubuntu-latest
- crate: swc_css_modules
os: ubuntu-latest
runner: ubuntu-latest
- crate: swc_css_parser
os: ubuntu-latest
runner: ubuntu-latest

18
Cargo.lock generated
View File

@ -3197,6 +3197,7 @@ dependencies = [
"swc_css_ast",
"swc_css_codegen",
"swc_css_minifier",
"swc_css_modules",
"swc_css_parser",
"swc_css_utils",
"swc_css_visit",
@ -3280,6 +3281,23 @@ dependencies = [
"testing",
]
[[package]]
name = "swc_css_modules"
version = "0.1.0"
dependencies = [
"rustc-hash",
"serde",
"serde_json",
"swc_atoms",
"swc_common",
"swc_css_ast",
"swc_css_codegen",
"swc_css_parser",
"swc_css_visit",
"swc_ecma_loader",
"testing",
]
[[package]]
name = "swc_css_parser"
version = "0.123.5"

View File

@ -1,27 +1,29 @@
[package]
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
description = "CSS apis for rust"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
description = "CSS apis for rust"
documentation = "https://rustdoc.swc.rs/swc_css/"
edition = "2021"
license = "Apache-2.0"
name = "swc_css"
repository = "https://github.com/swc-project/swc.git"
version = "0.127.6"
edition = "2021"
license = "Apache-2.0"
name = "swc_css"
repository = "https://github.com/swc-project/swc.git"
version = "0.127.6"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[lib]
bench = false
[features]
minifier = ["swc_css_minifier"]
modules = ["swc_css_modules"]
[dependencies]
swc_css_ast = {version = "0.114.5", path = "../swc_css_ast"}
swc_css_codegen = {version = "0.124.5", path = "../swc_css_codegen"}
swc_css_minifier = {version = "0.89.6", path = "../swc_css_minifier", optional = true}
swc_css_parser = {version = "0.123.5", path = "../swc_css_parser"}
swc_css_utils = {version = "0.111.5", path = "../swc_css_utils/"}
swc_css_visit = {version = "0.113.5", path = "../swc_css_visit"}
swc_css_ast = { version = "0.114.5", path = "../swc_css_ast" }
swc_css_codegen = { version = "0.124.5", path = "../swc_css_codegen" }
swc_css_minifier = { version = "0.89.6", path = "../swc_css_minifier", optional = true }
swc_css_modules = { version = "0.1.0", path = "../swc_css_modules", optional = true }
swc_css_parser = { version = "0.123.5", path = "../swc_css_parser" }
swc_css_utils = { version = "0.111.5", path = "../swc_css_utils/" }
swc_css_visit = { version = "0.113.5", path = "../swc_css_visit" }

View File

@ -3,6 +3,9 @@ pub extern crate swc_css_codegen as codegen;
#[cfg(feature = "swc_css_minifier")]
#[cfg_attr(docsrs, doc(cfg(feature = "minifier")))]
pub extern crate swc_css_minifier as minifier;
#[cfg(feature = "swc_css_modules")]
#[cfg_attr(docsrs, doc(cfg(feature = "modules")))]
pub extern crate swc_css_modules as modules;
pub extern crate swc_css_parser as parser;
pub extern crate swc_css_utils as utils;
pub extern crate swc_css_visit as visit;

View File

@ -1,7 +1,7 @@
use is_macro::Is;
use string_enum::StringEnum;
use swc_atoms::JsWord;
use swc_common::{ast_node, EqIgnoreSpan, Span};
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span};
use crate::{Delimiter, Ident, ListOfComponentValues, Str, TokenAndSpan};
@ -65,6 +65,15 @@ pub struct ComplexSelector {
pub children: Vec<ComplexSelectorChildren>,
}
impl Take for ComplexSelector {
fn dummy() -> Self {
Self {
span: Take::dummy(),
children: Take::dummy(),
}
}
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum ComplexSelectorChildren {

View File

@ -6,7 +6,7 @@ use std::{
use is_macro::Is;
use string_enum::StringEnum;
use swc_atoms::JsWord;
use swc_common::{ast_node, EqIgnoreSpan, Span};
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span};
use crate::Function;
@ -26,6 +26,16 @@ impl EqIgnoreSpan for Ident {
}
}
impl Take for Ident {
fn dummy() -> Self {
Self {
span: Default::default(),
value: Default::default(),
raw: Default::default(),
}
}
}
#[ast_node("CustomIdent")]
#[derive(Eq, Hash)]
pub struct CustomIdent {

View File

@ -0,0 +1,30 @@
[package]
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
description = "CSS modules"
documentation = "https://rustdoc.swc.rs/swc_css_modules/"
edition = "2021"
include = ["Cargo.toml", "src/**/*.rs"]
license = "Apache-2.0"
name = "swc_css_modules"
repository = "https://github.com/swc-project/swc.git"
version = "0.1.0"
[lib]
bench = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rustc-hash = "1.1.0"
serde = { version = "1", features = ["derive"] }
swc_atoms = { version = "0.4.18", path = "../swc_atoms" }
swc_common = { version = "0.29.4", path = "../swc_common" }
swc_css_ast = { version = "0.114.4", path = "../swc_css_ast" }
swc_css_codegen = { version = "0.124.5", path = "../swc_css_codegen" }
swc_css_parser = { version = "0.123.5", path = "../swc_css_parser" }
swc_css_visit = { version = "0.113.4", path = "../swc_css_visit" }
swc_ecma_loader = { version = "0.41.3", path = "../swc_ecma_loader" }
[dev-dependencies]
serde_json = "1"
testing = { version = "0.31.4", path = "../testing" }

View File

@ -0,0 +1,68 @@
//! Import/export analyzer
use swc_atoms::{js_word, JsWord};
use swc_css_ast::{
ComponentValue, Declaration, DeclarationName, Ident, ImportPrelude, ImportPreludeHref,
Stylesheet, UrlValue,
};
use swc_css_visit::{Visit, VisitWith};
pub fn analyze_imports(ss: &Stylesheet) -> Vec<JsWord> {
let mut v = Analyzer {
imports: Default::default(),
};
ss.visit_with(&mut v);
v.imports.sort();
v.imports.dedup();
v.imports
}
struct Analyzer {
imports: Vec<JsWord>,
}
impl Visit for Analyzer {
fn visit_import_prelude(&mut self, n: &ImportPrelude) {
n.visit_children_with(self);
match &*n.href {
ImportPreludeHref::Url(u) => {
if let Some(s) = &u.value {
match &**s {
UrlValue::Str(s) => {
self.imports.push(s.value.clone());
}
UrlValue::Raw(v) => {
self.imports.push(v.value.clone());
}
}
}
}
ImportPreludeHref::Str(s) => {
self.imports.push(s.value.clone());
}
}
}
fn visit_declaration(&mut self, d: &Declaration) {
d.visit_children_with(self);
if let DeclarationName::Ident(name) = &d.name {
if &*name.value == "composes" {
// comoses: name from 'foo.css'
if d.value.len() >= 3 {
if let (
ComponentValue::Ident(Ident {
value: js_word!("from"),
..
}),
ComponentValue::Str(s),
) = (&d.value[d.value.len() - 2], &d.value[d.value.len() - 1])
{
self.imports.push(s.value.clone());
}
}
}
}
}
}

View File

@ -0,0 +1,437 @@
use rustc_hash::FxHashMap;
use serde::Serialize;
use swc_atoms::{js_word, JsWord};
use swc_common::util::take::Take;
use swc_css_ast::{
ComplexSelector, ComplexSelectorChildren, ComponentValue, Declaration, DeclarationName,
DeclarationOrAtRule, Delimiter, DelimiterValue, Ident, KeyframesName, QualifiedRule,
QualifiedRulePrelude, StyleBlock, Stylesheet, SubclassSelector,
};
use swc_css_parser::{parse_tokens, parser::ParserConfig};
use swc_css_visit::{VisitMut, VisitMutWith};
use util::to_tokens::to_tokens_vec;
pub mod imports;
mod util;
/// Various configurations for the css modules.
///
/// # Note
///
/// This is a trait rather than a struct because api like `fn() -> String` is
/// too restricted and `Box<Fn() -> String` is (needlessly) slow.
pub trait TransformConfig {
/// Creates a class name for the given `local_name`.
fn new_name_for(&self, local: &JsWord) -> JsWord;
// /// Used for `@value` imports.
// fn get_value(&self, import_source: &str, value_name: &JsWord) ->
// ComponentValue;
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum CssClassName {
Local {
/// Tranformed css class name
name: JsWord,
},
Global {
name: JsWord,
},
Import {
/// The exported class name. This is the value specified by the user.
name: JsWord,
/// The module specifier.
from: JsWord,
},
}
#[derive(Debug, Clone)]
pub struct TransformResult {
/// A map of js class name to css class names.
pub renamed: FxHashMap<JsWord, Vec<CssClassName>>,
}
/// Returns a map from local name to exported name.
pub fn compile(ss: &mut Stylesheet, config: impl TransformConfig) -> TransformResult {
let mut compiler = Compiler {
config,
data: Default::default(),
result: TransformResult {
renamed: Default::default(),
},
};
ss.visit_mut_with(&mut compiler);
compiler.result
}
struct Compiler<C>
where
C: TransformConfig,
{
config: C,
data: Data,
result: TransformResult,
}
#[derive(Default)]
struct Data {
/// Context for `composes`
composes_for_current: Option<Vec<CssClassName>>,
renamed_to_orig: FxHashMap<JsWord, JsWord>,
orig_to_renamed: FxHashMap<JsWord, JsWord>,
}
impl<C> VisitMut for Compiler<C>
where
C: TransformConfig,
{
fn visit_mut_qualified_rule(&mut self, n: &mut QualifiedRule) {
let old_compose_stack = self.data.composes_for_current.take();
self.data.composes_for_current = Some(Default::default());
n.visit_mut_children_with(self);
if let QualifiedRulePrelude::SelectorList(sel) = &n.prelude {
//
if sel.children.len() == 1 && sel.children[0].children.len() == 1 {
if let ComplexSelectorChildren::CompoundSelector(sel) = &sel.children[0].children[0]
{
if sel.subclass_selectors.len() == 1 {
if let SubclassSelector::Class(class_sel) = &sel.subclass_selectors[0] {
if let Some(composes) = self.data.composes_for_current.take() {
let key = self
.data
.renamed_to_orig
.get(&class_sel.text.value)
.cloned();
if let Some(key) = key {
self.result.renamed.entry(key).or_default().extend(composes);
}
}
}
}
}
}
}
self.data.composes_for_current = old_compose_stack;
}
fn visit_mut_component_values(&mut self, n: &mut Vec<ComponentValue>) {
n.visit_mut_children_with(self);
n.retain(|v| match v {
ComponentValue::StyleBlock(StyleBlock::Declaration(d))
| ComponentValue::DeclarationOrAtRule(DeclarationOrAtRule::Declaration(d)) => {
if let DeclarationName::Ident(ident) = &d.name {
if &*ident.value == "composes" {
return false;
}
}
true
}
_ => true,
});
}
/// Handles `composes`
fn visit_mut_declaration(&mut self, n: &mut Declaration) {
n.visit_mut_children_with(self);
if let Some(composes_for_current) = &mut self.data.composes_for_current {
if let DeclarationName::Ident(name) = &n.name {
if &*name.value == "composes" {
// comoses: name from 'foo.css'
if n.value.len() >= 3 {
match (&n.value[n.value.len() - 2], &n.value[n.value.len() - 1]) {
(
ComponentValue::Ident(Ident {
value: js_word!("from"),
..
}),
ComponentValue::Str(import_source),
) => {
for class_name in n.value.iter().take(n.value.len() - 2) {
if let ComponentValue::Ident(Ident { value, .. }) = class_name {
composes_for_current.push(CssClassName::Import {
name: value.clone(),
from: import_source.value.clone(),
});
}
}
return;
}
(
ComponentValue::Ident(Ident {
value: js_word!("from"),
..
}),
ComponentValue::Ident(Ident {
value: js_word!("global"),
..
}),
) => {
for class_name in n.value.iter().take(n.value.len() - 2) {
if let ComponentValue::Ident(Ident { value, .. }) = class_name {
composes_for_current.push(CssClassName::Global {
name: value.clone(),
});
}
}
return;
}
_ => (),
}
}
for class_name in n.value.iter() {
if let ComponentValue::Ident(Ident { value, .. }) = class_name {
if let Some(value) = self.data.orig_to_renamed.get(value) {
composes_for_current.push(CssClassName::Local {
name: value.clone(),
});
}
}
}
}
}
}
if let DeclarationName::Ident(name) = &n.name {
match name.value.to_ascii_lowercase() {
js_word!("animation") => {
let mut can_change = true;
for v in &mut n.value {
if can_change {
if let ComponentValue::Ident(Ident { value, raw, .. }) = v {
*raw = None;
rename(
&mut self.config,
&mut self.result,
&mut self.data.orig_to_renamed,
&mut self.data.renamed_to_orig,
value,
);
can_change = false;
}
} else if let ComponentValue::Delimiter(Delimiter {
value: DelimiterValue::Comma,
..
}) = v
{
can_change = true;
}
}
}
js_word!("animation-name") => {
for v in &mut n.value {
if let ComponentValue::Ident(Ident { value, raw, .. }) = v {
*raw = None;
rename(
&mut self.config,
&mut self.result,
&mut self.data.orig_to_renamed,
&mut self.data.renamed_to_orig,
value,
);
}
}
}
_ => {}
}
}
}
fn visit_mut_complex_selector(&mut self, n: &mut ComplexSelector) {
n.visit_mut_children_with(self);
let mut new_children = Vec::with_capacity(n.children.len());
'complex: for mut n in n.children.take() {
match &mut n {
ComplexSelectorChildren::CompoundSelector(sel) => {
//
for sel in &mut sel.subclass_selectors {
match sel {
SubclassSelector::Class(..) | SubclassSelector::Id(..) => {
process_local(
&mut self.config,
&mut self.result,
&mut self.data.orig_to_renamed,
&mut self.data.renamed_to_orig,
sel,
);
}
SubclassSelector::PseudoClass(class_sel) => {
match &*class_sel.name.value {
"local" => {
if let Some(children) = &mut class_sel.children {
let tokens = to_tokens_vec(&*children);
let mut sel: ComplexSelector = parse_tokens(
&tokens,
ParserConfig {
..Default::default()
},
&mut vec![],
)
.unwrap();
sel.visit_mut_with(self);
new_children.extend(sel.children);
continue 'complex;
}
}
"global" => {
if let Some(children) = &mut class_sel.children {
let tokens = to_tokens_vec(&*children);
let sel: ComplexSelector = parse_tokens(
&tokens,
ParserConfig {
..Default::default()
},
&mut vec![],
)
.unwrap();
new_children.extend(sel.children);
continue 'complex;
}
}
_ => {}
}
}
_ => {
sel.visit_mut_children_with(self);
}
}
}
}
ComplexSelectorChildren::Combinator(_) => {}
}
new_children.push(n);
}
n.children = new_children;
}
fn visit_mut_complex_selectors(&mut self, n: &mut Vec<ComplexSelector>) {
n.visit_mut_children_with(self);
n.retain_mut(|s| !s.children.is_empty());
}
fn visit_mut_keyframes_name(&mut self, n: &mut KeyframesName) {
n.visit_mut_children_with(self);
match n {
KeyframesName::CustomIdent(n) => {
n.raw = None;
rename(
&mut self.config,
&mut self.result,
&mut self.data.orig_to_renamed,
&mut self.data.renamed_to_orig,
&mut n.value,
)
}
KeyframesName::Str(n) => {
n.raw = None;
rename(
&mut self.config,
&mut self.result,
&mut self.data.orig_to_renamed,
&mut self.data.renamed_to_orig,
&mut n.value,
)
}
}
}
}
fn rename<C>(
config: &mut C,
result: &mut TransformResult,
orig_to_renamed: &mut FxHashMap<JsWord, JsWord>,
renamed_to_orig: &mut FxHashMap<JsWord, JsWord>,
name: &mut JsWord,
) where
C: TransformConfig,
{
if let Some(renamed) = orig_to_renamed.get(name) {
*name = renamed.clone();
return;
}
let new = config.new_name_for(name);
orig_to_renamed.insert(name.clone(), new.clone());
renamed_to_orig.insert(new.clone(), name.clone());
{
let e = result.renamed.entry(name.clone()).or_default();
let v = CssClassName::Local { name: new.clone() };
if !e.contains(&v) {
e.push(v);
}
}
*name = new;
}
fn process_local<C>(
config: &mut C,
result: &mut TransformResult,
orig_to_renamed: &mut FxHashMap<JsWord, JsWord>,
renamed_to_orig: &mut FxHashMap<JsWord, JsWord>,
sel: &mut SubclassSelector,
) where
C: TransformConfig,
{
match sel {
SubclassSelector::Id(sel) => {
sel.text.raw = None;
rename(
config,
result,
orig_to_renamed,
renamed_to_orig,
&mut sel.text.value,
);
}
SubclassSelector::Class(sel) => {
sel.text.raw = None;
rename(
config,
result,
orig_to_renamed,
renamed_to_orig,
&mut sel.text.value,
);
}
SubclassSelector::Attribute(_) => {}
SubclassSelector::PseudoClass(_) => {}
SubclassSelector::PseudoElement(_) => {}
}
}

View File

@ -0,0 +1 @@
pub mod to_tokens;

View File

@ -0,0 +1,63 @@
use swc_common::{input::StringInput, Span, Spanned};
use swc_css_ast::Tokens;
use swc_css_codegen::{
writer::basic::{BasicCssWriter, BasicCssWriterConfig, IndentType},
CodeGenerator, CodegenConfig, Emit,
};
use swc_css_parser::{lexer::Lexer, parser::ParserConfig};
pub(crate) fn to_tokens_vec<N>(n: &[N]) -> Tokens
where
N: Spanned,
for<'aa, 'ab> CodeGenerator<BasicCssWriter<'aa, &'ab mut String>>: swc_css_codegen::Emit<N>,
{
let lo = n.first().span().lo();
let hi = n.last().span().lo();
let tokens = n.iter().flat_map(|n| to_tokens(n).tokens).collect();
Tokens {
span: Span::new(lo, hi, Default::default()),
tokens,
}
}
pub(crate) fn to_tokens<N>(n: &N) -> Tokens
where
N: Spanned,
for<'aa, 'ab> CodeGenerator<BasicCssWriter<'aa, &'ab mut String>>: swc_css_codegen::Emit<N>,
{
let span = n.span();
let mut buf = String::new();
{
let wr = BasicCssWriter::new(
&mut buf,
None,
BasicCssWriterConfig {
indent_type: IndentType::Tab,
..Default::default()
},
);
let mut g = CodeGenerator::new(
wr,
CodegenConfig {
..Default::default()
},
);
g.emit(n).unwrap();
}
let lexer = Lexer::new(
StringInput::new(&buf, span.lo, span.hi),
ParserConfig {
allow_wrong_line_comments: true,
},
);
Tokens {
span,
tokens: lexer.collect(),
}
}

View File

@ -0,0 +1,95 @@
use std::path::PathBuf;
use swc_atoms::JsWord;
use swc_css_codegen::{
writer::basic::{BasicCssWriter, BasicCssWriterConfig, IndentType},
CodeGenerator, CodegenConfig, Emit,
};
use testing::NormalizedOutput;
#[testing::fixture("tests/fixture/**/*.css", exclude("compiled\\.css"))]
fn imports(input: PathBuf) {
testing::run_test(false, |cm, handler| {
let fm = cm.load_file(&input).unwrap();
let mut errors = vec![];
let ss = swc_css_parser::parse_file(&fm, Default::default(), &mut errors).unwrap();
let result = swc_css_modules::imports::analyze_imports(&ss);
if result.is_empty() {
return Ok(());
}
let s = serde_json::to_string_pretty(&result).unwrap();
NormalizedOutput::from(s)
.compare_to_file(input.with_file_name(format!(
"{}.imports.json",
input.file_stem().unwrap().to_string_lossy()
)))
.unwrap();
Ok(())
})
.unwrap();
}
#[testing::fixture("tests/fixture/**/*.css", exclude("compiled\\.css"))]
fn compile(input: PathBuf) {
testing::run_test(false, |cm, handler| {
let fm = cm.load_file(&input).unwrap();
let mut errors = vec![];
let mut ss = swc_css_parser::parse_file(&fm, Default::default(), &mut errors).unwrap();
let result = swc_css_modules::imports::analyze_imports(&ss);
let transform_result = swc_css_modules::compile(&mut ss, TestConfig {});
let mut buf = String::new();
{
let mut wr = BasicCssWriter::new(
&mut buf,
None,
BasicCssWriterConfig {
indent_type: IndentType::Space,
indent_width: 2,
..Default::default()
},
);
let mut g = CodeGenerator::new(
wr,
CodegenConfig {
..Default::default()
},
);
g.emit(&ss).unwrap();
}
NormalizedOutput::from(buf)
.compare_to_file(input.with_file_name(format!(
"{}.compiled.css",
input.file_stem().unwrap().to_string_lossy()
)))
.unwrap();
if !transform_result.renamed.is_empty() {
let transformed_classes =
serde_json::to_string_pretty(&transform_result.renamed).unwrap();
NormalizedOutput::from(transformed_classes)
.compare_to_file(input.with_file_name(format!(
"{}.transform.json",
input.file_stem().unwrap().to_string_lossy()
)))
.unwrap();
}
Ok(())
})
.unwrap();
}
struct TestConfig {}
impl swc_css_modules::TransformConfig for TestConfig {
fn new_name_for(&self, local: &JsWord) -> JsWord {
format!("__local__{}", local).into()
}
}

View File

@ -0,0 +1,111 @@
@charset "UTF-8";
.__local__class {
color: red;
background: url("./url/img.png");
}
.__local__class-duplicate-url {
background: url("./url/img.png");
}
:root {
--foo: 1px;
--bar: 2px;
}
.__local__class {
a: b c d;
}
.__local__two {}
.__local__u-m\+ {
a: b c d;
}
.__local__class {
content: "\F10C";
}
@media only screen and (max-width: 600px) {
body {
background-color: lightblue;
}
}
.__local__class {
content: "\2193";
content: "\2193\2193";
content: "\2193 \2193";
content: "\2193\2193\2193";
content: "\2193 \2193 \2193";
}
.__local__-top {}
.__local__-top {}
#__local__\#test {}
.__local__grid {
display: flex;
flex-wrap: wrap;
}
.__local__grid.__local__-top {
align-items: flex-start;
}
.__local__grid.__local__-top {
align-items: flex-start;
}
.__local__grid.__local__-middle {
align-items: center;
}
.__local__grid.__local__-bottom {
align-items: flex-end;
}
.__local__u-m\+ {}
.__local__u-m00002b {}
#__local__u-m\+ {}
body {
font-family: '微软雅黑';
}
.__local__myStyle {
content: '\e901';
}
.__local__myStyle {
content: '\E901';
}
.__local__ {}
.__local__\:\`\( {}
.__local__1a2b3c {}
#__local__\#fake-id {}
#__local__-a-b-c- {}
#__local__© {}
:root {
--title-align: center;
--sr-only: {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
overflow: hidden;
clip: rect(0,0,0,0);
white-space: nowrap;
clip-path: inset(50%);
border: 0;
};
}
.__local__test {
content: "\2014\A0";
content: "\2014 \A0";
content: "\A0 \2014";
content: "\A0\2014";
margin-top: 1px\9;
background-color: #000\9;
}
.__local__light.__local__on .__local__bulb:before {
content: '💡';
}
.__local__base64 {
background: url(data:img/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAhxJREFUSA3tk71rU1EYxnMTEoJUkowWwdJ2akEHBfGjCiIF6ZylVUKSm2TqZLGI+A/oIu2UXm8C4lAyF4SWji0tdFLo1Eo7VN0SaBEhH7e/Nz0nPTfGOjiaCyfPc5734zlfCQT6X/8E/vUErL81KBaL9y3LSnued5PcITjUOwR3gsFg2bbtjYt6/NGgXC4P1et1l2aPLmpAbD0SidjpdPqgV15PA9d17zQajU8UxHQRK/4G35Q5pveAK8LlI1ZjPMnlcltnyvnvbwaO41xvtVqy7YHztMACq5xnlb9EY3dRdvcGo1kj5wR+t1AofDG0gM+A875E8DNjRCexsrV8Pj9ZqVQitVrtqejxePxjMpmss5hVTB4buXvMb2DyU2tBTRS+BjvNlVYUpPl7iuVO3Gq1uoQx1FtSOW1gPgp5ZWrdBtNmUDgv5asgxQ8F1af5vhY0YjyjuWC3wTszKJz7GBOkcFlQfW2ONq4FjWi+Hj6DRCKxQOK2TlY4x92EuYd5dvMAbYIzfikau3pu5tJ8KxaLLfo0cyKci7tK4TZjUMcoXAmHwzle0Q/RaC5P1GFMyVx9R9Fo9HYqlTrSgqDvFelAqVQa5hmuMR/WGtjAaBdjwBoDQ0ZsnwVMZjKZ9n0Zem8DSeDPdrnZbL6F2l3NOvUYNZk4oVDoRTabPe4EDNJzB0ZcjAYxeoZ2i3FNxQ7BHYw/cB/fldaH//UETgHHO8S44KbfXgAAAABJRU5ErkJggg==);
}
a[href=''] {
color: red;
}
a[href='' i] {
color: red;
}
a[href=""] {
color: blue;
}
a[href="" i] {
color: blue;
}

View File

@ -0,0 +1,135 @@
@charset "UTF-8";
/* Comment */
.class {
color: red;
background: url("./url/img.png");
}
.class-duplicate-url {
background: url("./url/img.png");
}
:root {
--foo: 1px;
--bar: 2px;
}
.class { a: b c d; }
.two {}
.u-m\+ { a: b c d; }
.class { content: "\F10C" }
@media only screen and (max-width: 600px) {
body {
background-color: lightblue;
}
}
.class {
content: "\2193";
content: "\2193\2193";
content: "\2193 \2193";
content: "\2193\2193\2193";
content: "\2193 \2193 \2193";
}
.-top {}
.\-top {}
#\#test {}
.grid {
display: flex;
flex-wrap: wrap;
}
.grid.\-top {
align-items: flex-start;
}
.grid.-top {
align-items: flex-start;
}
.grid.\-middle {
align-items: center;
}
.grid.\-bottom {
align-items: flex-end;
}
.u-m\00002b {}
.u-m00002b {}
#u-m\+ {}
body {
font-family: '微软雅黑'; /* some chinese font name */
}
.myStyle {
content: '\e901';
}
.myStyle {
content: '\E901';
}
. {}
.\3A \`\( {} /* matches elements with class=":`(" */
.\31 a2b3c {} /* matches elements with class="1a2b3c" */
#\#fake-id {} /* matches the element with id="#fake-id" */
#-a-b-c- {} /* matches the element with id="-a-b-c-" */
#© {} /* matches the element with id="©" */
:root {
--title-align: center;
--sr-only: {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
overflow: hidden;
clip: rect(0,0,0,0);
white-space: nowrap;
clip-path: inset(50%);
border: 0;
};
}
.test {
content: "\2014\A0";
content: "\2014 \A0";
content: "\A0 \2014";
content: "\A0\2014";
margin-top: 1px\9;
background-color: #000\9;
}
.light.on .bulb:before{
content: '💡';
}
.base64 {
background: url(data:img/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAhxJREFUSA3tk71rU1EYxnMTEoJUkowWwdJ2akEHBfGjCiIF6ZylVUKSm2TqZLGI+A/oIu2UXm8C4lAyF4SWji0tdFLo1Eo7VN0SaBEhH7e/Nz0nPTfGOjiaCyfPc5734zlfCQT6X/8E/vUErL81KBaL9y3LSnued5PcITjUOwR3gsFg2bbtjYt6/NGgXC4P1et1l2aPLmpAbD0SidjpdPqgV15PA9d17zQajU8UxHQRK/4G35Q5pveAK8LlI1ZjPMnlcltnyvnvbwaO41xvtVqy7YHztMACq5xnlb9EY3dRdvcGo1kj5wR+t1AofDG0gM+A875E8DNjRCexsrV8Pj9ZqVQitVrtqejxePxjMpmss5hVTB4buXvMb2DyU2tBTRS+BjvNlVYUpPl7iuVO3Gq1uoQx1FtSOW1gPgp5ZWrdBtNmUDgv5asgxQ8F1af5vhY0YjyjuWC3wTszKJz7GBOkcFlQfW2ONq4FjWi+Hj6DRCKxQOK2TlY4x92EuYd5dvMAbYIzfikau3pu5tJ8KxaLLfo0cyKci7tK4TZjUMcoXAmHwzle0Q/RaC5P1GFMyVx9R9Fo9HYqlTrSgqDvFelAqVQa5hmuMR/WGtjAaBdjwBoDQ0ZsnwVMZjKZ9n0Zem8DSeDPdrnZbL6F2l3NOvUYNZk4oVDoRTabPe4EDNJzB0ZcjAYxeoZ2i3FNxQ7BHYw/cB/fldaH//UETgHHO8S44KbfXgAAAABJRU5ErkJggg==);
}
a[href=''] {
color: red;
}
a[href='' i] {
color: red;
}
a[href=""] {
color: blue;
}
a[href="" i] {
color: blue;
}

View File

@ -0,0 +1,134 @@
{
"bulb": [
{
"type": "local",
"name": "__local__bulb"
}
],
"class": [
{
"type": "local",
"name": "__local__class"
}
],
"class-duplicate-url": [
{
"type": "local",
"name": "__local__class-duplicate-url"
}
],
"two": [
{
"type": "local",
"name": "__local__two"
}
],
"grid": [
{
"type": "local",
"name": "__local__grid"
}
],
"-top": [
{
"type": "local",
"name": "__local__-top"
}
],
"-bottom": [
{
"type": "local",
"name": "__local__-bottom"
}
],
"#test": [
{
"type": "local",
"name": "__local__#test"
}
],
"myStyle": [
{
"type": "local",
"name": "__local__myStyle"
}
],
"♫": [
{
"type": "local",
"name": "__local__♫"
}
],
":`(": [
{
"type": "local",
"name": "__local__:`("
}
],
"#fake-id": [
{
"type": "local",
"name": "__local__#fake-id"
}
],
"-a-b-c-": [
{
"type": "local",
"name": "__local__-a-b-c-"
}
],
"light": [
{
"type": "local",
"name": "__local__light"
}
],
"u-m+": [
{
"type": "local",
"name": "__local__u-m+"
}
],
"base64": [
{
"type": "local",
"name": "__local__base64"
}
],
"©": [
{
"type": "local",
"name": "__local__©"
}
],
"on": [
{
"type": "local",
"name": "__local__on"
}
],
"-middle": [
{
"type": "local",
"name": "__local__-middle"
}
],
"u-m00002b": [
{
"type": "local",
"name": "__local__u-m00002b"
}
],
"test": [
{
"type": "local",
"name": "__local__test"
}
],
"1a2b3c": [
{
"type": "local",
"name": "__local__1a2b3c"
}
]
}

View File

@ -0,0 +1,112 @@
@charset "UTF-8";
@import 'imported.css';
.__local__class {
color: red;
background: url("./url/img.png");
}
.__local__class-duplicate-url {
background: url("./url/img.png");
}
:root {
--foo: 1px;
--bar: 2px;
}
.__local__class {
a: b c d;
}
.__local__two {}
.__local__u-m\+ {
a: b c d;
}
.__local__class {
content: "\F10C";
}
@media only screen and (max-width: 600px) {
body {
background-color: lightblue;
}
}
.__local__class {
content: "\2193";
content: "\2193\2193";
content: "\2193 \2193";
content: "\2193\2193\2193";
content: "\2193 \2193 \2193";
}
.__local__-top {}
.__local__-top {}
#__local__\#test {}
.__local__grid {
display: flex;
flex-wrap: wrap;
}
.__local__grid.__local__-top {
align-items: flex-start;
}
.__local__grid.__local__-top {
align-items: flex-start;
}
.__local__grid.__local__-middle {
align-items: center;
}
.__local__grid.__local__-bottom {
align-items: flex-end;
}
.__local__u-m\+ {}
.__local__u-m00002b {}
#__local__u-m\+ {}
body {
font-family: '微软雅黑';
}
.__local__myStyle {
content: '\e901';
}
.__local__myStyle {
content: '\E901';
}
.__local__ {}
.__local__\:\`\( {}
.__local__1a2b3c {}
#__local__\#fake-id {}
#__local__-a-b-c- {}
#__local__© {}
:root {
--title-align: center;
--sr-only: {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
overflow: hidden;
clip: rect(0,0,0,0);
white-space: nowrap;
clip-path: inset(50%);
border: 0;
};
}
.__local__test {
content: "\2014\A0";
content: "\2014 \A0";
content: "\A0 \2014";
content: "\A0\2014";
margin-top: 1px\9;
background-color: #000\9;
}
.__local__light.__local__on .__local__bulb:before {
content: '💡';
}
.__local__base64 {
background: url(data:img/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAhxJREFUSA3tk71rU1EYxnMTEoJUkowWwdJ2akEHBfGjCiIF6ZylVUKSm2TqZLGI+A/oIu2UXm8C4lAyF4SWji0tdFLo1Eo7VN0SaBEhH7e/Nz0nPTfGOjiaCyfPc5734zlfCQT6X/8E/vUErL81KBaL9y3LSnued5PcITjUOwR3gsFg2bbtjYt6/NGgXC4P1et1l2aPLmpAbD0SidjpdPqgV15PA9d17zQajU8UxHQRK/4G35Q5pveAK8LlI1ZjPMnlcltnyvnvbwaO41xvtVqy7YHztMACq5xnlb9EY3dRdvcGo1kj5wR+t1AofDG0gM+A875E8DNjRCexsrV8Pj9ZqVQitVrtqejxePxjMpmss5hVTB4buXvMb2DyU2tBTRS+BjvNlVYUpPl7iuVO3Gq1uoQx1FtSOW1gPgp5ZWrdBtNmUDgv5asgxQ8F1af5vhY0YjyjuWC3wTszKJz7GBOkcFlQfW2ONq4FjWi+Hj6DRCKxQOK2TlY4x92EuYd5dvMAbYIzfikau3pu5tJ8KxaLLfo0cyKci7tK4TZjUMcoXAmHwzle0Q/RaC5P1GFMyVx9R9Fo9HYqlTrSgqDvFelAqVQa5hmuMR/WGtjAaBdjwBoDQ0ZsnwVMZjKZ9n0Zem8DSeDPdrnZbL6F2l3NOvUYNZk4oVDoRTabPe4EDNJzB0ZcjAYxeoZ2i3FNxQ7BHYw/cB/fldaH//UETgHHO8S44KbfXgAAAABJRU5ErkJggg==);
}
a[href=''] {
color: red;
}
a[href='' i] {
color: red;
}
a[href=""] {
color: blue;
}
a[href="" i] {
color: blue;
}

View File

@ -0,0 +1,137 @@
@charset "UTF-8";
@import 'imported.css';
/* Comment */
.class {
color: red;
background: url("./url/img.png");
}
.class-duplicate-url {
background: url("./url/img.png");
}
:root {
--foo: 1px;
--bar: 2px;
}
.class { a: b c d; }
.two {}
.u-m\+ { a: b c d; }
.class { content: "\F10C" }
@media only screen and (max-width: 600px) {
body {
background-color: lightblue;
}
}
.class {
content: "\2193";
content: "\2193\2193";
content: "\2193 \2193";
content: "\2193\2193\2193";
content: "\2193 \2193 \2193";
}
.-top {}
.\-top {}
#\#test {}
.grid {
display: flex;
flex-wrap: wrap;
}
.grid.\-top {
align-items: flex-start;
}
.grid.-top {
align-items: flex-start;
}
.grid.\-middle {
align-items: center;
}
.grid.\-bottom {
align-items: flex-end;
}
.u-m\00002b {}
.u-m00002b {}
#u-m\+ {}
body {
font-family: '微软雅黑'; /* some chinese font name */
}
.myStyle {
content: '\e901';
}
.myStyle {
content: '\E901';
}
. {}
.\3A \`\( {} /* matches elements with class=":`(" */
.\31 a2b3c {} /* matches elements with class="1a2b3c" */
#\#fake-id {} /* matches the element with id="#fake-id" */
#-a-b-c- {} /* matches the element with id="-a-b-c-" */
#© {} /* matches the element with id="©" */
:root {
--title-align: center;
--sr-only: {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
overflow: hidden;
clip: rect(0,0,0,0);
white-space: nowrap;
clip-path: inset(50%);
border: 0;
};
}
.test {
content: "\2014\A0";
content: "\2014 \A0";
content: "\A0 \2014";
content: "\A0\2014";
margin-top: 1px\9;
background-color: #000\9;
}
.light.on .bulb:before{
content: '💡';
}
.base64 {
background: url(data:img/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAhxJREFUSA3tk71rU1EYxnMTEoJUkowWwdJ2akEHBfGjCiIF6ZylVUKSm2TqZLGI+A/oIu2UXm8C4lAyF4SWji0tdFLo1Eo7VN0SaBEhH7e/Nz0nPTfGOjiaCyfPc5734zlfCQT6X/8E/vUErL81KBaL9y3LSnued5PcITjUOwR3gsFg2bbtjYt6/NGgXC4P1et1l2aPLmpAbD0SidjpdPqgV15PA9d17zQajU8UxHQRK/4G35Q5pveAK8LlI1ZjPMnlcltnyvnvbwaO41xvtVqy7YHztMACq5xnlb9EY3dRdvcGo1kj5wR+t1AofDG0gM+A875E8DNjRCexsrV8Pj9ZqVQitVrtqejxePxjMpmss5hVTB4buXvMb2DyU2tBTRS+BjvNlVYUpPl7iuVO3Gq1uoQx1FtSOW1gPgp5ZWrdBtNmUDgv5asgxQ8F1af5vhY0YjyjuWC3wTszKJz7GBOkcFlQfW2ONq4FjWi+Hj6DRCKxQOK2TlY4x92EuYd5dvMAbYIzfikau3pu5tJ8KxaLLfo0cyKci7tK4TZjUMcoXAmHwzle0Q/RaC5P1GFMyVx9R9Fo9HYqlTrSgqDvFelAqVQa5hmuMR/WGtjAaBdjwBoDQ0ZsnwVMZjKZ9n0Zem8DSeDPdrnZbL6F2l3NOvUYNZk4oVDoRTabPe4EDNJzB0ZcjAYxeoZ2i3FNxQ7BHYw/cB/fldaH//UETgHHO8S44KbfXgAAAABJRU5ErkJggg==);
}
a[href=''] {
color: red;
}
a[href='' i] {
color: red;
}
a[href=""] {
color: blue;
}
a[href="" i] {
color: blue;
}

View File

@ -0,0 +1,3 @@
[
"imported.css"
]

View File

@ -0,0 +1,134 @@
{
"bulb": [
{
"type": "local",
"name": "__local__bulb"
}
],
"class": [
{
"type": "local",
"name": "__local__class"
}
],
"class-duplicate-url": [
{
"type": "local",
"name": "__local__class-duplicate-url"
}
],
"two": [
{
"type": "local",
"name": "__local__two"
}
],
"grid": [
{
"type": "local",
"name": "__local__grid"
}
],
"-top": [
{
"type": "local",
"name": "__local__-top"
}
],
"-bottom": [
{
"type": "local",
"name": "__local__-bottom"
}
],
"#test": [
{
"type": "local",
"name": "__local__#test"
}
],
"myStyle": [
{
"type": "local",
"name": "__local__myStyle"
}
],
"♫": [
{
"type": "local",
"name": "__local__♫"
}
],
":`(": [
{
"type": "local",
"name": "__local__:`("
}
],
"#fake-id": [
{
"type": "local",
"name": "__local__#fake-id"
}
],
"-a-b-c-": [
{
"type": "local",
"name": "__local__-a-b-c-"
}
],
"light": [
{
"type": "local",
"name": "__local__light"
}
],
"u-m+": [
{
"type": "local",
"name": "__local__u-m+"
}
],
"base64": [
{
"type": "local",
"name": "__local__base64"
}
],
"©": [
{
"type": "local",
"name": "__local__©"
}
],
"on": [
{
"type": "local",
"name": "__local__on"
}
],
"-middle": [
{
"type": "local",
"name": "__local__-middle"
}
],
"u-m00002b": [
{
"type": "local",
"name": "__local__u-m00002b"
}
],
"test": [
{
"type": "local",
"name": "__local__test"
}
],
"1a2b3c": [
{
"type": "local",
"name": "__local__1a2b3c"
}
]
}

View File

@ -0,0 +1,2 @@
.__local__some {
invalid css;}

View File

@ -0,0 +1,3 @@
.some {
invalid css;
}

View File

@ -0,0 +1,8 @@
{
"some": [
{
"type": "local",
"name": "__local__some"
}
]
}

View File

@ -0,0 +1,3 @@
.__local__foo {
color: red;
}

View File

@ -0,0 +1,3 @@
.foo {
color: red;
}

View File

@ -0,0 +1,8 @@
{
"foo": [
{
"type": "local",
"name": "__local__foo"
}
]
}

View File

@ -0,0 +1,6 @@
@charset "UTF-8";
@import './imported.css';
.__local__class {
color: red;
background: url("./img.png");
}

View File

@ -0,0 +1,10 @@
@charset "UTF-8";
@import './imported.css';
/* Comment */
.class {
color: red;
background: url("./img.png");
}

View File

@ -0,0 +1,3 @@
[
"./imported.css"
]

View File

@ -0,0 +1,8 @@
{
"class": [
{
"type": "local",
"name": "__local__class"
}
]
}

View File

@ -0,0 +1,9 @@
.__local__header-baz {
color: red;
}
.__local__body {
color: coral;
}
.__local__footer {
color: blue;
}

View File

@ -0,0 +1,11 @@
:local(.header-baz) {
color: red;
}
:local(.body) {
color: coral;
}
:local(.footer) {
color: blue;
}

View File

@ -0,0 +1,20 @@
{
"body": [
{
"type": "local",
"name": "__local__body"
}
],
"footer": [
{
"type": "local",
"name": "__local__footer"
}
],
"header-baz": [
{
"type": "local",
"name": "__local__header-baz"
}
]
}

View File

@ -0,0 +1,4 @@
@import url("https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/imported.css");
a {
background: url("https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/img.png");
}

View File

@ -0,0 +1,5 @@
@import url("https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/imported.css");
a {
background: url("https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/img.png");
}

View File

@ -0,0 +1,3 @@
[
"https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/imported.css"
]

View File

@ -0,0 +1,3 @@
.__local__alias {
color: red;
}

View File

@ -0,0 +1,3 @@
.alias {
color: red;
}

View File

@ -0,0 +1,8 @@
{
"alias": [
{
"type": "local",
"name": "__local__alias"
}
]
}

View File

@ -0,0 +1,4 @@
@import url(circular.css);
div {
color: red;
}

View File

@ -0,0 +1,5 @@
@import url(circular.css);
div {
color: red;
}

View File

@ -0,0 +1,3 @@
[
"circular.css"
]

View File

@ -0,0 +1,6 @@
@import url(circular.css);
@import url(circular.css);
@import url("relative.css");
a {
color: red;
}

View File

@ -0,0 +1,11 @@
@import url(circular.css);
@import url(circular.css);
/*
// TODO fixed nested circular `@import`
@import url(circular-nested.css);
*/
@import url("relative.css");
a {
color: red;
}

View File

@ -0,0 +1,4 @@
[
"circular.css",
"relative.css"
]

View File

@ -0,0 +1,5 @@
@import url("data:text/css;charset=utf-8;base64,YSB7DQogIGNvbG9yOiByZWQ7DQp9");
a {
display: block;
width: 100px;
}

View File

@ -0,0 +1,6 @@
@import url("data:text/css;charset=utf-8;base64,YSB7DQogIGNvbG9yOiByZWQ7DQp9");
a {
display: block;
width: 100px;
}

View File

@ -0,0 +1,3 @@
[
"data:text/css;charset=utf-8;base64,YSB7DQogIGNvbG9yOiByZWQ7DQp9"
]

View File

@ -0,0 +1,6 @@
@import url("./import-with-layer.css") layer(form);
@layer form {
.__local__bar {
color: red;
}
}

View File

@ -0,0 +1,7 @@
@import url("./import-with-layer.css") layer(form);
@layer form {
.bar {
color: red;
}
}

View File

@ -0,0 +1,3 @@
[
"./import-with-layer.css"
]

View File

@ -0,0 +1,8 @@
{
"bar": [
{
"type": "local",
"name": "__local__bar"
}
]
}

View File

@ -0,0 +1 @@
@import url("./import-with-media.css") screen and (min-width: 400px);

View File

@ -0,0 +1 @@
@import url("./import-with-media.css") screen and (min-width: 400px);

View File

@ -0,0 +1,3 @@
[
"./import-with-media.css"
]

View File

@ -0,0 +1 @@
@import url("./import-with-supports.css") supports(display: block);

View File

@ -0,0 +1 @@
@import url("./import-with-supports.css") supports(display: block);

View File

@ -0,0 +1,3 @@
[
"./import-with-supports.css"
]

View File

@ -0,0 +1,2 @@
@import url("./relative.css") layer;
@import url("./test.css") layer;

View File

@ -0,0 +1,3 @@
/* unnamed wrapper layers around each sub-file */
@import url("./relative.css") layer;
@import url("./test.css") layer;

View File

@ -0,0 +1,4 @@
[
"./relative.css",
"./test.css"
]

View File

@ -0,0 +1 @@
@import url("./deep-layer-base.css") layer(base);

View File

@ -0,0 +1,2 @@
/* the internal names are hidden from access, subsumed in "base" */
@import url("./deep-layer-base.css") layer(base);

View File

@ -0,0 +1,3 @@
[
"./deep-layer-base.css"
]

View File

@ -0,0 +1,6 @@
@import url(./deep-layer-first-level.css) layer(bootstrap);
@layer bootstrap {
.__local__test {
color: red;
}
}

View File

@ -0,0 +1,8 @@
@import url(./deep-layer-first-level.css) layer(bootstrap);
/* Adds additional styles to the bootstrap layer: */
@layer bootstrap {
.test {
color: red;
}
}

View File

@ -0,0 +1,3 @@
[
"./deep-layer-first-level.css"
]

View File

@ -0,0 +1,8 @@
{
"test": [
{
"type": "local",
"name": "__local__test"
}
]
}

View File

@ -0,0 +1,3 @@
div {
color: red;
}

View File

@ -0,0 +1,4 @@
@import url(./extensions-imported);
a {
color: red;
}

View File

@ -0,0 +1,5 @@
@import url(./extensions-imported);
a {
color: red;
}

View File

@ -0,0 +1,3 @@
[
"./extensions-imported"
]

View File

@ -0,0 +1,4 @@
@import "/style.css";
.__local__class {
color: red;
}

View File

@ -0,0 +1,5 @@
@import "/style.css";
.class {
color: red;
}

View File

@ -0,0 +1,3 @@
[
"/style.css"
]

View File

@ -0,0 +1,8 @@
{
"class": [
{
"type": "local",
"name": "__local__class"
}
]
}

View File

@ -0,0 +1 @@
@import "~package-with-exports";

View File

@ -0,0 +1 @@
@import "~package-with-exports";

View File

@ -0,0 +1,3 @@
[
"~package-with-exports"
]

View File

@ -0,0 +1 @@
@import url("./import-with-supports-and-media.css") supports(display: flex) screen and (min-width: 400px);

View File

@ -0,0 +1 @@
@import url("./import-with-supports-and-media.css") supports(display: flex) screen and (min-width: 400px);

View File

@ -0,0 +1,3 @@
[
"./import-with-supports-and-media.css"
]

View File

@ -0,0 +1,5 @@
@import url("./test.css") layer;
@import url("./relative.css") layer;
.__local__foo {
color: red;
}

View File

@ -0,0 +1,6 @@
@import url("./test.css") layer;
@import url("./relative.css") layer;
.foo {
color: red;
}

View File

@ -0,0 +1,4 @@
[
"./relative.css",
"./test.css"
]

View File

@ -0,0 +1,8 @@
{
"foo": [
{
"type": "local",
"name": "__local__foo"
}
]
}

View File

@ -0,0 +1,7 @@
@import url('./test.css') layer(base);
@import url('./relative.css') layer(base);
@layer base {
.__local__foo {
color: red;
}
}

View File

@ -0,0 +1,8 @@
@import url('./test.css') layer(base);
@import url('./relative.css') layer(base);
@layer base {
.foo {
color: red;
}
}

View File

@ -0,0 +1,4 @@
[
"./relative.css",
"./test.css"
]

View File

@ -0,0 +1,8 @@
{
"foo": [
{
"type": "local",
"name": "__local__foo"
}
]
}

View File

@ -0,0 +1,3 @@
@import "test";
@import "issue-683";
@import "aliasesPackage";

View File

@ -0,0 +1,3 @@
@import "test";
@import "issue-683";
@import "aliasesPackage";

View File

@ -0,0 +1,5 @@
[
"aliasesPackage",
"issue-683",
"test"
]

View File

@ -0,0 +1,5 @@
@import url(/import/test.css);
@import "/import/test.css";
.__local__class {
a: b c d;
}

View File

@ -0,0 +1,6 @@
@import url(/import/test.css);
@import "/import/test.css";
.class {
a: b c d;
}

View File

@ -0,0 +1,3 @@
[
"/import/test.css"
]

View File

@ -0,0 +1,8 @@
{
"class": [
{
"type": "local",
"name": "__local__class"
}
]
}

View File

@ -0,0 +1,4 @@
@import url("./test.css") layer;
.__local__foo {
color: red;
}

View File

@ -0,0 +1,5 @@
@import url("./test.css") layer;
.foo {
color: red;
}

View File

@ -0,0 +1,3 @@
[
"./test.css"
]

Some files were not shown because too many files have changed in this diff Show More