swc_react_remove_properties_visitor/
lib.rs

1use 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}