pub mod a11y;
pub mod baseline;
pub mod color;
pub mod edge;
pub mod opacity;
pub mod radius;
pub mod shadow;
pub mod sibling;
pub mod spacing;
pub mod type_;
pub mod z;
mod util;
use crate::config::Config;
use crate::report::{Severity, ViolationSink};
use crate::snapshot::SnapshotCtx;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RuleMetadata {
pub id: String,
pub summary: String,
pub doc_url: String,
pub default_severity: Severity,
}
impl RuleMetadata {
#[must_use]
pub fn from_rule(rule: &dyn Rule) -> Self {
Self {
id: rule.id().to_owned(),
summary: rule.summary().to_owned(),
doc_url: rule.doc_url(),
default_severity: rule.default_severity(),
}
}
}
pub trait Rule: Send + Sync {
fn id(&self) -> &'static str;
fn default_severity(&self) -> Severity;
fn summary(&self) -> &'static str;
fn doc_url(&self) -> String {
let slug = self.id().replace('/', "-");
format!("https://plumb.aramhammoudeh.com/rules/{slug}")
}
fn check(&self, ctx: &SnapshotCtx<'_>, config: &Config, sink: &mut ViolationSink<'_>);
}
#[must_use]
pub fn register_builtin() -> Vec<Box<dyn Rule>> {
vec![
Box::new(a11y::touch_target::TouchTarget),
Box::new(baseline::rhythm::Rhythm),
Box::new(color::contrast_aa::ContrastAa),
Box::new(color::palette_conformance::PaletteConformance),
Box::new(edge::near_alignment::NearAlignment),
Box::new(opacity::scale_conformance::ScaleConformance),
Box::new(radius::scale_conformance::ScaleConformance),
Box::new(shadow::scale_conformance::ScaleConformance),
Box::new(sibling::height_consistency::HeightConsistency),
Box::new(sibling::padding_consistency::PaddingConsistency),
Box::new(spacing::grid_conformance::GridConformance),
Box::new(spacing::scale_conformance::ScaleConformance),
Box::new(type_::family_conformance::FamilyConformance),
Box::new(type_::scale_conformance::ScaleConformance),
Box::new(type_::weight_conformance::WeightConformance),
Box::new(z::scale_conformance::ScaleConformance),
]
}
#[must_use]
pub fn builtin_rule_metadata() -> Vec<RuleMetadata> {
let mut metadata: Vec<RuleMetadata> = register_builtin()
.iter()
.map(|rule| RuleMetadata::from_rule(rule.as_ref()))
.collect();
metadata.sort_by(|a, b| a.id.cmp(&b.id));
metadata
}