forked from vercel/next.js
/
react_remove_properties.rs
73 lines (64 loc) · 1.81 KB
/
react_remove_properties.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
use regex::Regex;
use serde::Deserialize;
use next_binding::swc::core::{
ecma::ast::*,
ecma::visit::{noop_fold_type, Fold, FoldWith},
};
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum Config {
All(bool),
WithOptions(Options),
}
impl Config {
pub fn truthy(&self) -> bool {
match self {
Config::All(b) => *b,
Config::WithOptions(_) => true,
}
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct Options {
#[serde(default)]
pub properties: Vec<String>,
}
struct RemoveProperties {
properties: Vec<Regex>,
}
impl RemoveProperties {
fn should_remove_property(&self, name: &str) -> bool {
self.properties.iter().any(|p| p.is_match(name))
}
}
impl Fold for RemoveProperties {
noop_fold_type!();
fn fold_jsx_opening_element(&mut self, mut el: JSXOpeningElement) -> JSXOpeningElement {
el.attrs.retain(|attr| {
!matches!(attr, JSXAttrOrSpread::JSXAttr(JSXAttr {
name: JSXAttrName::Ident(ident),
..
}) if self.should_remove_property(ident.sym.as_ref()))
});
el.fold_children_with(self)
}
}
pub fn remove_properties(config: Config) -> impl Fold {
let mut properties: Vec<Regex> = match config {
Config::WithOptions(x) => x
.properties
.iter()
.map(|pattern| {
Regex::new(pattern).unwrap_or_else(|e| {
panic!("error compiling property regex `{}`: {}", pattern, e);
})
})
.collect(),
_ => vec![],
};
if properties.is_empty() {
// Keep the default regex identical to `babel-plugin-react-remove-properties`.
properties.push(Regex::new(r"^data-test").unwrap());
}
RemoveProperties { properties }
}