mdbook_lint_core/
standard_provider.rs

1//! Standard markdown rules (MD001-MD059).
2
3use crate::{engine::RuleProvider, registry::RuleRegistry};
4
5/// Provider for standard markdown rules (MD001-MD059)
6pub struct StandardRuleProvider;
7
8impl RuleProvider for StandardRuleProvider {
9    fn provider_id(&self) -> &'static str {
10        "mdbook-lint-standard"
11    }
12
13    fn description(&self) -> &'static str {
14        "Standard markdownlint-compatible rules (MD001-MD059)"
15    }
16
17    fn version(&self) -> &'static str {
18        env!("CARGO_PKG_VERSION")
19    }
20
21    fn register_rules(&self, registry: &mut RuleRegistry) {
22        // Structure and heading rules
23        registry.register(Box::new(crate::rules::standard::md001::MD001));
24        registry.register(Box::new(crate::rules::standard::md002::MD002::new()));
25        registry.register(Box::new(crate::rules::standard::md003::MD003::new()));
26
27        // MD004-MD007: List rules
28        registry.register(Box::new(crate::rules::standard::md004::MD004::new()));
29        registry.register(Box::new(crate::rules::standard::md005::MD005));
30        registry.register(Box::new(crate::rules::standard::md006::MD006));
31        registry.register(Box::new(crate::rules::standard::md007::MD007::new()));
32        registry.register(Box::new(crate::rules::standard::md008::MD008));
33
34        // MD009-MD014: Whitespace and formatting rules
35        registry.register(Box::new(crate::rules::standard::md009::MD009::new()));
36        registry.register(Box::new(crate::rules::standard::md010::MD010::new()));
37        registry.register(Box::new(crate::rules::standard::md011::MD011));
38        registry.register(Box::new(crate::rules::standard::md012::MD012::new()));
39        registry.register(Box::new(crate::rules::standard::md013::MD013::new()));
40        registry.register(Box::new(crate::rules::standard::md014::MD014));
41        registry.register(Box::new(crate::rules::standard::md015::MD015));
42        registry.register(Box::new(crate::rules::standard::md016::MD016));
43        registry.register(Box::new(crate::rules::standard::md017::MD017));
44
45        // MD018-MD028: Link and image rules
46        registry.register(Box::new(crate::rules::standard::md018::MD018));
47        registry.register(Box::new(crate::rules::standard::md019::MD019));
48        registry.register(Box::new(crate::rules::standard::md020::MD020));
49        registry.register(Box::new(crate::rules::standard::md021::MD021));
50        registry.register(Box::new(crate::rules::standard::md022::MD022));
51        registry.register(Box::new(crate::rules::standard::md023::MD023));
52        registry.register(Box::new(crate::rules::standard::md024::MD024::new()));
53        registry.register(Box::new(crate::rules::standard::md025::MD025::new()));
54        registry.register(Box::new(crate::rules::standard::md026::MD026::new()));
55        registry.register(Box::new(crate::rules::standard::md027::MD027));
56        registry.register(Box::new(crate::rules::standard::md028::MD028));
57
58        // MD029-MD032: Advanced formatting rules
59        registry.register(Box::new(crate::rules::standard::md029::MD029::new()));
60        registry.register(Box::new(crate::rules::standard::md030::MD030::new()));
61        registry.register(Box::new(crate::rules::standard::md031::MD031));
62        registry.register(Box::new(crate::rules::standard::md032::MD032));
63
64        // MD033-MD040: HTML and code rules
65        registry.register(Box::new(crate::rules::standard::md033::MD033));
66        registry.register(Box::new(crate::rules::standard::md034::MD034));
67        registry.register(Box::new(crate::rules::standard::md035::MD035::new()));
68        registry.register(Box::new(crate::rules::standard::md036::MD036::new()));
69        registry.register(Box::new(crate::rules::standard::md037::MD037));
70        registry.register(Box::new(crate::rules::standard::md038::MD038));
71        registry.register(Box::new(crate::rules::standard::md039::MD039));
72        registry.register(Box::new(crate::rules::standard::md040::MD040));
73
74        // MD041-MD048: Document structure rules
75        registry.register(Box::new(crate::rules::standard::md041::MD041));
76        registry.register(Box::new(crate::rules::standard::md042::MD042));
77        registry.register(Box::new(crate::rules::standard::md043::MD043::new()));
78        registry.register(Box::new(crate::rules::standard::md044::MD044::new()));
79        registry.register(Box::new(crate::rules::standard::md045::MD045));
80        registry.register(Box::new(crate::rules::standard::md046::MD046::new()));
81        registry.register(Box::new(crate::rules::standard::md047::MD047));
82        registry.register(Box::new(crate::rules::standard::md048::MD048::new()));
83
84        // MD049-MD059: Advanced linting rules
85        registry.register(Box::new(crate::rules::standard::md049::MD049::new()));
86        registry.register(Box::new(crate::rules::standard::md050::MD050::new()));
87        registry.register(Box::new(crate::rules::standard::md051::MD051::new()));
88        registry.register(Box::new(crate::rules::standard::md052::MD052::new()));
89        registry.register(Box::new(crate::rules::standard::md053::MD053::new()));
90        registry.register(Box::new(crate::rules::standard::md054::MD054::new()));
91        registry.register(Box::new(crate::rules::standard::md055::MD055::new()));
92        registry.register(Box::new(crate::rules::standard::md056::MD056::new()));
93        registry.register(Box::new(crate::rules::standard::md057::MD057));
94        registry.register(Box::new(crate::rules::standard::md058::MD058));
95        registry.register(Box::new(crate::rules::standard::md059::MD059::new()));
96    }
97
98    fn rule_ids(&self) -> Vec<&'static str> {
99        vec![
100            "MD001", "MD002", "MD003", "MD004", "MD005", "MD006", "MD007", "MD008", "MD009",
101            "MD010", "MD011", "MD012", "MD013", "MD014", "MD015", "MD016", "MD017", "MD018",
102            "MD019", "MD020", "MD021", "MD022", "MD023", "MD024", "MD025", "MD026", "MD027",
103            "MD028", "MD029", "MD030", "MD031", "MD032", "MD033", "MD034", "MD035", "MD036",
104            "MD037", "MD038", "MD039", "MD040", "MD041", "MD042", "MD043", "MD044", "MD045",
105            "MD046", "MD047", "MD048", "MD049", "MD050", "MD051", "MD052", "MD053", "MD054",
106            "MD055", "MD056", "MD057", "MD058", "MD059",
107        ]
108    }
109}
110
111/// Create a lint engine with standard rules only
112///
113/// This is a convenience function for creating an engine with just the
114/// standard markdownlint-compatible rules.
115pub fn create_standard_engine() -> crate::LintEngine {
116    let mut registry = crate::PluginRegistry::new();
117    registry
118        .register_provider(Box::new(StandardRuleProvider))
119        .unwrap();
120    registry.create_engine().unwrap()
121}
122
123#[cfg(test)]
124mod tests {
125    use super::*;
126
127    #[test]
128    fn test_standard_provider_metadata() {
129        let provider = StandardRuleProvider;
130        assert_eq!(provider.provider_id(), "mdbook-lint-standard");
131        assert!(provider.description().contains("markdownlint"));
132        assert!(!provider.version().is_empty());
133    }
134
135    #[test]
136    fn test_standard_provider_rule_count() {
137        let provider = StandardRuleProvider;
138        let rule_ids = provider.rule_ids();
139
140        // Should have 59 standard rules (MD001-MD059 with all gaps filled)
141        assert_eq!(rule_ids.len(), 59);
142
143        // Check some key rules are present
144        assert!(rule_ids.contains(&"MD001"));
145        assert!(rule_ids.contains(&"MD013"));
146        assert!(rule_ids.contains(&"MD040"));
147        assert!(rule_ids.contains(&"MD059"));
148
149        // Should not contain mdBook rules
150        assert!(!rule_ids.contains(&"MDBOOK001"));
151    }
152
153    #[test]
154    fn test_standard_provider_registration() {
155        let mut registry = crate::RuleRegistry::new();
156        let provider = StandardRuleProvider;
157
158        // Registry should be empty initially
159        assert_eq!(registry.len(), 0);
160
161        // Register the provider's rules
162        provider.register_rules(&mut registry);
163
164        // Should now have all standard rules
165        assert_eq!(registry.len(), 59);
166
167        // Check specific rules are registered
168        assert!(registry.get_rule("MD001").is_some());
169        assert!(registry.get_rule("MD013").is_some());
170        assert!(registry.get_rule("MD040").is_some());
171        assert!(registry.get_rule("MDBOOK001").is_none());
172    }
173
174    #[test]
175    fn test_create_standard_engine() {
176        let engine = create_standard_engine();
177        let rule_ids = engine.available_rules();
178
179        // Should have all standard rules
180        assert_eq!(rule_ids.len(), 59);
181        assert!(rule_ids.contains(&"MD001"));
182        assert!(rule_ids.contains(&"MD059"));
183
184        // Should not have mdBook rules
185        assert!(!rule_ids.contains(&"MDBOOK001"));
186    }
187}