Skip to content

Commit 644a0d3

Browse files
committed
feat: 将样式转为对象插入到代码中
1 parent ae91b2c commit 644a0d3

File tree

4 files changed

+109
-11
lines changed

4 files changed

+109
-11
lines changed

src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,11 @@ pub fn parse(component: String, styles: Vec<String>) -> String {
2929
let css = styles.join("\n");
3030
let mut style_parser = StyleParser::new(&document);
3131
style_parser.parse(&css);
32-
let style_record = style_parser.calc();
32+
let style_data = style_parser.calc();
3333

3434
let program = Rc::new(RefCell::new(document.program.as_ref().unwrap().clone()));
3535
let jsx_record = Rc::new(RefCell::new(document.jsx_record.as_ref().unwrap().clone()));
36-
let style_record = Rc::new(RefCell::new(style_record));
37-
let mut style_write = StyleWrite::new(program.clone(), jsx_record.clone(), style_record.clone());
36+
let mut style_write = StyleWrite::new(program.clone(), jsx_record.clone(), style_data.style_record.clone(), style_data.all_style.clone());
3837
style_write.write();
3938

4039
// ast 转代码

src/style_parser.rs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{cell::RefCell, collections::HashMap, convert::Infallible, rc::Rc};
1+
use std::{cell::RefCell, collections::HashMap, convert::Infallible, rc::Rc, hash::Hash};
22

33
use lightningcss::{
44
declaration::DeclarationBlock,
@@ -11,6 +11,11 @@ use lightningcss::{
1111

1212
use crate::{document::JSXDocument, visitor::SpanKey};
1313

14+
pub struct StyleData<'i> {
15+
pub style_record: Rc<RefCell<HashMap<SpanKey, StyleDeclaration<'i>>>>,
16+
pub all_style: Rc<RefCell<HashMap<String, StyleDeclaration<'i>>>>,
17+
}
18+
1419
#[derive(Debug, Clone)]
1520
pub struct StyleDeclaration<'i> {
1621
pub specificity: u32,
@@ -19,16 +24,19 @@ pub struct StyleDeclaration<'i> {
1924

2025
pub struct StyleVisitor<'i> {
2126
pub style_record: Rc<RefCell<HashMap<SpanKey, Vec<StyleDeclaration<'i>>>>>,
27+
pub all_style: Rc<RefCell<HashMap<String, Vec<StyleDeclaration<'i>>>>>,
2228
pub document: &'i JSXDocument,
2329
}
2430

2531
impl<'i> StyleVisitor<'i> {
2632
pub fn new(
2733
document: &'i JSXDocument,
2834
style_record: Rc<RefCell<HashMap<SpanKey, Vec<StyleDeclaration<'i>>>>>,
35+
all_style: Rc<RefCell<HashMap<String, Vec<StyleDeclaration<'i>>>>>,
2936
) -> Self {
3037
StyleVisitor {
3138
style_record,
39+
all_style,
3240
document,
3341
}
3442
}
@@ -44,6 +52,15 @@ impl<'i> Visitor<'i> for StyleVisitor<'i> {
4452
let selectors = selectors_str.split(",").collect::<Vec<&str>>();
4553
for index in 0..selectors.len() {
4654
let selector = selectors[index].trim().replace(".", "");
55+
{
56+
let mut all_style = self.all_style.borrow_mut();
57+
let declarations: &mut Vec<StyleDeclaration<'_>> =
58+
all_style.entry(selector.clone()).or_insert(vec![]);
59+
declarations.push(StyleDeclaration {
60+
specificity: style.selectors.0.get(index).unwrap().specificity(),
61+
declaration: style.declarations.clone(),
62+
});
63+
}
4764
let elements = self.document.select(selector.as_str());
4865
for element in elements {
4966
let mut style_record = self.style_record.borrow_mut();
@@ -64,26 +81,26 @@ impl<'i> Visitor<'i> for StyleVisitor<'i> {
6481

6582
pub struct StyleParser<'i> {
6683
pub style_record: Rc<RefCell<HashMap<SpanKey, Vec<StyleDeclaration<'i>>>>>,
84+
pub all_style: Rc<RefCell<HashMap<String, Vec<StyleDeclaration<'i>>>>>,
6785
pub document: &'i JSXDocument,
6886
}
6987

7088
impl<'i> StyleParser<'i> {
7189
pub fn new(document: &'i JSXDocument) -> Self {
7290
StyleParser {
7391
style_record: Rc::new(RefCell::new(HashMap::new())),
92+
all_style: Rc::new(RefCell::new(HashMap::new())),
7493
document,
7594
}
7695
}
7796

7897
pub fn parse(&mut self, css: &'i str) {
7998
let mut stylesheet = StyleSheet::parse(css, ParserOptions::default()).expect("解析样式失败");
80-
let mut style_visitor = StyleVisitor::new(self.document, Rc::clone(&self.style_record));
99+
let mut style_visitor = StyleVisitor::new(self.document, Rc::clone(&self.style_record), Rc::clone(&self.all_style));
81100
stylesheet.visit(&mut style_visitor).unwrap();
82101
}
83102

84-
pub fn calc(&self) -> HashMap<SpanKey, StyleDeclaration<'i>> {
85-
// 遍历 style_record,计算每个节点的最终样式
86-
let mut style_record = self.style_record.borrow_mut();
103+
fn calc_style_record<T: Hash + Eq + Clone>(&self, style_record: &mut HashMap<T, Vec<StyleDeclaration<'i>>>) -> HashMap<T, StyleDeclaration<'i>> {
87104
let mut final_style_record = HashMap::new();
88105
for (id, declarations) in style_record.iter_mut() {
89106
declarations.sort_by(|a, b| a.specificity.cmp(&b.specificity));
@@ -117,7 +134,7 @@ impl<'i> StyleParser<'i> {
117134
}
118135
}
119136
final_style_record.insert(
120-
*id,
137+
(*id).clone(),
121138
StyleDeclaration {
122139
specificity: 0,
123140
declaration: DeclarationBlock {
@@ -129,4 +146,16 @@ impl<'i> StyleParser<'i> {
129146
}
130147
final_style_record
131148
}
149+
150+
pub fn calc(&self) -> StyleData<'i> {
151+
// 遍历 style_record,计算每个节点的最终样式
152+
let mut style_record = self.style_record.borrow_mut();
153+
let mut all_style = self.all_style.borrow_mut();
154+
let final_style_record = self.calc_style_record(&mut style_record);
155+
let final_all_style = self.calc_style_record(&mut all_style);
156+
StyleData {
157+
style_record: Rc::new(RefCell::new(final_style_record)),
158+
all_style: Rc::new(RefCell::new(final_all_style)),
159+
}
160+
}
132161
}

src/style_write.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,26 @@ pub struct StyleWrite<'i> {
1212
pub module: Rc<RefCell<Program>>,
1313
pub jsx_record: Rc<RefCell<JSXRecord>>,
1414
pub style_record: Rc<RefCell<HashMap<SpanKey, StyleDeclaration<'i>>>>,
15+
pub all_style: Rc<RefCell<HashMap<String, StyleDeclaration<'i>>>>,
1516
}
1617

1718
impl<'i> StyleWrite<'i> {
1819
pub fn new(
1920
module: Rc<RefCell<Program>>,
2021
jsx_record: Rc<RefCell<JSXRecord>>,
2122
style_record: Rc<RefCell<HashMap<SpanKey, StyleDeclaration<'i>>>>,
23+
all_style: Rc<RefCell<HashMap<String, StyleDeclaration<'i>>>>,
2224
) -> Self {
2325
StyleWrite {
2426
module,
2527
jsx_record,
2628
style_record,
29+
all_style,
2730
}
2831
}
2932

3033
pub fn write(&mut self) {
31-
let mut style_visitor = AstMutVisitor::new(self.jsx_record.clone(), self.style_record.clone());
34+
let mut style_visitor = AstMutVisitor::new(self.jsx_record.clone(), self.style_record.clone(), self.all_style.clone());
3235
self.module.borrow_mut().visit_mut_with(&mut style_visitor);
3336
}
3437
}

src/visitor.rs

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use swc_ecma_ast::{
1212
Expr,
1313
Ident, JSXAttr, JSXAttrName, JSXAttrOrSpread, JSXAttrValue, JSXElement,
1414
JSXElementName, JSXExpr, KeyValueProp, Lit, Prop, PropName,
15-
PropOrSpread, Str, JSXFragment, ImportDecl, ImportSpecifier, CallExpr, Callee, Null, ExprOrSpread, JSXExprContainer,
15+
PropOrSpread, Str, JSXFragment, ImportDecl, ImportSpecifier, CallExpr, Callee, Null, ExprOrSpread, JSXExprContainer, Module, Stmt, ObjectLit, ExprStmt, AssignExpr, PatOrExpr,Pat, BindingIdent, ModuleItem, ModuleDecl, Decl, VarDecl, VarDeclKind, VarDeclarator
1616
};
1717
use swc_ecma_visit::{
1818
noop_visit_mut_type, noop_visit_type, VisitMut, VisitMutWith, VisitAll, Visit, VisitAllWith,
@@ -175,23 +175,90 @@ impl<'a> VisitAll for AstVisitor<'a> {
175175
pub struct AstMutVisitor<'a> {
176176
pub jsx_record: Rc<RefCell<JSXRecord>>,
177177
pub style_record: Rc<RefCell<HashMap<SpanKey, StyleDeclaration<'a>>>>,
178+
pub all_style: Rc<RefCell<HashMap<String, StyleDeclaration<'a>>>>,
178179
}
179180

180181
impl<'a> AstMutVisitor<'a> {
181182
pub fn new(
182183
jsx_record: Rc<RefCell<JSXRecord>>,
183184
style_record: Rc<RefCell<HashMap<SpanKey, StyleDeclaration<'a>>>>,
185+
all_style: Rc<RefCell<HashMap<String, StyleDeclaration<'a>>>>,
184186
) -> Self {
185187
AstMutVisitor {
186188
jsx_record,
187189
style_record,
190+
all_style,
188191
}
189192
}
190193
}
191194

192195
impl<'a> VisitMut for AstMutVisitor<'a> {
193196
noop_visit_mut_type!();
194197

198+
fn visit_mut_module(&mut self, module: &mut Module) {
199+
let inner_style_stmt = Stmt::Decl(Decl::Var(Box::new(VarDecl {
200+
span: DUMMY_SP,
201+
kind: VarDeclKind::Var,
202+
declare: false,
203+
decls: vec![VarDeclarator {
204+
span: DUMMY_SP,
205+
name: Pat::Ident(BindingIdent {
206+
id: Ident::new("__inner_style__".into(), DUMMY_SP),
207+
type_ann: None,
208+
}),
209+
definite: false,
210+
init: Some(Box::new(Expr::Object(ObjectLit {
211+
span: DUMMY_SP,
212+
props: self
213+
.all_style
214+
.borrow()
215+
.iter()
216+
.map(|(key, value)| {
217+
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
218+
key: PropName::Ident(Ident::new(key.clone().into(), DUMMY_SP)),
219+
value: Box::new(Expr::Object(ObjectLit {
220+
span: DUMMY_SP,
221+
props: value
222+
.declaration
223+
.declarations
224+
.iter()
225+
.map(|declaration| {
226+
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
227+
key: PropName::Ident(Ident::new(
228+
declaration
229+
.property_id()
230+
.to_css_string(PrinterOptions::default())
231+
.unwrap()
232+
.into(),
233+
DUMMY_SP,
234+
)),
235+
value: declaration
236+
.value_to_css_string(PrinterOptions::default())
237+
.unwrap()
238+
.into(),
239+
})))
240+
})
241+
.collect::<Vec<PropOrSpread>>()
242+
.into(),
243+
})),
244+
})))
245+
})
246+
.collect::<Vec<PropOrSpread>>()
247+
.into(),
248+
})))
249+
}]
250+
})));
251+
252+
// 将 inner_style_stmt 插入到 module 的最后一条 import 语句之后
253+
let mut last_import_index: i32 = -1;
254+
for (index, stmt) in module.body.iter().enumerate() {
255+
if let ModuleItem::ModuleDecl(ModuleDecl::Import(_)) = stmt {
256+
last_import_index = index as i32;
257+
}
258+
}
259+
module.body.insert((last_import_index + 1) as usize, ModuleItem::Stmt(inner_style_stmt));
260+
}
261+
195262
fn visit_mut_jsx_element(&mut self, n: &mut JSXElement) {
196263
let span_key = SpanKey(n.span);
197264
if let Some(element) = self.jsx_record.borrow().get(&span_key) {

0 commit comments

Comments
 (0)