swc_react_remove_properties_visitor/
lib.rs1use matchable::Matchable;
2use swc_core::ecma::{
3 ast::*,
4 visit::{VisitMut, VisitMutWith},
5};
6
7pub struct ReactRemovePropertiesVisitor {
8 pub properties: Vec<Matchable>,
9}
10
11impl VisitMut for ReactRemovePropertiesVisitor {
12 fn visit_mut_jsx_opening_element(&mut self, jsx_opening_element: &mut JSXOpeningElement) {
13 jsx_opening_element.visit_mut_children_with(self);
14
15 jsx_opening_element.attrs.retain(|attr| {
16 if let JSXAttrOrSpread::JSXAttr(JSXAttr {
17 name: JSXAttrName::Ident(Ident { sym, .. }),
18 ..
19 }) = attr
20 {
21 self.properties
22 .iter()
23 .all(|matchable| !matchable.is_match(sym))
24 } else {
25 true
26 }
27 });
28 }
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34 use regex::Regex;
35 use swc_core::ecma::{transforms::testing::test, visit::as_folder};
36 use swc_ecma_parser::{EsConfig, Syntax};
37
38 test!(
39 Syntax::Es(EsConfig {
40 jsx: true,
41 ..Default::default()
42 }),
43 |_| as_folder(ReactRemovePropertiesVisitor {
44 properties: vec![
45 Matchable::Str("data-foo".into()),
46 Matchable::Str("data-bar".into())
47 ]
48 }),
49 array,
50 "<div data-test data-foo data-bar></div>",
51 "<div data-test></div>"
52 );
53
54 test!(
55 Syntax::Es(EsConfig {
56 jsx: true,
57 ..Default::default()
58 }),
59 |_| as_folder(ReactRemovePropertiesVisitor {
60 properties: vec![Matchable::Regex(Regex::new("^data-test").unwrap()),]
61 }),
62 simple,
63 r#"<div className="bar" data-test="thisIsASelectorForSelenium"></div>"#,
64 r#"<div className="bar"></div>"#
65 );
66
67 test!(
68 Syntax::Es(EsConfig {
69 jsx: true,
70 ..Default::default()
71 }),
72 |_| as_folder(ReactRemovePropertiesVisitor {
73 properties: vec![Matchable::Regex(Regex::new("^data-test").unwrap()),]
74 }),
75 regex,
76 r#"<div className="bar" data-test-long-string="thisIsASelectorForSelenium"></div>"#,
77 r#"<div className="bar"></div>"#
78 );
79}