Add/styled jsx swc (#29005)
Co-authored-by: Tim Neutkens <tim@timneutkens.nl> Co-authored-by: Tim Neutkens <timneutkens@me.com>
This commit is contained in:
parent
2cfdc68650
commit
4a2d5a1b49
85 changed files with 3514 additions and 244 deletions
4
.github/workflows/build_native.yml
vendored
4
.github/workflows/build_native.yml
vendored
|
@ -37,7 +37,7 @@ jobs:
|
|||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly-2021-03-25
|
||||
toolchain: nightly-2021-08-12
|
||||
target: ${{ matrix.target }}
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v1
|
||||
|
@ -54,7 +54,7 @@ jobs:
|
|||
uses: actions/cache@v2
|
||||
with:
|
||||
path: packages/next/native/**
|
||||
key: next-swc-nightly-2021-03-25-${{ matrix.target }}-${{ hashFiles('.github/workflows/build_native.yml', 'packages/next/build/swc/**') }}
|
||||
key: next-swc-nightly-2021-08-12-${{ matrix.target }}-${{ hashFiles('.github/workflows/build_native.yml', 'packages/next/build/swc/**') }}
|
||||
- name: Cross build aarch64 setup
|
||||
if: ${{ matrix.target == 'aarch64-apple-darwin' && steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
run: |
|
||||
|
|
6
.github/workflows/build_test_deploy.yml
vendored
6
.github/workflows/build_test_deploy.yml
vendored
|
@ -471,7 +471,7 @@ jobs:
|
|||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly-2021-03-25
|
||||
toolchain: nightly-2021-08-12
|
||||
target: ${{ matrix.target }}
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v1
|
||||
|
@ -491,7 +491,7 @@ jobs:
|
|||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
with:
|
||||
path: packages/next/native/next-swc.*.node
|
||||
key: next-swc-nightly-2021-03-25-${{ matrix.target }}-${{ hashFiles('.github/workflows/build_test_deploy.yml', 'packages/next/build/swc/**') }}
|
||||
key: next-swc-nightly-2021-08-12-${{ matrix.target }}-${{ hashFiles('.github/workflows/build_test_deploy.yml', 'packages/next/build/swc/**') }}
|
||||
- name: Cross build aarch64 setup
|
||||
if: ${{ matrix.target == 'aarch64-apple-darwin' && steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
run: |
|
||||
|
@ -531,7 +531,7 @@ jobs:
|
|||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly-2021-03-25
|
||||
toolchain: nightly-2021-08-12
|
||||
profile: minimal
|
||||
- run: cd packages/next/build/swc && cargo test
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
|
|
@ -10,6 +10,7 @@ packages/react-dev-overlay/lib/**
|
|||
**/__tmp__/**
|
||||
lerna.json
|
||||
.github/actions/next-stats-action/.work
|
||||
packages/next/build/swc/tests/fixture/**/*
|
||||
packages/next-codemod/transforms/__testfixtures__/**/*
|
||||
packages/next-codemod/transforms/__tests__/**/*
|
||||
packages/next-codemod/**/*.js
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
**/.next/**
|
||||
**/_next/**
|
||||
**/dist/**
|
||||
packages/next/build/swc/tests/**
|
||||
packages/next/compiled/**/*
|
||||
packages/next/bundles/webpack/packages/*.runtime.js
|
||||
lerna.json
|
||||
|
|
155
packages/next/build/swc/Cargo.lock
generated
155
packages/next/build/swc/Cargo.lock
generated
|
@ -93,6 +93,18 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "auto_impl"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42cbf586c80ada5e5ccdecae80d3ef0854f224e2dd74435f8d87e6831b8d0a38"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.7"
|
||||
|
@ -134,9 +146,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
|
@ -330,6 +342,12 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "easy-error"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04cc9717c61d2908f50d16ebb5677c7e82ea2bdf7cb52f66b30fe079f3212e16"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
|
@ -700,6 +718,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"backtrace",
|
||||
"easy-error",
|
||||
"fxhash",
|
||||
"log",
|
||||
"napi",
|
||||
|
@ -714,10 +733,13 @@ dependencies = [
|
|||
"swc",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_css",
|
||||
"swc_css_codegen",
|
||||
"swc_ecma_preset_env",
|
||||
"swc_ecma_transforms_testing",
|
||||
"swc_ecmascript",
|
||||
"swc_node_base",
|
||||
"swc_stylis",
|
||||
"testing",
|
||||
]
|
||||
|
||||
|
@ -949,6 +971,30 @@ dependencies = [
|
|||
"output_vt100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
|
@ -1603,6 +1649,97 @@ dependencies = [
|
|||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_css"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30b6bedb0b7ea4ccccb288d7f2a9300fe1405d16564f49c1c7f809a1e3f0c742"
|
||||
dependencies = [
|
||||
"swc_css_ast",
|
||||
"swc_css_codegen",
|
||||
"swc_css_parser",
|
||||
"swc_css_utils",
|
||||
"swc_css_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_css_ast"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "483dfb43c4014dec1e77b188b449668c8e4a1d997b17ff68879de192b6443a0c"
|
||||
dependencies = [
|
||||
"is-macro",
|
||||
"serde",
|
||||
"string_enum",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_css_codegen"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf323b2d07f777735cc3d34e31f2b6115d2d2f6ccb211afa519c99764a02e0c1"
|
||||
dependencies = [
|
||||
"auto_impl",
|
||||
"bitflags",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_css_ast",
|
||||
"swc_css_codegen_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_css_codegen_macros"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe27425548d11afee43ddbe1d0cd882cb5e042f61b1503651dae2219c92333f5"
|
||||
dependencies = [
|
||||
"pmutil",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"swc_macros_common",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_css_parser"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbbb971b273235ad4fc02698f92ab1a242bc12f3dde79a7191d6c522d583b835"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"lexical",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_css_ast",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_css_utils"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acca437ca271d610fca62849723513130a8967414d10c404a5233796c01aca8a"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_css_ast",
|
||||
"swc_css_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_css_visit"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b6166ea9b15898554d518ca6bdb49ea21e64bf07f2b1f42613bed78011a4242"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_css_ast",
|
||||
"swc_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_ast"
|
||||
version = "0.52.0"
|
||||
|
@ -2009,6 +2146,7 @@ checksum = "ba53c5582d6e5881b093ece9aaa4b561465afab0560abb19948f2c4bbff1bdb9"
|
|||
dependencies = [
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_codegen",
|
||||
"swc_ecma_minifier",
|
||||
"swc_ecma_parser",
|
||||
"swc_ecma_transforms",
|
||||
"swc_ecma_utils",
|
||||
|
@ -2050,6 +2188,19 @@ dependencies = [
|
|||
"swc_common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_stylis"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eee38c781219cf66533d27debde66f7054e07123e6e5fa860610135ed8a5e904"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_css_ast",
|
||||
"swc_css_utils",
|
||||
"swc_css_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_visit"
|
||||
version = "0.2.6"
|
||||
|
|
|
@ -9,6 +9,7 @@ crate-type = ["cdylib"]
|
|||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
backtrace = "0.3"
|
||||
easy-error = "1.0.0"
|
||||
napi = { version = "1", features = ["serde-json"] }
|
||||
napi-derive = "1"
|
||||
path-clean = "0.1"
|
||||
|
@ -18,9 +19,12 @@ serde_json = "1"
|
|||
swc = "0.51"
|
||||
swc_atoms = "0.2"
|
||||
swc_common = { version = "0.12", features = ["tty-emitter", "sourcemap"] }
|
||||
swc_node_base = "0.3"
|
||||
swc_ecmascript = { version = "0.63", features = ["codegen", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
|
||||
swc_css = "0.6"
|
||||
swc_css_codegen = "0.4"
|
||||
swc_ecmascript = { version = "0.63", features = ["codegen", "minifier", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
|
||||
swc_ecma_preset_env = "0.42"
|
||||
swc_node_base = "0.3"
|
||||
swc_stylis = "0.3"
|
||||
fxhash = "0.2.1"
|
||||
retain_mut = "0.1.3"
|
||||
log = "0.4.14"
|
||||
|
|
|
@ -1 +1 @@
|
|||
nightly-2021-03-25
|
||||
nightly-2021-08-12
|
|
@ -45,6 +45,7 @@ mod hook_optimizer;
|
|||
mod minify;
|
||||
mod next_dynamic;
|
||||
pub mod next_ssg;
|
||||
mod styled_jsx;
|
||||
mod transform;
|
||||
mod util;
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ use swc_atoms::js_word;
|
|||
use swc_common::{FileName, DUMMY_SP};
|
||||
use swc_ecmascript::ast::{
|
||||
ArrayLit, ArrowExpr, BinExpr, BinaryOp, BlockStmtOrExpr, CallExpr, Expr, ExprOrSpread,
|
||||
ExprOrSuper, Ident, ImportDecl, ImportSpecifier, KeyValueProp, Lit, MemberExpr, ObjectLit,
|
||||
Prop, PropName, PropOrSpread, Str, StrKind,
|
||||
ExprOrSuper, Ident, ImportDecl, ImportSpecifier, KeyValueProp, Lit, MemberExpr, ObjectLit, Prop,
|
||||
PropName, PropOrSpread, Str, StrKind,
|
||||
};
|
||||
use swc_ecmascript::utils::{
|
||||
ident::{Id, IdentLike},
|
||||
|
@ -19,6 +19,8 @@ pub fn next_dynamic(filename: FileName, pages_dir: Option<PathBuf>) -> impl Fold
|
|||
pages_dir,
|
||||
filename,
|
||||
dynamic_bindings: vec![],
|
||||
is_next_dynamic_first_arg: false,
|
||||
dynamically_imported_specifier: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +29,8 @@ struct NextDynamicPatcher {
|
|||
pages_dir: Option<PathBuf>,
|
||||
filename: FileName,
|
||||
dynamic_bindings: Vec<Id>,
|
||||
is_next_dynamic_first_arg: bool,
|
||||
dynamically_imported_specifier: Option<String>,
|
||||
}
|
||||
|
||||
impl Fold for NextDynamicPatcher {
|
||||
|
@ -48,6 +52,18 @@ impl Fold for NextDynamicPatcher {
|
|||
}
|
||||
|
||||
fn fold_call_expr(&mut self, expr: CallExpr) -> CallExpr {
|
||||
if self.is_next_dynamic_first_arg {
|
||||
if let ExprOrSuper::Expr(e) = &expr.callee {
|
||||
if let Expr::Ident(Ident { sym, .. }) = &**e {
|
||||
if sym == "import" {
|
||||
if let Expr::Lit(Lit::Str(Str { value, .. })) = &*expr.args[0].expr {
|
||||
self.dynamically_imported_specifier = Some(value.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return expr.fold_children_with(self);
|
||||
}
|
||||
let mut expr = expr.fold_children_with(self);
|
||||
if let ExprOrSuper::Expr(i) = &expr.callee {
|
||||
if let Expr::Ident(identifier) = &**i {
|
||||
|
@ -61,56 +77,31 @@ impl Fold for NextDynamicPatcher {
|
|||
)
|
||||
.emit()
|
||||
});
|
||||
return expr;
|
||||
} else if expr.args.len() > 2 {
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
identifier.span,
|
||||
"next/dynamic only accepts 2 arguments",
|
||||
)
|
||||
.struct_span_err(identifier.span, "next/dynamic only accepts 2 arguments")
|
||||
.emit()
|
||||
});
|
||||
return expr;
|
||||
}
|
||||
|
||||
let mut import_specifier = None;
|
||||
if let Expr::Arrow(ArrowExpr {
|
||||
body: BlockStmtOrExpr::Expr(e),
|
||||
..
|
||||
}) = &*expr.args[0].expr
|
||||
{
|
||||
if let Expr::Call(CallExpr {
|
||||
args: a, callee, ..
|
||||
}) = &**e
|
||||
{
|
||||
if let ExprOrSuper::Expr(e) = callee {
|
||||
if let Expr::Ident(Ident { sym, .. }) = &**e {
|
||||
if sym == "import" {
|
||||
if a.len() == 0 {
|
||||
// Do nothing, import_specifier will
|
||||
// remain None
|
||||
// triggering error below
|
||||
} else if let Expr::Lit(Lit::Str(Str { value, .. })) =
|
||||
&*a[0].expr
|
||||
{
|
||||
import_specifier = Some(value.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.is_next_dynamic_first_arg = true;
|
||||
expr.args[0].expr = expr.args[0].expr.clone().fold_with(self);
|
||||
self.is_next_dynamic_first_arg = false;
|
||||
|
||||
if let None = import_specifier {
|
||||
if let None = self.dynamically_imported_specifier {
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
identifier.span,
|
||||
"First argument for next/dynamic must be an arrow function \
|
||||
returning a valid dynamic import call e.g. `dynamic(() => \
|
||||
import('../some-component'))`",
|
||||
"First argument for next/dynamic must be an arrow function returning a valid \
|
||||
dynamic import call e.g. `dynamic(() => import('../some-component'))`",
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
return expr;
|
||||
}
|
||||
|
||||
// loadableGenerated: {
|
||||
|
@ -127,15 +118,12 @@ impl Fold for NextDynamicPatcher {
|
|||
body: BlockStmtOrExpr::Expr(Box::new(Expr::Array(ArrayLit {
|
||||
elems: vec![Some(ExprOrSpread {
|
||||
expr: Box::new(Expr::Call(CallExpr {
|
||||
callee: ExprOrSuper::Expr(Box::new(Expr::Member(
|
||||
MemberExpr {
|
||||
obj: ExprOrSuper::Expr(Box::new(
|
||||
Expr::Ident(Ident {
|
||||
callee: ExprOrSuper::Expr(Box::new(Expr::Member(MemberExpr {
|
||||
obj: ExprOrSuper::Expr(Box::new(Expr::Ident(Ident {
|
||||
sym: js_word!("require"),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}),
|
||||
)),
|
||||
}))),
|
||||
prop: Box::new(Expr::Ident(Ident {
|
||||
sym: "resolveWeak".into(),
|
||||
span: DUMMY_SP,
|
||||
|
@ -143,8 +131,7 @@ impl Fold for NextDynamicPatcher {
|
|||
})),
|
||||
computed: false,
|
||||
span: DUMMY_SP,
|
||||
},
|
||||
))),
|
||||
}))),
|
||||
args: vec![ExprOrSpread {
|
||||
expr: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
value: self.filename.to_string().into(),
|
||||
|
@ -178,10 +165,7 @@ impl Fold for NextDynamicPatcher {
|
|||
left: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
value: format!(
|
||||
"{} -> ",
|
||||
rel_filename(
|
||||
self.pages_dir.as_deref(),
|
||||
&self.filename
|
||||
)
|
||||
rel_filename(self.pages_dir.as_deref(), &self.filename)
|
||||
)
|
||||
.into(),
|
||||
span: DUMMY_SP,
|
||||
|
@ -189,7 +173,12 @@ impl Fold for NextDynamicPatcher {
|
|||
has_escape: false,
|
||||
}))),
|
||||
right: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
value: import_specifier.unwrap(),
|
||||
value: self
|
||||
.dynamically_imported_specifier
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into(),
|
||||
span: DUMMY_SP,
|
||||
kind: StrKind::Normal {
|
||||
contains_quote: false,
|
||||
|
@ -205,8 +194,7 @@ impl Fold for NextDynamicPatcher {
|
|||
],
|
||||
}));
|
||||
|
||||
let mut props =
|
||||
vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
let mut props = vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new("loadableGenerated".into(), DUMMY_SP)),
|
||||
value: generated,
|
||||
})))];
|
||||
|
@ -229,7 +217,12 @@ impl Fold for NextDynamicPatcher {
|
|||
})),
|
||||
};
|
||||
|
||||
expr.args.push(second_arg);
|
||||
if expr.args.len() == 2 {
|
||||
expr.args[1] = second_arg;
|
||||
} else {
|
||||
expr.args.push(second_arg)
|
||||
}
|
||||
self.dynamically_imported_specifier = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
774
packages/next/build/swc/src/styled_jsx/mod.rs
Normal file
774
packages/next/build/swc/src/styled_jsx/mod.rs
Normal file
|
@ -0,0 +1,774 @@
|
|||
use easy_error::{bail, Error};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use swc_common::{collections::AHashSet, Span, DUMMY_SP};
|
||||
use swc_ecmascript::ast::*;
|
||||
use swc_ecmascript::minifier::{
|
||||
eval::{EvalResult, Evaluator},
|
||||
marks::Marks,
|
||||
};
|
||||
use swc_ecmascript::utils::{
|
||||
collect_decls,
|
||||
ident::{Id, IdentLike},
|
||||
prepend, HANDLER,
|
||||
};
|
||||
use swc_ecmascript::visit::{Fold, FoldWith};
|
||||
|
||||
//use external::external_styles;
|
||||
use transform_css::transform_css;
|
||||
use utils::*;
|
||||
|
||||
mod transform_css;
|
||||
mod utils;
|
||||
|
||||
pub fn styled_jsx() -> impl Fold {
|
||||
StyledJSXTransformer::default()
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct StyledJSXTransformer {
|
||||
styles: Vec<JSXStyle>,
|
||||
static_class_name: Option<String>,
|
||||
class_name: Option<Expr>,
|
||||
file_has_styled_jsx: bool,
|
||||
has_styled_jsx: bool,
|
||||
bindings: AHashSet<Id>,
|
||||
nearest_scope_bindings: AHashSet<Id>,
|
||||
style_import_name: Option<String>,
|
||||
external_bindings: Vec<Id>,
|
||||
file_has_css_resolve: bool,
|
||||
external_hash: Option<String>,
|
||||
add_hash: Option<(String, String)>,
|
||||
add_default_decl: Option<(String, Expr)>,
|
||||
evaluator: Option<Evaluator>,
|
||||
}
|
||||
|
||||
pub struct LocalStyle {
|
||||
hash: String,
|
||||
css: String,
|
||||
css_span: Span,
|
||||
is_dynamic: bool,
|
||||
expressions: Vec<Box<Expr>>,
|
||||
}
|
||||
|
||||
pub struct ExternalStyle {
|
||||
expr: Expr,
|
||||
identifier: Ident,
|
||||
is_global: bool,
|
||||
}
|
||||
|
||||
pub enum JSXStyle {
|
||||
Local(LocalStyle),
|
||||
External(ExternalStyle),
|
||||
}
|
||||
|
||||
impl Fold for StyledJSXTransformer {
|
||||
fn fold_jsx_element(&mut self, el: JSXElement) -> JSXElement {
|
||||
if self.has_styled_jsx && is_styled_jsx(&el) {
|
||||
match self.replace_jsx_style(&el) {
|
||||
Ok(el) => return el,
|
||||
Err(_) => return el,
|
||||
}
|
||||
} else if self.has_styled_jsx {
|
||||
return el.fold_children_with(self);
|
||||
}
|
||||
|
||||
self.check_children_for_jsx_styles(&el.children);
|
||||
let el = el.fold_children_with(self);
|
||||
self.reset_styles_state();
|
||||
|
||||
el
|
||||
}
|
||||
|
||||
fn fold_jsx_fragment(&mut self, fragment: JSXFragment) -> JSXFragment {
|
||||
if self.has_styled_jsx {
|
||||
return fragment.fold_children_with(self);
|
||||
}
|
||||
|
||||
self.check_children_for_jsx_styles(&fragment.children);
|
||||
let fragment = fragment.fold_children_with(self);
|
||||
self.reset_styles_state();
|
||||
|
||||
fragment
|
||||
}
|
||||
|
||||
fn fold_jsx_opening_element(&mut self, mut el: JSXOpeningElement) -> JSXOpeningElement {
|
||||
if !self.has_styled_jsx {
|
||||
return el;
|
||||
}
|
||||
|
||||
if let JSXElementName::Ident(Ident { sym, span, .. }) = &el.name {
|
||||
if sym != "style"
|
||||
&& sym != self.style_import_name.as_ref().unwrap()
|
||||
&& (!is_capitalized(&*sym)
|
||||
|| self
|
||||
.nearest_scope_bindings
|
||||
.contains(&(sym.clone(), span.ctxt)))
|
||||
{
|
||||
let (existing_class_name, existing_index, existing_spread_index) =
|
||||
get_existing_class_name(&el);
|
||||
|
||||
let new_class_name = match (existing_class_name, &self.class_name) {
|
||||
(Some(existing_class_name), Some(class_name)) => Some(add(
|
||||
add(class_name.clone(), string_literal_expr(" ")),
|
||||
existing_class_name,
|
||||
)),
|
||||
(Some(existing_class_name), None) => Some(existing_class_name),
|
||||
(None, Some(class_name)) => Some(class_name.clone()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(new_class_name) = new_class_name {
|
||||
let class_name_attr = JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
span: DUMMY_SP,
|
||||
name: JSXAttrName::Ident(ident("className")),
|
||||
value: Some(JSXAttrValue::JSXExprContainer(JSXExprContainer {
|
||||
expr: JSXExpr::Expr(Box::new(new_class_name)),
|
||||
span: DUMMY_SP,
|
||||
})),
|
||||
});
|
||||
el.attrs.push(class_name_attr);
|
||||
}
|
||||
if let Some(existing_spread_index) = existing_spread_index {
|
||||
el.attrs.remove(existing_spread_index);
|
||||
}
|
||||
if let Some(existing_index) = existing_index {
|
||||
el.attrs.remove(existing_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
el
|
||||
}
|
||||
|
||||
fn fold_import_decl(&mut self, decl: ImportDecl) -> ImportDecl {
|
||||
let ImportDecl {
|
||||
ref src,
|
||||
ref specifiers,
|
||||
..
|
||||
} = decl;
|
||||
if &src.value == "styled-jsx/css" {
|
||||
for specifier in specifiers {
|
||||
match specifier {
|
||||
ImportSpecifier::Default(default_specifier) => {
|
||||
self.external_bindings.push(default_specifier.local.to_id())
|
||||
}
|
||||
ImportSpecifier::Named(named_specifier) => {
|
||||
self.external_bindings.push(named_specifier.local.to_id())
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decl
|
||||
}
|
||||
|
||||
fn fold_expr(&mut self, expr: Expr) -> Expr {
|
||||
let expr = expr.fold_children_with(self);
|
||||
match expr {
|
||||
Expr::TaggedTpl(tagged_tpl) => match &*tagged_tpl.tag {
|
||||
Expr::Ident(identifier) => {
|
||||
if self.external_bindings.contains(&identifier.to_id()) {
|
||||
match self.process_tagged_template_expr(&tagged_tpl) {
|
||||
Ok(expr) => expr,
|
||||
Err(_) => Expr::TaggedTpl(tagged_tpl),
|
||||
}
|
||||
} else {
|
||||
Expr::TaggedTpl(tagged_tpl)
|
||||
}
|
||||
}
|
||||
Expr::Member(MemberExpr {
|
||||
obj: ExprOrSuper::Expr(boxed_ident),
|
||||
..
|
||||
}) => {
|
||||
if let Expr::Ident(identifier) = &**boxed_ident {
|
||||
if self.external_bindings.contains(&identifier.to_id()) {
|
||||
match self.process_tagged_template_expr(&tagged_tpl) {
|
||||
Ok(expr) => expr,
|
||||
Err(_) => Expr::TaggedTpl(tagged_tpl),
|
||||
}
|
||||
} else {
|
||||
Expr::TaggedTpl(tagged_tpl)
|
||||
}
|
||||
} else {
|
||||
Expr::TaggedTpl(tagged_tpl)
|
||||
}
|
||||
}
|
||||
_ => Expr::TaggedTpl(tagged_tpl),
|
||||
},
|
||||
expr => expr,
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_var_declarator(&mut self, declarator: VarDeclarator) -> VarDeclarator {
|
||||
let declarator = declarator.fold_children_with(self);
|
||||
if let Some(external_hash) = &self.external_hash.take() {
|
||||
match &declarator.name {
|
||||
Pat::Ident(BindingIdent {
|
||||
id: Ident { sym, .. },
|
||||
..
|
||||
}) => {
|
||||
self.add_hash = Some((sym.to_string(), external_hash.clone()));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
declarator
|
||||
}
|
||||
|
||||
fn fold_export_default_expr(&mut self, default_expr: ExportDefaultExpr) -> ExportDefaultExpr {
|
||||
let default_expr = default_expr.fold_children_with(self);
|
||||
if let Some(external_hash) = &self.external_hash.take() {
|
||||
let default_ident = "_defaultExport";
|
||||
self.add_hash = Some((String::from(default_ident), external_hash.clone()));
|
||||
self.add_default_decl = Some((String::from(default_ident), *default_expr.expr));
|
||||
return ExportDefaultExpr {
|
||||
expr: Box::new(Expr::Ident(Ident {
|
||||
sym: default_ident.into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
})),
|
||||
span: DUMMY_SP,
|
||||
};
|
||||
}
|
||||
default_expr
|
||||
}
|
||||
|
||||
fn fold_block_stmt(&mut self, mut block: BlockStmt) -> BlockStmt {
|
||||
let mut new_stmts = vec![];
|
||||
for stmt in block.stmts {
|
||||
new_stmts.push(stmt.fold_children_with(self));
|
||||
if let Some(add_hash) = self.add_hash.take() {
|
||||
new_stmts.push(add_hash_statment(add_hash));
|
||||
}
|
||||
}
|
||||
|
||||
block.stmts = new_stmts;
|
||||
block
|
||||
}
|
||||
|
||||
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
|
||||
let mut new_items = vec![];
|
||||
for item in items {
|
||||
let new_item = item.fold_children_with(self);
|
||||
if let Some((default_ident, default_expr)) = &self.add_default_decl {
|
||||
new_items.push(ModuleItem::Stmt(Stmt::Decl(Decl::Var(VarDecl {
|
||||
kind: VarDeclKind::Const,
|
||||
declare: false,
|
||||
decls: vec![VarDeclarator {
|
||||
name: Pat::Ident(BindingIdent {
|
||||
id: Ident {
|
||||
sym: default_ident.clone().into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
},
|
||||
type_ann: None,
|
||||
}),
|
||||
init: Some(Box::new(default_expr.clone())),
|
||||
definite: false,
|
||||
span: DUMMY_SP,
|
||||
}],
|
||||
span: DUMMY_SP,
|
||||
}))));
|
||||
self.add_default_decl = None;
|
||||
if let Some(add_hash) = self.add_hash.take() {
|
||||
new_items.push(ModuleItem::Stmt(add_hash_statment(add_hash)));
|
||||
}
|
||||
}
|
||||
if !is_styled_css_import(&new_item) {
|
||||
new_items.push(new_item);
|
||||
}
|
||||
if let Some(add_hash) = self.add_hash.take() {
|
||||
new_items.push(ModuleItem::Stmt(add_hash_statment(add_hash)));
|
||||
}
|
||||
}
|
||||
|
||||
if self.file_has_styled_jsx || self.file_has_css_resolve {
|
||||
prepend(
|
||||
&mut new_items,
|
||||
styled_jsx_import_decl(&self.style_import_name.as_ref().unwrap()),
|
||||
);
|
||||
}
|
||||
|
||||
new_items
|
||||
}
|
||||
|
||||
fn fold_function(&mut self, func: Function) -> Function {
|
||||
let nearest_scope_bindings = self.nearest_scope_bindings.clone();
|
||||
self.nearest_scope_bindings = collect_decls(&func);
|
||||
let func = func.fold_children_with(self);
|
||||
self.nearest_scope_bindings = nearest_scope_bindings;
|
||||
func
|
||||
}
|
||||
|
||||
fn fold_arrow_expr(&mut self, func: ArrowExpr) -> ArrowExpr {
|
||||
let current_bindings = self.nearest_scope_bindings.clone();
|
||||
self.nearest_scope_bindings = collect_decls(&func);
|
||||
let func = func.fold_children_with(self);
|
||||
self.nearest_scope_bindings = current_bindings;
|
||||
func
|
||||
}
|
||||
|
||||
fn fold_module(&mut self, module: Module) -> Module {
|
||||
self.bindings = collect_decls(&module);
|
||||
self.evaluator = Some(Evaluator::new(module.clone(), Marks::new()));
|
||||
self.style_import_name = Some(get_usable_import_specifier(&module.body));
|
||||
module.fold_children_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl StyledJSXTransformer {
|
||||
fn check_children_for_jsx_styles(&mut self, children: &Vec<JSXElementChild>) {
|
||||
let mut styles = vec![];
|
||||
for i in 0..children.len() {
|
||||
if let JSXElementChild::JSXElement(child_el) = &children[i] {
|
||||
if is_styled_jsx(&child_el) {
|
||||
self.file_has_styled_jsx = true;
|
||||
self.has_styled_jsx = true;
|
||||
let expr = get_style_expr(&child_el);
|
||||
let style_info = self.get_jsx_style(expr, is_global(&child_el));
|
||||
styles.insert(0, style_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.has_styled_jsx {
|
||||
let (static_class_name, class_name) =
|
||||
compute_class_names(&styles, self.style_import_name.as_ref().unwrap());
|
||||
self.styles = styles;
|
||||
self.static_class_name = static_class_name;
|
||||
self.class_name = class_name;
|
||||
}
|
||||
}
|
||||
|
||||
fn get_jsx_style(&mut self, expr: &Expr, is_global_jsx_element: bool) -> JSXStyle {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
let css: String;
|
||||
let css_span: Span;
|
||||
let is_dynamic;
|
||||
let mut expressions = vec![];
|
||||
match expr {
|
||||
Expr::Lit(Lit::Str(Str { value, span, .. })) => {
|
||||
hasher.write(value.as_ref().as_bytes());
|
||||
css = value.to_string().clone();
|
||||
css_span = span.clone();
|
||||
is_dynamic = false;
|
||||
}
|
||||
Expr::Tpl(Tpl {
|
||||
exprs,
|
||||
quasis,
|
||||
span,
|
||||
}) => {
|
||||
if exprs.is_empty() {
|
||||
hasher.write(quasis[0].raw.value.as_bytes());
|
||||
css = quasis[0].raw.value.to_string();
|
||||
css_span = span.clone();
|
||||
is_dynamic = false;
|
||||
} else {
|
||||
expr.clone().hash(&mut hasher);
|
||||
let mut s = String::new();
|
||||
for i in 0..quasis.len() {
|
||||
let placeholder = if i == quasis.len() - 1 {
|
||||
String::new()
|
||||
} else {
|
||||
format!("__styled-jsx-placeholder__{}", i)
|
||||
};
|
||||
s = format!("{}{}{}", s, quasis[i].raw.value, placeholder)
|
||||
}
|
||||
css = String::from(s);
|
||||
css_span = *span;
|
||||
let res = self.evaluator.as_mut().unwrap().eval(&expr);
|
||||
is_dynamic = if let Some(EvalResult::Lit(_)) = res {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
};
|
||||
expressions = exprs.clone();
|
||||
}
|
||||
}
|
||||
Expr::Ident(ident) => {
|
||||
return JSXStyle::External(ExternalStyle {
|
||||
expr: Expr::Member(MemberExpr {
|
||||
obj: ExprOrSuper::Expr(Box::new(Expr::Ident(ident.clone()))),
|
||||
prop: Box::new(Expr::Ident(Ident {
|
||||
sym: "__hash".into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
})),
|
||||
computed: false,
|
||||
span: DUMMY_SP,
|
||||
}),
|
||||
identifier: ident.clone(),
|
||||
is_global: is_global_jsx_element,
|
||||
});
|
||||
}
|
||||
_ => panic!("Not implemented"), // TODO: handle bad style input
|
||||
}
|
||||
|
||||
return JSXStyle::Local(LocalStyle {
|
||||
hash: format!("{:x}", hasher.finish()),
|
||||
css,
|
||||
css_span,
|
||||
is_dynamic,
|
||||
expressions,
|
||||
});
|
||||
}
|
||||
|
||||
fn replace_jsx_style(&mut self, el: &JSXElement) -> Result<JSXElement, Error> {
|
||||
let style_info = self.styles.pop().unwrap();
|
||||
|
||||
let is_global = el.opening.attrs.iter().any(|attr| {
|
||||
if let JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
name: JSXAttrName::Ident(Ident { sym, .. }),
|
||||
..
|
||||
}) = &attr
|
||||
{
|
||||
if sym == "global" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
});
|
||||
|
||||
match &style_info {
|
||||
JSXStyle::Local(style_info) => {
|
||||
let css = transform_css(&style_info, is_global, &self.static_class_name)?;
|
||||
Ok(make_local_styled_jsx_el(
|
||||
&style_info,
|
||||
css,
|
||||
self.style_import_name.as_ref().unwrap(),
|
||||
))
|
||||
}
|
||||
JSXStyle::External(style) => Ok(make_external_styled_jsx_el(
|
||||
style,
|
||||
self.style_import_name.as_ref().unwrap(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn process_tagged_template_expr(&mut self, tagged_tpl: &TaggedTpl) -> Result<Expr, Error> {
|
||||
let style = self.get_jsx_style(&Expr::Tpl(tagged_tpl.tpl.clone()), false);
|
||||
let styles = vec![style];
|
||||
let (static_class_name, class_name) =
|
||||
compute_class_names(&styles, &self.style_import_name.as_ref().unwrap());
|
||||
let tag = match &*tagged_tpl.tag {
|
||||
Expr::Ident(Ident { sym, .. }) => sym.to_string(),
|
||||
Expr::Member(MemberExpr { prop, .. }) => {
|
||||
if let Expr::Ident(Ident { sym, .. }) = &**prop {
|
||||
sym.to_string()
|
||||
} else {
|
||||
String::from("not_styled_jsx_tag")
|
||||
}
|
||||
}
|
||||
_ => String::from("not_styled_jsx_tag"),
|
||||
};
|
||||
let style = if let JSXStyle::Local(style) = &styles[0] {
|
||||
if tag != "resolve" {
|
||||
self.external_hash = Some(hash_string(&style.hash.clone()));
|
||||
}
|
||||
style
|
||||
} else {
|
||||
bail!("This shouldn't happen, we already know that this is a template literal");
|
||||
};
|
||||
let css = transform_css(&style, tag == "global", &static_class_name)?;
|
||||
if tag == "resolve" {
|
||||
self.file_has_css_resolve = true;
|
||||
return Ok(Expr::Object(ObjectLit {
|
||||
props: vec![
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident {
|
||||
sym: "styles".into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}),
|
||||
value: Box::new(Expr::JSXElement(Box::new(make_local_styled_jsx_el(
|
||||
&style,
|
||||
css,
|
||||
&self.style_import_name.as_ref().unwrap(),
|
||||
)))),
|
||||
}))),
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident {
|
||||
sym: "className".into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}),
|
||||
value: Box::new(class_name.unwrap()),
|
||||
}))),
|
||||
],
|
||||
span: DUMMY_SP,
|
||||
}));
|
||||
}
|
||||
Ok(Expr::New(NewExpr {
|
||||
callee: Box::new(Expr::Ident(Ident {
|
||||
sym: "String".into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
})),
|
||||
args: Some(vec![ExprOrSpread {
|
||||
expr: Box::new(css),
|
||||
spread: None,
|
||||
}]),
|
||||
span: DUMMY_SP,
|
||||
type_args: None,
|
||||
}))
|
||||
}
|
||||
|
||||
fn reset_styles_state(&mut self) {
|
||||
self.has_styled_jsx = false;
|
||||
self.static_class_name = None;
|
||||
self.class_name = None;
|
||||
}
|
||||
}
|
||||
|
||||
fn is_styled_jsx(el: &JSXElement) -> bool {
|
||||
if let JSXElementName::Ident(Ident { sym, .. }) = &el.opening.name {
|
||||
if sym != "style" {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
el.opening.attrs.iter().any(|attr| {
|
||||
if let JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
name: JSXAttrName::Ident(Ident { sym, .. }),
|
||||
..
|
||||
}) = &attr
|
||||
{
|
||||
if sym == "jsx" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
fn is_global(el: &JSXElement) -> bool {
|
||||
if let JSXElementName::Ident(Ident { sym, .. }) = &el.opening.name {
|
||||
if sym != "style" {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
el.opening.attrs.iter().any(|attr| {
|
||||
if let JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
name: JSXAttrName::Ident(Ident { sym, .. }),
|
||||
..
|
||||
}) = &attr
|
||||
{
|
||||
if sym == "global" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
fn get_style_expr(el: &JSXElement) -> &Expr {
|
||||
let non_whitespace_children: &Vec<&JSXElementChild> = &el
|
||||
.children
|
||||
.iter()
|
||||
.filter(|child| {
|
||||
if let JSXElementChild::JSXText(txt) = child {
|
||||
if txt.value.chars().all(char::is_whitespace) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
})
|
||||
.collect();
|
||||
|
||||
if non_whitespace_children.len() != 1 {
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
el.span,
|
||||
&format!(
|
||||
"Expected one child under JSX style tag, but got {} (eg: <style jsx>{{`hi`}}</style>)",
|
||||
non_whitespace_children.len()
|
||||
),
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
panic!("styled-jsx style error");
|
||||
}
|
||||
|
||||
if let JSXElementChild::JSXExprContainer(JSXExprContainer {
|
||||
expr: JSXExpr::Expr(expr),
|
||||
..
|
||||
}) = non_whitespace_children[0]
|
||||
{
|
||||
return &**expr;
|
||||
}
|
||||
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
el.span,
|
||||
"Expected a single child of type JSXExpressionContainer under JSX Style tag (eg: <style \
|
||||
jsx>{{`hi`}}</style>)",
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
panic!("next-swc compilation error");
|
||||
}
|
||||
|
||||
fn get_existing_class_name(el: &JSXOpeningElement) -> (Option<Expr>, Option<usize>, Option<usize>) {
|
||||
let mut spreads = vec![];
|
||||
let mut class_name_expr = None;
|
||||
let mut existing_index = None;
|
||||
let mut existing_spread_index = None;
|
||||
for i in (0..el.attrs.len()).rev() {
|
||||
match &el.attrs[i] {
|
||||
JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
name: JSXAttrName::Ident(Ident { sym, .. }),
|
||||
value,
|
||||
..
|
||||
}) => {
|
||||
if sym == "className" {
|
||||
existing_index = Some(i);
|
||||
class_name_expr = match value {
|
||||
Some(JSXAttrValue::Lit(str_lit)) => Some(Expr::Lit(str_lit.clone())),
|
||||
Some(JSXAttrValue::JSXExprContainer(JSXExprContainer {
|
||||
expr: JSXExpr::Expr(expr),
|
||||
..
|
||||
})) => Some(*expr.clone()),
|
||||
None => None,
|
||||
_ => None,
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
JSXAttrOrSpread::SpreadElement(SpreadElement { expr, .. }) => {
|
||||
if let Expr::Object(ObjectLit { props, .. }) = &**expr {
|
||||
let mut has_spread = false;
|
||||
let mut has_class_name = false;
|
||||
for j in 0..props.len() {
|
||||
if let PropOrSpread::Prop(prop) = &props[j] {
|
||||
if let Prop::KeyValue(KeyValueProp { key, value }) = &**prop {
|
||||
if let PropName::Ident(Ident { sym, .. }) = key {
|
||||
if sym == "className" {
|
||||
has_class_name = true;
|
||||
class_name_expr = Some(*value.clone());
|
||||
if props.len() == 1 {
|
||||
existing_spread_index = Some(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
has_spread = true;
|
||||
}
|
||||
}
|
||||
if has_class_name {
|
||||
break;
|
||||
}
|
||||
if !has_spread {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let valid_spread = match &**expr {
|
||||
Expr::Member(_) => true,
|
||||
Expr::Ident(_) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if valid_spread {
|
||||
let member_dot_name = Expr::Member(MemberExpr {
|
||||
obj: ExprOrSuper::Expr(Box::new(*expr.clone())),
|
||||
prop: Box::new(Expr::Ident(ident("className"))),
|
||||
span: DUMMY_SP,
|
||||
computed: false,
|
||||
});
|
||||
// `${name} && ${name}.className != null && ${name}.className`
|
||||
spreads.push(and(
|
||||
and(
|
||||
*expr.clone(),
|
||||
not_eq(
|
||||
member_dot_name.clone(),
|
||||
Expr::Lit(Lit::Null(Null { span: DUMMY_SP })),
|
||||
),
|
||||
),
|
||||
member_dot_name.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
let spread_expr = match spreads.len() {
|
||||
0 => None,
|
||||
_ => Some(join_spreads(spreads)),
|
||||
};
|
||||
|
||||
let class_name_expr = match class_name_expr {
|
||||
Some(e @ Expr::Tpl(_) | e @ Expr::Lit(Lit::Str(_))) => Some(e),
|
||||
None => None,
|
||||
_ => Some(or(class_name_expr.unwrap(), string_literal_expr(""))),
|
||||
};
|
||||
|
||||
let existing_class_name_expr = match (spread_expr, class_name_expr) {
|
||||
(Some(spread_expr), Some(class_name_expr)) => Some(or(spread_expr, class_name_expr)),
|
||||
(Some(spread_expr), None) => Some(or(spread_expr, string_literal_expr(""))),
|
||||
(None, Some(class_name_expr)) => Some(class_name_expr),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
(
|
||||
existing_class_name_expr,
|
||||
existing_index,
|
||||
existing_spread_index,
|
||||
)
|
||||
}
|
||||
|
||||
fn join_spreads(spreads: Vec<Expr>) -> Expr {
|
||||
let mut new_expr = spreads[0].clone();
|
||||
for i in 1..spreads.len() {
|
||||
new_expr = Expr::Bin(BinExpr {
|
||||
op: op!("||"),
|
||||
left: Box::new(new_expr.clone()),
|
||||
right: Box::new(spreads[i].clone()),
|
||||
span: DUMMY_SP,
|
||||
})
|
||||
}
|
||||
new_expr
|
||||
}
|
||||
|
||||
fn add_hash_statment((ident, hash): (String, String)) -> Stmt {
|
||||
Stmt::Expr(ExprStmt {
|
||||
expr: Box::new(Expr::Assign(AssignExpr {
|
||||
left: PatOrExpr::Expr(Box::new(Expr::Member(MemberExpr {
|
||||
obj: ExprOrSuper::Expr(Box::new(Expr::Ident(Ident {
|
||||
sym: ident.into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}))),
|
||||
prop: Box::new(Expr::Ident(Ident {
|
||||
sym: "__hash".into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
})),
|
||||
span: DUMMY_SP,
|
||||
computed: false,
|
||||
}))),
|
||||
right: Box::new(string_literal_expr(&hash)),
|
||||
op: op!("="),
|
||||
span: DUMMY_SP,
|
||||
})),
|
||||
span: DUMMY_SP,
|
||||
})
|
||||
}
|
||||
|
||||
fn is_styled_css_import(item: &ModuleItem) -> bool {
|
||||
if let ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl {
|
||||
src: Str { value, .. },
|
||||
..
|
||||
})) = item
|
||||
{
|
||||
if value == "styled-jsx/css" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
255
packages/next/build/swc/src/styled_jsx/transform_css.rs
Normal file
255
packages/next/build/swc/src/styled_jsx/transform_css.rs
Normal file
|
@ -0,0 +1,255 @@
|
|||
use easy_error::{bail, Error};
|
||||
use swc_common::{source_map::Pos, BytePos, Span, SyntaxContext, DUMMY_SP};
|
||||
use swc_css::ast::*;
|
||||
use swc_css::parser::{parse_str, parse_tokens, parser::ParserConfig};
|
||||
use swc_css::visit::{VisitMut, VisitMutWith};
|
||||
use swc_css_codegen::{
|
||||
writer::basic::{BasicCssWriter, BasicCssWriterConfig},
|
||||
CodegenConfig, Emit,
|
||||
};
|
||||
use swc_ecmascript::ast::{Expr, Str, StrKind, Tpl, TplElement};
|
||||
use swc_ecmascript::utils::HANDLER;
|
||||
use swc_stylis::prefixer::prefixer;
|
||||
|
||||
use super::{hash_string, string_literal_expr, LocalStyle};
|
||||
|
||||
pub fn transform_css(
|
||||
style_info: &LocalStyle,
|
||||
is_global: bool,
|
||||
class_name: &Option<String>,
|
||||
) -> Result<Expr, Error> {
|
||||
let result: Result<Stylesheet, _> = parse_str(
|
||||
&style_info.css,
|
||||
style_info.css_span.lo,
|
||||
style_info.css_span.hi,
|
||||
ParserConfig {
|
||||
parse_values: false,
|
||||
},
|
||||
);
|
||||
let mut ss = match result {
|
||||
Ok(ss) => ss,
|
||||
Err(_) => {
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
style_info.css_span,
|
||||
"Failed to parse css in styled jsx component",
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
bail!("Failed to parse css");
|
||||
}
|
||||
};
|
||||
// ? Do we need to support optionally prefixing?
|
||||
ss.visit_mut_with(&mut prefixer());
|
||||
ss.visit_mut_with(&mut Namespacer {
|
||||
class_name: match class_name {
|
||||
Some(s) => s.clone(),
|
||||
None => format!("jsx-{}", &hash_string(&style_info.hash)),
|
||||
},
|
||||
is_global,
|
||||
is_dynamic: style_info.is_dynamic,
|
||||
});
|
||||
|
||||
let mut s = String::new();
|
||||
{
|
||||
let mut wr = BasicCssWriter::new(&mut s, BasicCssWriterConfig { indent: " " });
|
||||
let mut gen = swc_css_codegen::CodeGenerator::new(&mut wr, CodegenConfig { minify: true });
|
||||
|
||||
gen.emit(&ss).unwrap();
|
||||
}
|
||||
|
||||
if style_info.expressions.len() == 0 {
|
||||
return Ok(string_literal_expr(&s));
|
||||
}
|
||||
|
||||
let mut parts: Vec<&str> = s.split("__styled-jsx-placeholder__").collect();
|
||||
let mut final_expressions = vec![];
|
||||
for i in 1..parts.len() {
|
||||
let expression_index = parts[i].chars().nth(0).unwrap().to_digit(10).unwrap() as usize;
|
||||
final_expressions.push(style_info.expressions[expression_index].clone());
|
||||
let substr = &parts[i][1..];
|
||||
parts[i] = substr;
|
||||
}
|
||||
|
||||
Ok(Expr::Tpl(Tpl {
|
||||
quasis: parts
|
||||
.iter()
|
||||
.map(|quasi| TplElement {
|
||||
cooked: None, // ? Do we need cooked as well
|
||||
raw: Str {
|
||||
value: (*quasi).into(),
|
||||
span: DUMMY_SP,
|
||||
has_escape: false,
|
||||
kind: StrKind::Synthesized {},
|
||||
},
|
||||
span: DUMMY_SP,
|
||||
tail: false,
|
||||
})
|
||||
.collect(),
|
||||
exprs: final_expressions,
|
||||
span: DUMMY_SP,
|
||||
}))
|
||||
}
|
||||
|
||||
struct Namespacer {
|
||||
class_name: String,
|
||||
is_global: bool,
|
||||
is_dynamic: bool,
|
||||
}
|
||||
|
||||
impl VisitMut for Namespacer {
|
||||
fn visit_mut_complex_selector(&mut self, node: &mut ComplexSelector) {
|
||||
let mut new_selectors = vec![];
|
||||
for selector in &node.selectors {
|
||||
let transformed_selectors = self.get_transformed_selectors(selector.clone());
|
||||
new_selectors.extend(transformed_selectors);
|
||||
}
|
||||
node.selectors = new_selectors;
|
||||
}
|
||||
}
|
||||
|
||||
impl Namespacer {
|
||||
fn get_transformed_selectors(&mut self, mut node: CompoundSelector) -> Vec<CompoundSelector> {
|
||||
if self.is_global {
|
||||
return vec![node];
|
||||
}
|
||||
|
||||
let mut pseudo_index = None;
|
||||
for (i, selector) in node.subclass_selectors.iter().enumerate() {
|
||||
if let SubclassSelector::Pseudo(PseudoSelector { name, args, .. }) = selector {
|
||||
// One off global selector
|
||||
if &name.value == "global" {
|
||||
let block_tokens = get_block_tokens(&args);
|
||||
let mut args = args.clone();
|
||||
args.tokens.extend(block_tokens);
|
||||
let complex_selectors: Vec<ComplexSelector> = parse_tokens(
|
||||
&args,
|
||||
ParserConfig {
|
||||
parse_values: false,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
return complex_selectors[0].selectors.clone();
|
||||
} else if pseudo_index.is_none() {
|
||||
pseudo_index = Some(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let subclass_selector = match self.is_dynamic {
|
||||
true => "__jsx-style-dynamic-selector",
|
||||
false => &self.class_name,
|
||||
};
|
||||
let insert_index = match pseudo_index {
|
||||
None => node.subclass_selectors.len(),
|
||||
Some(i) => i,
|
||||
};
|
||||
node.subclass_selectors.insert(
|
||||
insert_index,
|
||||
SubclassSelector::Class(ClassSelector {
|
||||
span: DUMMY_SP,
|
||||
text: Text {
|
||||
value: subclass_selector.into(),
|
||||
span: DUMMY_SP,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
vec![node]
|
||||
}
|
||||
}
|
||||
|
||||
fn get_block_tokens(selector_tokens: &Tokens) -> Vec<TokenAndSpan> {
|
||||
let start_pos = selector_tokens.span.hi.to_u32();
|
||||
vec![
|
||||
TokenAndSpan {
|
||||
span: Span {
|
||||
lo: BytePos(start_pos + 0),
|
||||
hi: BytePos(start_pos + 1),
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
token: Token::WhiteSpace,
|
||||
},
|
||||
TokenAndSpan {
|
||||
span: Span {
|
||||
lo: BytePos(start_pos + 1),
|
||||
hi: BytePos(start_pos + 2),
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
token: Token::LBrace,
|
||||
},
|
||||
TokenAndSpan {
|
||||
span: Span {
|
||||
lo: BytePos(start_pos + 2),
|
||||
hi: BytePos(start_pos + 3),
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
token: Token::WhiteSpace,
|
||||
},
|
||||
TokenAndSpan {
|
||||
span: Span {
|
||||
lo: BytePos(start_pos + 3),
|
||||
hi: BytePos(start_pos + 8),
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
token: Token::Ident("color".into()),
|
||||
},
|
||||
TokenAndSpan {
|
||||
span: Span {
|
||||
lo: BytePos(start_pos + 8),
|
||||
hi: BytePos(start_pos + 9),
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
token: Token::Colon,
|
||||
},
|
||||
TokenAndSpan {
|
||||
span: Span {
|
||||
lo: BytePos(start_pos + 9),
|
||||
hi: BytePos(start_pos + 10),
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
token: Token::WhiteSpace,
|
||||
},
|
||||
TokenAndSpan {
|
||||
span: Span {
|
||||
lo: BytePos(start_pos + 10),
|
||||
hi: BytePos(start_pos + 13),
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
token: Token::Ident("red".into()),
|
||||
},
|
||||
TokenAndSpan {
|
||||
span: Span {
|
||||
lo: BytePos(start_pos + 13),
|
||||
hi: BytePos(start_pos + 14),
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
token: Token::Semi,
|
||||
},
|
||||
TokenAndSpan {
|
||||
span: Span {
|
||||
lo: BytePos(start_pos + 14),
|
||||
hi: BytePos(start_pos + 15),
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
token: Token::WhiteSpace,
|
||||
},
|
||||
TokenAndSpan {
|
||||
span: Span {
|
||||
lo: BytePos(start_pos + 15),
|
||||
hi: BytePos(start_pos + 16),
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
token: Token::RBrace,
|
||||
},
|
||||
TokenAndSpan {
|
||||
span: Span {
|
||||
lo: BytePos(start_pos + 16),
|
||||
hi: BytePos(start_pos + 17),
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
token: Token::WhiteSpace,
|
||||
},
|
||||
]
|
||||
}
|
365
packages/next/build/swc/src/styled_jsx/utils.rs
Normal file
365
packages/next/build/swc/src/styled_jsx/utils.rs
Normal file
|
@ -0,0 +1,365 @@
|
|||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::Hasher;
|
||||
use swc_common::DUMMY_SP;
|
||||
use swc_ecmascript::ast::*;
|
||||
|
||||
use super::{ExternalStyle, JSXStyle, LocalStyle};
|
||||
|
||||
fn tpl_element(value: &str) -> TplElement {
|
||||
TplElement {
|
||||
raw: Str {
|
||||
value: value.into(),
|
||||
span: DUMMY_SP,
|
||||
kind: StrKind::Synthesized,
|
||||
has_escape: false,
|
||||
},
|
||||
cooked: None,
|
||||
span: DUMMY_SP,
|
||||
tail: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_class_names(
|
||||
styles: &Vec<JSXStyle>,
|
||||
style_import_name: &str,
|
||||
) -> (Option<String>, Option<Expr>) {
|
||||
let mut static_class_name = None;
|
||||
let mut external_jsx_id = None;
|
||||
let mut static_hashes = vec![];
|
||||
let mut dynamic_styles = vec![];
|
||||
let mut external_styles = vec![];
|
||||
for style_info in styles {
|
||||
match &style_info {
|
||||
JSXStyle::Local(style_info) => {
|
||||
if !style_info.is_dynamic {
|
||||
static_hashes.push(style_info.hash.clone());
|
||||
} else {
|
||||
dynamic_styles.push(style_info.clone());
|
||||
}
|
||||
}
|
||||
JSXStyle::External(external) => {
|
||||
if !external.is_global {
|
||||
external_styles.push(external.expr.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if external_styles.len() > 0 {
|
||||
let mut quasis = vec![tpl_element("jsx-")];
|
||||
for _i in 1..external_styles.len() {
|
||||
quasis.push(tpl_element(" jsx-"))
|
||||
}
|
||||
quasis.push(tpl_element(""));
|
||||
external_jsx_id = Some(Expr::Tpl(Tpl {
|
||||
quasis,
|
||||
exprs: external_styles
|
||||
.iter()
|
||||
.map(|external| Box::new(external.clone()))
|
||||
.collect(),
|
||||
span: DUMMY_SP,
|
||||
}));
|
||||
}
|
||||
|
||||
if static_hashes.len() > 0 {
|
||||
static_class_name = Some(format!("jsx-{}", hash_string(&static_hashes.join(","))));
|
||||
}
|
||||
|
||||
let dynamic_class_name = match dynamic_styles.len() {
|
||||
0 => None,
|
||||
_ => Some(Expr::Call(CallExpr {
|
||||
callee: ExprOrSuper::Expr(Box::new(Expr::Member(MemberExpr {
|
||||
obj: ExprOrSuper::Expr(Box::new(Expr::Ident(Ident {
|
||||
sym: style_import_name.into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}))),
|
||||
prop: Box::new(Expr::Ident(Ident {
|
||||
sym: "dynamic".into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
})),
|
||||
span: DUMMY_SP,
|
||||
computed: false,
|
||||
}))),
|
||||
args: dynamic_styles
|
||||
.iter()
|
||||
.map(|style_info| {
|
||||
let hash_input = match &static_class_name {
|
||||
Some(class_name) => format!("{}{}", style_info.hash, class_name),
|
||||
None => style_info.hash.clone(),
|
||||
};
|
||||
ExprOrSpread {
|
||||
expr: Box::new(Expr::Array(ArrayLit {
|
||||
elems: vec![
|
||||
Some(ExprOrSpread {
|
||||
expr: Box::new(string_literal_expr(&hash_string(&hash_input))),
|
||||
spread: None,
|
||||
}),
|
||||
Some(ExprOrSpread {
|
||||
expr: Box::new(Expr::Array(ArrayLit {
|
||||
elems: style_info
|
||||
.expressions
|
||||
.iter()
|
||||
.map(|expression| {
|
||||
Some(ExprOrSpread {
|
||||
expr: expression.clone(),
|
||||
spread: None,
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
span: DUMMY_SP,
|
||||
})),
|
||||
spread: None,
|
||||
}),
|
||||
],
|
||||
span: DUMMY_SP,
|
||||
})),
|
||||
spread: None,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
span: DUMMY_SP,
|
||||
type_args: None,
|
||||
})),
|
||||
};
|
||||
|
||||
let class_name_expr = match (
|
||||
static_class_name.clone(),
|
||||
dynamic_class_name,
|
||||
external_jsx_id,
|
||||
) {
|
||||
(Some(static_class_name), Some(dynamic_class_name), Some(external_jsx_id)) => Some(add(
|
||||
add(
|
||||
external_jsx_id,
|
||||
string_literal_expr(&format!(" {} ", static_class_name)),
|
||||
),
|
||||
dynamic_class_name,
|
||||
)),
|
||||
(Some(static_class_name), Some(dynamic_class_name), None) => Some(add(
|
||||
string_literal_expr(&format!("{} ", static_class_name)),
|
||||
dynamic_class_name,
|
||||
)),
|
||||
(Some(static_class_name), None, Some(external_jsx_id)) => Some(add(
|
||||
string_literal_expr(&format!("{} ", static_class_name)),
|
||||
external_jsx_id,
|
||||
)),
|
||||
(None, Some(dynamic_class_name), Some(external_jsx_id)) => Some(add(
|
||||
add(external_jsx_id, string_literal_expr(" ")),
|
||||
dynamic_class_name,
|
||||
)),
|
||||
(Some(static_class_name), None, None) => Some(string_literal_expr(&static_class_name)),
|
||||
(None, Some(dynamic_class_name), None) => Some(dynamic_class_name),
|
||||
(None, None, Some(external_jsx_id)) => Some(external_jsx_id),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
(static_class_name, class_name_expr)
|
||||
}
|
||||
|
||||
pub fn make_external_styled_jsx_el(style: &ExternalStyle, style_import_name: &str) -> JSXElement {
|
||||
let attrs = vec![JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
name: JSXAttrName::Ident(Ident {
|
||||
sym: "id".into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}),
|
||||
value: Some(JSXAttrValue::JSXExprContainer(JSXExprContainer {
|
||||
expr: JSXExpr::Expr(Box::new(style.expr.clone())),
|
||||
span: DUMMY_SP,
|
||||
})),
|
||||
span: DUMMY_SP,
|
||||
})];
|
||||
let opening = JSXOpeningElement {
|
||||
name: JSXElementName::Ident(Ident {
|
||||
sym: style_import_name.into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}),
|
||||
attrs,
|
||||
span: DUMMY_SP,
|
||||
self_closing: false,
|
||||
type_args: None,
|
||||
};
|
||||
|
||||
let closing = Some(JSXClosingElement {
|
||||
name: JSXElementName::Ident(Ident {
|
||||
sym: style_import_name.into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}),
|
||||
span: DUMMY_SP,
|
||||
});
|
||||
|
||||
let children = vec![JSXElementChild::JSXExprContainer(JSXExprContainer {
|
||||
expr: JSXExpr::Expr(Box::new(Expr::Ident(style.identifier.clone()))),
|
||||
span: DUMMY_SP,
|
||||
})];
|
||||
JSXElement {
|
||||
opening,
|
||||
closing,
|
||||
children,
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_local_styled_jsx_el(
|
||||
style_info: &LocalStyle,
|
||||
css_expr: Expr,
|
||||
style_import_name: &str,
|
||||
) -> JSXElement {
|
||||
let mut attrs = vec![JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
name: JSXAttrName::Ident(Ident {
|
||||
sym: "id".into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}),
|
||||
value: Some(JSXAttrValue::JSXExprContainer(JSXExprContainer {
|
||||
expr: JSXExpr::Expr(Box::new(string_literal_expr(
|
||||
hash_string(&style_info.hash).as_str(),
|
||||
))),
|
||||
span: DUMMY_SP,
|
||||
})),
|
||||
span: DUMMY_SP,
|
||||
})];
|
||||
|
||||
if style_info.is_dynamic {
|
||||
attrs.push(JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
name: JSXAttrName::Ident(Ident {
|
||||
sym: "dynamic".into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}),
|
||||
value: Some(JSXAttrValue::JSXExprContainer(JSXExprContainer {
|
||||
expr: JSXExpr::Expr(Box::new(Expr::Array(ArrayLit {
|
||||
elems: style_info
|
||||
.expressions
|
||||
.iter()
|
||||
.map(|expression| {
|
||||
Some(ExprOrSpread {
|
||||
expr: expression.clone(),
|
||||
spread: None,
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
span: DUMMY_SP,
|
||||
}))),
|
||||
span: DUMMY_SP,
|
||||
})),
|
||||
span: DUMMY_SP,
|
||||
}));
|
||||
}
|
||||
|
||||
let opening = JSXOpeningElement {
|
||||
name: JSXElementName::Ident(Ident {
|
||||
sym: style_import_name.into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}),
|
||||
attrs,
|
||||
span: DUMMY_SP,
|
||||
self_closing: false,
|
||||
type_args: None,
|
||||
};
|
||||
|
||||
let closing = Some(JSXClosingElement {
|
||||
name: JSXElementName::Ident(Ident {
|
||||
sym: style_import_name.into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}),
|
||||
span: DUMMY_SP,
|
||||
});
|
||||
|
||||
let children = vec![JSXElementChild::JSXExprContainer(JSXExprContainer {
|
||||
expr: JSXExpr::Expr(Box::new(css_expr)),
|
||||
span: DUMMY_SP,
|
||||
})];
|
||||
JSXElement {
|
||||
opening,
|
||||
closing,
|
||||
children,
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_usable_import_specifier(_items: &Vec<ModuleItem>) -> String {
|
||||
// TODO
|
||||
String::from("_JSXStyle")
|
||||
}
|
||||
|
||||
pub fn styled_jsx_import_decl(style_import_name: &str) -> ModuleItem {
|
||||
ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl {
|
||||
asserts: None,
|
||||
span: DUMMY_SP,
|
||||
type_only: false,
|
||||
specifiers: vec![ImportSpecifier::Default(ImportDefaultSpecifier {
|
||||
local: Ident {
|
||||
sym: style_import_name.into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
},
|
||||
span: DUMMY_SP,
|
||||
})],
|
||||
src: Str {
|
||||
has_escape: false,
|
||||
kind: StrKind::Synthesized {},
|
||||
span: DUMMY_SP,
|
||||
value: "styled-jsx/style".into(),
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
// TODO: maybe use DJBHasher (need to implement)
|
||||
pub fn hash_string(str: &String) -> String {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
hasher.write(str.as_bytes());
|
||||
let hash_result = hasher.finish();
|
||||
format!("{:x}", hash_result)
|
||||
}
|
||||
|
||||
pub fn string_literal_expr(str: &str) -> Expr {
|
||||
Expr::Lit(Lit::Str(Str {
|
||||
value: str.into(),
|
||||
span: DUMMY_SP,
|
||||
has_escape: false,
|
||||
kind: StrKind::Synthesized {},
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn ident(str: &str) -> Ident {
|
||||
Ident {
|
||||
sym: str.into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_capitalized(word: &str) -> bool {
|
||||
word.chars().next().unwrap().is_uppercase()
|
||||
}
|
||||
|
||||
pub fn add(left: Expr, right: Expr) -> Expr {
|
||||
binary_expr(BinaryOp::Add, left, right)
|
||||
}
|
||||
|
||||
pub fn and(left: Expr, right: Expr) -> Expr {
|
||||
binary_expr(BinaryOp::LogicalAnd, left, right)
|
||||
}
|
||||
|
||||
pub fn or(left: Expr, right: Expr) -> Expr {
|
||||
binary_expr(BinaryOp::LogicalOr, left, right)
|
||||
}
|
||||
|
||||
pub fn not_eq(left: Expr, right: Expr) -> Expr {
|
||||
binary_expr(BinaryOp::NotEq, left, right)
|
||||
}
|
||||
|
||||
pub fn binary_expr(op: BinaryOp, left: Expr, right: Expr) -> Expr {
|
||||
Expr::Bin(BinExpr {
|
||||
op,
|
||||
left: Box::new(left),
|
||||
right: Box::new(right),
|
||||
span: DUMMY_SP,
|
||||
})
|
||||
}
|
|
@ -32,6 +32,7 @@ use crate::{
|
|||
hook_optimizer::hook_optimizer,
|
||||
next_dynamic::next_dynamic,
|
||||
next_ssg::next_ssg,
|
||||
styled_jsx::styled_jsx,
|
||||
util::{CtxtExt, MapErr},
|
||||
};
|
||||
use anyhow::{Context as _, Error};
|
||||
|
@ -82,6 +83,7 @@ impl Task for TransformTask {
|
|||
Optional::new(next_ssg(), !self.options.disable_next_ssg),
|
||||
amp_attributes(),
|
||||
next_dynamic(s.name.clone(), self.options.pages_dir.clone()),
|
||||
styled_jsx()
|
||||
);
|
||||
self.c.process_js_with_custom_pass(
|
||||
s.clone(),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use self::amp_attributes::amp_attributes;
|
||||
use self::next_dynamic::next_dynamic;
|
||||
use self::next_ssg::next_ssg;
|
||||
use self::styled_jsx::styled_jsx;
|
||||
use std::path::PathBuf;
|
||||
use swc_common::{chain, comments::SingleThreadedComments, FileName};
|
||||
use swc_ecma_transforms_testing::{test, test_fixture};
|
||||
|
@ -16,6 +17,8 @@ mod amp_attributes;
|
|||
mod next_dynamic;
|
||||
#[path = "../src/next_ssg.rs"]
|
||||
mod next_ssg;
|
||||
#[path = "../src/styled_jsx/mod.rs"]
|
||||
mod styled_jsx;
|
||||
|
||||
fn syntax() -> Syntax {
|
||||
Syntax::Es(EsConfig {
|
||||
|
@ -75,3 +78,9 @@ fn next_ssg_fixture(input: PathBuf) {
|
|||
&output,
|
||||
);
|
||||
}
|
||||
|
||||
#[fixture("tests/fixture/styled-jsx/**/input.js")]
|
||||
fn styled_jsx_fixture(input: PathBuf) {
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(syntax(), &|_tr| styled_jsx(), &input, &output);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import dynamic from 'next/dynamic'
|
||||
const DynamicComponentWithCustomLoading = dynamic(
|
||||
() => import('../components/hello'),
|
||||
{
|
||||
loading: () => <p>...</p>,
|
||||
},
|
||||
{
|
||||
import dynamic from "next/dynamic";
|
||||
const DynamicComponentWithCustomLoading = dynamic(()=>import("../components/hello")
|
||||
, {
|
||||
loadableGenerated: {
|
||||
webpack: () => [require.resolveWeak('/some-project/src/some-file.js')],
|
||||
modules: ['some-file.js -> ' + '../components/hello'],
|
||||
webpack: ()=>[
|
||||
require.resolveWeak("/some-project/src/some-file.js")
|
||||
]
|
||||
,
|
||||
modules: [
|
||||
"some-file.js -> " + "../components/hello"
|
||||
]
|
||||
},
|
||||
loading: () => <p>...</p>,
|
||||
}
|
||||
)
|
||||
loading: ()=><p >...</p>
|
||||
});
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
import dynamic from 'next/dynamic'
|
||||
const DynamicComponent = dynamic(() => handleImport(import('./components/hello')), {
|
||||
loading: () => null,
|
||||
ssr: false,
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
import dynamic from "next/dynamic";
|
||||
const DynamicComponent = dynamic(()=>handleImport(import("./components/hello"))
|
||||
, {
|
||||
loadableGenerated: {
|
||||
webpack: ()=>[
|
||||
require.resolveWeak("/some-project/src/some-file.js")
|
||||
]
|
||||
,
|
||||
modules: [
|
||||
"some-file.js -> " + "./components/hello"
|
||||
]
|
||||
},
|
||||
loading: ()=>null
|
||||
,
|
||||
ssr: false
|
||||
});
|
|
@ -0,0 +1,6 @@
|
|||
const a = () => (
|
||||
<div>
|
||||
<p>hi</p>
|
||||
<style>{'woot'}</style>
|
||||
</div>
|
||||
)
|
|
@ -0,0 +1,5 @@
|
|||
const a = ()=><div >
|
||||
<p >hi</p>
|
||||
<style >{"woot"}</style>
|
||||
</div>
|
||||
;
|
|
@ -0,0 +1,55 @@
|
|||
export default () => {
|
||||
const Element = 'div'
|
||||
return (
|
||||
<div>
|
||||
<div className="test" {...test.test} />
|
||||
<div className="test" {...test.test.test} />
|
||||
<div className="test" {...this.test.test} />
|
||||
<div data-test="test" />
|
||||
<div className={'test'} />
|
||||
<div className={`test`} />
|
||||
<div className={`test${true ? ' test2' : ''}`} />
|
||||
<div className={'test ' + test} />
|
||||
<div className={['test', 'test2'].join(' ')} />
|
||||
<div className={true && 'test'} />
|
||||
<div className={test ? 'test' : null} />
|
||||
<div className={test} />
|
||||
<div className={test && 'test'} />
|
||||
<div className={test && test('test')} />
|
||||
<div className={undefined} />
|
||||
<div className={null} />
|
||||
<div className={false} />
|
||||
<div className={'test'} data-test />
|
||||
<div data-test className={'test'} />
|
||||
<div className={'test'} data-test="test" />
|
||||
<div className={'test'} {...props} />
|
||||
<div className={'test'} {...props} {...rest} />
|
||||
<div className={`test ${test ? 'test' : ''}`} {...props} />
|
||||
<div className={test && test('test')} {...props} />
|
||||
<div className={test && test('test') && 'test'} {...props} />
|
||||
<div className={test && test('test') && test2('test')} {...props} />
|
||||
<div {...props} className={'test'} />
|
||||
<div {...props} {...rest} className={'test'} />
|
||||
<div {...props} className={'test'} {...rest} />
|
||||
<div {...props} />
|
||||
<div {...props} {...rest} />
|
||||
<div {...props} data-foo {...rest} />
|
||||
<div {...props} className={'test'} data-foo {...rest} />
|
||||
<div {...{ id: 'foo' }} />
|
||||
<div {...{ className: 'foo' }} />
|
||||
<div {...{ className: 'foo' }} className="test" />
|
||||
<div className="test" {...{ className: 'foo' }} />
|
||||
<div {...{ className: 'foo' }} {...bar} />
|
||||
<div {...{ className: 'foo' }} {...bar} className="test" />
|
||||
<div className="test" {...{ className: 'foo' }} {...bar} />
|
||||
<div className="test" {...{ className: props.className }} />
|
||||
<div className="test" {...{ className: props.className }} {...bar} />
|
||||
<div className="test" {...bar} {...{ className: props.className }} />
|
||||
<div className="test" {...bar()} />
|
||||
<Element />
|
||||
<Element className="test" />
|
||||
<Element {...props} />
|
||||
<style jsx>{'div { color: red }'}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
export default (()=>{
|
||||
const Element = "div";
|
||||
return <div className={"jsx-abb4c2202db1a207"}>
|
||||
<div {...test.test} className={"jsx-abb4c2202db1a207" + " " + (test.test && test.test.className != null && test.test.className || "test")}/>
|
||||
<div {...test.test.test} className={"jsx-abb4c2202db1a207" + " " + (test.test.test && test.test.test.className != null && test.test.test.className || "test")}/>
|
||||
<div {...this.test.test} className={"jsx-abb4c2202db1a207" + " " + (this.test.test && this.test.test.className != null && this.test.test.className || "test")}/>
|
||||
<div data-test="test" className={"jsx-abb4c2202db1a207"}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + "test"}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + `test`}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + `test${true ? " test2" : ""}`}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + ("test " + test || "")}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + ([
|
||||
"test",
|
||||
"test2"
|
||||
].join(" ") || "")}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + (true && "test" || "")}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + ((test ? "test" : null) || "")}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + (test || "")}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + (test && "test" || "")}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + (test && test("test") || "")}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + (undefined || "")}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + (null || "")}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + (false || "")}/>
|
||||
<div data-test className={"jsx-abb4c2202db1a207" + " " + "test"}/>
|
||||
<div data-test className={"jsx-abb4c2202db1a207" + " " + "test"}/>
|
||||
<div data-test="test" className={"jsx-abb4c2202db1a207" + " " + "test"}/>
|
||||
<div {...props} className={"jsx-abb4c2202db1a207" + " " + (props && props.className != null && props.className || "test")}/>
|
||||
<div {...props} {...rest} className={"jsx-abb4c2202db1a207" + " " + (rest && rest.className != null && rest.className || props && props.className != null && props.className || "test")}/>
|
||||
<div {...props} className={"jsx-abb4c2202db1a207" + " " + (props && props.className != null && props.className || `test ${test ? "test" : ""}`)}/>
|
||||
<div {...props} className={"jsx-abb4c2202db1a207" + " " + (props && props.className != null && props.className || test && test("test") || "")}/>
|
||||
<div {...props} className={"jsx-abb4c2202db1a207" + " " + (props && props.className != null && props.className || test && test("test") && "test" || "")}/>
|
||||
<div {...props} className={"jsx-abb4c2202db1a207" + " " + (props && props.className != null && props.className || test && test("test") && test2("test") || "")}/>
|
||||
<div {...props} className={"jsx-abb4c2202db1a207" + " " + "test"}/>
|
||||
<div {...props} {...rest} className={"jsx-abb4c2202db1a207" + " " + "test"}/>
|
||||
<div {...props} {...rest} className={"jsx-abb4c2202db1a207" + " " + (rest && rest.className != null && rest.className || "test")}/>
|
||||
<div {...props} className={"jsx-abb4c2202db1a207" + " " + (props && props.className != null && props.className || "")}/>
|
||||
<div {...props} {...rest} className={"jsx-abb4c2202db1a207" + " " + (rest && rest.className != null && rest.className || props && props.className != null && props.className || "")}/>
|
||||
<div {...props} data-foo {...rest} className={"jsx-abb4c2202db1a207" + " " + (rest && rest.className != null && rest.className || props && props.className != null && props.className || "")}/>
|
||||
<div {...props} data-foo {...rest} className={"jsx-abb4c2202db1a207" + " " + (rest && rest.className != null && rest.className || "test")}/>
|
||||
<div {...{
|
||||
id: "foo"
|
||||
}} className={"jsx-abb4c2202db1a207"}/>
|
||||
<div className={"jsx-abb4c2202db1a207" + " " + "foo"}/>
|
||||
<div {...{
|
||||
className: "foo"
|
||||
}} className={"jsx-abb4c2202db1a207" + " " + "test"}/>
|
||||
<div className="test" className={"jsx-abb4c2202db1a207" + " " + "foo"}/>
|
||||
<div {...bar} className={"jsx-abb4c2202db1a207" + " " + (bar && bar.className != null && bar.className || "foo")}/>
|
||||
<div {...{
|
||||
className: "foo"
|
||||
}} {...bar} className={"jsx-abb4c2202db1a207" + " " + "test"}/>
|
||||
<div className="test" {...bar} className={"jsx-abb4c2202db1a207" + " " + (bar && bar.className != null && bar.className || "foo")}/>
|
||||
<div className="test" className={"jsx-abb4c2202db1a207" + " " + (props.className || "")}/>
|
||||
<div className="test" {...bar} className={"jsx-abb4c2202db1a207" + " " + (bar && bar.className != null && bar.className || props.className || "")}/>
|
||||
<div className="test" {...bar} className={"jsx-abb4c2202db1a207" + " " + (props.className || "")}/>
|
||||
<div {...bar()} className={"jsx-abb4c2202db1a207" + " " + "test"}/>
|
||||
<Element className={"jsx-abb4c2202db1a207"}/>
|
||||
<Element className={"jsx-abb4c2202db1a207" + " " + "test"}/>
|
||||
<Element {...props} className={"jsx-abb4c2202db1a207" + " " + (props && props.className != null && props.className || "")}/>
|
||||
<_JSXStyle id={"abb4c2202db1a207"}>{"div.jsx-abb4c2202db1a207 {color:red}"}</_JSXStyle>
|
||||
</div>;
|
||||
});
|
|
@ -0,0 +1,166 @@
|
|||
import styles from './styles'
|
||||
|
||||
const styles2 = require('./styles2')
|
||||
|
||||
// external only
|
||||
export const Test1 = () => (
|
||||
<div>
|
||||
<p>external only</p>
|
||||
<style jsx>{styles}</style>
|
||||
<style jsx>{styles2}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
// external and static
|
||||
export const Test2 = () => (
|
||||
<div>
|
||||
<p>external and static</p>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{styles}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
// external and dynamic
|
||||
export const Test3 = ({ color }) => (
|
||||
<div>
|
||||
<p>external and dynamic</p>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: ${color};
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{styles}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
// external, static and dynamic
|
||||
export const Test4 = ({ color }) => (
|
||||
<div>
|
||||
<p>external, static and dynamic</p>
|
||||
<style jsx>{`
|
||||
p {
|
||||
display: inline-block;
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: ${color};
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{styles}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
// static only
|
||||
export const Test5 = () => (
|
||||
<div>
|
||||
<p>static only</p>
|
||||
<style jsx>{`
|
||||
p {
|
||||
display: inline-block;
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
// static and dynamic
|
||||
export const Test6 = ({ color }) => (
|
||||
<div>
|
||||
<p>static and dynamic</p>
|
||||
<style jsx>{`
|
||||
p {
|
||||
display: inline-block;
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: ${color};
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
// dynamic only
|
||||
export const Test7 = ({ color }) => (
|
||||
<div>
|
||||
<p>dynamic only</p>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: ${color};
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
// dynamic with scoped compound variable
|
||||
export const Test8 = ({ color }) => {
|
||||
if (color) {
|
||||
const innerProps = { color }
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>dynamic with scoped compound variable</p>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: ${innerProps.color};
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// dynamic with compound variable
|
||||
export const Test9 = ({ color }) => {
|
||||
const innerProps = { color }
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>dynamic with compound variable</p>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: ${innerProps.color};
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const foo = 'red'
|
||||
|
||||
// dynamic with constant variable
|
||||
export const Test10 = () => (
|
||||
<div>
|
||||
<p>dynamic with constant variable</p>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: ${foo};
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
// dynamic with complex scope
|
||||
export const Test11 = ({ color }) => {
|
||||
const items = Array.from({ length: 5 }).map((item, i) => (
|
||||
<li className="item" key={i}>
|
||||
<style jsx>{`
|
||||
.item {
|
||||
color: ${color};
|
||||
}
|
||||
`}</style>
|
||||
Item #{i + 1}
|
||||
</li>
|
||||
))
|
||||
|
||||
return <ul className="items">{items}</ul>
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
import styles from "./styles";
|
||||
const styles2 = require("./styles2");
|
||||
export const Test1 = ()=><div className={`jsx-${styles2.__hash} jsx-${styles.__hash}`}>
|
||||
<p className={`jsx-${styles2.__hash} jsx-${styles.__hash}`}>external only</p>
|
||||
<_JSXStyle id={styles.__hash}>{styles}</_JSXStyle>
|
||||
<_JSXStyle id={styles2.__hash}>{styles2}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
export const Test2 = ()=><div className={"jsx-81a68341e430a972 " + `jsx-${styles.__hash}`}>
|
||||
<p className={"jsx-81a68341e430a972 " + `jsx-${styles.__hash}`}>external and static</p>
|
||||
<_JSXStyle id={"81a68341e430a972"}>{"p.jsx-81a68341e430a972 {color:red}"}</_JSXStyle>
|
||||
<_JSXStyle id={styles.__hash}>{styles}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
export const Test3 = ({ color })=><div className={`jsx-${styles.__hash}` + " " + _JSXStyle.dynamic([
|
||||
"26b457d3bc475235",
|
||||
[
|
||||
color
|
||||
]
|
||||
])}>
|
||||
<p className={`jsx-${styles.__hash}` + " " + _JSXStyle.dynamic([
|
||||
"26b457d3bc475235",
|
||||
[
|
||||
color
|
||||
]
|
||||
])}>external and dynamic</p>
|
||||
<_JSXStyle id={"26b457d3bc475235"} dynamic={[
|
||||
color
|
||||
]}>{`p.__jsx-style-dynamic-selector {color:${color}}`}</_JSXStyle>
|
||||
<_JSXStyle id={styles.__hash}>{styles}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
export const Test4 = ({ color })=><div className={`jsx-${styles.__hash}` + " jsx-ceba8c9ce34e3d0c " + _JSXStyle.dynamic([
|
||||
"e6cca97eb9ca1a15",
|
||||
[
|
||||
color
|
||||
]
|
||||
])}>
|
||||
<p className={`jsx-${styles.__hash}` + " jsx-ceba8c9ce34e3d0c " + _JSXStyle.dynamic([
|
||||
"e6cca97eb9ca1a15",
|
||||
[
|
||||
color
|
||||
]
|
||||
])}>external, static and dynamic</p>
|
||||
<_JSXStyle id={"ceba8c9ce34e3d0c"}>{"p.jsx-ceba8c9ce34e3d0c {display:inline-block}"}</_JSXStyle>
|
||||
<_JSXStyle id={"c86b0d7e7328204f"} dynamic={[
|
||||
color
|
||||
]}>{`p.__jsx-style-dynamic-selector {color:${color}}`}</_JSXStyle>
|
||||
<_JSXStyle id={styles.__hash}>{styles}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
export const Test5 = ()=><div className={"jsx-df0159ebd3f9fb6f"}>
|
||||
<p className={"jsx-df0159ebd3f9fb6f"}>static only</p>
|
||||
<_JSXStyle id={"ceba8c9ce34e3d0c"}>{"p.jsx-df0159ebd3f9fb6f {display:inline-block}"}</_JSXStyle>
|
||||
<_JSXStyle id={"81a68341e430a972"}>{"p.jsx-df0159ebd3f9fb6f {color:red}"}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
export const Test6 = ({ color })=><div className={"jsx-ceba8c9ce34e3d0c " + _JSXStyle.dynamic([
|
||||
"a55f0611581d64ca",
|
||||
[
|
||||
color
|
||||
]
|
||||
])}>
|
||||
<p className={"jsx-ceba8c9ce34e3d0c " + _JSXStyle.dynamic([
|
||||
"a55f0611581d64ca",
|
||||
[
|
||||
color
|
||||
]
|
||||
])}>static and dynamic</p>
|
||||
<_JSXStyle id={"ceba8c9ce34e3d0c"}>{"p.jsx-ceba8c9ce34e3d0c {display:inline-block}"}</_JSXStyle>
|
||||
<_JSXStyle id={"f0677f918e6b5a01"} dynamic={[
|
||||
color
|
||||
]}>{`p.__jsx-style-dynamic-selector {color:${color}}`}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
export const Test7 = ({ color })=><div className={_JSXStyle.dynamic([
|
||||
"4adc07771eb3723",
|
||||
[
|
||||
color
|
||||
]
|
||||
])}>
|
||||
<p className={_JSXStyle.dynamic([
|
||||
"4adc07771eb3723",
|
||||
[
|
||||
color
|
||||
]
|
||||
])}>dynamic only</p>
|
||||
<_JSXStyle id={"4adc07771eb3723"} dynamic={[
|
||||
color
|
||||
]}>{`p.__jsx-style-dynamic-selector {color:${color}}`}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
export const Test8 = ({ color })=>{
|
||||
if (color) {
|
||||
const innerProps = {
|
||||
color
|
||||
};
|
||||
return <div className={_JSXStyle.dynamic([
|
||||
"a552a4a765a9ca4e",
|
||||
[
|
||||
innerProps.color
|
||||
]
|
||||
])}>
|
||||
<p className={_JSXStyle.dynamic([
|
||||
"a552a4a765a9ca4e",
|
||||
[
|
||||
innerProps.color
|
||||
]
|
||||
])}>dynamic with scoped compound variable</p>
|
||||
<_JSXStyle id={"a552a4a765a9ca4e"} dynamic={[
|
||||
innerProps.color
|
||||
]}>{`p.__jsx-style-dynamic-selector {color:${innerProps.color}}`}</_JSXStyle>
|
||||
</div>;
|
||||
}
|
||||
};
|
||||
export const Test9 = ({ color })=>{
|
||||
const innerProps = {
|
||||
color
|
||||
};
|
||||
return <div className={_JSXStyle.dynamic([
|
||||
"7ef39e3312c80ead",
|
||||
[
|
||||
innerProps.color
|
||||
]
|
||||
])}>
|
||||
<p className={_JSXStyle.dynamic([
|
||||
"7ef39e3312c80ead",
|
||||
[
|
||||
innerProps.color
|
||||
]
|
||||
])}>dynamic with compound variable</p>
|
||||
<_JSXStyle id={"7ef39e3312c80ead"} dynamic={[
|
||||
innerProps.color
|
||||
]}>{`p.__jsx-style-dynamic-selector {color:${innerProps.color}}`}</_JSXStyle>
|
||||
</div>;
|
||||
};
|
||||
const foo = "red";
|
||||
export const Test10 = ()=><div className={"jsx-688a08f9e73a5653"}>
|
||||
<p className={"jsx-688a08f9e73a5653"}>dynamic with constant variable</p>
|
||||
<_JSXStyle id={"688a08f9e73a5653"}>{`p.jsx-688a08f9e73a5653 {color:${foo}}`}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
export const Test11 = ({ color })=>{
|
||||
const items = Array.from({
|
||||
length: 5
|
||||
}).map((item, i)=><li key={i} className={_JSXStyle.dynamic([
|
||||
"ebe03db0369a2939",
|
||||
[
|
||||
color
|
||||
]
|
||||
]) + " " + "item"}>
|
||||
<_JSXStyle id={"ebe03db0369a2939"} dynamic={[
|
||||
color
|
||||
]}>{`.item.__jsx-style-dynamic-selector {color:${color}}`}</_JSXStyle>
|
||||
Item #{i + 1}
|
||||
</li>
|
||||
);
|
||||
return <ul className="items">{items}</ul>;
|
||||
};
|
|
@ -0,0 +1,14 @@
|
|||
export default class {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<p>test</p>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
export default class {
|
||||
render() {
|
||||
return <div className={"jsx-b2b86d63f35d25ee"}>
|
||||
<p className={"jsx-b2b86d63f35d25ee"}>test</p>
|
||||
<_JSXStyle id={"b2b86d63f35d25ee"}>{"p.jsx-b2b86d63f35d25ee {color:red}"}</_JSXStyle>
|
||||
</div>;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
const Test = () => (
|
||||
<div>
|
||||
<span>test</span>
|
||||
<Component />
|
||||
<style jsx>{`
|
||||
span {
|
||||
color: red;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
|
@ -0,0 +1,7 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
const Test = ()=><div className={"jsx-a9535d7d5f32c3c4"}>
|
||||
<span className={"jsx-a9535d7d5f32c3c4"}>test</span>
|
||||
<Component />
|
||||
<_JSXStyle id={"a9535d7d5f32c3c4"}>{"span.jsx-a9535d7d5f32c3c4 {color:red}"}</_JSXStyle>
|
||||
</div>
|
||||
;
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
// TODO
|
||||
|
||||
// export const _JSXStyle = '_JSXStyle-literal'
|
||||
// export default function() {
|
||||
// return (
|
||||
// <div>
|
||||
// <p>test</p>
|
||||
// <style jsx>{`
|
||||
// p {
|
||||
// color: red;
|
||||
// }
|
||||
// `}</style>
|
||||
// </div>
|
||||
// )
|
||||
// }
|
|
@ -0,0 +1,25 @@
|
|||
import css from 'styled-jsx/css'
|
||||
|
||||
export default ({ children }) => (
|
||||
<div>
|
||||
<p>{children}</p>
|
||||
<style jsx>{styles}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
const styles = css`
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
`
|
||||
|
||||
class Test extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<p>{this.props.children}</p>
|
||||
<style jsx>{styles}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
export default (({ children })=><div className={`jsx-${styles.__hash}`}>
|
||||
<p className={`jsx-${styles.__hash}`}>{children}</p>
|
||||
<_JSXStyle id={styles.__hash}>{styles}</_JSXStyle>
|
||||
</div>
|
||||
);
|
||||
const styles = new String("p.jsx-556239d258b6d66a {color:red}");
|
||||
styles.__hash = "556239d258b6d66a";
|
||||
class Test extends React.Component {
|
||||
render() {
|
||||
return <div className={`jsx-${styles.__hash}`}>
|
||||
<p className={`jsx-${styles.__hash}`}>{this.props.children}</p>
|
||||
<_JSXStyle id={styles.__hash}>{styles}</_JSXStyle>
|
||||
</div>;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
const color = 'red'
|
||||
const otherColor = 'green'
|
||||
|
||||
const A = () => (
|
||||
<div>
|
||||
<p>test</p>
|
||||
<style jsx>{`p { color: ${color} }`}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
const B = () => (
|
||||
<div>
|
||||
<p>test</p>
|
||||
<style jsx>{`p { color: ${otherColor} }`}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<A />
|
||||
<B />
|
||||
</div>
|
||||
)
|
|
@ -0,0 +1,18 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
const color = "red";
|
||||
const otherColor = "green";
|
||||
const A = ()=><div className={"jsx-706d62168f5e52dc"}>
|
||||
<p className={"jsx-706d62168f5e52dc"}>test</p>
|
||||
<_JSXStyle id={"706d62168f5e52dc"}>{`p.jsx-706d62168f5e52dc {color:${color}}`}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
const B = ()=><div className={"jsx-d698fce2ff7d98bb"}>
|
||||
<p className={"jsx-d698fce2ff7d98bb"}>test</p>
|
||||
<_JSXStyle id={"d698fce2ff7d98bb"}>{`p.jsx-d698fce2ff7d98bb {color:${otherColor}}`}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
export default (()=><div >
|
||||
<A />
|
||||
<B />
|
||||
</div>
|
||||
);
|
|
@ -0,0 +1,32 @@
|
|||
export default class {
|
||||
render() {
|
||||
const Element = 'div'
|
||||
|
||||
return (
|
||||
<Element className="root">
|
||||
<p>dynamic element</p>
|
||||
<style jsx>{`
|
||||
.root {
|
||||
background: red;
|
||||
}
|
||||
`}</style>
|
||||
</Element>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Element2 = 'div'
|
||||
export const Test2 = class {
|
||||
render() {
|
||||
return (
|
||||
<Element2 className="root">
|
||||
<p>dynamic element</p>
|
||||
<style jsx>{`
|
||||
.root {
|
||||
background: red;
|
||||
}
|
||||
`}</style>
|
||||
</Element2>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
export default class {
|
||||
render() {
|
||||
const Element = "div";
|
||||
return <Element className={"jsx-f825b24bbab5b83b" + " " + "root"}>
|
||||
<p className={"jsx-f825b24bbab5b83b"}>dynamic element</p>
|
||||
<_JSXStyle id={"f825b24bbab5b83b"}>{".root.jsx-f825b24bbab5b83b {background:red}"}</_JSXStyle>
|
||||
</Element>;
|
||||
}
|
||||
}
|
||||
const Element2 = "div";
|
||||
export const Test2 = class {
|
||||
render() {
|
||||
return <Element2 className="root">
|
||||
<p className={"jsx-f825b24bbab5b83b"}>dynamic element</p>
|
||||
<_JSXStyle id={"f825b24bbab5b83b"}>{".root.jsx-f825b24bbab5b83b {background:red}"}</_JSXStyle>
|
||||
</Element2>;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import styles from './styles2'
|
||||
|
||||
export default ({ level = 1 }) => {
|
||||
const Element = `h${level}`
|
||||
|
||||
return (
|
||||
<Element className="root">
|
||||
<p>dynamic element</p>
|
||||
<style jsx>{styles}</style>
|
||||
</Element>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
import styles from "./styles2";
|
||||
export default (({ level =1 })=>{
|
||||
const Element = `h${level}`;
|
||||
return <Element className={`jsx-${styles.__hash}` + " " + "root"}>
|
||||
<p className={`jsx-${styles.__hash}`}>dynamic element</p>
|
||||
<_JSXStyle id={styles.__hash}>{styles}</_JSXStyle>
|
||||
</Element>;
|
||||
});
|
|
@ -0,0 +1,43 @@
|
|||
export default ({ level = 1 }) => {
|
||||
const Element = `h${level}`
|
||||
|
||||
return (
|
||||
<Element className="root">
|
||||
<p>dynamic element</p>
|
||||
<style jsx>{`
|
||||
.root {
|
||||
background: red;
|
||||
}
|
||||
`}</style>
|
||||
</Element>
|
||||
)
|
||||
}
|
||||
|
||||
export const TestLowerCase = ({ level = 1 }) => {
|
||||
const element = `h${level}`
|
||||
|
||||
return (
|
||||
<element className="root">
|
||||
<p>dynamic element</p>
|
||||
<style jsx>{`
|
||||
.root {
|
||||
background: red;
|
||||
}
|
||||
`}</style>
|
||||
</element>
|
||||
)
|
||||
}
|
||||
|
||||
const Element2 = 'div'
|
||||
export const Test2 = () => {
|
||||
return (
|
||||
<Element2 className="root">
|
||||
<p>dynamic element</p>
|
||||
<style jsx>{`
|
||||
.root {
|
||||
background: red;
|
||||
}
|
||||
`}</style>
|
||||
</Element2>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
export default (({ level =1 })=>{
|
||||
const Element = `h${level}`;
|
||||
return <Element className={"jsx-fca64cc3f069b519" + " " + "root"}>
|
||||
<p className={"jsx-fca64cc3f069b519"}>dynamic element</p>
|
||||
<_JSXStyle id={"fca64cc3f069b519"}>{".root.jsx-fca64cc3f069b519 {background:red}"}</_JSXStyle>
|
||||
</Element>;
|
||||
});
|
||||
export const TestLowerCase = ({ level =1 })=>{
|
||||
const element = `h${level}`;
|
||||
return <element className={"jsx-fca64cc3f069b519" + " " + "root"}>
|
||||
<p className={"jsx-fca64cc3f069b519"}>dynamic element</p>
|
||||
<_JSXStyle id={"fca64cc3f069b519"}>{".root.jsx-fca64cc3f069b519 {background:red}"}</_JSXStyle>
|
||||
</element>;
|
||||
};
|
||||
const Element2 = "div";
|
||||
export const Test2 = ()=>{
|
||||
return <Element2 className="root">
|
||||
<p className={"jsx-fca64cc3f069b519"}>dynamic element</p>
|
||||
<_JSXStyle id={"fca64cc3f069b519"}>{".root.jsx-fca64cc3f069b519 {background:red}"}</_JSXStyle>
|
||||
</Element2>;
|
||||
};
|
|
@ -0,0 +1,41 @@
|
|||
// TODO
|
||||
// import React, { Component } from 'react'
|
||||
|
||||
// export default class Index extends Component {
|
||||
// static getInitialProps() {
|
||||
// return { color: 'aquamarine' }
|
||||
// }
|
||||
|
||||
// render() {
|
||||
// return (
|
||||
// <div>
|
||||
// {[1, 2].map(idx => (
|
||||
// <div key={idx}>
|
||||
// {[3, 4].map(idx2 => (
|
||||
// <div key={idx2}>{this.props.color}</div>
|
||||
// ))}
|
||||
// </div>
|
||||
// ))}
|
||||
// {[1, 2].map(idx => (
|
||||
// <div key={idx}>
|
||||
// <div>
|
||||
// {this.props.color}
|
||||
// <div className="something">
|
||||
// <React.Fragment>
|
||||
// <div>
|
||||
// <div>{this.props.color} hello there</div>
|
||||
// </div>
|
||||
// </React.Fragment>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// ))}
|
||||
// <style jsx>{`
|
||||
// div {
|
||||
// background: ${this.props.color};
|
||||
// }
|
||||
// `}</style>
|
||||
// </div>
|
||||
// )
|
||||
// }
|
||||
// }
|
|
@ -0,0 +1 @@
|
|||
// module.exports = () => <p><style jsx>{`p { color:red; }`}</style></p>
|
|
@ -0,0 +1 @@
|
|||
// module.exports = () => <p><style>{`p { color:red; }`}</style></p>
|
|
@ -0,0 +1,90 @@
|
|||
const darken = c => c
|
||||
const color = 'red'
|
||||
const otherColor = 'green'
|
||||
const mediumScreen = '680px'
|
||||
const animationDuration = '200ms'
|
||||
const animationName = 'my-cool-animation'
|
||||
const obj = { display: 'block' }
|
||||
|
||||
export default ({ display }) => (
|
||||
<div>
|
||||
<p>test</p>
|
||||
<style jsx>{`
|
||||
p.${color} {
|
||||
color: ${otherColor};
|
||||
display: ${obj.display};
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{'p { color: red }'}</style>
|
||||
<style jsx global>{`
|
||||
body {
|
||||
background: ${color};
|
||||
}
|
||||
`}</style>
|
||||
<style jsx global>{`
|
||||
body {
|
||||
background: ${color};
|
||||
}
|
||||
`}</style>
|
||||
// TODO: the next two should have the same hash
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: ${color};
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: ${color};
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: ${darken(color)};
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: ${darken(color) + 2};
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{`
|
||||
@media (min-width: ${mediumScreen}) {
|
||||
p {
|
||||
color: green;
|
||||
}
|
||||
p {
|
||||
color: ${`red`};
|
||||
}
|
||||
}
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{`
|
||||
p {
|
||||
animation-duration: ${animationDuration};
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{`
|
||||
p {
|
||||
animation: ${animationDuration} forwards ${animationName};
|
||||
}
|
||||
div {
|
||||
background: ${color};
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<style jsx>{`
|
||||
span {
|
||||
display: ${display ? 'block' : 'none'};
|
||||
}
|
||||
`}</style>
|
||||
// TODO: causes bad syntax
|
||||
{/* <style jsx>{`
|
||||
span:before {
|
||||
display: ${display ? 'block' : 'none'};
|
||||
content: '\`';
|
||||
}
|
||||
`}</style> */}
|
||||
</div>
|
||||
)
|
|
@ -0,0 +1,73 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
const darken = (c)=>c
|
||||
;
|
||||
const color = "red";
|
||||
const otherColor = "green";
|
||||
const mediumScreen = "680px";
|
||||
const animationDuration = "200ms";
|
||||
const animationName = "my-cool-animation";
|
||||
const obj = {
|
||||
display: "block"
|
||||
};
|
||||
export default (({ display })=><div className={"jsx-802e359ee0ab20c4 " + _JSXStyle.dynamic([
|
||||
"76aa3eae4e21e4ca",
|
||||
[
|
||||
display ? "block" : "none"
|
||||
]
|
||||
], [
|
||||
"5ba905f763f40220",
|
||||
[
|
||||
darken(color) + 2
|
||||
]
|
||||
], [
|
||||
"c4bb394aae9bd00b",
|
||||
[
|
||||
darken(color)
|
||||
]
|
||||
])}>
|
||||
<p className={"jsx-802e359ee0ab20c4 " + _JSXStyle.dynamic([
|
||||
"76aa3eae4e21e4ca",
|
||||
[
|
||||
display ? "block" : "none"
|
||||
]
|
||||
], [
|
||||
"5ba905f763f40220",
|
||||
[
|
||||
darken(color) + 2
|
||||
]
|
||||
], [
|
||||
"c4bb394aae9bd00b",
|
||||
[
|
||||
darken(color)
|
||||
]
|
||||
])}>test</p>
|
||||
<_JSXStyle id={"f3d3af42197b4734"}>{`p.${color}.jsx-802e359ee0ab20c4 {color:${otherColor};
|
||||
display:${obj.display}}`}</_JSXStyle>
|
||||
<_JSXStyle id={"94239b6d6b42c9b5"}>{"p.jsx-802e359ee0ab20c4 {color:red}"}</_JSXStyle>
|
||||
<_JSXStyle id={"32d670fe91cc2fa1"}>{`body {background:${color}}`}</_JSXStyle>
|
||||
<_JSXStyle id={"3134af19d5bf663e"}>{`body {background:${color}}`}</_JSXStyle>
|
||||
// TODO: the next two should have the same hash
|
||||
<_JSXStyle id={"8e512e75f8a7c096"}>{`p.jsx-802e359ee0ab20c4 {color:${color}}`}</_JSXStyle>
|
||||
<_JSXStyle id={"c25992945d0883cd"}>{`p.jsx-802e359ee0ab20c4 {color:${color}}`}</_JSXStyle>
|
||||
<_JSXStyle id={"2f77c12736da5e9e"} dynamic={[
|
||||
darken(color)
|
||||
]}>{`p.__jsx-style-dynamic-selector {color:${darken(color)}}`}</_JSXStyle>
|
||||
<_JSXStyle id={"10454d61c818c6eb"} dynamic={[
|
||||
darken(color) + 2
|
||||
]}>{`p.__jsx-style-dynamic-selector {color:${darken(color) + 2}}`}</_JSXStyle>
|
||||
<_JSXStyle id={"281f7ed4d9150bac"}>{`@media (min-width:${mediumScreen}) {p.jsx-802e359ee0ab20c4 {color:green}
|
||||
p.jsx-802e359ee0ab20c4 {color:${`red`}}}
|
||||
p.jsx-802e359ee0ab20c4 {color:red}`}</_JSXStyle>
|
||||
<_JSXStyle id={"d8950943ae4cf3dc"}>{`p.jsx-802e359ee0ab20c4 {-webkit-animation-duration:${animationDuration};
|
||||
animation-duration:${animationDuration}}`}</_JSXStyle>
|
||||
<_JSXStyle id={"1ee00865f92bdbe7"}>{`p.jsx-802e359ee0ab20c4 {-webkit-animation:${animationDuration} forwards ${animationName};
|
||||
animation:${animationDuration} forwards ${animationName}}
|
||||
div.jsx-802e359ee0ab20c4 {background:${color}}`}</_JSXStyle>
|
||||
|
||||
<_JSXStyle id={"4925b8e0a7ab752a"} dynamic={[
|
||||
display ? "block" : "none"
|
||||
]}>{`span.__jsx-style-dynamic-selector {display:${display ? "block" : "none"}}`}</_JSXStyle>
|
||||
// TODO: causes bad syntax
|
||||
{}
|
||||
</div>
|
||||
);
|
|
@ -0,0 +1,5 @@
|
|||
import css from 'styled-jsx/css'
|
||||
|
||||
function test() {
|
||||
css.resolve`div { color: red }`
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
function test() {
|
||||
({
|
||||
styles: <_JSXStyle id={"abb4c2202db1a207"}>{"div.jsx-abb4c2202db1a207 {color:red}"}</_JSXStyle>,
|
||||
className: "jsx-abb4c2202db1a207"
|
||||
});
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
import styles, { foo as styles3 } from './styles'
|
||||
|
||||
const styles2 = require('./styles2')
|
||||
|
||||
export default () =>
|
||||
<div>
|
||||
<p>test</p>
|
||||
<div>woot</div>
|
||||
<p>woot</p>
|
||||
<style jsx global>
|
||||
{styles2}
|
||||
</style>
|
||||
<style jsx global>
|
||||
{styles3}
|
||||
</style>
|
||||
<style jsx global>
|
||||
{styles}
|
||||
</style>
|
||||
</div>
|
|
@ -0,0 +1,12 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
import styles, { foo as styles3 } from "./styles";
|
||||
const styles2 = require("./styles2");
|
||||
export default (()=><div >
|
||||
<p >test</p>
|
||||
<div >woot</div>
|
||||
<p >woot</p>
|
||||
<_JSXStyle id={styles2.__hash}>{styles2}</_JSXStyle>
|
||||
<_JSXStyle id={styles3.__hash}>{styles3}</_JSXStyle>
|
||||
<_JSXStyle id={styles.__hash}>{styles}</_JSXStyle>
|
||||
</div>
|
||||
);
|
|
@ -0,0 +1,9 @@
|
|||
import styles from './styles'
|
||||
|
||||
export default () =>
|
||||
<div>
|
||||
<p>test</p>
|
||||
<style jsx>
|
||||
{styles}
|
||||
</style>
|
||||
</div>
|
|
@ -0,0 +1,7 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
import styles from "./styles";
|
||||
export default (()=><div className={`jsx-${styles.__hash}`}>
|
||||
<p className={`jsx-${styles.__hash}`}>test</p>
|
||||
<_JSXStyle id={styles.__hash}>{styles}</_JSXStyle>
|
||||
</div>
|
||||
);
|
|
@ -0,0 +1,41 @@
|
|||
import styles from './styles'
|
||||
const styles2 = require('./styles2')
|
||||
import { foo as styles3 } from './styles'
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<p className="foo">test</p>
|
||||
<p>woot</p>
|
||||
<style jsx global>
|
||||
{styles2}
|
||||
</style>
|
||||
<style jsx>{styles3}</style>
|
||||
<div>woot</div>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
div {
|
||||
color: green;
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{styles}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
export const Test = () => (
|
||||
<div>
|
||||
<p className="foo">test</p>
|
||||
<p>woot</p>
|
||||
<style jsx>{styles3}</style>
|
||||
<div>woot</div>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
div {
|
||||
color: green;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
|
@ -0,0 +1,22 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
import styles from "./styles";
|
||||
const styles2 = require("./styles2");
|
||||
import { foo as styles3 } from "./styles";
|
||||
export default (()=><div className={"jsx-bee92b62eadf8a14 " + `jsx-${styles.__hash} jsx-${styles3.__hash}`}>
|
||||
<p className={"jsx-bee92b62eadf8a14 " + `jsx-${styles.__hash} jsx-${styles3.__hash}` + " " + "foo"}>test</p>
|
||||
<p className={"jsx-bee92b62eadf8a14 " + `jsx-${styles.__hash} jsx-${styles3.__hash}`}>woot</p>
|
||||
<_JSXStyle id={styles2.__hash}>{styles2}</_JSXStyle>
|
||||
<_JSXStyle id={styles3.__hash}>{styles3}</_JSXStyle>
|
||||
<div className={"jsx-bee92b62eadf8a14 " + `jsx-${styles.__hash} jsx-${styles3.__hash}`}>woot</div>
|
||||
<_JSXStyle id={"bee92b62eadf8a14"}>{"p.jsx-bee92b62eadf8a14 {color:red}\ndiv.jsx-bee92b62eadf8a14 {color:green}"}</_JSXStyle>
|
||||
<_JSXStyle id={styles.__hash}>{styles}</_JSXStyle>
|
||||
</div>
|
||||
);
|
||||
export const Test = ()=><div className={"jsx-bee92b62eadf8a14 " + `jsx-${styles3.__hash}`}>
|
||||
<p className={"jsx-bee92b62eadf8a14 " + `jsx-${styles3.__hash}` + " " + "foo"}>test</p>
|
||||
<p className={"jsx-bee92b62eadf8a14 " + `jsx-${styles3.__hash}`}>woot</p>
|
||||
<_JSXStyle id={styles3.__hash}>{styles3}</_JSXStyle>
|
||||
<div className={"jsx-bee92b62eadf8a14 " + `jsx-${styles3.__hash}`}>woot</div>
|
||||
<_JSXStyle id={"bee92b62eadf8a14"}>{"p.jsx-bee92b62eadf8a14 {color:red}\ndiv.jsx-bee92b62eadf8a14 {color:green}"}</_JSXStyle>
|
||||
</div>
|
||||
;
|
|
@ -0,0 +1,51 @@
|
|||
import React from 'react'
|
||||
|
||||
export default () => (
|
||||
<>
|
||||
<p>Testing!!!</p>
|
||||
<p className="foo">Bar</p>
|
||||
<>
|
||||
<h3 id="head">Title...</h3>
|
||||
<React.Fragment>
|
||||
<p>hello</p>
|
||||
<>
|
||||
<p>foo</p>
|
||||
<p>bar</p>
|
||||
</>
|
||||
<p>world</p>
|
||||
</React.Fragment>
|
||||
</>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: cyan;
|
||||
}
|
||||
.foo {
|
||||
font-size: 18px;
|
||||
color: hotpink;
|
||||
}
|
||||
#head {
|
||||
text-decoration: underline;
|
||||
}
|
||||
`}</style>
|
||||
</>
|
||||
)
|
||||
|
||||
function Component1() {
|
||||
return (
|
||||
<>
|
||||
<div>test</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function Component2() {
|
||||
return (
|
||||
<div>
|
||||
<style jsx>{`
|
||||
div {
|
||||
color: red;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
import React from "react";
|
||||
export default (()=><>
|
||||
<p className={"jsx-6dd5f97e085c0297"}>Testing!!!</p>
|
||||
<p className={"jsx-6dd5f97e085c0297" + " " + "foo"}>Bar</p>
|
||||
<>
|
||||
<h3 id="head" className={"jsx-6dd5f97e085c0297"}>Title...</h3>
|
||||
<React.Fragment >
|
||||
<p className={"jsx-6dd5f97e085c0297"}>hello</p>
|
||||
<>
|
||||
<p className={"jsx-6dd5f97e085c0297"}>foo</p>
|
||||
<p className={"jsx-6dd5f97e085c0297"}>bar</p>
|
||||
</>
|
||||
<p className={"jsx-6dd5f97e085c0297"}>world</p>
|
||||
</React.Fragment>
|
||||
</>
|
||||
<_JSXStyle id={"6dd5f97e085c0297"}>{"p.jsx-6dd5f97e085c0297 {color:cyan}\n.foo.jsx-6dd5f97e085c0297 {font-size:18px;\ncolor:hotpink}\n#head.jsx-6dd5f97e085c0297 {text-decoration:underline}"}</_JSXStyle>
|
||||
</>
|
||||
);
|
||||
function Component1() {
|
||||
return <>
|
||||
<div >test</div>
|
||||
</>;
|
||||
}
|
||||
function Component2() {
|
||||
return <div className={"jsx-678f41ca6d3b294b"}>
|
||||
<_JSXStyle id={"678f41ca6d3b294b"}>{"div.jsx-678f41ca6d3b294b {color:red}"}</_JSXStyle>
|
||||
</div>;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
const Test = () => (
|
||||
<div>
|
||||
<style jsx global>{`
|
||||
body {
|
||||
color: red
|
||||
}
|
||||
|
||||
:hover { color: red; display: flex;
|
||||
animation: foo 1s ease-out }
|
||||
|
||||
div a {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-test] > div {
|
||||
color: red;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
const Test2 = () => <style global jsx>{'p { color: red }'}</style>
|
|
@ -0,0 +1,7 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
const Test = ()=><div className={"jsx-d47d6adadf14e957"}>
|
||||
<_JSXStyle id={"d47d6adadf14e957"}>{"body {color:red}\n:hover {color:red;\ndisplay:-webkit-box;\ndisplay:-webkit-flex;\ndisplay:-ms-flexbox;\ndisplay:flex;\n-webkit-animation:foo 1s ease-out;\nanimation:foo 1s ease-out}\ndiv a {display:none}\n[data-test] >div {color:red}"}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
const Test2 = ()=><style global jsx>{"p { color: red }"}</style>
|
||||
;
|
|
@ -0,0 +1,9 @@
|
|||
const Test = () => <style global jsx>{'p { color: red }'}</style>
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<p>test</p>
|
||||
<style jsx global>{`body { background: red }`}</style>
|
||||
<style jsx>{'p { color: red }'}</style>
|
||||
</div>
|
||||
)
|
|
@ -0,0 +1,9 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
const Test = ()=><style global jsx>{"p { color: red }"}</style>
|
||||
;
|
||||
export default (()=><div className={"jsx-3822e6e1fb9fa41a"}>
|
||||
<p className={"jsx-3822e6e1fb9fa41a"}>test</p>
|
||||
<_JSXStyle id={"b7efb453c85593c1"}>{"body {background:red}"}</_JSXStyle>
|
||||
<_JSXStyle id={"94239b6d6b42c9b5"}>{"p.jsx-3822e6e1fb9fa41a {color:red}"}</_JSXStyle>
|
||||
</div>
|
||||
);
|
|
@ -0,0 +1,43 @@
|
|||
const attrs = {
|
||||
id: 'test'
|
||||
}
|
||||
|
||||
const Test1 = () => (
|
||||
<div>
|
||||
<span {...attrs} data-test="test">test</span>
|
||||
<Component />
|
||||
<style jsx>{`
|
||||
span {
|
||||
color: red;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
const Test2 = () => <span>test</span>
|
||||
|
||||
const Test3 = () => (
|
||||
<div>
|
||||
<span>test</span>
|
||||
<style jsx>{`
|
||||
span {
|
||||
color: red;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
export default class {
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<p>test</p>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
const attrs = {
|
||||
id: "test"
|
||||
};
|
||||
const Test1 = ()=><div className={"jsx-a9535d7d5f32c3c4"}>
|
||||
<span {...attrs} data-test="test" className={"jsx-a9535d7d5f32c3c4" + " " + (attrs && attrs.className != null && attrs.className || "")}>test</span>
|
||||
<Component />
|
||||
<_JSXStyle id={"a9535d7d5f32c3c4"}>{"span.jsx-a9535d7d5f32c3c4 {color:red}"}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
const Test2 = ()=><span >test</span>
|
||||
;
|
||||
const Test3 = ()=><div className={"jsx-a9535d7d5f32c3c4"}>
|
||||
<span className={"jsx-a9535d7d5f32c3c4"}>test</span>
|
||||
<_JSXStyle id={"a9535d7d5f32c3c4"}>{"span.jsx-a9535d7d5f32c3c4 {color:red}"}</_JSXStyle>
|
||||
</div>
|
||||
;
|
||||
export default class {
|
||||
render() {
|
||||
return <div className={"jsx-b2b86d63f35d25ee"}>
|
||||
<p className={"jsx-b2b86d63f35d25ee"}>test</p>
|
||||
<_JSXStyle id={"b2b86d63f35d25ee"}>{"p.jsx-b2b86d63f35d25ee {color:red}"}</_JSXStyle>
|
||||
</div>;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
export default () => (
|
||||
<div>
|
||||
<p>woot</p>
|
||||
<style dangerouslySetInnerHTML={{ __html: `body { margin: 0; }` }}></style>
|
||||
<style jsx>{'p { color: red }'}</style>
|
||||
</div>
|
||||
)
|
|
@ -0,0 +1,9 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
export default (()=><div className={"jsx-94239b6d6b42c9b5"}>
|
||||
<p className={"jsx-94239b6d6b42c9b5"}>woot</p>
|
||||
<style dangerouslySetInnerHTML={{
|
||||
__html: `body { margin: 0; }`
|
||||
}}></style>
|
||||
<_JSXStyle id={"94239b6d6b42c9b5"}>{"p.jsx-94239b6d6b42c9b5 {color:red}"}</_JSXStyle>
|
||||
</div>
|
||||
);
|
|
@ -0,0 +1,30 @@
|
|||
import css from 'hell'
|
||||
|
||||
const color = 'red'
|
||||
|
||||
const bar = css`
|
||||
div {
|
||||
font-size: 3em;
|
||||
}
|
||||
`
|
||||
export const uh = bar
|
||||
|
||||
export const foo = css`div { color: ${color}}`
|
||||
|
||||
export default css`
|
||||
div {
|
||||
font-size: 3em;
|
||||
}
|
||||
p {
|
||||
color: ${color};
|
||||
}
|
||||
`
|
||||
|
||||
const Title = styled.h1`
|
||||
color: red;
|
||||
font-size: 50px;
|
||||
`
|
||||
|
||||
const AnotherTitle = Title.extend`color: blue;`
|
||||
|
||||
export const Component = () => <AnotherTitle>My page</AnotherTitle>
|
|
@ -0,0 +1,24 @@
|
|||
import css from "hell";
|
||||
const color = "red";
|
||||
const bar = css`
|
||||
div {
|
||||
font-size: 3em;
|
||||
}
|
||||
`;
|
||||
export const uh = bar;
|
||||
export const foo = css`div { color: ${color}}`;
|
||||
export default css`
|
||||
div {
|
||||
font-size: 3em;
|
||||
}
|
||||
p {
|
||||
color: ${color};
|
||||
}
|
||||
`;
|
||||
const Title = styled.h1`
|
||||
color: red;
|
||||
font-size: 50px;
|
||||
`;
|
||||
const AnotherTitle = Title.extend`color: blue;`;
|
||||
export const Component = ()=><AnotherTitle >My page</AnotherTitle>
|
||||
;
|
|
@ -0,0 +1,8 @@
|
|||
// TODO: needs sourcemaps
|
||||
// export default () => (
|
||||
// <div>
|
||||
// <p>test</p>
|
||||
// <p>woot</p>
|
||||
// <style jsx>{'p { color: red }'}</style>
|
||||
// </div>
|
||||
// )
|
|
@ -0,0 +1,8 @@
|
|||
export default () => (
|
||||
<div>
|
||||
<p>test</p>
|
||||
<p>woot</p>
|
||||
<p>woot</p>
|
||||
<style jsx>{'p { color: red }'}</style>
|
||||
</div>
|
||||
)
|
|
@ -0,0 +1,8 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
export default (()=><div className={"jsx-94239b6d6b42c9b5"}>
|
||||
<p className={"jsx-94239b6d6b42c9b5"}>test</p>
|
||||
<p className={"jsx-94239b6d6b42c9b5"}>woot</p>
|
||||
<p className={"jsx-94239b6d6b42c9b5"}>woot</p>
|
||||
<_JSXStyle id={"94239b6d6b42c9b5"}>{"p.jsx-94239b6d6b42c9b5 {color:red}"}</_JSXStyle>
|
||||
</div>
|
||||
);
|
|
@ -0,0 +1,13 @@
|
|||
// TODO
|
||||
// import css from 'styled-jsx/css'
|
||||
|
||||
// const color = 'red'
|
||||
|
||||
// export const foo = css`div { color: ${color}}`
|
||||
|
||||
// const props = { color: 'red ' }
|
||||
|
||||
// export default css`
|
||||
// div { font-size: 3em; color: ${props.color} }
|
||||
// p { color: ${this.props.color};}
|
||||
// `
|
|
@ -0,0 +1,11 @@
|
|||
// TODO
|
||||
// import css from 'styled-jsx/css'
|
||||
|
||||
// const color = 'red'
|
||||
|
||||
// export const foo = css`div { color: ${color}}`
|
||||
|
||||
// export default css`
|
||||
// div { font-size: 3em }
|
||||
// p { color: ${props.color};}
|
||||
// `
|
|
@ -0,0 +1,58 @@
|
|||
import css, { resolve, global } from 'styled-jsx/css'
|
||||
import colors, { size } from './constants'
|
||||
const color = 'red'
|
||||
|
||||
const bar = css`
|
||||
div {
|
||||
font-size: 3em;
|
||||
}
|
||||
`
|
||||
|
||||
const baz = css.global`
|
||||
div {
|
||||
font-size: 3em;
|
||||
}
|
||||
`
|
||||
|
||||
const a = global`
|
||||
div {
|
||||
font-size: ${size}em;
|
||||
}
|
||||
`
|
||||
|
||||
export const uh = bar
|
||||
|
||||
export const foo = css`div { color: ${color}}`
|
||||
|
||||
// TODO: the next 3 should not transformed as dynamic
|
||||
css.resolve`
|
||||
div {
|
||||
color: ${colors.green.light};
|
||||
}
|
||||
a { color: red }
|
||||
`
|
||||
|
||||
const b = resolve`
|
||||
div {
|
||||
color: ${colors.green.light};
|
||||
}
|
||||
a { color: red }
|
||||
`
|
||||
|
||||
const dynamic = colors => {
|
||||
const b = resolve`
|
||||
div {
|
||||
color: ${colors.green.light};
|
||||
}
|
||||
a { color: red }
|
||||
`
|
||||
}
|
||||
|
||||
export default css.resolve`
|
||||
div {
|
||||
font-size: 3em;
|
||||
}
|
||||
p {
|
||||
color: ${color};
|
||||
}
|
||||
`
|
|
@ -0,0 +1,55 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
import colors, { size } from "./constants";
|
||||
const color = "red";
|
||||
const bar = new String("div.jsx-aaed0341accea8f {font-size:3em}");
|
||||
bar.__hash = "aaed0341accea8f";
|
||||
const baz = new String("div {font-size:3em}");
|
||||
baz.__hash = "aaed0341accea8f";
|
||||
const a = new String(`div {font-size:${size}em}`);
|
||||
a.__hash = "611c3773b76f8ea3";
|
||||
export const uh = bar;
|
||||
export const foo = new String(`div.jsx-e46da79e05d23fff {color:${color}}`);
|
||||
foo.__hash = "e46da79e05d23fff";
|
||||
({
|
||||
styles: <_JSXStyle id={"12e2c41a8d37fe78"} dynamic={[
|
||||
colors.green.light
|
||||
]}>{`div.__jsx-style-dynamic-selector {color:${colors.green.light}}
|
||||
a.__jsx-style-dynamic-selector {color:red}`}</_JSXStyle>,
|
||||
className: _JSXStyle.dynamic([
|
||||
"12e2c41a8d37fe78",
|
||||
[
|
||||
colors.green.light
|
||||
]
|
||||
])
|
||||
});
|
||||
const b = {
|
||||
styles: <_JSXStyle id={"d5617758481f82cd"} dynamic={[
|
||||
colors.green.light
|
||||
]}>{`div.__jsx-style-dynamic-selector {color:${colors.green.light}}
|
||||
a.__jsx-style-dynamic-selector {color:red}`}</_JSXStyle>,
|
||||
className: _JSXStyle.dynamic([
|
||||
"d5617758481f82cd",
|
||||
[
|
||||
colors.green.light
|
||||
]
|
||||
])
|
||||
};
|
||||
const dynamic = (colors)=>{
|
||||
const b = {
|
||||
styles: <_JSXStyle id={"a7ac579c753e9d90"} dynamic={[
|
||||
colors.green.light
|
||||
]}>{`div.__jsx-style-dynamic-selector {color:${colors.green.light}}
|
||||
a.__jsx-style-dynamic-selector {color:red}`}</_JSXStyle>,
|
||||
className: _JSXStyle.dynamic([
|
||||
"a7ac579c753e9d90",
|
||||
[
|
||||
colors.green.light
|
||||
]
|
||||
])
|
||||
};
|
||||
};
|
||||
export default {
|
||||
styles: <_JSXStyle id={"e4642e4164827181"}>{`div.jsx-e4642e4164827181 {font-size:3em}
|
||||
p.jsx-e4642e4164827181 {color:${color}}`}</_JSXStyle>,
|
||||
className: "jsx-e4642e4164827181"
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
// TODO: support common js
|
||||
// import css from 'styled-jsx/css'
|
||||
|
||||
// module.exports = css`
|
||||
// div { font-size: 3em }
|
||||
// `
|
|
@ -0,0 +1,176 @@
|
|||
export default () => (
|
||||
<div>
|
||||
<p>test</p>
|
||||
<style jsx>{`
|
||||
html {
|
||||
background-image:
|
||||
linear-gradient(0deg, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8)),
|
||||
url(/static/background.svg);
|
||||
}
|
||||
|
||||
:global(p) {
|
||||
color: blue
|
||||
}
|
||||
|
||||
:global(p){
|
||||
color: blue;
|
||||
}
|
||||
|
||||
:global(p), a {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
:global(.foo + a) {
|
||||
color: red;
|
||||
}
|
||||
|
||||
:global(body) {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
|
||||
p{
|
||||
color: red
|
||||
}
|
||||
|
||||
* {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
[href="woot"] {
|
||||
color: red;
|
||||
}
|
||||
|
||||
p a span {
|
||||
color: red;
|
||||
}
|
||||
|
||||
p :global(span) {
|
||||
background: blue
|
||||
}
|
||||
|
||||
p a[title="'w ' ' t'"] {
|
||||
margin: auto
|
||||
}
|
||||
|
||||
p :global(span:not(.test)) {
|
||||
color: green
|
||||
}
|
||||
|
||||
p, h1 {
|
||||
color: blue;
|
||||
animation: hahaha 3s ease forwards infinite;
|
||||
animation-name: hahaha;
|
||||
animation-delay: 100ms;
|
||||
}
|
||||
|
||||
p {
|
||||
animation: hahaha 1s, hehehe 2s;
|
||||
}
|
||||
|
||||
p:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
p::before {
|
||||
color: red;
|
||||
}
|
||||
|
||||
:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
::before {
|
||||
color: red;
|
||||
}
|
||||
|
||||
:hover p {
|
||||
color: red;
|
||||
}
|
||||
|
||||
p + a {
|
||||
color: red;
|
||||
}
|
||||
|
||||
p ~ a {
|
||||
color: red;
|
||||
}
|
||||
|
||||
p > a {
|
||||
color: red;
|
||||
}
|
||||
|
||||
@keyframes hahaha {
|
||||
from { top: 0 }
|
||||
to { top: 100 }
|
||||
}
|
||||
|
||||
@keyframes hehehe {
|
||||
from { left: 0 }
|
||||
to { left: 100 }
|
||||
}
|
||||
|
||||
@media (min-width: 500px) {
|
||||
.test {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
.test {
|
||||
/* test, test */
|
||||
display: block;
|
||||
/*
|
||||
|
||||
test
|
||||
*/
|
||||
}
|
||||
|
||||
.inline-flex {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.test {
|
||||
box-shadow: 0 0 10px black, inset 0 0 5px black
|
||||
}
|
||||
|
||||
.test[title=","] {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.test.is-status .test {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.a-selector:hover,
|
||||
.a-selector:focus
|
||||
{
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@media (min-width: 1px) and (max-width: 768px) {
|
||||
[class*='grid__col--'] {
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 64em) {
|
||||
.test {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
@supports (-moz-appearance: none) and (display: contents) {
|
||||
.test {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
|
@ -0,0 +1,6 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
export default (()=><div className={"jsx-768337a97aceabd1"}>
|
||||
<p className={"jsx-768337a97aceabd1"}>test</p>
|
||||
<_JSXStyle id={"768337a97aceabd1"}>{"html.jsx-768337a97aceabd1 {background-image:linear-gradient(0deg, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8)), url(/static/background.svg)}\np {color:blue}\np {color:blue}\np, a.jsx-768337a97aceabd1 {color:blue}\n.foo +a {color:red}\nbody {font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif}\np.jsx-768337a97aceabd1 {color:red}\np.jsx-768337a97aceabd1 {color:red}\n*.jsx-768337a97aceabd1 {color:blue}\n[href = 'woot'].jsx-768337a97aceabd1 {color:red}\np.jsx-768337a97aceabd1 a.jsx-768337a97aceabd1 span.jsx-768337a97aceabd1 {color:red}\np.jsx-768337a97aceabd1 span {background:blue}\np.jsx-768337a97aceabd1 a[title = ''w ' ' t''].jsx-768337a97aceabd1 {margin:auto}\np.jsx-768337a97aceabd1 span:not(.test) {color:green}\np.jsx-768337a97aceabd1, h1.jsx-768337a97aceabd1 {color:blue;\n-webkit-animation:hahaha 3s ease forwards infinite;\nanimation:hahaha 3s ease forwards infinite;\n-webkit-animation-name:hahaha;\nanimation-name:hahaha;\nanimation-delay:100ms}\np.jsx-768337a97aceabd1 {-webkit-animation:hahaha 1s, hehehe 2s;\nanimation:hahaha 1s, hehehe 2s}\np.jsx-768337a97aceabd1:hover {color:red}\np.jsx-768337a97aceabd1::before {color:red}\n.jsx-768337a97aceabd1:hover {color:red}\n.jsx-768337a97aceabd1::before {color:red}\n.jsx-768337a97aceabd1:hover p.jsx-768337a97aceabd1 {color:red}\np.jsx-768337a97aceabd1 +a.jsx-768337a97aceabd1 {color:red}\np.jsx-768337a97aceabd1 ~a.jsx-768337a97aceabd1 {color:red}\np.jsx-768337a97aceabd1 >a.jsx-768337a97aceabd1 {color:red}\n@keyframes hahaha {from {top:0}to {top:100}}\n@keyframes hehehe {from {left:0}to {left:100}}\n@media (min-width:500px) {.test.jsx-768337a97aceabd1 {color:red}}\n.test.jsx-768337a97aceabd1 {display:block}\n.inline-flex.jsx-768337a97aceabd1 {display:-webkit-inline-box;\ndisplay:-webkit-inline-flex;\ndisplay:-ms-inline-flexbox;\ndisplay:inline-flex}\n.flex.jsx-768337a97aceabd1 {display:-webkit-box;\ndisplay:-webkit-flex;\ndisplay:-ms-flexbox;\ndisplay:flex}\n.test.jsx-768337a97aceabd1 {box-shadow:0 0 10px black, inset 0 0 5px black}\n.test[title = ','].jsx-768337a97aceabd1 {display:inline-block}\n.test.is-status.jsx-768337a97aceabd1 .test.jsx-768337a97aceabd1 {color:red}\n.a-selector.jsx-768337a97aceabd1:hover, .a-selector.jsx-768337a97aceabd1:focus {outline:none}\n@media (min-width:1px) and (max-width:768px) {[class *= 'grid__col--'].jsx-768337a97aceabd1 {margin-top:12px;\nmargin-bottom:12px}}\n@media (max-width:64em) {.test.jsx-768337a97aceabd1 {margin-bottom:1em}\n@supports (-moz-appearance:none) and (display:contents) {.test.jsx-768337a97aceabd1 {margin-bottom:2rem}}}"}</_JSXStyle>
|
||||
</div>
|
||||
);
|
|
@ -0,0 +1,12 @@
|
|||
export default () => (
|
||||
<div>
|
||||
<p>test</p>
|
||||
<p>woot</p>
|
||||
<p>woot</p>
|
||||
<style jsx>
|
||||
{
|
||||
'p { color: red }'
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
)
|
|
@ -0,0 +1,8 @@
|
|||
import _JSXStyle from "styled-jsx/style";
|
||||
export default (()=><div className={"jsx-94239b6d6b42c9b5"}>
|
||||
<p className={"jsx-94239b6d6b42c9b5"}>test</p>
|
||||
<p className={"jsx-94239b6d6b42c9b5"}>woot</p>
|
||||
<p className={"jsx-94239b6d6b42c9b5"}>woot</p>
|
||||
<_JSXStyle id={"94239b6d6b42c9b5"}>{"p.jsx-94239b6d6b42c9b5 {color:red}"}</_JSXStyle>
|
||||
</div>
|
||||
);
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue