From 43b415d030f7b5b27a814fdb578576d500b71001 Mon Sep 17 00:00:00 2001 From: luckyadam Date: Mon, 16 Oct 2023 22:34:41 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/document.rs | 15 ++--- src/lib.rs | 9 ++- src/scraper.rs | 45 +++++++++----- src/style_parser.rs | 13 +++- src/style_write.rs | 6 +- src/visitor.rs | 140 +++++++++++++++++++++++--------------------- 6 files changed, 131 insertions(+), 97 deletions(-) diff --git a/src/document.rs b/src/document.rs index 6c71781..8263a39 100644 --- a/src/document.rs +++ b/src/document.rs @@ -2,19 +2,20 @@ use std::collections::HashMap; use selectors::attr::CaseSensitivity; use swc_common::{ + comments::SingleThreadedComments, errors::{ColorConfig, Handler}, sync::Lrc, - SourceMap, Mark, comments::SingleThreadedComments, Globals, GLOBALS, + Globals, Mark, SourceMap, GLOBALS, }; use swc_ecma_ast::{EsVersion, Program}; use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax, TsConfig}; -use swc_ecma_visit::{VisitWith, FoldWith, VisitAllWith}; use swc_ecma_transforms_base::{fixer::fixer, hygiene::hygiene, resolver}; +use swc_ecma_visit::{FoldWith, VisitAllWith, VisitWith}; use swc_ecmascript::transforms::typescript::strip; use crate::{ scraper::Element, - visitor::{AstVisitor, JSXRecord, CollectVisitor}, + visitor::{AstVisitor, CollectVisitor, JSXRecord}, }; pub struct JSXDocument { @@ -53,10 +54,10 @@ impl JSXDocument { e.into_diagnostic(&handler).emit(); } let program = parser - .parse_program() - .map_err(|e| e.into_diagnostic(&handler).emit()) - .expect("解析 JSX 失败"); - + .parse_program() + .map_err(|e| e.into_diagnostic(&handler).emit()) + .expect("解析 JSX 失败"); + let globals = Globals::default(); GLOBALS.set(&globals, || { let unresolved_mark = Mark::new(); diff --git a/src/lib.rs b/src/lib.rs index 7871551..a3a6533 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ use std::{cell::RefCell, rc::Rc}; -use swc_common::{comments::SingleThreadedComments, SourceMap, sync::Lrc}; +use swc_common::{comments::SingleThreadedComments, sync::Lrc, SourceMap}; use swc_ecma_codegen::{text_writer::JsWriter, Emitter}; use crate::{document::JSXDocument, style_parser::StyleParser, style_write::StyleWrite}; @@ -33,7 +33,12 @@ pub fn parse(component: String, styles: Vec) -> String { let program = Rc::new(RefCell::new(document.program.as_ref().unwrap().clone())); let jsx_record = Rc::new(RefCell::new(document.jsx_record.as_ref().unwrap().clone())); - let mut style_write = StyleWrite::new(program.clone(), jsx_record.clone(), style_data.style_record.clone(), style_data.all_style.clone()); + let mut style_write = StyleWrite::new( + program.clone(), + jsx_record.clone(), + style_data.style_record.clone(), + style_data.all_style.clone(), + ); style_write.write(); // ast 转代码 diff --git a/src/scraper.rs b/src/scraper.rs index 809e0b4..1154c28 100644 --- a/src/scraper.rs +++ b/src/scraper.rs @@ -1,15 +1,18 @@ // inpired by https://github.com/causal-agent/scraper use core::fmt; -use std::{cell::OnceCell, collections::HashMap, ops::Deref, slice::Iter as SliceIter, collections::hash_map::Iter as HashMapIter}; +use std::{ + cell::OnceCell, collections::hash_map::Iter as HashMapIter, collections::HashMap, ops::Deref, + slice::Iter as SliceIter, +}; -use html5ever::{QualName, tendril::StrTendril, LocalName, Attribute}; +use html5ever::{tendril::StrTendril, Attribute, LocalName, QualName}; use selectors::attr::CaseSensitivity; use crate::visitor::SpanKey; pub struct Classes<'a> { - inner: SliceIter<'a, LocalName> + inner: SliceIter<'a, LocalName>, } impl<'a> Iterator for Classes<'a> { @@ -23,7 +26,7 @@ pub type AttributesIter<'a> = HashMapIter<'a, QualName, StrTendril>; #[derive(Debug, Clone)] pub struct Attrs<'a> { - inner: AttributesIter<'a> + inner: AttributesIter<'a>, } impl<'a> Iterator for Attrs<'a> { @@ -41,7 +44,7 @@ pub struct Element { pub attrs: Attributes, pub span: SpanKey, id: OnceCell>, - classes: OnceCell> + classes: OnceCell>, } impl Element { @@ -55,7 +58,7 @@ impl Element { span, attrs, id: OnceCell::new(), - classes: OnceCell::new() + classes: OnceCell::new(), } } @@ -64,22 +67,28 @@ impl Element { } pub fn id(&self) -> Option<&str> { - self.id.get_or_init(|| { - self.attrs - .iter() - .find(|(name,_ )| name.local.as_ref() == "id") - .map(|(_, value)| value.clone()) - }).as_deref() + self + .id + .get_or_init(|| { + self + .attrs + .iter() + .find(|(name, _)| name.local.as_ref() == "id") + .map(|(_, value)| value.clone()) + }) + .as_deref() } pub fn has_class(&self, class: &str, case_sensitive: CaseSensitivity) -> bool { - self.classes() + self + .classes() .any(|class_name| case_sensitive.eq(class.as_bytes(), class_name.as_bytes())) } pub fn classes(&self) -> Classes { let classes = self.classes.get_or_init(|| { - let mut classes: Vec = self.attrs + let mut classes: Vec = self + .attrs .iter() .filter(|(name, _)| name.local.as_ref() == "className") .flat_map(|(_, value)| value.split_whitespace().map(LocalName::from)) @@ -89,11 +98,15 @@ impl Element { classes }); - Classes { inner: classes.iter() } + Classes { + inner: classes.iter(), + } } pub fn attrs(&self) -> Attrs { - Attrs { inner: self.attrs.iter() } + Attrs { + inner: self.attrs.iter(), + } } } diff --git a/src/style_parser.rs b/src/style_parser.rs index 1425a56..fee5f81 100644 --- a/src/style_parser.rs +++ b/src/style_parser.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, collections::HashMap, convert::Infallible, rc::Rc, hash::Hash}; +use std::{cell::RefCell, collections::HashMap, convert::Infallible, hash::Hash, rc::Rc}; use lightningcss::{ declaration::DeclarationBlock, @@ -96,11 +96,18 @@ impl<'i> StyleParser<'i> { pub fn parse(&mut self, css: &'i str) { let mut stylesheet = StyleSheet::parse(css, ParserOptions::default()).expect("解析样式失败"); - let mut style_visitor = StyleVisitor::new(self.document, Rc::clone(&self.style_record), Rc::clone(&self.all_style)); + let mut style_visitor = StyleVisitor::new( + self.document, + Rc::clone(&self.style_record), + Rc::clone(&self.all_style), + ); stylesheet.visit(&mut style_visitor).unwrap(); } - fn calc_style_record(&self, style_record: &mut HashMap>>) -> HashMap> { + fn calc_style_record( + &self, + style_record: &mut HashMap>>, + ) -> HashMap> { let mut final_style_record = HashMap::new(); for (id, declarations) in style_record.iter_mut() { declarations.sort_by(|a, b| a.specificity.cmp(&b.specificity)); diff --git a/src/style_write.rs b/src/style_write.rs index 0890f86..4bf5f52 100644 --- a/src/style_write.rs +++ b/src/style_write.rs @@ -31,7 +31,11 @@ impl<'i> StyleWrite<'i> { } pub fn write(&mut self) { - let mut style_visitor = AstMutVisitor::new(self.jsx_record.clone(), self.style_record.clone(), self.all_style.clone()); + let mut style_visitor = AstMutVisitor::new( + self.jsx_record.clone(), + self.style_record.clone(), + self.all_style.clone(), + ); self.module.borrow_mut().visit_mut_with(&mut style_visitor); } } diff --git a/src/visitor.rs b/src/visitor.rs index 30cdee5..8361f03 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -9,13 +9,14 @@ use html5ever::{tendril::StrTendril, Attribute}; use lightningcss::{stylesheet::PrinterOptions, traits::ToCss}; use swc_common::{Span, DUMMY_SP}; use swc_ecma_ast::{ - Expr, - Ident, JSXAttr, JSXAttrName, JSXAttrOrSpread, JSXAttrValue, JSXElement, - JSXElementName, JSXExpr, KeyValueProp, Lit, Prop, PropName, - PropOrSpread, Str, JSXFragment, ImportDecl, ImportSpecifier, CallExpr, Callee, Null, ExprOrSpread, JSXExprContainer, Module, Stmt, ObjectLit, ExprStmt, AssignExpr, PatOrExpr,Pat, BindingIdent, ModuleItem, ModuleDecl, Decl, VarDecl, VarDeclKind, VarDeclarator + AssignExpr, BindingIdent, CallExpr, Callee, Decl, Expr, ExprOrSpread, ExprStmt, Ident, + ImportDecl, ImportSpecifier, JSXAttr, JSXAttrName, JSXAttrOrSpread, JSXAttrValue, JSXElement, + JSXElementName, JSXExpr, JSXExprContainer, JSXFragment, KeyValueProp, Lit, Module, ModuleDecl, + ModuleItem, Null, ObjectLit, Pat, PatOrExpr, Prop, PropName, PropOrSpread, Stmt, Str, VarDecl, + VarDeclKind, VarDeclarator, }; use swc_ecma_visit::{ - noop_visit_mut_type, noop_visit_type, VisitMut, VisitMutWith, VisitAll, Visit, VisitAllWith, + noop_visit_mut_type, noop_visit_type, Visit, VisitAll, VisitAllWith, VisitMut, VisitMutWith, }; use crate::{ @@ -59,9 +60,9 @@ impl Visit for CollectVisitor { if n.src.value.to_string().starts_with("@tarojs/components") { for specifier in &n.specifiers { match specifier { - ImportSpecifier::Named(named_specifier) => { - self.taro_components.push(named_specifier.local.sym.to_string()) - } + ImportSpecifier::Named(named_specifier) => self + .taro_components + .push(named_specifier.local.sym.to_string()), _ => {} } } @@ -245,8 +246,8 @@ impl<'a> VisitMut for AstMutVisitor<'a> { }) .collect::>() .into(), - }))) - }] + }))), + }], }))); // 将 inner_style_stmt 插入到 module 的最后一条 import 语句之后 @@ -256,7 +257,10 @@ impl<'a> VisitMut for AstMutVisitor<'a> { last_import_index = index as i32; } } - module.body.insert((last_import_index + 1) as usize, ModuleItem::Stmt(inner_style_stmt)); + module.body.insert( + (last_import_index + 1) as usize, + ModuleItem::Stmt(inner_style_stmt), + ); } fn visit_mut_jsx_element(&mut self, n: &mut JSXElement) { @@ -270,27 +274,26 @@ impl<'a> VisitMut for AstMutVisitor<'a> { let mut has_dynamic_style = false; let mut class_attr_value = None; let mut style_attr_value = None; - let has_dynamic_class = attrs.iter() - .any(|attr| { - if let JSXAttrOrSpread::JSXAttr(attr) = attr { - if let JSXAttrName::Ident(ident) = &attr.name { - if ident.sym.to_string() == "className" { - if let Some(value) = &attr.value { - if let JSXAttrValue::JSXExprContainer(expr_container) = value { - match &expr_container.expr { - JSXExpr::JSXEmptyExpr(_) => {}, - JSXExpr::Expr(expr) => { - class_attr_value = Some((**expr).clone()); - }, - }; - return true; - } + let has_dynamic_class = attrs.iter().any(|attr| { + if let JSXAttrOrSpread::JSXAttr(attr) = attr { + if let JSXAttrName::Ident(ident) = &attr.name { + if ident.sym.to_string() == "className" { + if let Some(value) = &attr.value { + if let JSXAttrValue::JSXExprContainer(expr_container) = value { + match &expr_container.expr { + JSXExpr::JSXEmptyExpr(_) => {} + JSXExpr::Expr(expr) => { + class_attr_value = Some((**expr).clone()); + } + }; + return true; } } } } - false - }); + } + false + }); for attr in attrs { if let JSXAttrOrSpread::JSXAttr(attr) = attr { if let JSXAttrName::Ident(ident) = &attr.name { @@ -362,26 +365,30 @@ impl<'a> VisitMut for AstMutVisitor<'a> { if !has_dynamic_class { let mut properties = Vec::new(); if let Some(style_declaration) = style_record.get(&element.span) { - for declaration in style_declaration.declaration.declarations.iter() { + for declaration in + style_declaration.declaration.declarations.iter() + { let mut has_property = false; for prop in lit.props.iter_mut() { match prop { PropOrSpread::Prop(prop) => match &**prop { - Prop::KeyValue(key_value_prop) => match &key_value_prop.key { - PropName::Ident(ident) => { - let property_id = ident.sym.to_string(); - if property_id - == declaration - .property_id() - .to_css_string(PrinterOptions::default()) - .unwrap() - { - has_property = true; - break; + Prop::KeyValue(key_value_prop) => { + match &key_value_prop.key { + PropName::Ident(ident) => { + let property_id = ident.sym.to_string(); + if property_id + == declaration + .property_id() + .to_css_string(PrinterOptions::default()) + .unwrap() + { + has_property = true; + break; + } } + _ => {} } - _ => {} - }, + } _ => {} }, PropOrSpread::Spread(_) => {} @@ -418,7 +425,7 @@ impl<'a> VisitMut for AstMutVisitor<'a> { has_dynamic_style = true; } } - }, + } } } JSXAttrValue::JSXElement(_) => { @@ -489,35 +496,32 @@ impl<'a> VisitMut for AstMutVisitor<'a> { } } } else { - let fun_call_expr = Expr::Call( - CallExpr { - span: DUMMY_SP, - callee: Callee::Expr(Box::new(Expr::Ident(Ident::new("__calc_style__".into(), DUMMY_SP)))), - args: vec![ - match class_attr_value { - Some(value) => ExprOrSpread::from(Box::new(value)), - None => ExprOrSpread::from(Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP })))), - }, - match style_attr_value { - Some(value) => ExprOrSpread::from(Box::new(value)), - None => ExprOrSpread::from(Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP })))), - }, - ], - type_args: None, - } - ); + let fun_call_expr = Expr::Call(CallExpr { + span: DUMMY_SP, + callee: Callee::Expr(Box::new(Expr::Ident(Ident::new( + "__calc_style__".into(), + DUMMY_SP, + )))), + args: vec![ + match class_attr_value { + Some(value) => ExprOrSpread::from(Box::new(value)), + None => ExprOrSpread::from(Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP })))), + }, + match style_attr_value { + Some(value) => ExprOrSpread::from(Box::new(value)), + None => ExprOrSpread::from(Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP })))), + }, + ], + type_args: None, + }); for attr in &mut n.opening.attrs { if let JSXAttrOrSpread::JSXAttr(attr) = attr { if let JSXAttrName::Ident(ident) = &attr.name { if ident.sym.to_string() == "style" { - attr.value = Some( - JSXAttrValue::JSXExprContainer( - JSXExprContainer { - span: DUMMY_SP, - expr: JSXExpr::Expr(Box::new(fun_call_expr.clone())), - } - ) - ); + attr.value = Some(JSXAttrValue::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(fun_call_expr.clone())), + })); } } }