-
Notifications
You must be signed in to change notification settings - Fork 28k
/
Copy pathemotion.rs
116 lines (105 loc) · 3.39 KB
/
emotion.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#![allow(unused)]
use std::{
hash::{Hash, Hasher},
path::Path,
};
use anyhow::Result;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use swc_core::{
common::util::take::Take,
ecma::{
ast::{Module, Program},
visit::FoldWith,
},
};
use turbo_tasks::{trace::TraceRawVcs, ValueDefault, Vc};
use turbopack_ecmascript::{CustomTransformer, TransformContext};
#[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum EmotionLabelKind {
DevOnly,
Always,
Never,
}
//[TODO]: need to support importmap, there are type mismatch between
//next.config.js to swc's emotion options
#[turbo_tasks::value(shared)]
#[derive(Default, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct EmotionTransformConfig {
pub sourcemap: Option<bool>,
pub label_format: Option<String>,
pub auto_label: Option<EmotionLabelKind>,
}
#[turbo_tasks::value_impl]
impl EmotionTransformConfig {
#[turbo_tasks::function]
pub fn default_private() -> Vc<Self> {
Self::cell(Default::default())
}
}
impl ValueDefault for EmotionTransformConfig {
fn value_default() -> Vc<Self> {
EmotionTransformConfig::default_private()
}
}
#[derive(Debug)]
pub struct EmotionTransformer {
#[cfg(feature = "transform_emotion")]
config: swc_emotion::EmotionOptions,
}
#[cfg(feature = "transform_emotion")]
impl EmotionTransformer {
pub fn new(config: &EmotionTransformConfig) -> Option<Self> {
let config = swc_emotion::EmotionOptions {
// When you create a transformer structure, it is assumed that you are performing an
// emotion transform.
enabled: Some(true),
sourcemap: config.sourcemap,
label_format: config.label_format.clone(),
auto_label: if let Some(auto_label) = config.auto_label.as_ref() {
match auto_label {
EmotionLabelKind::Always => Some(true),
EmotionLabelKind::Never => Some(false),
// [TODO]: this is not correct coerece, need to be fixed
EmotionLabelKind::DevOnly => None,
}
} else {
None
},
..Default::default()
};
Some(EmotionTransformer { config })
}
}
#[cfg(not(feature = "transform_emotion"))]
impl EmotionTransformer {
pub fn new(_config: &EmotionTransformConfig) -> Option<Self> {
None
}
}
#[async_trait]
impl CustomTransformer for EmotionTransformer {
#[tracing::instrument(level = tracing::Level::TRACE, name = "emotion", skip_all)]
async fn transform(&self, program: &mut Program, ctx: &TransformContext<'_>) -> Result<()> {
#[cfg(feature = "transform_emotion")]
{
let p = std::mem::replace(program, Program::Module(Module::dummy()));
let hash = {
#[allow(clippy::disallowed_types)]
let mut hasher = std::collections::hash_map::DefaultHasher::new();
p.hash(&mut hasher);
hasher.finish()
};
*program = p.fold_with(&mut swc_emotion::emotion(
self.config.clone(),
Path::new(ctx.file_name_str),
hash as u32,
ctx.source_map.clone(),
ctx.comments.clone(),
));
}
Ok(())
}
}