mdbook_lint_core/
lib.rs

1//! Core linting engine for mdbook-lint
2//!
3//! This library provides markdown linting functionality with mdBook support.
4//! It includes both standard markdown rules (MD001-MD059) and mdBook-specific
5//! rules (MDBOOK001-007).
6//!
7//! # Basic Usage
8//!
9//! ```rust
10//! use mdbook_lint_core::{create_engine_with_all_rules, Document};
11//! use std::path::PathBuf;
12//!
13//! let engine = create_engine_with_all_rules();
14//! let document = Document::new("# Hello".to_string(), PathBuf::from("test.md"))?;
15//! let violations = engine.lint_document(&document)?;
16//! # Ok::<(), Box<dyn std::error::Error>>(())
17//! ```
18//!
19//! # Custom Rule Sets
20//!
21//! ```rust
22//! use mdbook_lint_core::{PluginRegistry, StandardRuleProvider, MdBookRuleProvider};
23//!
24//! let mut registry = PluginRegistry::new();
25//! registry.register_provider(Box::new(StandardRuleProvider))?;
26//! registry.register_provider(Box::new(MdBookRuleProvider))?;
27//! let engine = registry.create_engine()?;
28//! # Ok::<(), Box<dyn std::error::Error>>(())
29//! ```
30
31pub mod config;
32pub mod deduplication;
33pub mod document;
34pub mod engine;
35pub mod error;
36pub mod registry;
37pub mod rule;
38pub mod rules;
39pub mod standard_provider;
40#[cfg(test)]
41pub mod test_helpers;
42pub mod violation;
43
44// Re-export core types for convenience
45pub use config::Config;
46pub use document::Document;
47pub use engine::{LintEngine, PluginRegistry, RuleProvider};
48pub use error::{
49    ConfigError, DocumentError, ErrorContext, IntoMdBookLintError, MdBookLintError, MdlntError,
50    PluginError, Result, RuleError,
51};
52pub use registry::RuleRegistry;
53pub use rule::{AstRule, Rule, RuleCategory, RuleMetadata, RuleStability};
54pub use violation::{Severity, Violation};
55
56// Re-export rule providers
57pub use rules::MdBookRuleProvider;
58pub use standard_provider::StandardRuleProvider;
59
60/// Current version of mdbook-lint-core
61pub const VERSION: &str = env!("CARGO_PKG_VERSION");
62
63/// Human-readable name
64pub const NAME: &str = "mdbook-lint-core";
65
66/// Description
67pub const DESCRIPTION: &str = "Core linting engine for mdbook-lint";
68
69/// Create a lint engine with all available rules (standard + mdBook)
70pub fn create_engine_with_all_rules() -> LintEngine {
71    let mut registry = PluginRegistry::new();
72
73    // Register standard markdown rules (MD001-MD059)
74    registry
75        .register_provider(Box::new(StandardRuleProvider))
76        .unwrap();
77
78    // Register mdBook-specific rules (MDBOOK001-007)
79    registry
80        .register_provider(Box::new(MdBookRuleProvider))
81        .unwrap();
82
83    registry.create_engine().unwrap()
84}
85
86/// Create a lint engine with only standard markdown rules
87pub fn create_standard_engine() -> LintEngine {
88    let mut registry = PluginRegistry::new();
89    registry
90        .register_provider(Box::new(StandardRuleProvider))
91        .unwrap();
92    registry.create_engine().unwrap()
93}
94
95/// Create a lint engine with only mdBook-specific rules
96pub fn create_mdbook_engine() -> LintEngine {
97    let mut registry = PluginRegistry::new();
98    registry
99        .register_provider(Box::new(MdBookRuleProvider))
100        .unwrap();
101    registry.create_engine().unwrap()
102}
103
104/// Common imports
105pub mod prelude {
106    pub use crate::{
107        Document, create_engine_with_all_rules, create_mdbook_engine, create_standard_engine,
108        engine::{LintEngine, PluginRegistry, RuleProvider},
109        error::{ErrorContext, IntoMdBookLintError, MdBookLintError, MdlntError, Result},
110        registry::RuleRegistry,
111        rule::{AstRule, Rule, RuleCategory, RuleMetadata, RuleStability},
112        violation::{Severity, Violation},
113    };
114}
115
116#[cfg(test)]
117mod tests {
118    use super::*;
119
120    #[test]
121    fn test_version_info() {
122        assert_eq!(NAME, "mdbook-lint-core");
123        assert!(DESCRIPTION.contains("linting engine"));
124    }
125
126    #[test]
127    fn test_create_all_rules_engine() {
128        let engine = create_engine_with_all_rules();
129        let rules = engine.available_rules();
130        assert!(
131            rules.len() >= 60,
132            "Expected at least 60 rules, got {}",
133            rules.len()
134        );
135    }
136
137    #[test]
138    fn test_create_standard_engine() {
139        let engine = create_standard_engine();
140        let rules = engine.available_rules();
141        assert!(
142            rules.len() >= 50,
143            "Expected at least 50 standard rules, got {}",
144            rules.len()
145        );
146    }
147
148    #[test]
149    fn test_create_mdbook_engine() {
150        let engine = create_mdbook_engine();
151        let rules = engine.available_rules();
152        assert!(
153            rules.len() >= 4,
154            "Expected at least 4 mdbook rules, got {}",
155            rules.len()
156        );
157    }
158
159    #[test]
160    fn test_basic_engine_creation() {
161        let engine = LintEngine::new();
162        assert_eq!(engine.available_rules().len(), 0);
163    }
164
165    #[test]
166    fn test_plugin_registry_creation() {
167        let registry = PluginRegistry::new();
168        assert_eq!(registry.providers().len(), 0);
169    }
170
171    #[test]
172    fn test_rule_registry_creation() {
173        let registry = RuleRegistry::new();
174        assert!(registry.is_empty());
175    }
176}