chore: Update swc_core to v0.40.7
(#41613)
This commit is contained in:
parent
2e2cc5597a
commit
78138af505
282 changed files with 318 additions and 11130 deletions
455
packages/next-swc/Cargo.lock
generated
455
packages/next-swc/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -19,10 +19,10 @@ pathdiff = "0.2.0"
|
|||
regex = "1.5"
|
||||
serde = "1"
|
||||
serde_json = "1"
|
||||
swc_emotion = {path="../emotion"}
|
||||
styled_components = {path="../styled_components"}
|
||||
styled_jsx = {path="../styled_jsx"}
|
||||
modularize_imports = {path="../modularize_imports"}
|
||||
swc_emotion = "0.28.1"
|
||||
styled_components = "0.52.1"
|
||||
styled_jsx = "0.29.1"
|
||||
modularize_imports = "0.25.1"
|
||||
tracing = { version = "0.1.32", features = ["release_max_level_info"] }
|
||||
|
||||
swc_core = { features = [
|
||||
|
@ -42,9 +42,9 @@ swc_core = { features = [
|
|||
"ecma_parser_typescript",
|
||||
"cached",
|
||||
"base"
|
||||
], version = "0.39.7" }
|
||||
], version = "0.40.7" }
|
||||
|
||||
[dev-dependencies]
|
||||
swc_core = { features = ["testing_transform"], version = "0.39.7" }
|
||||
testing = "0.31.9"
|
||||
swc_core = { features = ["testing_transform"], version = "0.40.7" }
|
||||
testing = "0.31.10"
|
||||
walkdir = "2.3.2"
|
||||
|
|
|
@ -162,7 +162,10 @@ where
|
|||
_ => Either::Right(noop()),
|
||||
},
|
||||
if opts.styled_jsx {
|
||||
Either::Left(styled_jsx::styled_jsx(cm.clone(), file.name.clone()))
|
||||
Either::Left(styled_jsx::visitor::styled_jsx(
|
||||
cm.clone(),
|
||||
file.name.clone(),
|
||||
))
|
||||
} else {
|
||||
Either::Right(noop())
|
||||
},
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
[package]
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||
edition = "2018"
|
||||
description = "AST Transforms for emotion"
|
||||
license = "Apache-2.0"
|
||||
name = "swc_emotion"
|
||||
repository = "https://github.com/vercel/next.js.git"
|
||||
version = "0.22.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.13"
|
||||
byteorder = "1"
|
||||
fxhash = "0.2.1"
|
||||
once_cell = "1.13.0"
|
||||
radix_fmt = "1"
|
||||
regex = "1.5"
|
||||
serde = "1"
|
||||
sourcemap = "6.0.1"
|
||||
tracing = { version = "0.1.32", features = ["release_max_level_info"] }
|
||||
swc_core = { features = ["common", "ecma_ast","ecma_codegen", "ecma_utils", "ecma_visit", "trace_macro"], version = "0.39.7" }
|
||||
|
||||
[dev-dependencies]
|
||||
swc_core = { features = ["testing_transform", "ecma_transforms_react"], version = "0.39.7" }
|
||||
testing = "0.31.9"
|
||||
serde_json = "1"
|
|
@ -1,62 +0,0 @@
|
|||
// Ported from https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash2.cpp#L37-L86
|
||||
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
|
||||
const M: u32 = 0x5bd1_e995;
|
||||
|
||||
pub(crate) fn murmurhash2(key: &[u8], initial_state: u32) -> u32 {
|
||||
let mut h: u32 = initial_state;
|
||||
|
||||
let mut four_bytes_chunks = key.chunks_exact(4);
|
||||
for chunk in four_bytes_chunks.by_ref() {
|
||||
let mut k: u32 = LittleEndian::read_u32(chunk);
|
||||
k = k.wrapping_mul(M);
|
||||
k ^= k >> 24;
|
||||
h = k.wrapping_mul(M) ^ h.wrapping_mul(M);
|
||||
}
|
||||
let remainder = four_bytes_chunks.remainder();
|
||||
|
||||
// Handle the last few bytes of the input array
|
||||
match remainder.len() {
|
||||
3 => {
|
||||
h ^= u32::from(remainder[2]) << 16;
|
||||
}
|
||||
2 => {
|
||||
h ^= u32::from(remainder[1]) << 8;
|
||||
}
|
||||
1 => {
|
||||
h ^= u32::from(remainder[0]);
|
||||
h = h.wrapping_mul(M);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
h ^= h >> 13;
|
||||
h = h.wrapping_mul(M);
|
||||
h ^ (h >> 15)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use super::murmurhash2;
|
||||
|
||||
#[test]
|
||||
fn test_murmur2() {
|
||||
let s1 = "abcdef";
|
||||
let s2 = "abcdeg";
|
||||
for i in 0..5 {
|
||||
assert_eq!(
|
||||
murmurhash2(s1[i..5].as_bytes(), 0),
|
||||
murmurhash2(s2[i..5].as_bytes(), 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_hash() {
|
||||
assert_eq!(
|
||||
murmurhash2("something".as_bytes(), 0),
|
||||
u32::from_str_radix("crsxd7", 36).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use swc_core::{common::collections::AHashMap, ecma::atoms::JsWord};
|
||||
|
||||
use crate::{EmotionModuleConfig, ExportItem};
|
||||
|
||||
/// key: `importSource`
|
||||
pub type ImportMap = AHashMap<JsWord, ImportMapValue>;
|
||||
|
||||
/// key: `localExportName`
|
||||
pub type ImportMapValue = AHashMap<JsWord, Config>;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Config {
|
||||
canonical_import: ImportItem,
|
||||
}
|
||||
|
||||
/// `(packageName, exportName)`
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct ImportItem(JsWord, JsWord);
|
||||
|
||||
pub(crate) fn expand_import_map(
|
||||
map: Option<&ImportMap>,
|
||||
mut imports: Vec<EmotionModuleConfig>,
|
||||
) -> Vec<EmotionModuleConfig> {
|
||||
if let Some(map) = map {
|
||||
map.iter().for_each(|(import_source, value)| {
|
||||
value
|
||||
.iter()
|
||||
.for_each(|(local_export_name, Config { canonical_import })| {
|
||||
let ImportItem(package_name, export_name) = canonical_import;
|
||||
|
||||
if &**package_name == "@emotion/react" && &**export_name == "jsx" {
|
||||
return;
|
||||
}
|
||||
|
||||
let package_transformers = imports
|
||||
.iter()
|
||||
.find(|v| v.module_name == *package_name)
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"There is no transformer for the export '{}' in '{}'",
|
||||
export_name, package_name
|
||||
)
|
||||
})
|
||||
.clone();
|
||||
|
||||
let kind = package_transformers
|
||||
.exported_names
|
||||
.iter()
|
||||
.find(|v| v.name == **export_name)
|
||||
.map(|v| v.kind)
|
||||
.or_else(|| {
|
||||
if export_name == "default" {
|
||||
package_transformers.default_export
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"failed to find export '{}' from package '{}'",
|
||||
export_name, package_name
|
||||
)
|
||||
});
|
||||
|
||||
imports.push(EmotionModuleConfig {
|
||||
module_name: import_source.clone(),
|
||||
exported_names: vec![ExportItem {
|
||||
name: local_export_name.to_string(),
|
||||
kind,
|
||||
}],
|
||||
default_export: package_transformers.default_export,
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
imports
|
||||
}
|
|
@ -1,845 +0,0 @@
|
|||
use std::borrow::Cow;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use fxhash::FxHashMap;
|
||||
use import_map::ImportMap;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sourcemap::{RawToken, SourceMap as RawSourcemap};
|
||||
use swc_core::{
|
||||
common::{comments::Comments, util::take::Take, BytePos, SourceMapperDyn, DUMMY_SP},
|
||||
ecma::utils::ExprFactory,
|
||||
ecma::visit::{Fold, FoldWith},
|
||||
ecma::{
|
||||
ast::{
|
||||
ArrayLit, CallExpr, Callee, Expr, ExprOrSpread, Id, Ident, ImportDecl, ImportSpecifier,
|
||||
JSXAttr, JSXAttrName, JSXAttrOrSpread, JSXAttrValue, JSXElement, JSXElementName,
|
||||
JSXExpr, JSXExprContainer, JSXObject, KeyValueProp, MemberProp, ModuleExportName,
|
||||
ObjectLit, Pat, Prop, PropName, PropOrSpread, SourceMapperExt, Tpl, VarDeclarator,
|
||||
},
|
||||
atoms::JsWord,
|
||||
},
|
||||
trace_macro::swc_trace,
|
||||
};
|
||||
|
||||
mod hash;
|
||||
mod import_map;
|
||||
|
||||
static EMOTION_OFFICIAL_LIBRARIES: Lazy<Vec<EmotionModuleConfig>> = Lazy::new(|| {
|
||||
vec![
|
||||
EmotionModuleConfig {
|
||||
module_name: "@emotion/css".into(),
|
||||
exported_names: vec![ExportItem {
|
||||
name: "css".to_owned(),
|
||||
kind: ExprKind::Css,
|
||||
}],
|
||||
default_export: Some(ExprKind::Css),
|
||||
},
|
||||
EmotionModuleConfig {
|
||||
module_name: "@emotion/styled".into(),
|
||||
exported_names: vec![],
|
||||
default_export: Some(ExprKind::Styled),
|
||||
},
|
||||
EmotionModuleConfig {
|
||||
module_name: "@emotion/react".into(),
|
||||
exported_names: vec![
|
||||
ExportItem {
|
||||
name: "css".to_owned(),
|
||||
kind: ExprKind::Css,
|
||||
},
|
||||
ExportItem {
|
||||
name: "keyframes".to_owned(),
|
||||
kind: ExprKind::Css,
|
||||
},
|
||||
ExportItem {
|
||||
name: "Global".to_owned(),
|
||||
kind: ExprKind::GlobalJSX,
|
||||
},
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
EmotionModuleConfig {
|
||||
module_name: "@emotion/primitives".into(),
|
||||
exported_names: vec![ExportItem {
|
||||
name: "css".to_owned(),
|
||||
kind: ExprKind::Css,
|
||||
}],
|
||||
default_export: Some(ExprKind::Styled),
|
||||
},
|
||||
EmotionModuleConfig {
|
||||
module_name: "@emotion/native".into(),
|
||||
exported_names: vec![ExportItem {
|
||||
name: "css".to_owned(),
|
||||
kind: ExprKind::Css,
|
||||
}],
|
||||
default_export: Some(ExprKind::Styled),
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
static SPACE_AROUND_COLON: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(r"\s*(?P<s>[:;,\{,\}])\s*").unwrap());
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EmotionOptions {
|
||||
pub enabled: Option<bool>,
|
||||
pub sourcemap: Option<bool>,
|
||||
pub auto_label: Option<bool>,
|
||||
pub label_format: Option<String>,
|
||||
pub import_map: Option<ImportMap>,
|
||||
}
|
||||
|
||||
impl Default for EmotionOptions {
|
||||
fn default() -> Self {
|
||||
EmotionOptions {
|
||||
enabled: Some(false),
|
||||
sourcemap: Some(true),
|
||||
auto_label: Some(true),
|
||||
label_format: Some("[local]".to_owned()),
|
||||
import_map: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct EmotionModuleConfig {
|
||||
module_name: JsWord,
|
||||
exported_names: Vec<ExportItem>,
|
||||
default_export: Option<ExprKind>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
struct ExportItem {
|
||||
name: String,
|
||||
kind: ExprKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
enum ImportType {
|
||||
Named,
|
||||
Namespace,
|
||||
Default,
|
||||
}
|
||||
|
||||
impl Default for ImportType {
|
||||
fn default() -> Self {
|
||||
ImportType::Named
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
enum ExprKind {
|
||||
Css,
|
||||
Styled,
|
||||
GlobalJSX,
|
||||
}
|
||||
|
||||
impl Default for ExprKind {
|
||||
fn default() -> Self {
|
||||
ExprKind::Css
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum PackageMeta {
|
||||
Named(ExprKind),
|
||||
Namespace(EmotionModuleConfig),
|
||||
}
|
||||
|
||||
pub fn emotion<C: Comments>(
|
||||
emotion_options: EmotionOptions,
|
||||
path: &Path,
|
||||
cm: Arc<SourceMapperDyn>,
|
||||
comments: C,
|
||||
) -> impl Fold {
|
||||
EmotionTransformer::new(emotion_options, path, cm, comments)
|
||||
}
|
||||
|
||||
pub struct EmotionTransformer<C: Comments> {
|
||||
pub options: EmotionOptions,
|
||||
filepath_hash: Option<u32>,
|
||||
filepath: PathBuf,
|
||||
dir: Option<String>,
|
||||
filename: Option<String>,
|
||||
cm: Arc<SourceMapperDyn>,
|
||||
comments: C,
|
||||
import_packages: FxHashMap<Id, PackageMeta>,
|
||||
emotion_target_class_name_count: usize,
|
||||
current_context: Option<String>,
|
||||
// skip `css` transformation if it in JSX Element/Attribute
|
||||
in_jsx_element: bool,
|
||||
|
||||
registered_imports: Vec<EmotionModuleConfig>,
|
||||
}
|
||||
|
||||
#[swc_trace]
|
||||
impl<C: Comments> EmotionTransformer<C> {
|
||||
pub fn new(
|
||||
options: EmotionOptions,
|
||||
path: &Path,
|
||||
cm: Arc<SourceMapperDyn>,
|
||||
comments: C,
|
||||
) -> Self {
|
||||
let registered_imports = self::import_map::expand_import_map(
|
||||
options.import_map.as_ref(),
|
||||
EMOTION_OFFICIAL_LIBRARIES.to_vec(),
|
||||
);
|
||||
|
||||
EmotionTransformer {
|
||||
options,
|
||||
filepath_hash: None,
|
||||
filepath: path.to_owned(),
|
||||
dir: path.parent().and_then(|p| p.to_str()).map(|s| s.to_owned()),
|
||||
filename: path
|
||||
.file_name()
|
||||
.and_then(|filename| filename.to_str())
|
||||
.map(|s| s.to_owned()),
|
||||
cm,
|
||||
comments,
|
||||
import_packages: FxHashMap::default(),
|
||||
emotion_target_class_name_count: 0,
|
||||
current_context: None,
|
||||
in_jsx_element: false,
|
||||
registered_imports,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
// Compute file hash on demand
|
||||
// Memorize the hash of the file name
|
||||
fn get_filename_hash(&mut self) -> u32 {
|
||||
if self.filepath_hash.is_none() {
|
||||
self.filepath_hash = Some(hash::murmurhash2(
|
||||
self.filepath.to_string_lossy().as_bytes(),
|
||||
0,
|
||||
));
|
||||
}
|
||||
self.filepath_hash.unwrap()
|
||||
}
|
||||
|
||||
fn create_label(&self, with_prefix: bool) -> String {
|
||||
let prefix = if with_prefix { "label:" } else { "" };
|
||||
let mut label = format!(
|
||||
"{}{}",
|
||||
prefix,
|
||||
self.options
|
||||
.label_format
|
||||
.clone()
|
||||
.unwrap_or_else(|| "[local]".to_owned())
|
||||
);
|
||||
if let Some(current_context) = &self.current_context {
|
||||
label = label.replace("[local]", current_context);
|
||||
if let Some(filename) = self.filename.as_ref() {
|
||||
label = label.replace("[filename]", filename);
|
||||
}
|
||||
if let Some(dir) = self.dir.as_ref() {
|
||||
label = label.replace("[dir]", dir);
|
||||
};
|
||||
}
|
||||
label
|
||||
}
|
||||
|
||||
fn create_sourcemap(&mut self, pos: BytePos) -> Option<String> {
|
||||
if self.options.sourcemap.unwrap_or(false) {
|
||||
let loc = self.cm.get_code_map().lookup_char_pos(pos);
|
||||
let filename = self.filepath.to_str().map(|s| s.to_owned());
|
||||
let cm = RawSourcemap::new(
|
||||
filename.clone(),
|
||||
vec![RawToken {
|
||||
dst_line: 0,
|
||||
dst_col: 0,
|
||||
src_line: loc.line as u32 - 1,
|
||||
src_col: loc.col_display as u32,
|
||||
src_id: 0,
|
||||
name_id: 0,
|
||||
}],
|
||||
Vec::new(),
|
||||
vec![filename.unwrap_or_default()],
|
||||
Some(vec![Some(loc.file.src.to_string())]),
|
||||
);
|
||||
let mut writer = Vec::new();
|
||||
if cm.to_writer(&mut writer).is_ok() {
|
||||
return Some(format!(
|
||||
"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,{} */",
|
||||
base64::encode(writer)
|
||||
));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// Find the imported name from modules
|
||||
// These import statements are supported:
|
||||
// import styled from '@emotion/styled'
|
||||
// import { default as whateverStyled } from '@emotion/styled'
|
||||
// import { css } from '@emotion/react'
|
||||
// import * as emotionCss from '@emotion/react'
|
||||
fn generate_import_info(&mut self, expr: &ImportDecl) {
|
||||
for c in self.registered_imports.iter() {
|
||||
if expr.src.value == c.module_name {
|
||||
for specifier in expr.specifiers.iter() {
|
||||
match specifier {
|
||||
ImportSpecifier::Named(named) => {
|
||||
for exported in c.exported_names.iter() {
|
||||
let matched = match &named.imported {
|
||||
Some(imported) => match imported {
|
||||
ModuleExportName::Ident(v) => v.sym == exported.name,
|
||||
ModuleExportName::Str(v) => v.value == exported.name,
|
||||
},
|
||||
_ => named.local.as_ref() == exported.name,
|
||||
};
|
||||
if matched {
|
||||
self.import_packages.insert(
|
||||
named.local.to_id(),
|
||||
PackageMeta::Named(exported.kind),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ImportSpecifier::Default(default) => {
|
||||
if let Some(kind) = c.default_export {
|
||||
self.import_packages
|
||||
.insert(default.local.to_id(), PackageMeta::Named(kind));
|
||||
}
|
||||
}
|
||||
ImportSpecifier::Namespace(namespace) => {
|
||||
self.import_packages
|
||||
.insert(namespace.local.to_id(), PackageMeta::Namespace(c.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_label_prop_node(&mut self, key: &str) -> PropOrSpread {
|
||||
let stable_class_name = format!(
|
||||
"e{}{}",
|
||||
radix_fmt::radix_36(self.get_filename_hash()),
|
||||
self.emotion_target_class_name_count
|
||||
);
|
||||
self.emotion_target_class_name_count += 1;
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new(key.into(), DUMMY_SP)),
|
||||
value: stable_class_name.into(),
|
||||
})))
|
||||
}
|
||||
|
||||
fn create_args_from_tagged_tpl(&self, tagged_tpl: &mut Tpl) -> Vec<ExprOrSpread> {
|
||||
let args_len = tagged_tpl.exprs.len() + tagged_tpl.quasis.len();
|
||||
// 2 more capacity is for `label` and `sourceMap`
|
||||
let mut args = Vec::with_capacity(args_len + 2);
|
||||
for index in 0..args_len {
|
||||
let i = index / 2;
|
||||
if index % 2 == 0 {
|
||||
if let Some(q) = tagged_tpl.quasis.get_mut(i) {
|
||||
let q = q.take();
|
||||
let minified = minify_css_string(&q.raw, index == 0, index == args_len - 1);
|
||||
// Compress one more spaces into one space
|
||||
if minified.replace(' ', "").is_empty() {
|
||||
if index != 0 && index != args_len - 1 {
|
||||
args.push(" ".as_arg());
|
||||
}
|
||||
} else {
|
||||
args.push(minified.as_arg())
|
||||
}
|
||||
}
|
||||
} else if let Some(e) = tagged_tpl.exprs.get_mut(i) {
|
||||
args.push(e.take().as_arg());
|
||||
}
|
||||
}
|
||||
args
|
||||
}
|
||||
|
||||
fn rewrite_styles_attr(&mut self, attrs: &mut [JSXAttrOrSpread], pos: BytePos) {
|
||||
if let Some(attr_value) = attrs.iter_mut().find_map(|attr| {
|
||||
if let JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
name: JSXAttrName::Ident(i),
|
||||
value,
|
||||
..
|
||||
}) = attr
|
||||
{
|
||||
if i.as_ref() == "styles" {
|
||||
return value.as_mut();
|
||||
}
|
||||
}
|
||||
None
|
||||
}) {
|
||||
if let Some(raw_attr) = match attr_value {
|
||||
JSXAttrValue::Lit(lit) => Some(Box::new(Expr::Lit(lit.clone()))),
|
||||
JSXAttrValue::JSXExprContainer(JSXExprContainer {
|
||||
expr: JSXExpr::Expr(expr),
|
||||
..
|
||||
}) => Some(expr.take()),
|
||||
_ => None,
|
||||
} {
|
||||
*attr_value = self.create_styles_attr(raw_attr, pos);
|
||||
self.in_jsx_element = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_styles_attr(&mut self, mut raw_attr: Box<Expr>, pos: BytePos) -> JSXAttrValue {
|
||||
if let Expr::Array(array_lit) = raw_attr.as_mut() {
|
||||
if let Some(cm) = self.create_sourcemap(pos) {
|
||||
array_lit.elems.push(Some(cm.as_arg()));
|
||||
}
|
||||
JSXAttrValue::JSXExprContainer(JSXExprContainer {
|
||||
span: DUMMY_SP,
|
||||
expr: JSXExpr::Expr(raw_attr),
|
||||
})
|
||||
} else {
|
||||
JSXAttrValue::JSXExprContainer(JSXExprContainer {
|
||||
span: DUMMY_SP,
|
||||
expr: JSXExpr::Expr(Box::new(Expr::Array(ArrayLit {
|
||||
span: DUMMY_SP,
|
||||
elems: {
|
||||
let mut elements = Vec::with_capacity(2);
|
||||
elements.push(Some(raw_attr.as_arg()));
|
||||
if let Some(cm) = self.create_sourcemap(pos) {
|
||||
elements.push(Some(cm.as_arg()));
|
||||
}
|
||||
elements
|
||||
},
|
||||
}))),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Comments> Fold for EmotionTransformer<C> {
|
||||
// Collect import modules that indicator if this file need to be transformed
|
||||
fn fold_import_decl(&mut self, expr: ImportDecl) -> ImportDecl {
|
||||
if expr.type_only {
|
||||
return expr;
|
||||
}
|
||||
self.generate_import_info(&expr);
|
||||
expr
|
||||
}
|
||||
|
||||
fn fold_var_declarator(&mut self, dec: VarDeclarator) -> VarDeclarator {
|
||||
if let Pat::Ident(i) = &dec.name {
|
||||
self.current_context = Some(i.id.as_ref().to_owned());
|
||||
}
|
||||
dec.fold_children_with(self)
|
||||
}
|
||||
|
||||
fn fold_call_expr(&mut self, mut expr: CallExpr) -> CallExpr {
|
||||
// If no package that we care about is imported, skip the following
|
||||
// transformation logic.
|
||||
if self.import_packages.is_empty() {
|
||||
return expr;
|
||||
}
|
||||
if let Callee::Expr(e) = &mut expr.callee {
|
||||
match e.as_mut() {
|
||||
// css({})
|
||||
Expr::Ident(i) => {
|
||||
if let Some(package) = self.import_packages.get(&i.to_id()) {
|
||||
if !expr.args.is_empty() {
|
||||
if let PackageMeta::Named(kind) = package {
|
||||
if matches!(kind, ExprKind::Css) && !self.in_jsx_element {
|
||||
self.comments.add_pure_comment(expr.span.lo());
|
||||
if self.options.auto_label.unwrap_or(false) {
|
||||
expr.args.push(self.create_label(true).as_arg());
|
||||
}
|
||||
if let Some(cm) = self.create_sourcemap(expr.span.lo) {
|
||||
expr.args.push(cm.as_arg());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// styled('div')({})
|
||||
Expr::Call(c) => {
|
||||
if let Callee::Expr(callee_exp) = &c.callee {
|
||||
if let Expr::Ident(i) = callee_exp.as_ref() {
|
||||
if let Some(PackageMeta::Named(ExprKind::Styled)) =
|
||||
self.import_packages.get(&i.to_id())
|
||||
{
|
||||
if !c.args.is_empty() {
|
||||
let mut args_props = Vec::with_capacity(2);
|
||||
args_props.push(self.create_label_prop_node("target"));
|
||||
self.comments.add_pure_comment(expr.span.lo());
|
||||
if self.options.auto_label.unwrap_or(false) {
|
||||
args_props.push(PropOrSpread::Prop(Box::new(
|
||||
Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new(
|
||||
"label".into(),
|
||||
DUMMY_SP,
|
||||
)),
|
||||
value: self.create_label(false).into(),
|
||||
}),
|
||||
)));
|
||||
}
|
||||
if let Some(cm) = self.create_sourcemap(expr.span.lo()) {
|
||||
expr.args.push(cm.as_arg());
|
||||
}
|
||||
if let Some(ExprOrSpread { expr, .. }) = c.args.get_mut(1) {
|
||||
if let Expr::Object(ObjectLit { props, .. }) = expr.as_mut()
|
||||
{
|
||||
props.extend(args_props);
|
||||
} else {
|
||||
c.args.push(
|
||||
Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: args_props,
|
||||
})
|
||||
.as_arg(),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
c.args.push(
|
||||
Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: args_props,
|
||||
})
|
||||
.as_arg(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// styled.div({})
|
||||
// customEmotionReact.css({})
|
||||
Expr::Member(m) => {
|
||||
if let Expr::Ident(i) = m.obj.as_ref() {
|
||||
if let Some(package) = self.import_packages.get(&i.to_id()) {
|
||||
if let PackageMeta::Named(kind) = package {
|
||||
if matches!(kind, ExprKind::Styled) {
|
||||
if let MemberProp::Ident(prop) = &m.prop {
|
||||
let mut args_props = Vec::with_capacity(2);
|
||||
args_props.push(self.create_label_prop_node("target"));
|
||||
let mut args = vec![prop.sym.as_ref().as_arg()];
|
||||
if !self.in_jsx_element {
|
||||
self.comments.add_pure_comment(expr.span.lo());
|
||||
if self.options.auto_label.unwrap_or(false) {
|
||||
args_props.push(PropOrSpread::Prop(Box::new(
|
||||
Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new(
|
||||
"label".into(),
|
||||
DUMMY_SP,
|
||||
)),
|
||||
value: self.create_label(false).into(),
|
||||
}),
|
||||
)));
|
||||
}
|
||||
args.push(
|
||||
Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: args_props,
|
||||
})
|
||||
.as_arg(),
|
||||
);
|
||||
if let Some(cm) = self.create_sourcemap(expr.span.lo())
|
||||
{
|
||||
expr.args.push(cm.as_arg());
|
||||
}
|
||||
}
|
||||
return CallExpr {
|
||||
span: expr.span,
|
||||
type_args: expr.type_args,
|
||||
args: expr.args,
|
||||
callee: CallExpr {
|
||||
span: DUMMY_SP,
|
||||
type_args: None,
|
||||
callee: Ident::new(i.sym.clone(), i.span)
|
||||
.as_callee(),
|
||||
args,
|
||||
}
|
||||
.as_callee(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if let PackageMeta::Namespace(c) = package {
|
||||
if c.exported_names
|
||||
.iter()
|
||||
.any(|n| match_css_export(n, &m.prop))
|
||||
{
|
||||
self.comments.add_pure_comment(expr.span.lo());
|
||||
if self.options.auto_label.unwrap_or(false) {
|
||||
expr.args.push(self.create_label(true).as_arg());
|
||||
}
|
||||
if let Some(cm) = self.create_sourcemap(expr.span.lo()) {
|
||||
expr.args.push(cm.as_arg());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
expr
|
||||
}
|
||||
|
||||
fn fold_expr(&mut self, mut expr: Expr) -> Expr {
|
||||
if let Expr::TaggedTpl(tagged_tpl) = &mut expr {
|
||||
// styled('div')``
|
||||
match tagged_tpl.tag.as_mut() {
|
||||
Expr::Call(call) => {
|
||||
if let Callee::Expr(callee) = &call.callee {
|
||||
if let Expr::Ident(i) = callee.as_ref() {
|
||||
if let Some(PackageMeta::Named(ExprKind::Styled)) =
|
||||
self.import_packages.get(&i.to_id())
|
||||
{
|
||||
let mut callee = call.take();
|
||||
let mut object_props = Vec::with_capacity(2);
|
||||
object_props.push(self.create_label_prop_node("target"));
|
||||
self.comments.add_pure_comment(callee.span.lo());
|
||||
if self.options.auto_label.unwrap_or(false) {
|
||||
object_props.push(PropOrSpread::Prop(Box::new(
|
||||
Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new(
|
||||
"label".into(),
|
||||
DUMMY_SP,
|
||||
)),
|
||||
value: self.create_label(false).into(),
|
||||
}),
|
||||
)));
|
||||
}
|
||||
if let Some(ExprOrSpread { expr, .. }) = callee.args.get_mut(1) {
|
||||
if let Expr::Object(ObjectLit { props, .. }) = expr.as_mut() {
|
||||
props.extend(object_props);
|
||||
} else {
|
||||
callee.args.push(
|
||||
Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: object_props,
|
||||
})
|
||||
.as_arg(),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
callee.args.push(
|
||||
Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: object_props,
|
||||
})
|
||||
.as_arg(),
|
||||
);
|
||||
}
|
||||
return Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: callee.as_callee(),
|
||||
args: {
|
||||
let mut args: Vec<ExprOrSpread> = self
|
||||
.create_args_from_tagged_tpl(&mut tagged_tpl.tpl)
|
||||
.into_iter()
|
||||
.map(|exp| exp.fold_children_with(self))
|
||||
.collect();
|
||||
if let Some(cm) =
|
||||
self.create_sourcemap(tagged_tpl.span.lo())
|
||||
{
|
||||
args.push(cm.as_arg());
|
||||
}
|
||||
args
|
||||
},
|
||||
type_args: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// css``
|
||||
Expr::Ident(i) => {
|
||||
if let Some(PackageMeta::Named(ExprKind::Css)) =
|
||||
self.import_packages.get(&i.to_id())
|
||||
{
|
||||
let mut args = self.create_args_from_tagged_tpl(&mut tagged_tpl.tpl);
|
||||
if !self.in_jsx_element {
|
||||
self.comments.add_pure_comment(i.span.lo());
|
||||
if self.options.auto_label.unwrap_or(false) {
|
||||
args.push(self.create_label(false).as_arg());
|
||||
}
|
||||
if let Some(cm) = self.create_sourcemap(tagged_tpl.span.lo()) {
|
||||
args.push(cm.as_arg());
|
||||
}
|
||||
}
|
||||
return Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: i.take().as_callee(),
|
||||
args,
|
||||
type_args: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
// styled.div``
|
||||
// customEmotionReact.css``
|
||||
Expr::Member(member_expr) => {
|
||||
if let Expr::Ident(i) = member_expr.obj.as_mut() {
|
||||
if let Some(p) = self.import_packages.get(&i.to_id()) {
|
||||
match p {
|
||||
PackageMeta::Named(ExprKind::Styled) => {
|
||||
if let MemberProp::Ident(prop) = &mut member_expr.prop {
|
||||
let mut object_props = Vec::with_capacity(2);
|
||||
object_props.push(self.create_label_prop_node("target"));
|
||||
if self.options.auto_label.unwrap_or(false) {
|
||||
object_props.push(PropOrSpread::Prop(Box::new(
|
||||
Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new(
|
||||
"label".into(),
|
||||
DUMMY_SP,
|
||||
)),
|
||||
value: self.create_label(false).into(),
|
||||
}),
|
||||
)));
|
||||
}
|
||||
let mut args =
|
||||
self.create_args_from_tagged_tpl(&mut tagged_tpl.tpl);
|
||||
|
||||
if let Some(cm) =
|
||||
self.create_sourcemap(tagged_tpl.span.lo())
|
||||
{
|
||||
args.push(cm.as_arg());
|
||||
}
|
||||
|
||||
self.comments.add_pure_comment(member_expr.span.lo());
|
||||
return Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
type_args: None,
|
||||
callee: CallExpr {
|
||||
type_args: None,
|
||||
span: DUMMY_SP,
|
||||
callee: i.take().as_callee(),
|
||||
args: vec![
|
||||
prop.take().sym.as_arg(),
|
||||
Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: object_props,
|
||||
})
|
||||
.as_arg(),
|
||||
],
|
||||
}
|
||||
.as_callee(),
|
||||
args,
|
||||
});
|
||||
}
|
||||
}
|
||||
PackageMeta::Namespace(c) => {
|
||||
if c.exported_names
|
||||
.iter()
|
||||
.any(|item| match_css_export(item, &member_expr.prop))
|
||||
{
|
||||
self.comments.add_pure_comment(member_expr.span.lo());
|
||||
return Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: member_expr.take().as_callee(),
|
||||
args: {
|
||||
let mut args = self.create_args_from_tagged_tpl(
|
||||
&mut tagged_tpl.tpl,
|
||||
);
|
||||
if self.options.auto_label.unwrap_or(false) {
|
||||
args.push(self.create_label(true).as_arg());
|
||||
}
|
||||
if let Some(cm) =
|
||||
self.create_sourcemap(tagged_tpl.span.lo())
|
||||
{
|
||||
args.push(cm.as_arg());
|
||||
}
|
||||
args
|
||||
},
|
||||
type_args: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
expr.fold_children_with(self)
|
||||
}
|
||||
|
||||
fn fold_jsx_element(&mut self, mut expr: JSXElement) -> JSXElement {
|
||||
match &mut expr.opening.name {
|
||||
JSXElementName::Ident(i) => {
|
||||
if let Some(PackageMeta::Named(ExprKind::GlobalJSX)) =
|
||||
self.import_packages.get(&i.to_id())
|
||||
{
|
||||
self.rewrite_styles_attr(&mut expr.opening.attrs, i.span.lo());
|
||||
}
|
||||
}
|
||||
JSXElementName::JSXMemberExpr(member_exp) => {
|
||||
if let JSXObject::Ident(i) = &member_exp.obj {
|
||||
if let Some(PackageMeta::Namespace(EmotionModuleConfig {
|
||||
exported_names,
|
||||
..
|
||||
})) = self.import_packages.get(&i.to_id())
|
||||
{
|
||||
if exported_names.iter().any(|item| {
|
||||
matches!(item.kind, ExprKind::GlobalJSX)
|
||||
&& item.name == member_exp.prop.as_ref()
|
||||
}) {
|
||||
self.rewrite_styles_attr(&mut expr.opening.attrs, i.span.lo());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
let dest_expr = expr.fold_children_with(self);
|
||||
self.in_jsx_element = false;
|
||||
dest_expr
|
||||
}
|
||||
}
|
||||
|
||||
fn match_css_export(item: &ExportItem, prop: &MemberProp) -> bool {
|
||||
if matches!(item.kind, ExprKind::Css) {
|
||||
if let MemberProp::Ident(prop) = prop {
|
||||
if item.name.as_str() == prop.sym.as_ref() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn minify_css_string(input: &str, is_first_item: bool, is_last_item: bool) -> Cow<str> {
|
||||
let pattern = |c| c == '\n';
|
||||
let pattern_trim_spaces = |c| c == ' ' || c == '\n';
|
||||
SPACE_AROUND_COLON.replace_all(
|
||||
input
|
||||
.trim_start_matches(if is_first_item {
|
||||
pattern_trim_spaces
|
||||
} else {
|
||||
pattern
|
||||
})
|
||||
.trim_end_matches(if is_last_item {
|
||||
pattern_trim_spaces
|
||||
} else {
|
||||
pattern
|
||||
}),
|
||||
"$s",
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
mod test_emotion {
|
||||
use super::minify_css_string;
|
||||
|
||||
#[test]
|
||||
fn should_not_trim_end_space_in_first_item() {
|
||||
assert_eq!(
|
||||
minify_css_string(
|
||||
r#"
|
||||
box-shadow: inset 0px 0px 0px "#,
|
||||
true,
|
||||
false
|
||||
),
|
||||
"box-shadow:inset 0px 0px 0px "
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use swc_core::{
|
||||
common::{chain, comments::SingleThreadedComments, Mark},
|
||||
ecma::parser::{Syntax, TsConfig},
|
||||
ecma::transforms::react::{jsx, Runtime},
|
||||
ecma::transforms::testing::test_fixture,
|
||||
};
|
||||
use swc_emotion::EmotionOptions;
|
||||
use testing::fixture;
|
||||
|
||||
fn ts_syntax() -> Syntax {
|
||||
Syntax::Typescript(TsConfig {
|
||||
tsx: true,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
#[fixture("tests/fixture/**/input.tsx")]
|
||||
fn next_emotion_fixture(input: PathBuf) {
|
||||
let output = input.parent().unwrap().join("output.ts");
|
||||
test_fixture(
|
||||
ts_syntax(),
|
||||
&|tr| {
|
||||
let top_level_mark = Mark::fresh(Mark::root());
|
||||
let jsx = jsx::<SingleThreadedComments>(
|
||||
tr.cm.clone(),
|
||||
Some(tr.comments.as_ref().clone()),
|
||||
swc_core::ecma::transforms::react::Options {
|
||||
next: false.into(),
|
||||
runtime: Some(Runtime::Automatic),
|
||||
throw_if_namespace: false.into(),
|
||||
development: false.into(),
|
||||
use_builtins: true.into(),
|
||||
use_spread: true.into(),
|
||||
..Default::default()
|
||||
},
|
||||
top_level_mark,
|
||||
);
|
||||
|
||||
let test_import_map =
|
||||
serde_json::from_str(include_str!("./testImportMap.json")).unwrap();
|
||||
|
||||
chain!(
|
||||
swc_emotion::emotion(
|
||||
EmotionOptions {
|
||||
enabled: Some(true),
|
||||
sourcemap: Some(true),
|
||||
auto_label: Some(true),
|
||||
import_map: Some(test_import_map),
|
||||
..Default::default()
|
||||
},
|
||||
&PathBuf::from("input.ts"),
|
||||
tr.cm.clone(),
|
||||
tr.comments.as_ref().clone(),
|
||||
),
|
||||
jsx
|
||||
)
|
||||
},
|
||||
&input,
|
||||
&output,
|
||||
Default::default(),
|
||||
);
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
import { css } from '@emotion/react'
|
||||
import styled from '@emotion/styled'
|
||||
|
||||
const unitNormal = '1rem'
|
||||
const unitLarge = '2rem'
|
||||
|
||||
const Example = styled.div`
|
||||
margin: ${unitNormal} ${unitLarge};
|
||||
`
|
||||
|
||||
export const Animated = styled.div`
|
||||
& code {
|
||||
background-color: linen;
|
||||
}
|
||||
animation: ${({ animation }) => animation} 0.2s infinite ease-in-out alternate;
|
||||
`
|
||||
|
||||
const shadowBorder = ({ width = '1px', color }) =>
|
||||
css`
|
||||
box-shadow: inset 0px 0px 0px ${width} ${color};
|
||||
`
|
||||
|
||||
const StyledInput = styled.input`
|
||||
${shadowBorder({ color: 'red', width: '4px' })}
|
||||
`
|
|
@ -1,22 +0,0 @@
|
|||
import { css } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
const unitNormal = '1rem';
|
||||
const unitLarge = '2rem';
|
||||
const Example = /*#__PURE__*/ styled("div", {
|
||||
target: "ekie5mj0",
|
||||
label: "Example"
|
||||
})("margin:", unitNormal, " ", unitLarge, ";", "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5cbmNvbnN0IHVuaXROb3JtYWwgPSAnMXJlbSdcbmNvbnN0IHVuaXRMYXJnZSA9ICcycmVtJ1xuXG5jb25zdCBFeGFtcGxlID0gc3R5bGVkLmRpdmBcbiAgbWFyZ2luOiAke3VuaXROb3JtYWx9ICR7dW5pdExhcmdlfTtcbmBcblxuZXhwb3J0IGNvbnN0IEFuaW1hdGVkID0gc3R5bGVkLmRpdmBcbiAgJiBjb2RlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiBsaW5lbjtcbiAgfVxuICBhbmltYXRpb246ICR7KHsgYW5pbWF0aW9uIH0pID0+IGFuaW1hdGlvbn0gMC4ycyBpbmZpbml0ZSBlYXNlLWluLW91dCBhbHRlcm5hdGU7XG5gXG5cbmNvbnN0IHNoYWRvd0JvcmRlciA9ICh7IHdpZHRoID0gJzFweCcsIGNvbG9yIH0pID0+XG4gIGNzc2BcbiAgICBib3gtc2hhZG93OiBpbnNldCAwcHggMHB4IDBweCAke3dpZHRofSAke2NvbG9yfTtcbiAgYFxuXG5jb25zdCBTdHlsZWRJbnB1dCA9IHN0eWxlZC5pbnB1dGBcbiAgJHtzaGFkb3dCb3JkZXIoeyBjb2xvcjogJ3JlZCcsIHdpZHRoOiAnNHB4JyB9KX1cbmBcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNZ0IifQ== */");
|
||||
export const Animated = /*#__PURE__*/ styled("div", {
|
||||
target: "ekie5mj1",
|
||||
label: "Animated"
|
||||
})("& code{background-color:linen;}animation:", ({ animation })=>animation
|
||||
, " 0.2s infinite ease-in-out alternate;", "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5cbmNvbnN0IHVuaXROb3JtYWwgPSAnMXJlbSdcbmNvbnN0IHVuaXRMYXJnZSA9ICcycmVtJ1xuXG5jb25zdCBFeGFtcGxlID0gc3R5bGVkLmRpdmBcbiAgbWFyZ2luOiAke3VuaXROb3JtYWx9ICR7dW5pdExhcmdlfTtcbmBcblxuZXhwb3J0IGNvbnN0IEFuaW1hdGVkID0gc3R5bGVkLmRpdmBcbiAgJiBjb2RlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiBsaW5lbjtcbiAgfVxuICBhbmltYXRpb246ICR7KHsgYW5pbWF0aW9uIH0pID0+IGFuaW1hdGlvbn0gMC4ycyBpbmZpbml0ZSBlYXNlLWluLW91dCBhbHRlcm5hdGU7XG5gXG5cbmNvbnN0IHNoYWRvd0JvcmRlciA9ICh7IHdpZHRoID0gJzFweCcsIGNvbG9yIH0pID0+XG4gIGNzc2BcbiAgICBib3gtc2hhZG93OiBpbnNldCAwcHggMHB4IDBweCAke3dpZHRofSAke2NvbG9yfTtcbiAgYFxuXG5jb25zdCBTdHlsZWRJbnB1dCA9IHN0eWxlZC5pbnB1dGBcbiAgJHtzaGFkb3dCb3JkZXIoeyBjb2xvcjogJ3JlZCcsIHdpZHRoOiAnNHB4JyB9KX1cbmBcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFVd0IifQ== */");
|
||||
const shadowBorder = ({ width ='1px' , color })=>/*#__PURE__*/ css("box-shadow:inset 0px 0px 0px ", width, " ", color, ";", "shadowBorder", "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5cbmNvbnN0IHVuaXROb3JtYWwgPSAnMXJlbSdcbmNvbnN0IHVuaXRMYXJnZSA9ICcycmVtJ1xuXG5jb25zdCBFeGFtcGxlID0gc3R5bGVkLmRpdmBcbiAgbWFyZ2luOiAke3VuaXROb3JtYWx9ICR7dW5pdExhcmdlfTtcbmBcblxuZXhwb3J0IGNvbnN0IEFuaW1hdGVkID0gc3R5bGVkLmRpdmBcbiAgJiBjb2RlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiBsaW5lbjtcbiAgfVxuICBhbmltYXRpb246ICR7KHsgYW5pbWF0aW9uIH0pID0+IGFuaW1hdGlvbn0gMC4ycyBpbmZpbml0ZSBlYXNlLWluLW91dCBhbHRlcm5hdGU7XG5gXG5cbmNvbnN0IHNoYWRvd0JvcmRlciA9ICh7IHdpZHRoID0gJzFweCcsIGNvbG9yIH0pID0+XG4gIGNzc2BcbiAgICBib3gtc2hhZG93OiBpbnNldCAwcHggMHB4IDBweCAke3dpZHRofSAke2NvbG9yfTtcbiAgYFxuXG5jb25zdCBTdHlsZWRJbnB1dCA9IHN0eWxlZC5pbnB1dGBcbiAgJHtzaGFkb3dCb3JkZXIoeyBjb2xvcjogJ3JlZCcsIHdpZHRoOiAnNHB4JyB9KX1cbmBcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFrQkUifQ== */")
|
||||
;
|
||||
const StyledInput = /*#__PURE__*/ styled("input", {
|
||||
target: "ekie5mj2",
|
||||
label: "StyledInput"
|
||||
})(shadowBorder({
|
||||
color: 'red',
|
||||
width: '4px'
|
||||
}), "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5cbmNvbnN0IHVuaXROb3JtYWwgPSAnMXJlbSdcbmNvbnN0IHVuaXRMYXJnZSA9ICcycmVtJ1xuXG5jb25zdCBFeGFtcGxlID0gc3R5bGVkLmRpdmBcbiAgbWFyZ2luOiAke3VuaXROb3JtYWx9ICR7dW5pdExhcmdlfTtcbmBcblxuZXhwb3J0IGNvbnN0IEFuaW1hdGVkID0gc3R5bGVkLmRpdmBcbiAgJiBjb2RlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiBsaW5lbjtcbiAgfVxuICBhbmltYXRpb246ICR7KHsgYW5pbWF0aW9uIH0pID0+IGFuaW1hdGlvbn0gMC4ycyBpbmZpbml0ZSBlYXNlLWluLW91dCBhbHRlcm5hdGU7XG5gXG5cbmNvbnN0IHNoYWRvd0JvcmRlciA9ICh7IHdpZHRoID0gJzFweCcsIGNvbG9yIH0pID0+XG4gIGNzc2BcbiAgICBib3gtc2hhZG93OiBpbnNldCAwcHggMHB4IDBweCAke3dpZHRofSAke2NvbG9yfTtcbiAgYFxuXG5jb25zdCBTdHlsZWRJbnB1dCA9IHN0eWxlZC5pbnB1dGBcbiAgJHtzaGFkb3dCb3JkZXIoeyBjb2xvcjogJ3JlZCcsIHdpZHRoOiAnNHB4JyB9KX1cbmBcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFzQm9CIn0= */");
|
|
@ -1,86 +0,0 @@
|
|||
import { css, Global } from '@emotion/react'
|
||||
import styled from '@emotion/styled'
|
||||
import { PureComponent } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
const stylesInCallback = (props: any) =>
|
||||
css({
|
||||
color: 'red',
|
||||
background: 'yellow',
|
||||
width: `${props.scale * 100}px`,
|
||||
})
|
||||
|
||||
const styles = css({
|
||||
color: 'red',
|
||||
width: '20px',
|
||||
})
|
||||
|
||||
const styles2 = css`
|
||||
color: red;
|
||||
width: 20px;
|
||||
`
|
||||
|
||||
const DivContainer = styled.div({
|
||||
background: 'red',
|
||||
})
|
||||
|
||||
const DivContainer2 = styled.div`
|
||||
background: red;
|
||||
`
|
||||
|
||||
const ContainerWithOptions = styled('div', {
|
||||
shouldForwardProp: (propertyName: string) => !propertyName.startsWith('$'),
|
||||
})`
|
||||
color: hotpink;
|
||||
`
|
||||
|
||||
const SpanContainer = styled('span')({
|
||||
background: 'yellow',
|
||||
})
|
||||
|
||||
export const DivContainerExtended = styled(DivContainer)``
|
||||
export const DivContainerExtended2 = styled(DivContainer)({})
|
||||
|
||||
const Container = styled('button')`
|
||||
background: red;
|
||||
${stylesInCallback}
|
||||
${() =>
|
||||
css({
|
||||
background: 'red',
|
||||
})}
|
||||
color: yellow;
|
||||
font-size: 12px;
|
||||
`
|
||||
|
||||
const Container2 = styled.div`
|
||||
background: red;
|
||||
`
|
||||
|
||||
export class SimpleComponent extends PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<Container
|
||||
css={css`
|
||||
color: hotpink;
|
||||
`}
|
||||
>
|
||||
<Global
|
||||
styles={css`
|
||||
html,
|
||||
body {
|
||||
padding: 3rem 1rem;
|
||||
margin: 0;
|
||||
background: papayawhip;
|
||||
min-height: 100%;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-size: 24px;
|
||||
}
|
||||
`}
|
||||
/>
|
||||
<span>hello</span>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<SimpleComponent />, document.querySelector('#app'))
|
File diff suppressed because one or more lines are too long
|
@ -1,8 +0,0 @@
|
|||
import * as React from 'react'
|
||||
import { SomeGlobalFromCore } from 'package-two'
|
||||
|
||||
const getBgColor = () => ({ backgroundColor: '#fff' })
|
||||
|
||||
export default () => (
|
||||
<SomeGlobalFromCore styles={{ color: 'hotpink', ...getBgColor() }} />
|
||||
)
|
|
@ -1,15 +0,0 @@
|
|||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import * as React from 'react';
|
||||
import { SomeGlobalFromCore } from 'package-two';
|
||||
const getBgColor = ()=>({
|
||||
backgroundColor: '#fff'
|
||||
});
|
||||
export default (()=>/*#__PURE__*/ _jsx(SomeGlobalFromCore, {
|
||||
styles: [
|
||||
{
|
||||
color: 'hotpink',
|
||||
...getBgColor()
|
||||
},
|
||||
"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgU29tZUdsb2JhbEZyb21Db3JlIH0gZnJvbSAncGFja2FnZS10d28nXG5cbmNvbnN0IGdldEJnQ29sb3IgPSAoKSA9PiAoeyBiYWNrZ3JvdW5kQ29sb3I6ICcjZmZmJyB9KVxuXG5leHBvcnQgZGVmYXVsdCAoKSA9PiAoXG4gIDxTb21lR2xvYmFsRnJvbUNvcmUgc3R5bGVzPXt7IGNvbG9yOiAnaG90cGluaycsIC4uLmdldEJnQ29sb3IoKSB9fSAvPlxuKVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU1HIn0= */"
|
||||
]
|
||||
}));
|
|
@ -1,4 +0,0 @@
|
|||
import * as React from 'react'
|
||||
import { SomeGlobalFromCore } from 'package-two'
|
||||
|
||||
export default () => <SomeGlobalFromCore styles={{ color: 'hotpink' }} />
|
|
@ -1,11 +0,0 @@
|
|||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import * as React from 'react';
|
||||
import { SomeGlobalFromCore } from 'package-two';
|
||||
export default (()=>/*#__PURE__*/ _jsx(SomeGlobalFromCore, {
|
||||
styles: [
|
||||
{
|
||||
color: 'hotpink'
|
||||
},
|
||||
"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgU29tZUdsb2JhbEZyb21Db3JlIH0gZnJvbSAncGFja2FnZS10d28nXG5cbmV4cG9ydCBkZWZhdWx0ICgpID0+IDxTb21lR2xvYmFsRnJvbUNvcmUgc3R5bGVzPXt7IGNvbG9yOiAnaG90cGluaycgfX0gLz5cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHc0IifQ== */"
|
||||
]
|
||||
}));
|
|
@ -1,3 +0,0 @@
|
|||
import { nonDefaultStyled as someAlias } from 'package-one'
|
||||
|
||||
let SomeComp = someAlias.div({ color: 'hotpink' })
|
|
@ -1,7 +0,0 @@
|
|||
import { nonDefaultStyled as someAlias } from 'package-one';
|
||||
let SomeComp = /*#__PURE__*/ someAlias("div", {
|
||||
target: "ekie5mj0",
|
||||
label: "SomeComp"
|
||||
})({
|
||||
color: 'hotpink'
|
||||
}, "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG5vbkRlZmF1bHRTdHlsZWQgYXMgc29tZUFsaWFzIH0gZnJvbSAncGFja2FnZS1vbmUnXG5cbmxldCBTb21lQ29tcCA9IHNvbWVBbGlhcy5kaXYoeyBjb2xvcjogJ2hvdHBpbmsnIH0pXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRWUifQ== */");
|
|
@ -1,3 +0,0 @@
|
|||
import { nonDefaultStyled } from 'package-one'
|
||||
|
||||
let SomeComp = nonDefaultStyled.div({ color: 'hotpink' })
|
|
@ -1,7 +0,0 @@
|
|||
import { nonDefaultStyled } from 'package-one';
|
||||
let SomeComp = /*#__PURE__*/ nonDefaultStyled("div", {
|
||||
target: "ekie5mj0",
|
||||
label: "SomeComp"
|
||||
})({
|
||||
color: 'hotpink'
|
||||
}, "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG5vbkRlZmF1bHRTdHlsZWQgfSBmcm9tICdwYWNrYWdlLW9uZSdcblxubGV0IFNvbWVDb21wID0gbm9uRGVmYXVsdFN0eWxlZC5kaXYoeyBjb2xvcjogJ2hvdHBpbmsnIH0pXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRWUifQ== */");
|
|
@ -1,3 +0,0 @@
|
|||
import { nonDefaultStyled } from 'package-four'
|
||||
|
||||
let SomeComp = nonDefaultStyled.div({ color: 'hotpink' })
|
|
@ -1,7 +0,0 @@
|
|||
import { nonDefaultStyled } from 'package-four';
|
||||
let SomeComp = /*#__PURE__*/ nonDefaultStyled("div", {
|
||||
target: "ekie5mj0",
|
||||
label: "SomeComp"
|
||||
})({
|
||||
color: 'hotpink'
|
||||
}, "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG5vbkRlZmF1bHRTdHlsZWQgfSBmcm9tICdwYWNrYWdlLWZvdXInXG5cbmxldCBTb21lQ29tcCA9IG5vbkRlZmF1bHRTdHlsZWQuZGl2KHsgY29sb3I6ICdob3RwaW5rJyB9KVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVlIn0= */");
|
|
@ -1,3 +0,0 @@
|
|||
import { something } from 'package-three'
|
||||
|
||||
something({ color: 'green' })
|
|
@ -1,4 +0,0 @@
|
|||
import { something } from 'package-three';
|
||||
/*#__PURE__*/ something({
|
||||
color: 'green'
|
||||
}, "label:[local]", "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNvbWV0aGluZyB9IGZyb20gJ3BhY2thZ2UtdGhyZWUnXG5cbnNvbWV0aGluZyh7IGNvbG9yOiAnZ3JlZW4nIH0pXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEifQ== */");
|
|
@ -1,9 +0,0 @@
|
|||
import styled from '@emotion/styled'
|
||||
|
||||
const SelectedComponent = styled.p`
|
||||
color: red;
|
||||
|
||||
&:after {
|
||||
content: ' | ';
|
||||
}
|
||||
`
|
|
@ -1,5 +0,0 @@
|
|||
import styled from '@emotion/styled';
|
||||
const SelectedComponent = /*#__PURE__*/ styled("p", {
|
||||
target: "ekie5mj0",
|
||||
label: "SelectedComponent"
|
||||
})("color:red;&:after{content:' | ';}", "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkJ1xuXG5jb25zdCBTZWxlY3RlZENvbXBvbmVudCA9IHN0eWxlZC5wYFxuICBjb2xvcjogcmVkO1xuXG4gICY6YWZ0ZXIge1xuICAgIGNvbnRlbnQ6ICcgfCAnO1xuICB9XG5gXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRTBCIn0= */");
|
|
@ -1,32 +0,0 @@
|
|||
import * as emotionReact from '@emotion/react'
|
||||
import { PureComponent } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
const stylesInCallback = (props: any) =>
|
||||
emotionReact.css({
|
||||
color: 'red',
|
||||
background: 'yellow',
|
||||
width: `${props.scale * 100}px`,
|
||||
})
|
||||
|
||||
const styles = emotionReact.css({
|
||||
color: 'red',
|
||||
width: '20px',
|
||||
})
|
||||
|
||||
const styles2 = emotionReact.css`
|
||||
color: red;
|
||||
width: 20px;
|
||||
`
|
||||
|
||||
export class SimpleComponent extends PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<div className={styles}>
|
||||
<span>hello</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<SimpleComponent />, document.querySelector('#app'))
|
|
@ -1,26 +0,0 @@
|
|||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import * as emotionReact from '@emotion/react';
|
||||
import { PureComponent } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
const stylesInCallback = (props: any)=>/*#__PURE__*/ emotionReact.css({
|
||||
color: 'red',
|
||||
background: 'yellow',
|
||||
width: `${props.scale * 100}px`
|
||||
}, "label:stylesInCallback", "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGVtb3Rpb25SZWFjdCBmcm9tICdAZW1vdGlvbi9yZWFjdCdcbmltcG9ydCB7IFB1cmVDb21wb25lbnQgfSBmcm9tICdyZWFjdCdcbmltcG9ydCBSZWFjdERPTSBmcm9tICdyZWFjdC1kb20nXG5cbmNvbnN0IHN0eWxlc0luQ2FsbGJhY2sgPSAocHJvcHM6IGFueSkgPT5cbiAgZW1vdGlvblJlYWN0LmNzcyh7XG4gICAgY29sb3I6ICdyZWQnLFxuICAgIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxuICAgIHdpZHRoOiBgJHtwcm9wcy5zY2FsZSAqIDEwMH1weGAsXG4gIH0pXG5cbmNvbnN0IHN0eWxlcyA9IGVtb3Rpb25SZWFjdC5jc3Moe1xuICBjb2xvcjogJ3JlZCcsXG4gIHdpZHRoOiAnMjBweCcsXG59KVxuXG5jb25zdCBzdHlsZXMyID0gZW1vdGlvblJlYWN0LmNzc2BcbiAgY29sb3I6IHJlZDtcbiAgd2lkdGg6IDIwcHg7XG5gXG5cbmV4cG9ydCBjbGFzcyBTaW1wbGVDb21wb25lbnQgZXh0ZW5kcyBQdXJlQ29tcG9uZW50IHtcbiAgcmVuZGVyKCkge1xuICAgIHJldHVybiAoXG4gICAgICA8ZGl2IGNsYXNzTmFtZT17c3R5bGVzfT5cbiAgICAgICAgPHNwYW4+aGVsbG88L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICApXG4gIH1cbn1cblxuUmVhY3RET00ucmVuZGVyKDxTaW1wbGVDb21wb25lbnQgLz4sIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNhcHAnKSlcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLRSJ9 */")
|
||||
;
|
||||
const styles = /*#__PURE__*/ emotionReact.css({
|
||||
color: 'red',
|
||||
width: '20px'
|
||||
}, "label:styles", "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGVtb3Rpb25SZWFjdCBmcm9tICdAZW1vdGlvbi9yZWFjdCdcbmltcG9ydCB7IFB1cmVDb21wb25lbnQgfSBmcm9tICdyZWFjdCdcbmltcG9ydCBSZWFjdERPTSBmcm9tICdyZWFjdC1kb20nXG5cbmNvbnN0IHN0eWxlc0luQ2FsbGJhY2sgPSAocHJvcHM6IGFueSkgPT5cbiAgZW1vdGlvblJlYWN0LmNzcyh7XG4gICAgY29sb3I6ICdyZWQnLFxuICAgIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxuICAgIHdpZHRoOiBgJHtwcm9wcy5zY2FsZSAqIDEwMH1weGAsXG4gIH0pXG5cbmNvbnN0IHN0eWxlcyA9IGVtb3Rpb25SZWFjdC5jc3Moe1xuICBjb2xvcjogJ3JlZCcsXG4gIHdpZHRoOiAnMjBweCcsXG59KVxuXG5jb25zdCBzdHlsZXMyID0gZW1vdGlvblJlYWN0LmNzc2BcbiAgY29sb3I6IHJlZDtcbiAgd2lkdGg6IDIwcHg7XG5gXG5cbmV4cG9ydCBjbGFzcyBTaW1wbGVDb21wb25lbnQgZXh0ZW5kcyBQdXJlQ29tcG9uZW50IHtcbiAgcmVuZGVyKCkge1xuICAgIHJldHVybiAoXG4gICAgICA8ZGl2IGNsYXNzTmFtZT17c3R5bGVzfT5cbiAgICAgICAgPHNwYW4+aGVsbG88L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICApXG4gIH1cbn1cblxuUmVhY3RET00ucmVuZGVyKDxTaW1wbGVDb21wb25lbnQgLz4sIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNhcHAnKSlcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFXZSJ9 */");
|
||||
const styles2 = /*#__PURE__*/ emotionReact.css("color:red;width:20px;", "label:styles2", "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGVtb3Rpb25SZWFjdCBmcm9tICdAZW1vdGlvbi9yZWFjdCdcbmltcG9ydCB7IFB1cmVDb21wb25lbnQgfSBmcm9tICdyZWFjdCdcbmltcG9ydCBSZWFjdERPTSBmcm9tICdyZWFjdC1kb20nXG5cbmNvbnN0IHN0eWxlc0luQ2FsbGJhY2sgPSAocHJvcHM6IGFueSkgPT5cbiAgZW1vdGlvblJlYWN0LmNzcyh7XG4gICAgY29sb3I6ICdyZWQnLFxuICAgIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxuICAgIHdpZHRoOiBgJHtwcm9wcy5zY2FsZSAqIDEwMH1weGAsXG4gIH0pXG5cbmNvbnN0IHN0eWxlcyA9IGVtb3Rpb25SZWFjdC5jc3Moe1xuICBjb2xvcjogJ3JlZCcsXG4gIHdpZHRoOiAnMjBweCcsXG59KVxuXG5jb25zdCBzdHlsZXMyID0gZW1vdGlvblJlYWN0LmNzc2BcbiAgY29sb3I6IHJlZDtcbiAgd2lkdGg6IDIwcHg7XG5gXG5cbmV4cG9ydCBjbGFzcyBTaW1wbGVDb21wb25lbnQgZXh0ZW5kcyBQdXJlQ29tcG9uZW50IHtcbiAgcmVuZGVyKCkge1xuICAgIHJldHVybiAoXG4gICAgICA8ZGl2IGNsYXNzTmFtZT17c3R5bGVzfT5cbiAgICAgICAgPHNwYW4+aGVsbG88L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICApXG4gIH1cbn1cblxuUmVhY3RET00ucmVuZGVyKDxTaW1wbGVDb21wb25lbnQgLz4sIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNhcHAnKSlcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFnQmdCIn0= */");
|
||||
export class SimpleComponent extends PureComponent {
|
||||
render() {
|
||||
return /*#__PURE__*/ _jsx("div", {
|
||||
className: styles,
|
||||
children: /*#__PURE__*/ _jsx("span", {
|
||||
children: "hello"
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
ReactDOM.render(/*#__PURE__*/ _jsx(SimpleComponent, {}), document.querySelector('#app'));
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"package-one": {
|
||||
"nonDefaultStyled": { "canonicalImport": ["@emotion/styled", "default"] }
|
||||
},
|
||||
"package-two": {
|
||||
"someJsx": { "canonicalImport": ["@emotion/react", "jsx"] },
|
||||
"someCssFromCore": { "canonicalImport": ["@emotion/react", "css"] },
|
||||
"SomeGlobalFromCore": { "canonicalImport": ["@emotion/react", "Global"] }
|
||||
},
|
||||
"package-three": {
|
||||
"something": { "canonicalImport": ["@emotion/css", "css"] }
|
||||
},
|
||||
"package-four": {
|
||||
"nonDefaultStyled": {
|
||||
"canonicalImport": ["@emotion/styled", "default"],
|
||||
"styledBaseImport": ["package-four/base", "something"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
[package]
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||
description = "AST Transforms for import modularizer"
|
||||
edition = "2018"
|
||||
license = "Apache-2.0"
|
||||
name = "modularize_imports"
|
||||
repository = "https://github.com/vercel/next.js.git"
|
||||
version = "0.20.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
convert_case = "0.5.0"
|
||||
handlebars = "4.2.1"
|
||||
once_cell = "1.13.0"
|
||||
regex = "1.5"
|
||||
serde = "1"
|
||||
swc_core = { features = ["cached", "ecma_ast", "ecma_visit"], version = "0.39.7" }
|
||||
|
||||
[dev-dependencies]
|
||||
swc_core = { features = ["testing_transform"], version = "0.39.7" }
|
||||
testing = "0.31.9"
|
|
@ -1,249 +0,0 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use convert_case::{Case, Casing};
|
||||
use handlebars::{Context, Handlebars, Helper, HelperResult, Output, RenderContext};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::{Captures, Regex};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use swc_core::{
|
||||
cached::regex::CachedRegex,
|
||||
ecma::ast::*,
|
||||
ecma::visit::{noop_fold_type, Fold},
|
||||
};
|
||||
|
||||
static DUP_SLASH_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"//").unwrap());
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct Config {
|
||||
pub packages: HashMap<String, PackageConfig>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PackageConfig {
|
||||
pub transform: String,
|
||||
#[serde(default)]
|
||||
pub prevent_full_import: bool,
|
||||
#[serde(default)]
|
||||
pub skip_default_conversion: bool,
|
||||
}
|
||||
|
||||
struct FoldImports {
|
||||
renderer: handlebars::Handlebars<'static>,
|
||||
packages: Vec<(CachedRegex, PackageConfig)>,
|
||||
}
|
||||
|
||||
struct Rewriter<'a> {
|
||||
renderer: &'a handlebars::Handlebars<'static>,
|
||||
key: &'a str,
|
||||
config: &'a PackageConfig,
|
||||
group: Vec<&'a str>,
|
||||
}
|
||||
|
||||
impl<'a> Rewriter<'a> {
|
||||
fn rewrite(&self, old_decl: &ImportDecl) -> Vec<ImportDecl> {
|
||||
if old_decl.type_only || old_decl.asserts.is_some() {
|
||||
return vec![old_decl.clone()];
|
||||
}
|
||||
|
||||
let mut out: Vec<ImportDecl> = Vec::with_capacity(old_decl.specifiers.len());
|
||||
|
||||
for spec in &old_decl.specifiers {
|
||||
match spec {
|
||||
ImportSpecifier::Named(named_spec) => {
|
||||
#[derive(Serialize)]
|
||||
#[serde(untagged)]
|
||||
enum Data<'a> {
|
||||
Plain(&'a str),
|
||||
Array(&'a [&'a str]),
|
||||
}
|
||||
let mut ctx: HashMap<&str, Data> = HashMap::new();
|
||||
ctx.insert("matches", Data::Array(&self.group[..]));
|
||||
ctx.insert(
|
||||
"member",
|
||||
Data::Plain(
|
||||
named_spec
|
||||
.imported
|
||||
.as_ref()
|
||||
.map(|x| match x {
|
||||
ModuleExportName::Ident(x) => x.as_ref(),
|
||||
ModuleExportName::Str(x) => x.value.as_ref(),
|
||||
})
|
||||
.unwrap_or_else(|| named_spec.local.as_ref()),
|
||||
),
|
||||
);
|
||||
let new_path = self
|
||||
.renderer
|
||||
.render_template(&self.config.transform, &ctx)
|
||||
.unwrap_or_else(|e| {
|
||||
panic!("error rendering template for '{}': {}", self.key, e);
|
||||
});
|
||||
let new_path = DUP_SLASH_REGEX.replace_all(&new_path, |_: &Captures| "/");
|
||||
let specifier = if self.config.skip_default_conversion {
|
||||
ImportSpecifier::Named(named_spec.clone())
|
||||
} else {
|
||||
ImportSpecifier::Default(ImportDefaultSpecifier {
|
||||
local: named_spec.local.clone(),
|
||||
span: named_spec.span,
|
||||
})
|
||||
};
|
||||
out.push(ImportDecl {
|
||||
specifiers: vec![specifier],
|
||||
src: Box::new(Str::from(new_path.as_ref())),
|
||||
span: old_decl.span,
|
||||
type_only: false,
|
||||
asserts: None,
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
if self.config.prevent_full_import {
|
||||
panic!(
|
||||
"import {:?} causes the entire module to be imported",
|
||||
old_decl
|
||||
);
|
||||
} else {
|
||||
// Give up
|
||||
return vec![old_decl.clone()];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
impl FoldImports {
|
||||
fn should_rewrite<'a>(&'a self, name: &'a str) -> Option<Rewriter<'a>> {
|
||||
for (regex, config) in &self.packages {
|
||||
let group = regex.captures(name);
|
||||
if let Some(group) = group {
|
||||
let group = group
|
||||
.iter()
|
||||
.map(|x| x.map(|x| x.as_str()).unwrap_or_default())
|
||||
.collect::<Vec<&str>>();
|
||||
return Some(Rewriter {
|
||||
renderer: &self.renderer,
|
||||
key: name,
|
||||
config,
|
||||
group,
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold for FoldImports {
|
||||
noop_fold_type!();
|
||||
fn fold_module(&mut self, mut module: Module) -> Module {
|
||||
let mut new_items: Vec<ModuleItem> = vec![];
|
||||
for item in module.body {
|
||||
match item {
|
||||
ModuleItem::ModuleDecl(ModuleDecl::Import(decl)) => {
|
||||
match self.should_rewrite(&decl.src.value) {
|
||||
Some(rewriter) => {
|
||||
let rewritten = rewriter.rewrite(&decl);
|
||||
new_items.extend(
|
||||
rewritten
|
||||
.into_iter()
|
||||
.map(|x| ModuleItem::ModuleDecl(ModuleDecl::Import(x))),
|
||||
);
|
||||
}
|
||||
None => new_items.push(ModuleItem::ModuleDecl(ModuleDecl::Import(decl))),
|
||||
}
|
||||
}
|
||||
x => {
|
||||
new_items.push(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
module.body = new_items;
|
||||
module
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modularize_imports(config: Config) -> impl Fold {
|
||||
let mut folder = FoldImports {
|
||||
renderer: handlebars::Handlebars::new(),
|
||||
packages: vec![],
|
||||
};
|
||||
folder
|
||||
.renderer
|
||||
.register_helper("lowerCase", Box::new(helper_lower_case));
|
||||
folder
|
||||
.renderer
|
||||
.register_helper("upperCase", Box::new(helper_upper_case));
|
||||
folder
|
||||
.renderer
|
||||
.register_helper("camelCase", Box::new(helper_camel_case));
|
||||
folder
|
||||
.renderer
|
||||
.register_helper("kebabCase", Box::new(helper_kebab_case));
|
||||
for (mut k, v) in config.packages {
|
||||
// XXX: Should we keep this hack?
|
||||
if !k.starts_with('^') && !k.ends_with('$') {
|
||||
k = format!("^{}$", k);
|
||||
}
|
||||
folder.packages.push((
|
||||
CachedRegex::new(&k).expect("transform-imports: invalid regex"),
|
||||
v,
|
||||
));
|
||||
}
|
||||
folder
|
||||
}
|
||||
|
||||
fn helper_lower_case(
|
||||
h: &Helper<'_, '_>,
|
||||
_: &Handlebars<'_>,
|
||||
_: &Context,
|
||||
_: &mut RenderContext<'_, '_>,
|
||||
out: &mut dyn Output,
|
||||
) -> HelperResult {
|
||||
// get parameter from helper or throw an error
|
||||
let param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
|
||||
out.write(param.to_lowercase().as_ref())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn helper_upper_case(
|
||||
h: &Helper<'_, '_>,
|
||||
_: &Handlebars<'_>,
|
||||
_: &Context,
|
||||
_: &mut RenderContext<'_, '_>,
|
||||
out: &mut dyn Output,
|
||||
) -> HelperResult {
|
||||
// get parameter from helper or throw an error
|
||||
let param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
|
||||
out.write(param.to_uppercase().as_ref())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn helper_camel_case(
|
||||
h: &Helper<'_, '_>,
|
||||
_: &Handlebars<'_>,
|
||||
_: &Context,
|
||||
_: &mut RenderContext<'_, '_>,
|
||||
out: &mut dyn Output,
|
||||
) -> HelperResult {
|
||||
// get parameter from helper or throw an error
|
||||
let param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
|
||||
|
||||
out.write(param.to_case(Case::Camel).as_ref())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn helper_kebab_case(
|
||||
h: &Helper<'_, '_>,
|
||||
_: &Handlebars<'_>,
|
||||
_: &Context,
|
||||
_: &mut RenderContext<'_, '_>,
|
||||
out: &mut dyn Output,
|
||||
) -> HelperResult {
|
||||
// get parameter from helper or throw an error
|
||||
let param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
|
||||
|
||||
out.write(param.to_case(Case::Kebab).as_ref())?;
|
||||
Ok(())
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use modularize_imports::{modularize_imports, PackageConfig};
|
||||
use swc_core::{
|
||||
ecma::parser::{EsConfig, Syntax},
|
||||
ecma::transforms::testing::{test_fixture, FixtureTestConfig},
|
||||
};
|
||||
use testing::fixture;
|
||||
|
||||
fn syntax() -> Syntax {
|
||||
Syntax::Es(EsConfig {
|
||||
jsx: true,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
#[fixture("tests/fixture/**/input.js")]
|
||||
fn modularize_imports_fixture(input: PathBuf) {
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(
|
||||
syntax(),
|
||||
&|_tr| {
|
||||
modularize_imports(modularize_imports::Config {
|
||||
packages: vec![
|
||||
(
|
||||
"react-bootstrap".to_string(),
|
||||
PackageConfig {
|
||||
transform: "react-bootstrap/lib/{{member}}".into(),
|
||||
prevent_full_import: false,
|
||||
skip_default_conversion: false,
|
||||
},
|
||||
),
|
||||
(
|
||||
"my-library/?(((\\w*)?/?)*)".to_string(),
|
||||
PackageConfig {
|
||||
transform: "my-library/{{ matches.[1] }}/{{member}}".into(),
|
||||
prevent_full_import: false,
|
||||
skip_default_conversion: false,
|
||||
},
|
||||
),
|
||||
(
|
||||
"my-library-2".to_string(),
|
||||
PackageConfig {
|
||||
transform: "my-library-2/{{ camelCase member }}".into(),
|
||||
prevent_full_import: false,
|
||||
skip_default_conversion: true,
|
||||
},
|
||||
),
|
||||
(
|
||||
"my-library-3".to_string(),
|
||||
PackageConfig {
|
||||
transform: "my-library-3/{{ kebabCase member }}".into(),
|
||||
prevent_full_import: false,
|
||||
skip_default_conversion: true,
|
||||
},
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
})
|
||||
},
|
||||
&input,
|
||||
&output,
|
||||
FixtureTestConfig {
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
import { MyModule } from 'my-library';
|
||||
import { App } from 'my-library/components';
|
||||
import { Header, Footer } from 'my-library/components/App';
|
|
@ -1,4 +0,0 @@
|
|||
import MyModule from "my-library/MyModule";
|
||||
import App from "my-library/components/App";
|
||||
import Header from "my-library/components/App/Header";
|
||||
import Footer from "my-library/components/App/Footer";
|
|
@ -1,3 +0,0 @@
|
|||
import { Grid, Row, Col as Col1 } from 'react-bootstrap';
|
||||
import { MyModule, Widget } from 'my-library-2';
|
||||
import { MyModule } from 'my-library-3';
|
|
@ -1,6 +0,0 @@
|
|||
import Grid from "react-bootstrap/lib/Grid";
|
||||
import Row from "react-bootstrap/lib/Row";
|
||||
import Col1 from "react-bootstrap/lib/Col";
|
||||
import { MyModule } from "my-library-2/myModule";
|
||||
import { Widget } from "my-library-2/widget";
|
||||
import { MyModule } from "my-library-3/my-module";
|
|
@ -50,7 +50,7 @@ swc_core = { features = [
|
|||
"ecma_transforms_typescript",
|
||||
"ecma_utils",
|
||||
"ecma_visit",
|
||||
], version = "0.39.7" }
|
||||
], version = "0.40.7" }
|
||||
tracing = { version = "0.1.32", features = ["release_max_level_info"] }
|
||||
tracing-futures = "0.2.5"
|
||||
tracing-subscriber = "0.3.9"
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
[package]
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||
description = "AST Transforms for styled-components"
|
||||
edition = "2018"
|
||||
include = ["Cargo.toml", "src/**/*.rs"]
|
||||
license = "Apache-2.0"
|
||||
name = "styled_components"
|
||||
repository = "https://github.com/vercel/next.js.git"
|
||||
version = "0.45.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
Inflector = "0.11.4"
|
||||
once_cell = "1.13.0"
|
||||
regex = {version = "1.5.4", features = ["std", "perf"], default-features = false}
|
||||
serde = {version = "1.0.130", features = ["derive"]}
|
||||
tracing = "0.1.32"
|
||||
swc_core = { features = [
|
||||
"common",
|
||||
"ecma_ast",
|
||||
"ecma_utils",
|
||||
"ecma_visit"
|
||||
], version = "0.39.7" }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1"
|
||||
testing = "0.31.9"
|
||||
swc_core = { features = [
|
||||
"ecma_parser",
|
||||
"ecma_transforms",
|
||||
"testing_transform"
|
||||
], version = "0.39.7" }
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,91 +0,0 @@
|
|||
#![deny(unused)]
|
||||
|
||||
pub use crate::{
|
||||
utils::{analyze, analyzer, State},
|
||||
visitors::{
|
||||
display_name_and_id::display_name_and_id, transpile_css_prop::transpile::transpile_css_prop,
|
||||
},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use swc_core::{
|
||||
common::{chain, pass::Optional, FileName},
|
||||
ecma::atoms::JsWord,
|
||||
ecma::visit::{Fold, VisitMut},
|
||||
};
|
||||
|
||||
mod css;
|
||||
mod utils;
|
||||
mod visitors;
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct Config {
|
||||
#[serde(default = "true_by_default")]
|
||||
pub display_name: bool,
|
||||
|
||||
#[serde(default = "true_by_default")]
|
||||
pub ssr: bool,
|
||||
|
||||
#[serde(default = "true_by_default")]
|
||||
pub file_name: bool,
|
||||
|
||||
#[serde(default = "default_index_file_name")]
|
||||
pub meaningless_file_names: Vec<String>,
|
||||
|
||||
#[serde(default)]
|
||||
pub namespace: String,
|
||||
|
||||
#[serde(default)]
|
||||
pub top_level_import_paths: Vec<JsWord>,
|
||||
|
||||
#[serde(default)]
|
||||
pub transpile_template_literals: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub minify: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub pure: bool,
|
||||
|
||||
#[serde(default = "true_by_default")]
|
||||
pub css_prop: bool,
|
||||
}
|
||||
|
||||
fn true_by_default() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn default_index_file_name() -> Vec<String> {
|
||||
vec!["index".to_string()]
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub(crate) fn use_namespace(&self) -> String {
|
||||
if self.namespace.is_empty() {
|
||||
return String::new();
|
||||
}
|
||||
format!("{}__", self.namespace)
|
||||
}
|
||||
}
|
||||
|
||||
/// NOTE: **This is not complete**.
|
||||
///
|
||||
/// Only [analyzer] and [display_name_and_id] is implemented.
|
||||
pub fn styled_components(
|
||||
file_name: FileName,
|
||||
src_file_hash: u128,
|
||||
config: Config,
|
||||
) -> impl Fold + VisitMut {
|
||||
let state: Rc<RefCell<State>> = Default::default();
|
||||
let config = Rc::new(config);
|
||||
|
||||
chain!(
|
||||
analyzer(config.clone(), state.clone()),
|
||||
Optional {
|
||||
enabled: config.css_prop,
|
||||
visitor: transpile_css_prop(state.clone())
|
||||
},
|
||||
display_name_and_id(file_name, src_file_hash, config.clone(), state)
|
||||
)
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
use super::State;
|
||||
use crate::Config;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use swc_core::{
|
||||
ecma::ast::*,
|
||||
ecma::visit::{
|
||||
as_folder, noop_visit_mut_type, noop_visit_type, Fold, Visit, VisitMut, VisitWith,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn analyzer(config: Rc<Config>, state: Rc<RefCell<State>>) -> impl VisitMut + Fold {
|
||||
as_folder(AsAnalyzer { config, state })
|
||||
}
|
||||
|
||||
struct AsAnalyzer {
|
||||
config: Rc<Config>,
|
||||
state: Rc<RefCell<State>>,
|
||||
}
|
||||
|
||||
impl VisitMut for AsAnalyzer {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_module(&mut self, p: &mut Module) {
|
||||
let mut v = Analyzer {
|
||||
config: &self.config,
|
||||
state: &mut self.state.borrow_mut(),
|
||||
};
|
||||
|
||||
p.visit_with(&mut v);
|
||||
}
|
||||
|
||||
fn visit_mut_script(&mut self, p: &mut Script) {
|
||||
let mut v = Analyzer {
|
||||
config: &self.config,
|
||||
state: &mut self.state.borrow_mut(),
|
||||
};
|
||||
|
||||
p.visit_with(&mut v);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn analyze(config: &Config, program: &Program) -> State {
|
||||
let mut state = State::default();
|
||||
|
||||
let mut v = Analyzer {
|
||||
config,
|
||||
state: &mut state,
|
||||
};
|
||||
|
||||
program.visit_with(&mut v);
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
struct Analyzer<'a> {
|
||||
config: &'a Config,
|
||||
state: &'a mut State,
|
||||
}
|
||||
|
||||
impl Visit for Analyzer<'_> {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_var_declarator(&mut self, v: &VarDeclarator) {
|
||||
v.visit_children_with(self);
|
||||
|
||||
if let (
|
||||
Pat::Ident(name),
|
||||
Some(Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(callee),
|
||||
args,
|
||||
..
|
||||
})),
|
||||
) = (&v.name, v.init.as_deref())
|
||||
{
|
||||
if let Expr::Ident(callee) = &**callee {
|
||||
if &*callee.sym == "require" && args.len() == 1 && args[0].spread.is_none() {
|
||||
if let Expr::Lit(Lit::Str(v)) = &*args[0].expr {
|
||||
let is_styled = if self.config.top_level_import_paths.is_empty() {
|
||||
&*v.value == "styled-components"
|
||||
|| v.value.starts_with("styled-components/")
|
||||
} else {
|
||||
self.config.top_level_import_paths.contains(&v.value)
|
||||
};
|
||||
|
||||
if is_styled {
|
||||
self.state.styled_required = Some(name.id.to_id());
|
||||
self.state.unresolved_ctxt = Some(callee.span.ctxt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_import_decl(&mut self, i: &ImportDecl) {
|
||||
let is_custom = !self.config.top_level_import_paths.is_empty();
|
||||
|
||||
let is_styled = if self.config.top_level_import_paths.is_empty() {
|
||||
&*i.src.value == "styled-components" || i.src.value.starts_with("styled-components/")
|
||||
} else {
|
||||
self.config.top_level_import_paths.contains(&i.src.value)
|
||||
};
|
||||
|
||||
if is_styled {
|
||||
for s in &i.specifiers {
|
||||
match s {
|
||||
ImportSpecifier::Named(s) => {
|
||||
if is_custom
|
||||
&& s.imported
|
||||
.as_ref()
|
||||
.map(|v| match v {
|
||||
ModuleExportName::Ident(v) => &*v.sym,
|
||||
ModuleExportName::Str(v) => &*v.value,
|
||||
})
|
||||
.unwrap_or(&*s.local.sym)
|
||||
== "styled"
|
||||
{
|
||||
self.state.imported_local_name = Some(s.local.to_id());
|
||||
}
|
||||
}
|
||||
ImportSpecifier::Default(s) => {
|
||||
self.state.imported_local_name = Some(s.local.to_id());
|
||||
}
|
||||
ImportSpecifier::Namespace(s) => {
|
||||
self.state.imported_local_ns = Some(s.local.to_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,324 +0,0 @@
|
|||
pub use self::analyzer::{analyze, analyzer};
|
||||
use std::{borrow::Cow, cell::RefCell};
|
||||
use swc_core::{
|
||||
common::{collections::AHashMap, SyntaxContext},
|
||||
ecma::ast::*,
|
||||
ecma::atoms::js_word,
|
||||
};
|
||||
|
||||
mod analyzer;
|
||||
|
||||
pub(crate) fn get_prop_key_as_expr(p: &Prop) -> Cow<Expr> {
|
||||
match p {
|
||||
Prop::Shorthand(p) => Cow::Owned(Expr::Ident(p.clone())),
|
||||
Prop::KeyValue(p) => prop_name_to_expr(&p.key),
|
||||
Prop::Assign(p) => Cow::Owned(Expr::Ident(p.key.clone())),
|
||||
Prop::Getter(p) => prop_name_to_expr(&p.key),
|
||||
Prop::Setter(p) => prop_name_to_expr(&p.key),
|
||||
Prop::Method(p) => prop_name_to_expr(&p.key),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn prop_name_to_expr(p: &PropName) -> Cow<Expr> {
|
||||
match p {
|
||||
PropName::Ident(p) => Cow::Owned(Expr::Ident(p.clone())),
|
||||
PropName::Str(p) => Cow::Owned(Expr::Lit(Lit::Str(p.clone()))),
|
||||
PropName::Num(p) => Cow::Owned(Expr::Lit(Lit::Num(p.clone()))),
|
||||
PropName::BigInt(p) => Cow::Owned(Expr::Lit(Lit::BigInt(p.clone()))),
|
||||
PropName::Computed(e) => Cow::Borrowed(&e.expr),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_prop_name(p: &Prop) -> Option<&PropName> {
|
||||
match p {
|
||||
Prop::Shorthand(..) => None,
|
||||
Prop::KeyValue(p) => Some(&p.key),
|
||||
Prop::Assign(..) => None,
|
||||
Prop::Getter(p) => Some(&p.key),
|
||||
Prop::Setter(p) => Some(&p.key),
|
||||
Prop::Method(p) => Some(&p.key),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_prop_name2(p: &Prop) -> PropName {
|
||||
match p {
|
||||
Prop::Shorthand(ident) => PropName::Ident(ident.clone()),
|
||||
Prop::KeyValue(p) => p.key.clone(),
|
||||
Prop::Assign(x) => PropName::Ident(x.key.clone()),
|
||||
Prop::Getter(p) => p.key.clone(),
|
||||
Prop::Setter(p) => p.key.clone(),
|
||||
Prop::Method(p) => p.key.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// This is created once per file.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct State {
|
||||
pub(crate) styled_required: Option<Id>,
|
||||
|
||||
unresolved_ctxt: Option<SyntaxContext>,
|
||||
|
||||
imported_local_name: Option<Id>,
|
||||
/// Namespace imports
|
||||
imported_local_ns: Option<Id>,
|
||||
import_name_cache: RefCell<AHashMap<Id, Id>>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub(crate) fn is_styled(&self, tag: &Expr) -> bool {
|
||||
if let Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(callee),
|
||||
..
|
||||
}) = tag
|
||||
{
|
||||
if let Expr::Member(MemberExpr {
|
||||
obj,
|
||||
prop: MemberProp::Ident(prop),
|
||||
..
|
||||
}) = &**callee
|
||||
{
|
||||
if prop.sym != js_word!("default") {
|
||||
return self.is_styled(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match tag {
|
||||
Expr::Member(MemberExpr {
|
||||
obj,
|
||||
prop: MemberProp::Ident(prop),
|
||||
..
|
||||
}) => {
|
||||
if let Expr::Ident(obj) = &**obj {
|
||||
if Some(obj.to_id()) == self.import_local_name("default", Some(obj))
|
||||
&& !self.is_helper(&Expr::Ident(prop.clone()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(callee),
|
||||
..
|
||||
}) => {
|
||||
if let Expr::Ident(callee) = &**callee {
|
||||
if Some(callee.to_id()) == self.import_local_name("default", Some(callee)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// styled-components might be imported using a require()
|
||||
if let Some(style_required) = self.styled_required.clone() {
|
||||
match tag {
|
||||
Expr::Member(MemberExpr {
|
||||
obj,
|
||||
prop: MemberProp::Ident(..),
|
||||
..
|
||||
}) => {
|
||||
if let Expr::Member(MemberExpr {
|
||||
obj: obj_of_obj,
|
||||
prop: MemberProp::Ident(prop),
|
||||
..
|
||||
}) = &**obj
|
||||
{
|
||||
if let Expr::Ident(obj_of_obj) = &**obj_of_obj {
|
||||
if prop.sym == js_word!("default")
|
||||
&& obj_of_obj.to_id() == style_required
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(callee),
|
||||
..
|
||||
}) => {
|
||||
if let Expr::Member(MemberExpr {
|
||||
obj: tag_callee_object,
|
||||
prop: MemberProp::Ident(tag_callee_property),
|
||||
..
|
||||
}) = &**callee
|
||||
{
|
||||
if let Expr::Ident(tag_callee_object) = &**tag_callee_object {
|
||||
if tag_callee_property.sym == js_word!("default")
|
||||
&& tag_callee_object.to_id() == style_required
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(import_local_name) = self.import_local_name("default", None) {
|
||||
match tag {
|
||||
Expr::Member(MemberExpr {
|
||||
obj,
|
||||
prop: MemberProp::Ident(..),
|
||||
..
|
||||
}) => {
|
||||
if let Expr::Member(MemberExpr {
|
||||
obj: obj_of_obj,
|
||||
prop: MemberProp::Ident(prop),
|
||||
..
|
||||
}) = &**obj
|
||||
{
|
||||
if let Expr::Ident(obj_of_obj) = &**obj_of_obj {
|
||||
if prop.sym == js_word!("default")
|
||||
&& obj_of_obj.to_id() == import_local_name
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(callee),
|
||||
..
|
||||
}) => {
|
||||
if let Expr::Member(MemberExpr {
|
||||
obj: tag_callee_object,
|
||||
prop: MemberProp::Ident(tag_callee_property),
|
||||
..
|
||||
}) = &**callee
|
||||
{
|
||||
if let Expr::Ident(tag_callee_object) = &**tag_callee_object {
|
||||
if tag_callee_property.sym == js_word!("default")
|
||||
&& tag_callee_object.to_id() == import_local_name
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub(crate) fn import_local_name(
|
||||
&self,
|
||||
name: &str,
|
||||
cache_identifier: Option<&Ident>,
|
||||
) -> Option<Id> {
|
||||
if name == "default" {
|
||||
if let Some(cached) = self.imported_local_name.clone() {
|
||||
return Some(cached);
|
||||
}
|
||||
if let Some(cached) = self.imported_local_ns.clone() {
|
||||
return Some(cached);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(..) = self.imported_local_ns {
|
||||
return Some((name.into(), Default::default()));
|
||||
}
|
||||
|
||||
let cache_key = cache_identifier.map(|i| i.to_id()).unwrap_or_default();
|
||||
|
||||
let ctxt = self.unresolved_ctxt.unwrap_or_default();
|
||||
|
||||
let local_name = if self.styled_required.is_some() {
|
||||
Some(if name == "default" {
|
||||
"styled".into()
|
||||
} else {
|
||||
name.into()
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(cached) = self.import_name_cache.borrow().get(&cache_key) {
|
||||
return Some(cached.clone());
|
||||
}
|
||||
|
||||
let name = local_name.map(|word| (word, ctxt));
|
||||
|
||||
if let Some(name) = name.clone() {
|
||||
self.import_name_cache.borrow_mut().insert(cache_key, name);
|
||||
}
|
||||
|
||||
name
|
||||
}
|
||||
|
||||
pub(crate) fn set_import_name(&mut self, id: Id) {
|
||||
self.imported_local_name = Some(id);
|
||||
}
|
||||
|
||||
fn is_helper(&self, e: &Expr) -> bool {
|
||||
self.is_create_global_style_helper(e)
|
||||
|| self.is_css_helper(e)
|
||||
|| self.is_inject_global_helper(e)
|
||||
|| self.is_use_theme(e)
|
||||
|| self.is_keyframes_helper(e)
|
||||
|| self.is_with_theme_helper(e)
|
||||
}
|
||||
|
||||
fn is_css_helper(&self, e: &Expr) -> bool {
|
||||
match e {
|
||||
Expr::Ident(e) => Some(e.to_id()) == self.import_local_name("css", None),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_create_global_style_helper(&self, e: &Expr) -> bool {
|
||||
match e {
|
||||
Expr::Ident(e) => Some(e.to_id()) == self.import_local_name("createGlobalStyle", None),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_inject_global_helper(&self, e: &Expr) -> bool {
|
||||
match e {
|
||||
Expr::Ident(e) => Some(e.to_id()) == self.import_local_name("injectGlobal", None),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_keyframes_helper(&self, e: &Expr) -> bool {
|
||||
match e {
|
||||
Expr::Ident(e) => Some(e.to_id()) == self.import_local_name("keyframes", None),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_with_theme_helper(&self, e: &Expr) -> bool {
|
||||
match e {
|
||||
Expr::Ident(e) => Some(e.to_id()) == self.import_local_name("withTheme", None),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_use_theme(&self, e: &Expr) -> bool {
|
||||
match e {
|
||||
Expr::Ident(e) => Some(e.to_id()) == self.import_local_name("useTheme", None),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prefix_leading_digit(s: &str) -> Cow<str> {
|
||||
if s.chars()
|
||||
.next()
|
||||
.map(|c| c.is_ascii_digit())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Cow::Owned(format!("sc-{}", s))
|
||||
} else {
|
||||
Cow::Borrowed(s)
|
||||
}
|
||||
}
|
|
@ -1,469 +0,0 @@
|
|||
use crate::{
|
||||
utils::{get_prop_name, prefix_leading_digit, State},
|
||||
Config,
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use std::{cell::RefCell, convert::TryInto, path::Path, rc::Rc};
|
||||
use swc_core::{
|
||||
common::{util::take::Take, FileName, DUMMY_SP},
|
||||
ecma::ast::*,
|
||||
ecma::atoms::{js_word, JsWord},
|
||||
ecma::utils::{quote_ident, ExprFactory},
|
||||
ecma::visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith},
|
||||
};
|
||||
use tracing::{debug, span, trace, Level};
|
||||
|
||||
pub fn display_name_and_id(
|
||||
file_name: FileName,
|
||||
src_file_hash: u128,
|
||||
config: Rc<Config>,
|
||||
state: Rc<RefCell<State>>,
|
||||
) -> impl Fold + VisitMut {
|
||||
as_folder(DisplayNameAndId {
|
||||
file_name,
|
||||
src_file_hash,
|
||||
|
||||
config,
|
||||
state,
|
||||
cur_display_name: Default::default(),
|
||||
component_id: 0,
|
||||
})
|
||||
}
|
||||
|
||||
static DISPLAY_NAME_REGEX: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(r"^[a-zA-Z][a-zA-Z0-9]$").unwrap());
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DisplayNameAndId {
|
||||
file_name: FileName,
|
||||
src_file_hash: u128,
|
||||
|
||||
config: Rc<Config>,
|
||||
state: Rc<RefCell<State>>,
|
||||
|
||||
cur_display_name: Option<JsWord>,
|
||||
|
||||
component_id: usize,
|
||||
}
|
||||
|
||||
impl DisplayNameAndId {
|
||||
fn get_block_name(&self, p: &Path) -> String {
|
||||
match p.file_stem().map(|s| s.to_string_lossy()) {
|
||||
Some(file_stem)
|
||||
if !self
|
||||
.config
|
||||
.meaningless_file_names
|
||||
.iter()
|
||||
.any(|meaningless| file_stem.as_ref() == meaningless) =>
|
||||
{
|
||||
file_stem.into()
|
||||
}
|
||||
_ => self.get_block_name(
|
||||
p.parent()
|
||||
.expect("path only contains meaningless filenames (e.g. /index/index)?"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_display_name(&mut self, _: &Expr) -> JsWord {
|
||||
let component_name = self.cur_display_name.clone().unwrap_or(js_word!(""));
|
||||
|
||||
match &self.file_name {
|
||||
FileName::Real(f) if self.config.file_name => {
|
||||
let block_name = self.get_block_name(f);
|
||||
|
||||
if block_name == *component_name {
|
||||
return component_name;
|
||||
}
|
||||
|
||||
if component_name.is_empty() {
|
||||
return prefix_leading_digit(&block_name).into();
|
||||
}
|
||||
|
||||
format!("{}__{}", prefix_leading_digit(&block_name), component_name).into()
|
||||
}
|
||||
|
||||
_ => component_name,
|
||||
}
|
||||
}
|
||||
|
||||
fn next_id(&mut self) -> usize {
|
||||
let ret = self.component_id;
|
||||
self.component_id += 1;
|
||||
ret
|
||||
}
|
||||
|
||||
fn get_component_id(&mut self) -> String {
|
||||
// Prefix the identifier with a character because CSS classes cannot start with
|
||||
// a number
|
||||
|
||||
let next_id = self.next_id();
|
||||
|
||||
let hash = {
|
||||
let base = self.src_file_hash;
|
||||
let base = base.to_be_bytes();
|
||||
let a = u32::from_be_bytes(base[0..4].try_into().unwrap());
|
||||
let b = u32::from_be_bytes(base[4..8].try_into().unwrap());
|
||||
let c = u32::from_be_bytes(base[8..12].try_into().unwrap());
|
||||
let d = u32::from_be_bytes(base[12..16].try_into().unwrap());
|
||||
|
||||
a ^ b ^ c ^ d
|
||||
};
|
||||
|
||||
format!("{}sc-{:x}-{}", self.config.use_namespace(), hash, next_id)
|
||||
}
|
||||
|
||||
fn add_config(
|
||||
&mut self,
|
||||
e: &mut Expr,
|
||||
display_name: Option<JsWord>,
|
||||
component_id: Option<JsWord>,
|
||||
) {
|
||||
if display_name.is_none() && component_id.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut with_config_props = vec![];
|
||||
|
||||
if let Some(display_name) = display_name {
|
||||
with_config_props.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("displayName")),
|
||||
value: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
span: DUMMY_SP,
|
||||
value: display_name,
|
||||
raw: None,
|
||||
}))),
|
||||
}))))
|
||||
}
|
||||
|
||||
if let Some(component_id) = component_id {
|
||||
with_config_props.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("componentId")),
|
||||
value: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
span: DUMMY_SP,
|
||||
value: component_id,
|
||||
raw: None,
|
||||
}))),
|
||||
}))))
|
||||
}
|
||||
|
||||
get_existing_config(e, |e| {
|
||||
if let Expr::Call(CallExpr { args, .. }) = e {
|
||||
if let Some(Expr::Object(existing_config)) = args.get_mut(0).map(|v| &mut *v.expr) {
|
||||
if !already_has(existing_config) {
|
||||
existing_config.props.extend(with_config_props.take());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if with_config_props.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(callee),
|
||||
args,
|
||||
..
|
||||
}) = e
|
||||
{
|
||||
if let Expr::Member(MemberExpr {
|
||||
prop: MemberProp::Ident(prop),
|
||||
..
|
||||
}) = &**callee
|
||||
{
|
||||
if &*prop.sym == "withConfig" {
|
||||
if let Some(first_arg) = args.get_mut(0) {
|
||||
if first_arg.spread.is_none() && first_arg.expr.is_object() {
|
||||
if let Expr::Object(obj) = &mut *first_arg.expr {
|
||||
if !already_has(&*obj) {
|
||||
obj.props.extend(with_config_props);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Expr::TaggedTpl(e) = e {
|
||||
e.tag = Box::new(Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: e
|
||||
.tag
|
||||
.take()
|
||||
.make_member(quote_ident!("withConfig"))
|
||||
.as_callee(),
|
||||
args: vec![ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: with_config_props,
|
||||
}
|
||||
.as_arg()],
|
||||
type_args: Default::default(),
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
if let Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(callee),
|
||||
..
|
||||
}) = e
|
||||
{
|
||||
*callee = Box::new(Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: callee
|
||||
.take()
|
||||
.make_member(quote_ident!("withConfig"))
|
||||
.as_callee(),
|
||||
args: vec![ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: with_config_props,
|
||||
}
|
||||
.as_arg()],
|
||||
type_args: Default::default(),
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
unreachable!("expr should be tagged tpl or call expr");
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitMut for DisplayNameAndId {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_assign_expr(&mut self, e: &mut AssignExpr) {
|
||||
let old = self.cur_display_name.clone();
|
||||
|
||||
if old.is_none() {
|
||||
self.cur_display_name = e.left.as_ident().map(|v| v.sym.clone());
|
||||
}
|
||||
|
||||
e.visit_mut_children_with(self);
|
||||
|
||||
self.cur_display_name = old;
|
||||
}
|
||||
|
||||
fn visit_mut_class_prop(&mut self, e: &mut ClassProp) {
|
||||
let old = self.cur_display_name.take();
|
||||
|
||||
if let PropName::Ident(i) = &e.key {
|
||||
self.cur_display_name = Some(i.sym.clone());
|
||||
}
|
||||
|
||||
e.visit_mut_children_with(self);
|
||||
|
||||
self.cur_display_name = old;
|
||||
}
|
||||
|
||||
fn visit_mut_expr(&mut self, expr: &mut Expr) {
|
||||
expr.visit_mut_children_with(self);
|
||||
|
||||
let is_styled = match expr {
|
||||
Expr::TaggedTpl(e) => self.state.borrow().is_styled(&e.tag),
|
||||
|
||||
Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(callee),
|
||||
args,
|
||||
..
|
||||
}) => {
|
||||
(
|
||||
// styled()
|
||||
self.state.borrow().is_styled(&*callee)
|
||||
&& get_property_as_ident(callee)
|
||||
.map(|v| v == "withConfig")
|
||||
.unwrap_or(false)
|
||||
) || (
|
||||
// styled(x)({})
|
||||
self.state.borrow().is_styled(&*callee)
|
||||
&& !get_callee(callee)
|
||||
.map(|callee| callee.is_member())
|
||||
.unwrap_or(false)
|
||||
) || (
|
||||
// styled(x).attrs()({})
|
||||
self.state.borrow().is_styled(callee)
|
||||
&& get_callee(callee)
|
||||
.map(|callee| {
|
||||
callee.is_member()
|
||||
&& get_property_as_ident(callee)
|
||||
.map(|v| v == "withConfig")
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.unwrap_or(false)
|
||||
) || (
|
||||
// styled(x).withConfig({})
|
||||
self.state.borrow().is_styled(&*callee)
|
||||
&& get_callee(callee)
|
||||
.map(|callee| {
|
||||
callee.is_member()
|
||||
&& get_property_as_ident(callee)
|
||||
.map(|v| v == "withConfig")
|
||||
.unwrap_or(false)
|
||||
&& !args.is_empty()
|
||||
&& args[0].spread.is_none()
|
||||
&& match &*args[0].expr {
|
||||
Expr::Object(first_arg) => {
|
||||
!first_arg.props.iter().any(|prop| match prop {
|
||||
PropOrSpread::Prop(prop) => {
|
||||
match get_prop_name(prop) {
|
||||
Some(PropName::Ident(prop_name)) => {
|
||||
matches!(
|
||||
&*prop_name.sym,
|
||||
"componentId" | "displayName"
|
||||
)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
})
|
||||
.unwrap_or(false)
|
||||
)
|
||||
}
|
||||
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if !is_styled {
|
||||
return;
|
||||
}
|
||||
debug!("Found styled component");
|
||||
|
||||
let _tracing = if cfg!(debug_assertions) {
|
||||
Some(span!(Level::ERROR, "display_name_and_id").entered())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let display_name = self
|
||||
.config
|
||||
.display_name
|
||||
.then(|| self.get_display_name(expr));
|
||||
trace!("display_name: {:?}", display_name);
|
||||
|
||||
let component_id = self.config.ssr.then(|| self.get_component_id().into());
|
||||
trace!("component_id: {:?}", display_name);
|
||||
|
||||
self.add_config(
|
||||
expr,
|
||||
display_name.map(|s| DISPLAY_NAME_REGEX.replace_all(&s, "").into()),
|
||||
component_id,
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_mut_key_value_prop(&mut self, e: &mut KeyValueProp) {
|
||||
let old = self.cur_display_name.take();
|
||||
|
||||
if let PropName::Ident(name) = &e.key {
|
||||
self.cur_display_name = Some(name.sym.clone());
|
||||
}
|
||||
|
||||
e.visit_mut_children_with(self);
|
||||
|
||||
self.cur_display_name = old;
|
||||
}
|
||||
|
||||
fn visit_mut_var_declarator(&mut self, v: &mut VarDeclarator) {
|
||||
let old = self.cur_display_name.take();
|
||||
|
||||
if let Pat::Ident(name) = &v.name {
|
||||
self.cur_display_name = Some(name.id.sym.clone());
|
||||
}
|
||||
|
||||
v.visit_mut_children_with(self);
|
||||
|
||||
self.cur_display_name = old;
|
||||
}
|
||||
}
|
||||
|
||||
fn get_callee(e: &Expr) -> Option<&Expr> {
|
||||
match e {
|
||||
Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(callee),
|
||||
..
|
||||
}) => Some(callee),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_property_as_ident(e: &Expr) -> Option<&JsWord> {
|
||||
if let Expr::Member(MemberExpr {
|
||||
prop: MemberProp::Ident(p),
|
||||
..
|
||||
}) = e
|
||||
{
|
||||
return Some(&p.sym);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn already_has(obj: &ObjectLit) -> bool {
|
||||
obj.props
|
||||
.iter()
|
||||
.filter_map(|v| match v {
|
||||
PropOrSpread::Prop(p) => Some(p),
|
||||
_ => None,
|
||||
})
|
||||
.filter_map(|v| get_prop_name(v))
|
||||
.any(|prop| match prop {
|
||||
PropName::Ident(ident) => &*ident.sym == "componentId" || &*ident.sym == "displayName",
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_existing_config<F>(e: &mut Expr, op: F)
|
||||
where
|
||||
F: FnOnce(&mut Expr),
|
||||
{
|
||||
if let Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(callee),
|
||||
..
|
||||
}) = e
|
||||
{
|
||||
if let Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(callee_callee),
|
||||
..
|
||||
}) = &mut **callee
|
||||
{
|
||||
if let Expr::Member(MemberExpr {
|
||||
prop: MemberProp::Ident(prop),
|
||||
..
|
||||
}) = &**callee_callee
|
||||
{
|
||||
if &*prop.sym == "withConfig" {
|
||||
return op(callee);
|
||||
}
|
||||
}
|
||||
|
||||
if let Expr::Member(MemberExpr {
|
||||
obj,
|
||||
prop: MemberProp::Ident(..),
|
||||
..
|
||||
}) = &mut **callee_callee
|
||||
{
|
||||
if let Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(callee),
|
||||
..
|
||||
}) = &**obj
|
||||
{
|
||||
if let Expr::Member(MemberExpr {
|
||||
prop: MemberProp::Ident(prop),
|
||||
..
|
||||
}) = &**callee
|
||||
{
|
||||
if &*prop.sym == "withConfig" {
|
||||
op(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
pub mod assign_style_required;
|
||||
pub mod display_name_and_id;
|
||||
pub mod minify;
|
||||
pub mod transpile_css_prop;
|
|
@ -1,2 +0,0 @@
|
|||
mod top_level_binding_collector;
|
||||
pub mod transpile;
|
|
@ -1,93 +0,0 @@
|
|||
use swc_core::{
|
||||
common::collections::AHashSet,
|
||||
ecma::ast::{
|
||||
ArrowExpr, ClassDecl, FnDecl, Function, Id, ImportDefaultSpecifier, ImportNamedSpecifier,
|
||||
ImportStarAsSpecifier, ObjectPatProp, Pat, VarDeclarator,
|
||||
},
|
||||
ecma::visit::{noop_visit_type, Visit, VisitWith},
|
||||
};
|
||||
|
||||
// Modified from swc_ecma_utils/src/lib.rs:BindingCollector.
|
||||
pub struct TopLevelBindingCollector {
|
||||
bindings: AHashSet<Id>,
|
||||
in_pat_decl: bool,
|
||||
}
|
||||
|
||||
impl TopLevelBindingCollector {
|
||||
fn add(&mut self, i: &Id) {
|
||||
self.bindings.insert(i.clone());
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for TopLevelBindingCollector {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_class_decl(&mut self, node: &ClassDecl) {
|
||||
self.add(&node.ident.to_id());
|
||||
}
|
||||
|
||||
fn visit_fn_decl(&mut self, node: &FnDecl) {
|
||||
self.add(&node.ident.to_id());
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, node: &Pat) {
|
||||
if !self.in_pat_decl {
|
||||
return;
|
||||
}
|
||||
match node {
|
||||
Pat::Ident(i) => self.add(&i.id.to_id()),
|
||||
Pat::Object(o) => {
|
||||
for prop in o.props.iter() {
|
||||
match prop {
|
||||
ObjectPatProp::Assign(a) => self.add(&a.key.to_id()),
|
||||
ObjectPatProp::KeyValue(k) => k.value.visit_with(self),
|
||||
ObjectPatProp::Rest(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Pat::Array(a) => {
|
||||
for elem in a.elems.iter() {
|
||||
elem.visit_with(self);
|
||||
}
|
||||
}
|
||||
Pat::Assign(a) => {
|
||||
a.left.visit_with(self);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_arrow_expr(&mut self, _: &ArrowExpr) {}
|
||||
fn visit_function(&mut self, _: &Function) {}
|
||||
|
||||
fn visit_import_default_specifier(&mut self, node: &ImportDefaultSpecifier) {
|
||||
self.add(&node.local.to_id());
|
||||
}
|
||||
|
||||
fn visit_import_named_specifier(&mut self, node: &ImportNamedSpecifier) {
|
||||
self.add(&node.local.to_id());
|
||||
}
|
||||
|
||||
fn visit_import_star_as_specifier(&mut self, node: &ImportStarAsSpecifier) {
|
||||
self.add(&node.local.to_id());
|
||||
}
|
||||
|
||||
fn visit_var_declarator(&mut self, node: &VarDeclarator) {
|
||||
let old = self.in_pat_decl;
|
||||
self.in_pat_decl = true;
|
||||
node.name.visit_with(self);
|
||||
self.in_pat_decl = old;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn collect_top_level_decls<N>(n: &N) -> AHashSet<Id>
|
||||
where
|
||||
N: VisitWith<TopLevelBindingCollector>,
|
||||
{
|
||||
let mut v = TopLevelBindingCollector {
|
||||
bindings: Default::default(),
|
||||
in_pat_decl: false,
|
||||
};
|
||||
n.visit_with(&mut v);
|
||||
v.bindings
|
||||
}
|
|
@ -1,653 +0,0 @@
|
|||
//! Port of https://github.com/styled-components/babel-plugin-styled-components/blob/a20c3033508677695953e7a434de4746168eeb4e/src/visitors/transpileCssProp.js
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::{borrow::Cow, collections::HashMap};
|
||||
|
||||
use crate::State;
|
||||
use inflector::Inflector;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use swc_core::{
|
||||
common::{
|
||||
collections::{AHashMap, AHashSet},
|
||||
util::take::Take,
|
||||
Spanned, DUMMY_SP,
|
||||
},
|
||||
ecma::ast::*,
|
||||
ecma::atoms::{js_word, JsWord},
|
||||
ecma::utils::{prepend_stmt, private_ident, quote_ident, ExprFactory},
|
||||
ecma::visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith},
|
||||
};
|
||||
|
||||
use crate::utils::{get_prop_key_as_expr, get_prop_name, get_prop_name2};
|
||||
|
||||
use super::top_level_binding_collector::collect_top_level_decls;
|
||||
|
||||
static TAG_NAME_REGEX: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new("^[a-z][a-z\\d]*(\\-[a-z][a-z\\d]*)?$").unwrap());
|
||||
|
||||
pub fn transpile_css_prop(state: Rc<RefCell<State>>) -> impl Fold + VisitMut {
|
||||
as_folder(TranspileCssProp {
|
||||
state,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TranspileCssProp {
|
||||
state: Rc<RefCell<State>>,
|
||||
|
||||
import_name: Option<Ident>,
|
||||
injected_nodes: Vec<Stmt>,
|
||||
interleaved_injections: AHashMap<Id, Vec<Stmt>>,
|
||||
|
||||
identifier_idx: usize,
|
||||
styled_idx: HashMap<JsWord, usize>,
|
||||
top_level_decls: Option<AHashSet<Id>>,
|
||||
}
|
||||
|
||||
impl TranspileCssProp {
|
||||
fn next_styled_idx(&mut self, key: JsWord) -> usize {
|
||||
let idx = self.styled_idx.entry(key).or_insert(0);
|
||||
*idx += 1;
|
||||
*idx
|
||||
}
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn is_top_level_ident(&mut self, ident: &Ident) -> bool {
|
||||
self.top_level_decls
|
||||
.as_ref()
|
||||
.map(|decls| decls.contains(&ident.to_id()))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitMut for TranspileCssProp {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_jsx_element(&mut self, elem: &mut JSXElement) {
|
||||
elem.visit_mut_children_with(self);
|
||||
|
||||
let mut extra_attrs = vec![];
|
||||
|
||||
for attr in elem.opening.attrs.iter_mut() {
|
||||
match &mut *attr {
|
||||
JSXAttrOrSpread::JSXAttr(attr) => {
|
||||
if !matches!(&attr.name, JSXAttrName::Ident(i) if &*i.sym == "css") {
|
||||
continue;
|
||||
}
|
||||
|
||||
let import_name = if let Some(ident) = self
|
||||
.state
|
||||
.borrow()
|
||||
.import_local_name("default", None)
|
||||
.map(Ident::from)
|
||||
{
|
||||
ident
|
||||
} else {
|
||||
self.import_name
|
||||
.get_or_insert_with(|| private_ident!("_styled"))
|
||||
.clone()
|
||||
};
|
||||
|
||||
let name = get_name_ident(&elem.opening.name);
|
||||
let id_sym = name.sym.to_class_case();
|
||||
|
||||
// Match the original plugin's behavior.
|
||||
let id_sym = id_sym.trim_end_matches(char::is_numeric);
|
||||
|
||||
let id_sym = JsWord::from(id_sym);
|
||||
let styled_idx = self.next_styled_idx(id_sym.clone());
|
||||
let id = quote_ident!(
|
||||
elem.opening.name.span(),
|
||||
append_if_gt_one(&format!("_Styled{}", id_sym), styled_idx)
|
||||
);
|
||||
|
||||
let (styled, inject_after) = if TAG_NAME_REGEX.is_match(&name.sym) {
|
||||
(
|
||||
(Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: import_name.as_callee(),
|
||||
args: vec![Lit::Str(Str {
|
||||
span: DUMMY_SP,
|
||||
value: name.sym,
|
||||
raw: None,
|
||||
})
|
||||
.as_arg()],
|
||||
type_args: Default::default(),
|
||||
})),
|
||||
None::<Ident>,
|
||||
)
|
||||
} else {
|
||||
let name_expr = get_name_expr(&elem.opening.name);
|
||||
|
||||
(
|
||||
Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: import_name.as_callee(),
|
||||
args: vec![name_expr.as_arg()],
|
||||
type_args: Default::default(),
|
||||
}),
|
||||
if self.is_top_level_ident(&name) {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
};
|
||||
|
||||
let mut css = match &mut attr.value {
|
||||
Some(css) => {
|
||||
//
|
||||
|
||||
match css {
|
||||
JSXAttrValue::Lit(Lit::Str(v)) => Expr::Tpl(Tpl {
|
||||
span: DUMMY_SP,
|
||||
exprs: Default::default(),
|
||||
quasis: vec![TplElement {
|
||||
span: DUMMY_SP,
|
||||
tail: true,
|
||||
cooked: None,
|
||||
raw: (&*v.value).into(),
|
||||
}],
|
||||
}),
|
||||
JSXAttrValue::JSXExprContainer(JSXExprContainer {
|
||||
expr: JSXExpr::Expr(v),
|
||||
..
|
||||
}) => match &mut **v {
|
||||
Expr::Tpl(..) => *v.take(),
|
||||
Expr::TaggedTpl(v)
|
||||
if match &*v.tag {
|
||||
Expr::Ident(i) => &*i.sym == "css",
|
||||
_ => false,
|
||||
} =>
|
||||
{
|
||||
Expr::Tpl(v.tpl.take())
|
||||
}
|
||||
Expr::Object(..) => *v.take(),
|
||||
_ => Expr::Tpl(Tpl {
|
||||
span: DUMMY_SP,
|
||||
exprs: vec![v.take()],
|
||||
quasis: vec![
|
||||
TplElement {
|
||||
span: DUMMY_SP,
|
||||
tail: false,
|
||||
cooked: None,
|
||||
raw: "".into(),
|
||||
},
|
||||
TplElement {
|
||||
span: DUMMY_SP,
|
||||
tail: true,
|
||||
cooked: None,
|
||||
raw: "".into(),
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
None => continue,
|
||||
};
|
||||
|
||||
// Remove this attribute
|
||||
attr.name = JSXAttrName::Ident(Take::dummy());
|
||||
|
||||
elem.opening.name = JSXElementName::Ident(id.clone());
|
||||
|
||||
if let Some(closing) = &mut elem.closing {
|
||||
closing.name = JSXElementName::Ident(id.clone());
|
||||
}
|
||||
|
||||
// object syntax
|
||||
if let Expr::Object(css_obj) = &mut css {
|
||||
// Original plugin says
|
||||
//
|
||||
//
|
||||
// for objects as CSS props, we have to recurse through the object and
|
||||
// replace any object key/value scope references with generated props
|
||||
// similar to how the template literal transform above creates dynamic
|
||||
// interpolations
|
||||
let p = quote_ident!("p");
|
||||
|
||||
let mut reducer = PropertyReducer {
|
||||
p: p.clone(),
|
||||
replace_object_with_prop_function: false,
|
||||
extra_attrs: Default::default(),
|
||||
identifier_idx: &mut self.identifier_idx,
|
||||
};
|
||||
|
||||
css_obj.props = css_obj
|
||||
.props
|
||||
.take()
|
||||
.into_iter()
|
||||
.fold(vec![], |acc, property| {
|
||||
reducer.reduce_object_properties(acc, property)
|
||||
});
|
||||
|
||||
extra_attrs.extend(reducer.extra_attrs);
|
||||
|
||||
if reducer.replace_object_with_prop_function {
|
||||
css = Expr::Arrow(ArrowExpr {
|
||||
span: DUMMY_SP,
|
||||
params: vec![Pat::Ident(p.clone().into())],
|
||||
body: BlockStmtOrExpr::Expr(Box::new(css.take())),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
type_params: Default::default(),
|
||||
return_type: Default::default(),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// tagged template literal
|
||||
let mut tpl = css.expect_tpl();
|
||||
|
||||
tpl.exprs =
|
||||
tpl.exprs
|
||||
.take()
|
||||
.into_iter()
|
||||
.fold(vec![], |mut acc, mut expr| {
|
||||
if expr.is_fn_expr() || expr.is_arrow() {
|
||||
acc.push(expr);
|
||||
return acc;
|
||||
} else if let Some(root) = trace_root_value(&mut expr) {
|
||||
let direct_access = match root {
|
||||
Expr::Lit(_) => true,
|
||||
Expr::Ident(id) if self.is_top_level_ident(id) => true,
|
||||
_ => false,
|
||||
};
|
||||
if direct_access {
|
||||
acc.push(expr);
|
||||
return acc;
|
||||
}
|
||||
}
|
||||
|
||||
let identifier =
|
||||
get_local_identifier(&mut self.identifier_idx, &expr);
|
||||
let p = quote_ident!("p");
|
||||
extra_attrs.push(JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
span: DUMMY_SP,
|
||||
name: JSXAttrName::Ident(identifier.clone()),
|
||||
value: Some(JSXAttrValue::JSXExprContainer(
|
||||
JSXExprContainer {
|
||||
span: DUMMY_SP,
|
||||
expr: JSXExpr::Expr(expr.take()),
|
||||
},
|
||||
)),
|
||||
}));
|
||||
|
||||
acc.push(Box::new(Expr::Arrow(ArrowExpr {
|
||||
span: DUMMY_SP,
|
||||
params: vec![Pat::Ident(p.clone().into())],
|
||||
body: BlockStmtOrExpr::Expr(Box::new(
|
||||
p.make_member(identifier),
|
||||
)),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
type_params: Default::default(),
|
||||
return_type: Default::default(),
|
||||
})));
|
||||
|
||||
acc
|
||||
});
|
||||
|
||||
css = Expr::Tpl(tpl);
|
||||
}
|
||||
|
||||
let var = VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(id.clone().into()),
|
||||
init: Some(match css {
|
||||
Expr::Object(..) | Expr::Arrow(..) => Box::new(Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: styled.as_callee(),
|
||||
args: vec![css.as_arg()],
|
||||
type_args: Default::default(),
|
||||
})),
|
||||
_ => Box::new(Expr::TaggedTpl(TaggedTpl {
|
||||
span: DUMMY_SP,
|
||||
tag: Box::new(styled),
|
||||
type_params: Default::default(),
|
||||
tpl: css.expect_tpl(),
|
||||
})),
|
||||
}),
|
||||
definite: false,
|
||||
};
|
||||
let stmt = Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: false,
|
||||
decls: vec![var],
|
||||
})));
|
||||
match inject_after {
|
||||
Some(injector) => {
|
||||
let id = injector.to_id();
|
||||
self.interleaved_injections
|
||||
.entry(id)
|
||||
.or_default()
|
||||
.push(stmt);
|
||||
}
|
||||
None => {
|
||||
self.injected_nodes.push(stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
JSXAttrOrSpread::SpreadElement(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
elem.opening.attrs.retain(|attr| {
|
||||
match attr {
|
||||
JSXAttrOrSpread::JSXAttr(attr) => {
|
||||
if matches!(
|
||||
attr.name,
|
||||
JSXAttrName::Ident(Ident {
|
||||
sym: js_word!(""),
|
||||
..
|
||||
})
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
JSXAttrOrSpread::SpreadElement(_) => {}
|
||||
}
|
||||
true
|
||||
});
|
||||
|
||||
elem.opening.attrs.extend(extra_attrs);
|
||||
}
|
||||
|
||||
fn visit_mut_module(&mut self, n: &mut Module) {
|
||||
// TODO: Skip if there are no css prop usage
|
||||
self.top_level_decls = Some(collect_top_level_decls(n));
|
||||
n.visit_mut_children_with(self);
|
||||
self.top_level_decls = None;
|
||||
|
||||
if let Some(import_name) = self.import_name.take() {
|
||||
self.state.borrow_mut().set_import_name(import_name.to_id());
|
||||
let specifier = ImportSpecifier::Default(ImportDefaultSpecifier {
|
||||
span: DUMMY_SP,
|
||||
local: import_name,
|
||||
});
|
||||
prepend_stmt(
|
||||
&mut n.body,
|
||||
ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl {
|
||||
span: DUMMY_SP,
|
||||
specifiers: vec![specifier],
|
||||
src: Box::new(Str {
|
||||
span: DUMMY_SP,
|
||||
value: "styled-components".into(),
|
||||
raw: None,
|
||||
}),
|
||||
type_only: Default::default(),
|
||||
asserts: Default::default(),
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
let mut serialized_body: Vec<ModuleItem> = vec![];
|
||||
let body = std::mem::take(&mut n.body);
|
||||
for item in body {
|
||||
serialized_body.push(item.clone());
|
||||
if let ModuleItem::Stmt(Stmt::Decl(Decl::Var(vd))) = &item {
|
||||
for decl in &vd.decls {
|
||||
if let Pat::Ident(ident) = &decl.name {
|
||||
let id = ident.to_id();
|
||||
let stmts = self.interleaved_injections.remove(&id);
|
||||
if let Some(stmts) = stmts {
|
||||
serialized_body.extend(stmts.into_iter().rev().map(ModuleItem::Stmt));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
n.body = serialized_body;
|
||||
|
||||
let mut remaining = std::mem::take(&mut self.interleaved_injections)
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>();
|
||||
remaining.sort_by_key(|x| x.0.clone());
|
||||
|
||||
remaining
|
||||
.into_iter()
|
||||
.for_each(|(_, stmts)| n.body.extend(stmts.into_iter().map(ModuleItem::Stmt)));
|
||||
|
||||
n.body
|
||||
.extend(self.injected_nodes.take().into_iter().map(ModuleItem::Stmt));
|
||||
}
|
||||
}
|
||||
|
||||
fn get_name_expr(name: &JSXElementName) -> Box<Expr> {
|
||||
fn get_name_expr_jsx_object(name: &JSXObject) -> Box<Expr> {
|
||||
match name {
|
||||
JSXObject::Ident(n) => Box::new(Expr::Ident(n.clone())),
|
||||
JSXObject::JSXMemberExpr(n) => Box::new(Expr::Member(MemberExpr {
|
||||
span: DUMMY_SP,
|
||||
obj: get_name_expr_jsx_object(&n.obj),
|
||||
prop: MemberProp::Ident(n.prop.clone()),
|
||||
})),
|
||||
}
|
||||
}
|
||||
match name {
|
||||
JSXElementName::Ident(n) => Box::new(Expr::Ident(n.clone())),
|
||||
JSXElementName::JSXMemberExpr(n) => Box::new(Expr::Member(MemberExpr {
|
||||
span: DUMMY_SP,
|
||||
obj: get_name_expr_jsx_object(&n.obj),
|
||||
prop: MemberProp::Ident(n.prop.clone()),
|
||||
})),
|
||||
JSXElementName::JSXNamespacedName(..) => {
|
||||
unimplemented!("get_name_expr for JSXNamespacedName")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct PropertyReducer<'a> {
|
||||
p: Ident,
|
||||
replace_object_with_prop_function: bool,
|
||||
extra_attrs: Vec<JSXAttrOrSpread>,
|
||||
|
||||
identifier_idx: &'a mut usize,
|
||||
}
|
||||
|
||||
impl PropertyReducer<'_> {
|
||||
fn reduce_object_properties(
|
||||
&mut self,
|
||||
mut acc: Vec<PropOrSpread>,
|
||||
mut property: PropOrSpread,
|
||||
) -> Vec<PropOrSpread> {
|
||||
match property {
|
||||
PropOrSpread::Spread(ref mut prop) => {
|
||||
// handle spread variables and such
|
||||
|
||||
if let Expr::Object(arg) = &mut *prop.expr {
|
||||
arg.props = arg
|
||||
.props
|
||||
.take()
|
||||
.into_iter()
|
||||
.fold(vec![], |acc, p| self.reduce_object_properties(acc, p));
|
||||
} else {
|
||||
self.replace_object_with_prop_function = true;
|
||||
|
||||
let identifier = get_local_identifier(self.identifier_idx, &prop.expr);
|
||||
|
||||
self.extra_attrs.push(JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
span: DUMMY_SP,
|
||||
name: JSXAttrName::Ident(identifier.clone()),
|
||||
value: Some(JSXAttrValue::JSXExprContainer(JSXExprContainer {
|
||||
span: DUMMY_SP,
|
||||
expr: JSXExpr::Expr(prop.expr.take()),
|
||||
})),
|
||||
}));
|
||||
|
||||
prop.expr = Box::new(self.p.clone().make_member(identifier));
|
||||
}
|
||||
|
||||
acc.push(property);
|
||||
}
|
||||
PropOrSpread::Prop(ref mut prop) => {
|
||||
let key = get_prop_key_as_expr(prop);
|
||||
let key_pn = get_prop_name(prop);
|
||||
|
||||
if key.is_member()
|
||||
|| key.is_call()
|
||||
|| (key.is_ident()
|
||||
&& key_pn.is_some()
|
||||
&& key_pn.unwrap().is_computed()
|
||||
&& !matches!(&**prop, Prop::Shorthand(..)))
|
||||
{
|
||||
self.replace_object_with_prop_function = true;
|
||||
|
||||
let identifier = get_local_identifier(self.identifier_idx, &key);
|
||||
|
||||
self.extra_attrs.push(JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
span: DUMMY_SP,
|
||||
name: identifier.clone().into(),
|
||||
value: Some(JSXAttrValue::JSXExprContainer(JSXExprContainer {
|
||||
span: DUMMY_SP,
|
||||
// TODO: Perf
|
||||
expr: JSXExpr::Expr(Box::new(key.clone().into_owned())),
|
||||
})),
|
||||
}));
|
||||
|
||||
set_key_of_prop(prop, Box::new(self.p.clone().make_member(identifier)));
|
||||
}
|
||||
|
||||
let mut value = take_prop_value(prop);
|
||||
|
||||
if let Expr::Object(value_obj) = &mut *value {
|
||||
value_obj.props = value_obj
|
||||
.props
|
||||
.take()
|
||||
.into_iter()
|
||||
.fold(vec![], |acc, p| self.reduce_object_properties(acc, p));
|
||||
|
||||
set_value_of_prop(prop, value);
|
||||
acc.push(property);
|
||||
} else if !matches!(&*value, Expr::Lit(..)) {
|
||||
// if a non-primitive value we have to interpolate it
|
||||
|
||||
self.replace_object_with_prop_function = true;
|
||||
|
||||
let identifier = get_local_identifier(self.identifier_idx, &value);
|
||||
|
||||
self.extra_attrs.push(JSXAttrOrSpread::JSXAttr(JSXAttr {
|
||||
span: DUMMY_SP,
|
||||
name: JSXAttrName::Ident(identifier.clone()),
|
||||
value: Some(JSXAttrValue::JSXExprContainer(JSXExprContainer {
|
||||
span: DUMMY_SP,
|
||||
expr: JSXExpr::Expr(value.take()),
|
||||
})),
|
||||
}));
|
||||
|
||||
let key = get_prop_name2(prop);
|
||||
|
||||
acc.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key,
|
||||
value: Box::new(self.p.clone().make_member(identifier)),
|
||||
}))));
|
||||
} else {
|
||||
set_value_of_prop(prop, value);
|
||||
acc.push(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
acc
|
||||
}
|
||||
}
|
||||
|
||||
fn set_value_of_prop(prop: &mut Prop, value: Box<Expr>) {
|
||||
match prop {
|
||||
Prop::Shorthand(p) => {
|
||||
*prop = Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(p.clone()),
|
||||
value,
|
||||
});
|
||||
}
|
||||
Prop::KeyValue(p) => {
|
||||
p.value = value;
|
||||
}
|
||||
Prop::Assign(..) => unreachable!("assign property is not allowed for object literals"),
|
||||
Prop::Getter(_p) => todo!(),
|
||||
Prop::Setter(_p) => todo!(),
|
||||
Prop::Method(_p) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn take_prop_value(prop: &mut Prop) -> Box<Expr> {
|
||||
match prop {
|
||||
Prop::Shorthand(p) => Box::new(Expr::Ident(p.clone())),
|
||||
Prop::KeyValue(p) => p.value.take(),
|
||||
Prop::Assign(..) => unreachable!("assign property is not allowed for object literals"),
|
||||
Prop::Getter(_p) => todo!(),
|
||||
Prop::Setter(_p) => todo!(),
|
||||
Prop::Method(_p) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_key_of_prop(prop: &mut Prop, key: Box<Expr>) {
|
||||
let value = take_prop_value(prop);
|
||||
|
||||
*prop = Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Computed(ComputedPropName {
|
||||
span: DUMMY_SP,
|
||||
expr: key,
|
||||
}),
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
fn get_local_identifier(idx: &mut usize, expr: &Expr) -> Ident {
|
||||
*idx += 1;
|
||||
|
||||
let identifier = quote_ident!(expr.span(), append_if_gt_one("$_css", *idx));
|
||||
|
||||
// TODO: Unique identifier
|
||||
|
||||
identifier
|
||||
}
|
||||
|
||||
fn append_if_gt_one(s: &str, suffix: usize) -> Cow<str> {
|
||||
if suffix > 1 {
|
||||
Cow::Owned(format!("{}{}", s, suffix))
|
||||
} else {
|
||||
Cow::Borrowed(s)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_name_ident(el: &JSXElementName) -> Ident {
|
||||
match el {
|
||||
JSXElementName::Ident(v) => v.clone(),
|
||||
JSXElementName::JSXMemberExpr(e) => Ident {
|
||||
sym: format!("{}_{}", get_name_of_jsx_obj(&e.obj), e.prop.sym).into(),
|
||||
span: e.prop.span,
|
||||
optional: false,
|
||||
},
|
||||
_ => {
|
||||
unimplemented!("get_name_ident for namespaced jsx element")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_name_of_jsx_obj(el: &JSXObject) -> JsWord {
|
||||
match el {
|
||||
JSXObject::Ident(v) => v.sym.clone(),
|
||||
JSXObject::JSXMemberExpr(e) => {
|
||||
format!("{}{}", get_name_of_jsx_obj(&e.obj), e.prop.sym).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn trace_root_value(e: &mut Expr) -> Option<&mut Expr> {
|
||||
match e {
|
||||
Expr::Member(e) => trace_root_value(&mut e.obj),
|
||||
Expr::Call(e) => match &mut e.callee {
|
||||
Callee::Expr(e) => trace_root_value(e),
|
||||
_ => None,
|
||||
},
|
||||
Expr::Ident(_) => Some(e),
|
||||
Expr::Lit(_) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
#![deny(unused)]
|
||||
|
||||
use std::{fs::read_to_string, path::PathBuf};
|
||||
use styled_components::{styled_components, Config};
|
||||
use swc_core::{
|
||||
common::{chain, Mark},
|
||||
ecma::parser::{EsConfig, Syntax},
|
||||
ecma::transforms::base::resolver,
|
||||
ecma::transforms::testing::test_fixture,
|
||||
};
|
||||
|
||||
#[testing::fixture("tests/fixtures/**/code.js")]
|
||||
fn fixture(input: PathBuf) {
|
||||
let dir = input.parent().unwrap();
|
||||
let config = read_to_string(dir.join("config.json")).expect("failed to read config.json");
|
||||
println!("---- Config -----\n{}", config);
|
||||
let config: Config = serde_json::from_str(&config).unwrap();
|
||||
|
||||
test_fixture(
|
||||
Syntax::Es(EsConfig {
|
||||
jsx: true,
|
||||
..Default::default()
|
||||
}),
|
||||
&|t| {
|
||||
//
|
||||
let fm = t.cm.load_file(&input).unwrap();
|
||||
|
||||
chain!(
|
||||
resolver(Mark::new(), Mark::new(), false),
|
||||
styled_components(fm.name.clone(), fm.src_hash, config.clone())
|
||||
)
|
||||
},
|
||||
&input,
|
||||
&dir.join("output.js"),
|
||||
Default::default(),
|
||||
)
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"ssr": false,
|
||||
"fileName": false,
|
||||
"transpileTemplateLiterals": false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
import styled from 'styled-components'
|
||||
|
||||
const WithAttrs = styled.div.attrs({ some: 'value' })``
|
||||
const WithAttrsWrapped = styled(Inner).attrs({ some: 'value' })``
|
|
@ -1,11 +0,0 @@
|
|||
import styled from 'styled-components';
|
||||
const WithAttrs = styled.div.attrs({
|
||||
some: 'value'
|
||||
}).withConfig({
|
||||
displayName: "WithAttrs"
|
||||
})``;
|
||||
const WithAttrsWrapped = styled(Inner).attrs({
|
||||
some: 'value'
|
||||
}).withConfig({
|
||||
displayName: "WithAttrsWrapped"
|
||||
})``;
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"pure": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
import { createGlobalStyle } from 'styled-components'
|
||||
|
||||
const GlobalStyle = createGlobalStyle`
|
||||
body {
|
||||
color: red;
|
||||
}
|
||||
`
|
|
@ -1,2 +0,0 @@
|
|||
import { createGlobalStyle } from 'styled-components';
|
||||
const GlobalStyle = /*#__PURE__*/createGlobalStyle(["body{color:red;}"]);
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"pure": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
import styled, { css } from 'styled-components'
|
||||
|
||||
const partial = css`
|
||||
color: red;
|
||||
`
|
||||
|
||||
const Component = styled.div`
|
||||
${partial};
|
||||
background: blue;
|
||||
`
|
|
@ -1,6 +0,0 @@
|
|||
import styled, { css } from 'styled-components';
|
||||
const partial = /*#__PURE__*/css(["color:red;"]);
|
||||
const Component = /*#__PURE__*/styled.div.withConfig({
|
||||
displayName: "code__Component",
|
||||
componentId: "sc-4wpzk3-0"
|
||||
})(["", ";background:blue;"], partial);
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"pure": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
import { keyframes } from 'styled-components'
|
||||
|
||||
const Animation = keyframes`
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
`
|
|
@ -1,2 +0,0 @@
|
|||
import { keyframes } from 'styled-components';
|
||||
const Animation = /*#__PURE__*/keyframes(["0%{opacity:0;}100%{opacity:1;}"]);
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"pure": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import styled from 'styled-components'
|
||||
|
||||
const Test = styled.div`
|
||||
width: 100%;
|
||||
`
|
||||
const Test2 = styled('div')``
|
||||
const Test3 = true ? styled.div`` : styled.div``
|
||||
const styles = { One: styled.div`` }
|
||||
let Component
|
||||
Component = styled.div``
|
||||
const WrappedComponent = styled(Inner)``
|
||||
const StyledObjectForm = styled.div({ color: red })
|
||||
const StyledFunctionForm = styled.div(p => ({ color: p.color || 'red' }))
|
||||
const normalFunc = add(5, 3)
|
|
@ -1,44 +0,0 @@
|
|||
import styled from 'styled-components';
|
||||
const Test = /*#__PURE__*/styled.div.withConfig({
|
||||
displayName: "code__Test",
|
||||
componentId: "sc-u20i28-0"
|
||||
})(["width:100%;"]);
|
||||
const Test2 = /*#__PURE__*/styled('div').withConfig({
|
||||
displayName: "code__Test2",
|
||||
componentId: "sc-u20i28-1"
|
||||
})([""]);
|
||||
const Test3 = true ? styled.div.withConfig({
|
||||
displayName: "code__Test3",
|
||||
componentId: "sc-u20i28-2"
|
||||
})([""]) : styled.div.withConfig({
|
||||
displayName: "code__Test3",
|
||||
componentId: "sc-u20i28-3"
|
||||
})([""]);
|
||||
const styles = {
|
||||
One: styled.div.withConfig({
|
||||
displayName: "code__One",
|
||||
componentId: "sc-u20i28-4"
|
||||
})([""])
|
||||
};
|
||||
let Component;
|
||||
Component = styled.div.withConfig({
|
||||
displayName: "code__Component",
|
||||
componentId: "sc-u20i28-5"
|
||||
})([""]);
|
||||
const WrappedComponent = /*#__PURE__*/styled(Inner).withConfig({
|
||||
displayName: "code__WrappedComponent",
|
||||
componentId: "sc-u20i28-6"
|
||||
})([""]);
|
||||
const StyledObjectForm = /*#__PURE__*/styled.div.withConfig({
|
||||
displayName: "code__StyledObjectForm",
|
||||
componentId: "sc-u20i28-7"
|
||||
})({
|
||||
color: red
|
||||
});
|
||||
const StyledFunctionForm = /*#__PURE__*/styled.div.withConfig({
|
||||
displayName: "code__StyledFunctionForm",
|
||||
componentId: "sc-u20i28-8"
|
||||
})(p => ({
|
||||
color: p.color || 'red'
|
||||
}));
|
||||
const normalFunc = add(5, 3);
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"pure": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
import { withTheme } from 'styled-components'
|
||||
|
||||
const ThemedComponent = withTheme(() => null)
|
|
@ -1,2 +0,0 @@
|
|||
import { withTheme } from 'styled-components';
|
||||
const ThemedComponent = /*#__PURE__*/withTheme(() => null);
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
import React from "react"
|
||||
import { css } from "styled-components"
|
||||
|
||||
export default function Example() {
|
||||
return <div css={someCss}>oops</div>
|
||||
}
|
||||
|
||||
const someCss = css`
|
||||
color: red;
|
||||
`
|
|
@ -1,12 +0,0 @@
|
|||
import _styled from "styled-components";
|
||||
import React from "react";
|
||||
import { css } from "styled-components";
|
||||
export default function Example() {
|
||||
return <_StyledDiv>oops</_StyledDiv>;
|
||||
}
|
||||
const someCss = css(["color:red;"]);
|
||||
|
||||
var _StyledDiv = _styled("div").withConfig({
|
||||
displayName: "code___StyledDiv",
|
||||
componentId: "sc-7mydya-0"
|
||||
})(["", ""], someCss);
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"ssr": false,
|
||||
"displayName": false,
|
||||
"transpileTemplateLiterals": false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import { createGlobalStyle, css, keyframes } from 'styled-components'
|
||||
|
||||
const key = keyframes`
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
`
|
||||
|
||||
const color = css`
|
||||
color: ${theColor};
|
||||
`
|
||||
|
||||
const GlobalStyles = createGlobalStyle`
|
||||
html {
|
||||
color: red;
|
||||
}
|
||||
`
|
|
@ -1,4 +0,0 @@
|
|||
import { createGlobalStyle, css, keyframes } from 'styled-components';
|
||||
const key = keyframes`to{transform:rotate(360deg);}`;
|
||||
const color = css`color:${theColor};`;
|
||||
const GlobalStyles = createGlobalStyle`html{color:red;}`;
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"presets": [
|
||||
"@babel/preset-env"
|
||||
],
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"ssr": false,
|
||||
"displayName": false,
|
||||
"transpileTemplateLiterals": false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import styled from 'styled-components';
|
||||
|
||||
const Simple = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const Interpolation = styled.div`
|
||||
content: " ${props => props.text} ";
|
||||
`;
|
||||
|
||||
const SpecialCharacters = styled.div`
|
||||
content: " ${props => props.text} ";\n color: red;
|
||||
`;
|
||||
|
||||
const Comment = styled.div`
|
||||
// comment
|
||||
color: red;
|
||||
`
|
||||
|
||||
const Parens = styled.div`
|
||||
&:hover {
|
||||
color: blue;
|
||||
}
|
||||
`;
|
|
@ -1,23 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var _styledComponents = _interopRequireDefault(require("styled-components"));
|
||||
|
||||
var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5;
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
||||
|
||||
function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
|
||||
|
||||
var Simple = _styledComponents["default"].div(_templateObject || (_templateObject = _taggedTemplateLiteral(["width:100%;"])));
|
||||
|
||||
var Interpolation = _styledComponents["default"].div(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["content:\" ", " \";"])), function (props) {
|
||||
return props.text;
|
||||
});
|
||||
|
||||
var SpecialCharacters = _styledComponents["default"].div(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["content:\" ", " \";color:red;"])), function (props) {
|
||||
return props.text;
|
||||
});
|
||||
|
||||
var Comment = _styledComponents["default"].div(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["color:red;"])));
|
||||
|
||||
var Parens = _styledComponents["default"].div(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["&:hover{color:blue;}"])));
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"ssr": false,
|
||||
"displayName": false,
|
||||
"transpileTemplateLiterals": false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
import styled from 'styled-components';
|
||||
|
||||
const Simple = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const Interpolation = styled.div`
|
||||
content: "https://test.com/${props => props.endpoint}";
|
||||
`;
|
||||
|
||||
const SpecialCharacters = styled.div`
|
||||
content: " ${props => props.text} ";\n color: red;
|
||||
`;
|
||||
|
||||
const Comment = styled.div`
|
||||
width: 100%;
|
||||
// comment
|
||||
color: red;
|
||||
`;
|
||||
|
||||
const Parens = styled.div`
|
||||
&:hover {
|
||||
color: blue;
|
||||
}
|
||||
color: red;
|
||||
`;
|
||||
|
||||
const UrlComments = styled.div`
|
||||
color: red;
|
||||
/* // */
|
||||
background: red;
|
||||
/* comment 1 */
|
||||
/* comment 2 */
|
||||
// comment 3
|
||||
border: 1px solid green;
|
||||
`;
|
|
@ -1,7 +0,0 @@
|
|||
import styled from 'styled-components';
|
||||
const Simple = styled.div`width:100%;`;
|
||||
const Interpolation = styled.div`content:"https://test.com/${props => props.endpoint}";`;
|
||||
const SpecialCharacters = styled.div`content:" ${props => props.text} ";color:red;`;
|
||||
const Comment = styled.div`width:100%;color:red;`;
|
||||
const Parens = styled.div`&:hover{color:blue;}color:red;`;
|
||||
const UrlComments = styled.div`color:red;background:red;border:1px solid green;`;
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"minify": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
import styled from 'styled-components'
|
||||
|
||||
const Test1 = styled.div`
|
||||
width: 100%;
|
||||
// color: ${'red'};
|
||||
`
|
||||
|
||||
const Test2 = styled.div`
|
||||
width: 100%;
|
||||
// color: pale${'red'};
|
||||
`
|
||||
|
||||
const Test3 = styled.div`
|
||||
width: 100%;
|
||||
// color
|
||||
${'red'};
|
||||
`
|
||||
|
||||
const Test4 = styled.div`
|
||||
width: 100%;
|
||||
// color: ${'red'}-blue;
|
||||
`
|
||||
|
||||
const Test5 = styled.div`
|
||||
width: 100%;
|
||||
// color: ${'red'}${'blue'};
|
||||
`
|
||||
|
||||
const Test6 = styled.div`
|
||||
background: url("https://google.com");
|
||||
width: 100%;
|
||||
${'green'} // color: ${'red'}${'blue'};
|
||||
`
|
||||
|
||||
const Test7 = styled.div`
|
||||
background: url("https://google.com");
|
||||
width: ${p => p.props.width};
|
||||
${'green'} // color: ${'red'}${'blue'};
|
||||
height: ${p => p.props.height};
|
||||
`
|
|
@ -1,29 +0,0 @@
|
|||
import styled from 'styled-components';
|
||||
const Test1 = styled.div.withConfig({
|
||||
displayName: "code__Test1",
|
||||
componentId: "sc-kc0mjf-0"
|
||||
})(["width:100%;"]);
|
||||
const Test2 = styled.div.withConfig({
|
||||
displayName: "code__Test2",
|
||||
componentId: "sc-kc0mjf-1"
|
||||
})(["width:100%;"]);
|
||||
const Test3 = styled.div.withConfig({
|
||||
displayName: "code__Test3",
|
||||
componentId: "sc-kc0mjf-2"
|
||||
})(["width:100%;", ";"], 'red');
|
||||
const Test4 = styled.div.withConfig({
|
||||
displayName: "code__Test4",
|
||||
componentId: "sc-kc0mjf-3"
|
||||
})(["width:100%;"]);
|
||||
const Test5 = styled.div.withConfig({
|
||||
displayName: "code__Test5",
|
||||
componentId: "sc-kc0mjf-4"
|
||||
})(["width:100%;"]);
|
||||
const Test6 = styled.div.withConfig({
|
||||
displayName: "code__Test6",
|
||||
componentId: "sc-kc0mjf-5"
|
||||
})(["background:url(\"https://google.com\");width:100%;", " "], 'green');
|
||||
const Test7 = styled.div.withConfig({
|
||||
displayName: "code__Test7",
|
||||
componentId: "sc-kc0mjf-6"
|
||||
})(["background:url(\"https://google.com\");width:", ";", " height:", ";"], p => p.props.width, 'green', p => p.props.height);
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
["@babel/plugin-transform-modules-commonjs"],
|
||||
[
|
||||
"../../../src"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
import React from "react";
|
||||
import { css } from "styled-components";
|
||||
import Icons from "./icons";
|
||||
|
||||
const someCss = css` background: purple;`;
|
||||
|
||||
const App1 = () => { return <Icons css={someCss} />; };
|
||||
|
||||
const App2 = () => { return <Icons.Foo css={someCss} />; };
|
||||
|
||||
const App3 = () => { return <Icons.Foo.Bar css={someCss} />; };
|
|
@ -1,42 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var _styledComponents = _interopRequireWildcard(require("styled-components"));
|
||||
|
||||
var _react = _interopRequireDefault(require("react"));
|
||||
|
||||
var _icons = _interopRequireDefault(require("./icons"));
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
||||
|
||||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||||
|
||||
const someCss = (0, _styledComponents.css)([" background:purple;"]);
|
||||
|
||||
const App1 = () => {
|
||||
return <_StyledIcons />;
|
||||
};
|
||||
|
||||
const App2 = () => {
|
||||
return <_StyledIconsFoo />;
|
||||
};
|
||||
|
||||
const App3 = () => {
|
||||
return <_StyledIconsFooBar />;
|
||||
};
|
||||
|
||||
var _StyledIcons = (0, _styledComponents.default)(_icons.default).withConfig({
|
||||
displayName: "code___StyledIcons",
|
||||
componentId: "sc-1wxehft-0"
|
||||
})(["", ""], someCss);
|
||||
|
||||
var _StyledIconsFoo = (0, _styledComponents.default)(_icons.default.Foo).withConfig({
|
||||
displayName: "code___StyledIconsFoo",
|
||||
componentId: "sc-1wxehft-1"
|
||||
})(["", ""], someCss);
|
||||
|
||||
var _StyledIconsFooBar = (0, _styledComponents.default)(_icons.default.Foo.Bar).withConfig({
|
||||
displayName: "code___StyledIconsFooBar",
|
||||
componentId: "sc-1wxehft-2"
|
||||
})(["", ""], someCss);
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"presets": ["@babel/preset-env"],
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"ssr": false,
|
||||
"displayName": true,
|
||||
"transpileTemplateLiterals": true,
|
||||
"minify": false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
import styled, { css, createGlobalStyle } from 'styled-components'
|
||||
|
||||
const Named = styled.div`
|
||||
width: 100%;
|
||||
`
|
||||
|
||||
const NamedWithInterpolation = styled.div`
|
||||
color: ${color => props.color};
|
||||
`
|
||||
|
||||
const Wrapped = styled(Inner)`
|
||||
color: red;
|
||||
`
|
||||
|
||||
const Foo = styled.div({
|
||||
color: 'green',
|
||||
})
|
||||
|
||||
const style = css`
|
||||
background: green;
|
||||
`
|
||||
|
||||
const GlobalStyle = createGlobalStyle`
|
||||
html {
|
||||
background: silver;
|
||||
}
|
||||
`
|
|
@ -1,32 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
||||
|
||||
var _styledComponents = _interopRequireWildcard(require("styled-components"));
|
||||
|
||||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
||||
|
||||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||||
|
||||
var Named = _styledComponents["default"].div.withConfig({
|
||||
displayName: "code__Named"
|
||||
})(["\n width: 100%;\n"]);
|
||||
|
||||
var NamedWithInterpolation = _styledComponents["default"].div.withConfig({
|
||||
displayName: "code__NamedWithInterpolation"
|
||||
})(["\n color: ", ";\n"], function (color) {
|
||||
return props.color;
|
||||
});
|
||||
|
||||
var Wrapped = (0, _styledComponents["default"])(Inner).withConfig({
|
||||
displayName: "code__Wrapped"
|
||||
})(["\n color: red;\n"]);
|
||||
|
||||
var Foo = _styledComponents["default"].div.withConfig({
|
||||
displayName: "code__Foo"
|
||||
})({
|
||||
color: 'green'
|
||||
});
|
||||
|
||||
var style = (0, _styledComponents.css)(["\n background: green;\n"]);
|
||||
var GlobalStyle = (0, _styledComponents.createGlobalStyle)(["\n html {\n background: silver;\n }\n"]);
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"presets": [
|
||||
"@babel/preset-env"
|
||||
],
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"ssr": false,
|
||||
"displayName": false,
|
||||
"transpileTemplateLiterals": true,
|
||||
"minify": false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
import styled from 'styled-components';
|
||||
|
||||
const Named = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const NamedWithInterpolation = styled.div`
|
||||
color: ${color => props.color};
|
||||
`;
|
||||
|
||||
const Wrapped = styled(Inner)`color: red;`;
|
|
@ -1,13 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var _styledComponents = _interopRequireDefault(require("styled-components"));
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
||||
|
||||
var Named = _styledComponents["default"].div(["\n width: 100%;\n"]);
|
||||
|
||||
var NamedWithInterpolation = _styledComponents["default"].div(["\n color: ", ";\n"], function (color) {
|
||||
return props.color;
|
||||
});
|
||||
|
||||
var Wrapped = (0, _styledComponents["default"])(Inner)(["color: red;"]);
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
[
|
||||
"../../../src",
|
||||
{
|
||||
"transpileTemplateLiterals": false,
|
||||
"ssr": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
const Test = s.div`width: 100%;`;
|
||||
import { default as s, css } from 'styled-components';
|
|
@ -1,5 +0,0 @@
|
|||
const Test = s.div.withConfig({
|
||||
displayName: "code__Test",
|
||||
componentId: "sc-1dds9bl-0"
|
||||
})`width:100%;`;
|
||||
import { default as s, css } from 'styled-components';
|
|
@ -1,15 +0,0 @@
|
|||
import styled from 'styled-components'
|
||||
|
||||
const Test = styled.div`
|
||||
width: 100%;
|
||||
`
|
||||
const Test2 = styled('div')``
|
||||
const Test3 = true ? styled.div`` : styled.div``
|
||||
const styles = { One: styled.div`` }
|
||||
let Component
|
||||
Component = styled.div``
|
||||
const WrappedComponent = styled(Inner)``
|
||||
class ClassComponent {
|
||||
static Child = styled.div``
|
||||
}
|
||||
var GoodName = BadName = styled.div``;
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"ssr": false,
|
||||
"fileName": false,
|
||||
"transpileTemplateLiterals": false
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
import styled from 'styled-components';
|
||||
const Test = styled.div.withConfig({
|
||||
displayName: "Test"
|
||||
})`
|
||||
width: 100%;
|
||||
`;
|
||||
const Test2 = styled('div').withConfig({
|
||||
displayName: "Test2"
|
||||
})``;
|
||||
const Test3 = true ? styled.div.withConfig({
|
||||
displayName: "Test3"
|
||||
})`` : styled.div.withConfig({
|
||||
displayName: "Test3"
|
||||
})``;
|
||||
const styles = {
|
||||
One: styled.div.withConfig({
|
||||
displayName: "One"
|
||||
})``
|
||||
};
|
||||
let Component;
|
||||
Component = styled.div.withConfig({
|
||||
displayName: "Component"
|
||||
})``;
|
||||
const WrappedComponent = styled(Inner).withConfig({
|
||||
displayName: "WrappedComponent"
|
||||
})``;
|
||||
class ClassComponent {
|
||||
static Child = styled.div.withConfig({
|
||||
displayName: "Child"
|
||||
})``;
|
||||
}
|
||||
var GoodName = BadName = styled.div.withConfig({
|
||||
displayName: "GoodName"
|
||||
})``;
|
|
@ -1,30 +0,0 @@
|
|||
import styled from 'styled-components'
|
||||
|
||||
const Test = styled.div`
|
||||
width: 100%;
|
||||
`
|
||||
const Test2 = true ? styled.div`` : styled.div``
|
||||
const styles = { One: styled.div`` }
|
||||
let Component
|
||||
Component = styled.div``
|
||||
const WrappedComponent = styled(Inner)``
|
||||
const WrappedComponent2 = styled.div({})
|
||||
const WrappedComponent3 = styled(Inner)({})
|
||||
const WrappedComponent4 = styled(Inner).attrs(() => ({ something: 'else' }))({})
|
||||
const WrappedComponent5 = styled.div.attrs(() => ({ something: 'else' }))({})
|
||||
const WrappedComponent6 = styled.div.attrs(() => ({ something: 'else' }))``
|
||||
const WrappedComponent7 = styled.div.withConfig({
|
||||
shouldForwardProp: () => {},
|
||||
})({})
|
||||
|
||||
const WrappedComponent8 = styled.div
|
||||
.withConfig({
|
||||
shouldForwardProp: () => {},
|
||||
})
|
||||
.attrs(() => ({ something: 'else' }))({})
|
||||
|
||||
const WrappedComponent9 = styled.div
|
||||
.attrs(() => ({ something: 'else' }))
|
||||
.withConfig({
|
||||
shouldForwardProp: () => {},
|
||||
})({})
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"fileName": false,
|
||||
"transpileTemplateLiterals": false,
|
||||
"ssr": true
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue