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
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
toolchain: nightly-2021-03-25
|
toolchain: nightly-2021-08-12
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
- name: Cache cargo registry
|
- name: Cache cargo registry
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
|
@ -54,7 +54,7 @@ jobs:
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: packages/next/native/**
|
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
|
- name: Cross build aarch64 setup
|
||||||
if: ${{ matrix.target == 'aarch64-apple-darwin' && steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
if: ${{ matrix.target == 'aarch64-apple-darwin' && steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||||
run: |
|
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' }}
|
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
toolchain: nightly-2021-03-25
|
toolchain: nightly-2021-08-12
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
- name: Cache cargo registry
|
- name: Cache cargo registry
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
|
@ -491,7 +491,7 @@ jobs:
|
||||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||||
with:
|
with:
|
||||||
path: packages/next/native/next-swc.*.node
|
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
|
- name: Cross build aarch64 setup
|
||||||
if: ${{ matrix.target == 'aarch64-apple-darwin' && steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
if: ${{ matrix.target == 'aarch64-apple-darwin' && steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||||
run: |
|
run: |
|
||||||
|
@ -531,7 +531,7 @@ jobs:
|
||||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: nightly-2021-03-25
|
toolchain: nightly-2021-08-12
|
||||||
profile: minimal
|
profile: minimal
|
||||||
- run: cd packages/next/build/swc && cargo test
|
- run: cd packages/next/build/swc && cargo test
|
||||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||||
|
|
|
@ -10,6 +10,7 @@ packages/react-dev-overlay/lib/**
|
||||||
**/__tmp__/**
|
**/__tmp__/**
|
||||||
lerna.json
|
lerna.json
|
||||||
.github/actions/next-stats-action/.work
|
.github/actions/next-stats-action/.work
|
||||||
|
packages/next/build/swc/tests/fixture/**/*
|
||||||
packages/next-codemod/transforms/__testfixtures__/**/*
|
packages/next-codemod/transforms/__testfixtures__/**/*
|
||||||
packages/next-codemod/transforms/__tests__/**/*
|
packages/next-codemod/transforms/__tests__/**/*
|
||||||
packages/next-codemod/**/*.js
|
packages/next-codemod/**/*.js
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
**/.next/**
|
**/.next/**
|
||||||
**/_next/**
|
**/_next/**
|
||||||
**/dist/**
|
**/dist/**
|
||||||
|
packages/next/build/swc/tests/**
|
||||||
packages/next/compiled/**/*
|
packages/next/compiled/**/*
|
||||||
packages/next/bundles/webpack/packages/*.runtime.js
|
packages/next/bundles/webpack/packages/*.runtime.js
|
||||||
lerna.json
|
lerna.json
|
||||||
|
|
155
packages/next/build/swc/Cargo.lock
generated
155
packages/next/build/swc/Cargo.lock
generated
|
@ -93,6 +93,18 @@ dependencies = [
|
||||||
"winapi",
|
"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]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
|
@ -134,9 +146,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.2.1"
|
version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
|
@ -330,6 +342,12 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "easy-error"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04cc9717c61d2908f50d16ebb5677c7e82ea2bdf7cb52f66b30fe079f3212e16"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.6.1"
|
version = "1.6.1"
|
||||||
|
@ -700,6 +718,7 @@ version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
|
"easy-error",
|
||||||
"fxhash",
|
"fxhash",
|
||||||
"log",
|
"log",
|
||||||
"napi",
|
"napi",
|
||||||
|
@ -714,10 +733,13 @@ dependencies = [
|
||||||
"swc",
|
"swc",
|
||||||
"swc_atoms",
|
"swc_atoms",
|
||||||
"swc_common",
|
"swc_common",
|
||||||
|
"swc_css",
|
||||||
|
"swc_css_codegen",
|
||||||
"swc_ecma_preset_env",
|
"swc_ecma_preset_env",
|
||||||
"swc_ecma_transforms_testing",
|
"swc_ecma_transforms_testing",
|
||||||
"swc_ecmascript",
|
"swc_ecmascript",
|
||||||
"swc_node_base",
|
"swc_node_base",
|
||||||
|
"swc_stylis",
|
||||||
"testing",
|
"testing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -949,6 +971,30 @@ dependencies = [
|
||||||
"output_vt100",
|
"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]]
|
[[package]]
|
||||||
name = "proc-macro-hack"
|
name = "proc-macro-hack"
|
||||||
version = "0.5.19"
|
version = "0.5.19"
|
||||||
|
@ -1603,6 +1649,97 @@ dependencies = [
|
||||||
"url",
|
"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]]
|
[[package]]
|
||||||
name = "swc_ecma_ast"
|
name = "swc_ecma_ast"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
|
@ -2009,6 +2146,7 @@ checksum = "ba53c5582d6e5881b093ece9aaa4b561465afab0560abb19948f2c4bbff1bdb9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"swc_ecma_ast",
|
"swc_ecma_ast",
|
||||||
"swc_ecma_codegen",
|
"swc_ecma_codegen",
|
||||||
|
"swc_ecma_minifier",
|
||||||
"swc_ecma_parser",
|
"swc_ecma_parser",
|
||||||
"swc_ecma_transforms",
|
"swc_ecma_transforms",
|
||||||
"swc_ecma_utils",
|
"swc_ecma_utils",
|
||||||
|
@ -2050,6 +2188,19 @@ dependencies = [
|
||||||
"swc_common",
|
"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]]
|
[[package]]
|
||||||
name = "swc_visit"
|
name = "swc_visit"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
|
|
|
@ -9,6 +9,7 @@ crate-type = ["cdylib"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
backtrace = "0.3"
|
backtrace = "0.3"
|
||||||
|
easy-error = "1.0.0"
|
||||||
napi = { version = "1", features = ["serde-json"] }
|
napi = { version = "1", features = ["serde-json"] }
|
||||||
napi-derive = "1"
|
napi-derive = "1"
|
||||||
path-clean = "0.1"
|
path-clean = "0.1"
|
||||||
|
@ -18,9 +19,12 @@ serde_json = "1"
|
||||||
swc = "0.51"
|
swc = "0.51"
|
||||||
swc_atoms = "0.2"
|
swc_atoms = "0.2"
|
||||||
swc_common = { version = "0.12", features = ["tty-emitter", "sourcemap"] }
|
swc_common = { version = "0.12", features = ["tty-emitter", "sourcemap"] }
|
||||||
swc_node_base = "0.3"
|
swc_css = "0.6"
|
||||||
swc_ecmascript = { version = "0.63", features = ["codegen", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
|
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_ecma_preset_env = "0.42"
|
||||||
|
swc_node_base = "0.3"
|
||||||
|
swc_stylis = "0.3"
|
||||||
fxhash = "0.2.1"
|
fxhash = "0.2.1"
|
||||||
retain_mut = "0.1.3"
|
retain_mut = "0.1.3"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
nightly-2021-03-25
|
nightly-2021-08-12
|
|
@ -45,6 +45,7 @@ mod hook_optimizer;
|
||||||
mod minify;
|
mod minify;
|
||||||
mod next_dynamic;
|
mod next_dynamic;
|
||||||
pub mod next_ssg;
|
pub mod next_ssg;
|
||||||
|
mod styled_jsx;
|
||||||
mod transform;
|
mod transform;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
|
|
@ -4,258 +4,251 @@ use pathdiff::diff_paths;
|
||||||
use swc_atoms::js_word;
|
use swc_atoms::js_word;
|
||||||
use swc_common::{FileName, DUMMY_SP};
|
use swc_common::{FileName, DUMMY_SP};
|
||||||
use swc_ecmascript::ast::{
|
use swc_ecmascript::ast::{
|
||||||
ArrayLit, ArrowExpr, BinExpr, BinaryOp, BlockStmtOrExpr, CallExpr, Expr, ExprOrSpread,
|
ArrayLit, ArrowExpr, BinExpr, BinaryOp, BlockStmtOrExpr, CallExpr, Expr, ExprOrSpread,
|
||||||
ExprOrSuper, Ident, ImportDecl, ImportSpecifier, KeyValueProp, Lit, MemberExpr, ObjectLit,
|
ExprOrSuper, Ident, ImportDecl, ImportSpecifier, KeyValueProp, Lit, MemberExpr, ObjectLit, Prop,
|
||||||
Prop, PropName, PropOrSpread, Str, StrKind,
|
PropName, PropOrSpread, Str, StrKind,
|
||||||
};
|
};
|
||||||
use swc_ecmascript::utils::{
|
use swc_ecmascript::utils::{
|
||||||
ident::{Id, IdentLike},
|
ident::{Id, IdentLike},
|
||||||
HANDLER,
|
HANDLER,
|
||||||
};
|
};
|
||||||
use swc_ecmascript::visit::{Fold, FoldWith};
|
use swc_ecmascript::visit::{Fold, FoldWith};
|
||||||
|
|
||||||
pub fn next_dynamic(filename: FileName, pages_dir: Option<PathBuf>) -> impl Fold {
|
pub fn next_dynamic(filename: FileName, pages_dir: Option<PathBuf>) -> impl Fold {
|
||||||
NextDynamicPatcher {
|
NextDynamicPatcher {
|
||||||
pages_dir,
|
pages_dir,
|
||||||
filename,
|
filename,
|
||||||
dynamic_bindings: vec![],
|
dynamic_bindings: vec![],
|
||||||
}
|
is_next_dynamic_first_arg: false,
|
||||||
|
dynamically_imported_specifier: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct NextDynamicPatcher {
|
struct NextDynamicPatcher {
|
||||||
pages_dir: Option<PathBuf>,
|
pages_dir: Option<PathBuf>,
|
||||||
filename: FileName,
|
filename: FileName,
|
||||||
dynamic_bindings: Vec<Id>,
|
dynamic_bindings: Vec<Id>,
|
||||||
|
is_next_dynamic_first_arg: bool,
|
||||||
|
dynamically_imported_specifier: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fold for NextDynamicPatcher {
|
impl Fold for NextDynamicPatcher {
|
||||||
fn fold_import_decl(&mut self, decl: ImportDecl) -> ImportDecl {
|
fn fold_import_decl(&mut self, decl: ImportDecl) -> ImportDecl {
|
||||||
let ImportDecl {
|
let ImportDecl {
|
||||||
ref src,
|
ref src,
|
||||||
ref specifiers,
|
ref specifiers,
|
||||||
..
|
..
|
||||||
} = decl;
|
} = decl;
|
||||||
if &src.value == "next/dynamic" {
|
if &src.value == "next/dynamic" {
|
||||||
for specifier in specifiers {
|
for specifier in specifiers {
|
||||||
if let ImportSpecifier::Default(default_specifier) = specifier {
|
if let ImportSpecifier::Default(default_specifier) = specifier {
|
||||||
self.dynamic_bindings.push(default_specifier.local.to_id());
|
self.dynamic_bindings.push(default_specifier.local.to_id());
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
decl
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_call_expr(&mut self, expr: CallExpr) -> CallExpr {
|
decl
|
||||||
let mut expr = expr.fold_children_with(self);
|
}
|
||||||
if let ExprOrSuper::Expr(i) = &expr.callee {
|
|
||||||
if let Expr::Ident(identifier) = &**i {
|
|
||||||
if self.dynamic_bindings.contains(&identifier.to_id()) {
|
|
||||||
if expr.args.len() == 0 {
|
|
||||||
HANDLER.with(|handler| {
|
|
||||||
handler
|
|
||||||
.struct_span_err(
|
|
||||||
identifier.span,
|
|
||||||
"next/dynamic requires at least one argument",
|
|
||||||
)
|
|
||||||
.emit()
|
|
||||||
});
|
|
||||||
} else if expr.args.len() > 2 {
|
|
||||||
HANDLER.with(|handler| {
|
|
||||||
handler
|
|
||||||
.struct_span_err(
|
|
||||||
identifier.span,
|
|
||||||
"next/dynamic only accepts 2 arguments",
|
|
||||||
)
|
|
||||||
.emit()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut import_specifier = None;
|
fn fold_call_expr(&mut self, expr: CallExpr) -> CallExpr {
|
||||||
if let Expr::Arrow(ArrowExpr {
|
if self.is_next_dynamic_first_arg {
|
||||||
body: BlockStmtOrExpr::Expr(e),
|
if let ExprOrSuper::Expr(e) = &expr.callee {
|
||||||
..
|
if let Expr::Ident(Ident { sym, .. }) = &**e {
|
||||||
}) = &*expr.args[0].expr
|
if sym == "import" {
|
||||||
{
|
if let Expr::Lit(Lit::Str(Str { value, .. })) = &*expr.args[0].expr {
|
||||||
if let Expr::Call(CallExpr {
|
self.dynamically_imported_specifier = Some(value.to_string());
|
||||||
args: a, callee, ..
|
}
|
||||||
}) = &**e
|
}
|
||||||
{
|
}
|
||||||
if let ExprOrSuper::Expr(e) = callee {
|
}
|
||||||
if let Expr::Ident(Ident { sym, .. }) = &**e {
|
return expr.fold_children_with(self);
|
||||||
if sym == "import" {
|
}
|
||||||
if a.len() == 0 {
|
let mut expr = expr.fold_children_with(self);
|
||||||
// Do nothing, import_specifier will
|
if let ExprOrSuper::Expr(i) = &expr.callee {
|
||||||
// remain None
|
if let Expr::Ident(identifier) = &**i {
|
||||||
// triggering error below
|
if self.dynamic_bindings.contains(&identifier.to_id()) {
|
||||||
} else if let Expr::Lit(Lit::Str(Str { value, .. })) =
|
if expr.args.len() == 0 {
|
||||||
&*a[0].expr
|
HANDLER.with(|handler| {
|
||||||
{
|
handler
|
||||||
import_specifier = Some(value.clone());
|
.struct_span_err(
|
||||||
}
|
identifier.span,
|
||||||
}
|
"next/dynamic requires at least one argument",
|
||||||
}
|
)
|
||||||
}
|
.emit()
|
||||||
}
|
});
|
||||||
}
|
return expr;
|
||||||
|
} else if expr.args.len() > 2 {
|
||||||
|
HANDLER.with(|handler| {
|
||||||
|
handler
|
||||||
|
.struct_span_err(identifier.span, "next/dynamic only accepts 2 arguments")
|
||||||
|
.emit()
|
||||||
|
});
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
if let None = import_specifier {
|
self.is_next_dynamic_first_arg = true;
|
||||||
HANDLER.with(|handler| {
|
expr.args[0].expr = expr.args[0].expr.clone().fold_with(self);
|
||||||
handler
|
self.is_next_dynamic_first_arg = false;
|
||||||
.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'))`",
|
|
||||||
)
|
|
||||||
.emit()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// loadableGenerated: {
|
if let None = self.dynamically_imported_specifier {
|
||||||
// webpack: () => [require.resolveWeak('../components/hello')],
|
HANDLER.with(|handler| {
|
||||||
// modules:
|
handler
|
||||||
// ["/project/src/file-being-transformed.js -> " + '../components/hello'] }
|
.struct_span_err(
|
||||||
let generated = Box::new(Expr::Object(ObjectLit {
|
identifier.span,
|
||||||
span: DUMMY_SP,
|
"First argument for next/dynamic must be an arrow function returning a valid \
|
||||||
props: vec![
|
dynamic import call e.g. `dynamic(() => import('../some-component'))`",
|
||||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
)
|
||||||
key: PropName::Ident(Ident::new("webpack".into(), DUMMY_SP)),
|
.emit()
|
||||||
value: Box::new(Expr::Arrow(ArrowExpr {
|
});
|
||||||
params: vec![],
|
return expr;
|
||||||
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 {
|
|
||||||
sym: js_word!("require"),
|
|
||||||
span: DUMMY_SP,
|
|
||||||
optional: false,
|
|
||||||
}),
|
|
||||||
)),
|
|
||||||
prop: Box::new(Expr::Ident(Ident {
|
|
||||||
sym: "resolveWeak".into(),
|
|
||||||
span: DUMMY_SP,
|
|
||||||
optional: false,
|
|
||||||
})),
|
|
||||||
computed: false,
|
|
||||||
span: DUMMY_SP,
|
|
||||||
},
|
|
||||||
))),
|
|
||||||
args: vec![ExprOrSpread {
|
|
||||||
expr: Box::new(Expr::Lit(Lit::Str(Str {
|
|
||||||
value: self.filename.to_string().into(),
|
|
||||||
span: DUMMY_SP,
|
|
||||||
kind: StrKind::Synthesized {},
|
|
||||||
has_escape: false,
|
|
||||||
}))),
|
|
||||||
spread: None,
|
|
||||||
}],
|
|
||||||
span: DUMMY_SP,
|
|
||||||
type_args: None,
|
|
||||||
})),
|
|
||||||
spread: None,
|
|
||||||
})],
|
|
||||||
span: DUMMY_SP,
|
|
||||||
}))),
|
|
||||||
is_async: false,
|
|
||||||
is_generator: false,
|
|
||||||
span: DUMMY_SP,
|
|
||||||
return_type: None,
|
|
||||||
type_params: None,
|
|
||||||
})),
|
|
||||||
}))),
|
|
||||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
|
||||||
key: PropName::Ident(Ident::new("modules".into(), DUMMY_SP)),
|
|
||||||
value: Box::new(Expr::Array(ArrayLit {
|
|
||||||
elems: vec![Some(ExprOrSpread {
|
|
||||||
expr: Box::new(Expr::Bin(BinExpr {
|
|
||||||
span: DUMMY_SP,
|
|
||||||
op: BinaryOp::Add,
|
|
||||||
left: Box::new(Expr::Lit(Lit::Str(Str {
|
|
||||||
value: format!(
|
|
||||||
"{} -> ",
|
|
||||||
rel_filename(
|
|
||||||
self.pages_dir.as_deref(),
|
|
||||||
&self.filename
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
span: DUMMY_SP,
|
|
||||||
kind: StrKind::Synthesized {},
|
|
||||||
has_escape: false,
|
|
||||||
}))),
|
|
||||||
right: Box::new(Expr::Lit(Lit::Str(Str {
|
|
||||||
value: import_specifier.unwrap(),
|
|
||||||
span: DUMMY_SP,
|
|
||||||
kind: StrKind::Normal {
|
|
||||||
contains_quote: false,
|
|
||||||
},
|
|
||||||
has_escape: false,
|
|
||||||
}))),
|
|
||||||
})),
|
|
||||||
spread: None,
|
|
||||||
})],
|
|
||||||
span: DUMMY_SP,
|
|
||||||
})),
|
|
||||||
}))),
|
|
||||||
],
|
|
||||||
}));
|
|
||||||
|
|
||||||
let mut props =
|
// loadableGenerated: {
|
||||||
vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
// webpack: () => [require.resolveWeak('../components/hello')],
|
||||||
key: PropName::Ident(Ident::new("loadableGenerated".into(), DUMMY_SP)),
|
// modules:
|
||||||
value: generated,
|
// ["/project/src/file-being-transformed.js -> " + '../components/hello'] }
|
||||||
})))];
|
let generated = Box::new(Expr::Object(ObjectLit {
|
||||||
|
span: DUMMY_SP,
|
||||||
if expr.args.len() == 2 {
|
props: vec![
|
||||||
if let Expr::Object(ObjectLit {
|
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||||
props: options_props,
|
key: PropName::Ident(Ident::new("webpack".into(), DUMMY_SP)),
|
||||||
..
|
value: Box::new(Expr::Arrow(ArrowExpr {
|
||||||
}) = &*expr.args[1].expr
|
params: vec![],
|
||||||
{
|
body: BlockStmtOrExpr::Expr(Box::new(Expr::Array(ArrayLit {
|
||||||
props.extend(options_props.iter().cloned());
|
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 {
|
||||||
let second_arg = ExprOrSpread {
|
sym: js_word!("require"),
|
||||||
spread: None,
|
|
||||||
expr: Box::new(Expr::Object(ObjectLit {
|
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
props,
|
optional: false,
|
||||||
})),
|
}))),
|
||||||
};
|
prop: Box::new(Expr::Ident(Ident {
|
||||||
|
sym: "resolveWeak".into(),
|
||||||
|
span: DUMMY_SP,
|
||||||
|
optional: false,
|
||||||
|
})),
|
||||||
|
computed: false,
|
||||||
|
span: DUMMY_SP,
|
||||||
|
}))),
|
||||||
|
args: vec![ExprOrSpread {
|
||||||
|
expr: Box::new(Expr::Lit(Lit::Str(Str {
|
||||||
|
value: self.filename.to_string().into(),
|
||||||
|
span: DUMMY_SP,
|
||||||
|
kind: StrKind::Synthesized {},
|
||||||
|
has_escape: false,
|
||||||
|
}))),
|
||||||
|
spread: None,
|
||||||
|
}],
|
||||||
|
span: DUMMY_SP,
|
||||||
|
type_args: None,
|
||||||
|
})),
|
||||||
|
spread: None,
|
||||||
|
})],
|
||||||
|
span: DUMMY_SP,
|
||||||
|
}))),
|
||||||
|
is_async: false,
|
||||||
|
is_generator: false,
|
||||||
|
span: DUMMY_SP,
|
||||||
|
return_type: None,
|
||||||
|
type_params: None,
|
||||||
|
})),
|
||||||
|
}))),
|
||||||
|
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||||
|
key: PropName::Ident(Ident::new("modules".into(), DUMMY_SP)),
|
||||||
|
value: Box::new(Expr::Array(ArrayLit {
|
||||||
|
elems: vec![Some(ExprOrSpread {
|
||||||
|
expr: Box::new(Expr::Bin(BinExpr {
|
||||||
|
span: DUMMY_SP,
|
||||||
|
op: BinaryOp::Add,
|
||||||
|
left: Box::new(Expr::Lit(Lit::Str(Str {
|
||||||
|
value: format!(
|
||||||
|
"{} -> ",
|
||||||
|
rel_filename(self.pages_dir.as_deref(), &self.filename)
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
span: DUMMY_SP,
|
||||||
|
kind: StrKind::Synthesized {},
|
||||||
|
has_escape: false,
|
||||||
|
}))),
|
||||||
|
right: Box::new(Expr::Lit(Lit::Str(Str {
|
||||||
|
value: self
|
||||||
|
.dynamically_imported_specifier
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.clone()
|
||||||
|
.into(),
|
||||||
|
span: DUMMY_SP,
|
||||||
|
kind: StrKind::Normal {
|
||||||
|
contains_quote: false,
|
||||||
|
},
|
||||||
|
has_escape: false,
|
||||||
|
}))),
|
||||||
|
})),
|
||||||
|
spread: None,
|
||||||
|
})],
|
||||||
|
span: DUMMY_SP,
|
||||||
|
})),
|
||||||
|
}))),
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
|
||||||
expr.args.push(second_arg);
|
let mut props = vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||||
}
|
key: PropName::Ident(Ident::new("loadableGenerated".into(), DUMMY_SP)),
|
||||||
|
value: generated,
|
||||||
|
})))];
|
||||||
|
|
||||||
|
if expr.args.len() == 2 {
|
||||||
|
if let Expr::Object(ObjectLit {
|
||||||
|
props: options_props,
|
||||||
|
..
|
||||||
|
}) = &*expr.args[1].expr
|
||||||
|
{
|
||||||
|
props.extend(options_props.iter().cloned());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let second_arg = ExprOrSpread {
|
||||||
|
spread: None,
|
||||||
|
expr: Box::new(Expr::Object(ObjectLit {
|
||||||
|
span: DUMMY_SP,
|
||||||
|
props,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
|
if expr.args.len() == 2 {
|
||||||
|
expr.args[1] = second_arg;
|
||||||
|
} else {
|
||||||
|
expr.args.push(second_arg)
|
||||||
|
}
|
||||||
|
self.dynamically_imported_specifier = None;
|
||||||
}
|
}
|
||||||
expr
|
}
|
||||||
}
|
}
|
||||||
|
expr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rel_filename(base: Option<&Path>, file: &FileName) -> String {
|
fn rel_filename(base: Option<&Path>, file: &FileName) -> String {
|
||||||
let base = match base {
|
let base = match base {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => return file.to_string(),
|
None => return file.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let file = match file {
|
let file = match file {
|
||||||
FileName::Real(v) => v,
|
FileName::Real(v) => v,
|
||||||
_ => {
|
_ => {
|
||||||
return file.to_string();
|
return file.to_string();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let rel_path = diff_paths(&file, base);
|
let rel_path = diff_paths(&file, base);
|
||||||
|
|
||||||
let rel_path = match rel_path {
|
let rel_path = match rel_path {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => return file.display().to_string(),
|
None => return file.display().to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
rel_path.display().to_string()
|
rel_path.display().to_string()
|
||||||
}
|
}
|
||||||
|
|
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,
|
hook_optimizer::hook_optimizer,
|
||||||
next_dynamic::next_dynamic,
|
next_dynamic::next_dynamic,
|
||||||
next_ssg::next_ssg,
|
next_ssg::next_ssg,
|
||||||
|
styled_jsx::styled_jsx,
|
||||||
util::{CtxtExt, MapErr},
|
util::{CtxtExt, MapErr},
|
||||||
};
|
};
|
||||||
use anyhow::{Context as _, Error};
|
use anyhow::{Context as _, Error};
|
||||||
|
@ -82,6 +83,7 @@ impl Task for TransformTask {
|
||||||
Optional::new(next_ssg(), !self.options.disable_next_ssg),
|
Optional::new(next_ssg(), !self.options.disable_next_ssg),
|
||||||
amp_attributes(),
|
amp_attributes(),
|
||||||
next_dynamic(s.name.clone(), self.options.pages_dir.clone()),
|
next_dynamic(s.name.clone(), self.options.pages_dir.clone()),
|
||||||
|
styled_jsx()
|
||||||
);
|
);
|
||||||
self.c.process_js_with_custom_pass(
|
self.c.process_js_with_custom_pass(
|
||||||
s.clone(),
|
s.clone(),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use self::amp_attributes::amp_attributes;
|
use self::amp_attributes::amp_attributes;
|
||||||
use self::next_dynamic::next_dynamic;
|
use self::next_dynamic::next_dynamic;
|
||||||
use self::next_ssg::next_ssg;
|
use self::next_ssg::next_ssg;
|
||||||
|
use self::styled_jsx::styled_jsx;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use swc_common::{chain, comments::SingleThreadedComments, FileName};
|
use swc_common::{chain, comments::SingleThreadedComments, FileName};
|
||||||
use swc_ecma_transforms_testing::{test, test_fixture};
|
use swc_ecma_transforms_testing::{test, test_fixture};
|
||||||
|
@ -16,6 +17,8 @@ mod amp_attributes;
|
||||||
mod next_dynamic;
|
mod next_dynamic;
|
||||||
#[path = "../src/next_ssg.rs"]
|
#[path = "../src/next_ssg.rs"]
|
||||||
mod next_ssg;
|
mod next_ssg;
|
||||||
|
#[path = "../src/styled_jsx/mod.rs"]
|
||||||
|
mod styled_jsx;
|
||||||
|
|
||||||
fn syntax() -> Syntax {
|
fn syntax() -> Syntax {
|
||||||
Syntax::Es(EsConfig {
|
Syntax::Es(EsConfig {
|
||||||
|
@ -75,3 +78,9 @@ fn next_ssg_fixture(input: PathBuf) {
|
||||||
&output,
|
&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'
|
import dynamic from "next/dynamic";
|
||||||
const DynamicComponentWithCustomLoading = dynamic(
|
const DynamicComponentWithCustomLoading = dynamic(()=>import("../components/hello")
|
||||||
() => import('../components/hello'),
|
, {
|
||||||
{
|
|
||||||
loading: () => <p>...</p>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
loadableGenerated: {
|
loadableGenerated: {
|
||||||
webpack: () => [require.resolveWeak('/some-project/src/some-file.js')],
|
webpack: ()=>[
|
||||||
modules: ['some-file.js -> ' + '../components/hello'],
|
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