swc_css_lints/rules/
color_hex_alpha.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
use serde::{Deserialize, Serialize};
use swc_css_ast::*;
use swc_css_visit::{Visit, VisitWith};

use crate::rule::{visitor_rule, LintRule, LintRuleContext};

pub type ColorHexAlphaConfig = Option<Preference>;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum Preference {
    Always,
    Never,
}

impl Default for Preference {
    fn default() -> Self {
        Self::Always
    }
}

pub fn color_hex_alpha(ctx: LintRuleContext<ColorHexAlphaConfig>) -> Box<dyn LintRule> {
    let preference = ctx.config().clone().unwrap_or_default();
    visitor_rule(ctx.reaction(), ColorHexAlpha { ctx, preference })
}

#[derive(Debug, Default)]
struct ColorHexAlpha {
    ctx: LintRuleContext<ColorHexAlphaConfig>,
    preference: Preference,
}

impl Visit for ColorHexAlpha {
    fn visit_hex_color(&mut self, hex_color: &HexColor) {
        let length = hex_color.value.len();
        match self.preference {
            Preference::Always if length == 3 || length == 6 => {
                self.ctx.report(
                    hex_color,
                    format!("Expected alpha channel in '#{}'.", hex_color.value),
                );
            }
            Preference::Never if length == 4 || length == 8 => {
                self.ctx.report(
                    hex_color,
                    format!("Unexpected alpha channel in '#{}'.", hex_color.value),
                );
            }
            _ => {}
        }

        hex_color.visit_children_with(self);
    }
}