1mod adjacent_code;
35mod bare_url;
36mod duplicate_heading;
37mod duplicate_link_label;
38mod escaped_emphasis;
39mod heading_punctuation;
40mod inconsistent_list_marker;
41mod info_string_typo;
42mod latex_command;
43mod list_tightness_flipped;
44mod math_render;
45mod math_unbalanced_braces;
46mod math_unbalanced_delim;
47mod math_unbalanced_env;
48mod orphan_reference_link;
49mod stray_dollar;
50mod subscript_damage;
51mod table_pipe_spacing;
52mod trailing_whitespace;
53mod unbalanced_backtick;
54mod unicodeable_subscript;
55
56use crate::rule::LintRule;
57use crate::rule_set::RuleSet;
58
59pub use adjacent_code::AdjacentCodeNoSpace;
60pub use bare_url::BareUrl;
61pub use duplicate_heading::DuplicateHeading;
62pub use duplicate_link_label::DuplicateLinkLabel;
63pub use escaped_emphasis::EscapedEmphasis;
64pub use heading_punctuation::HeadingPunctuation;
65pub use inconsistent_list_marker::InconsistentListMarker;
66pub use info_string_typo::InfoStringTypo;
67pub use latex_command::LatexCommand;
68pub use list_tightness_flipped::ListTightnessFlipped;
69pub use math_render::RenderCompat;
70pub use math_unbalanced_braces::MathUnbalancedBraces;
71pub use math_unbalanced_delim::MathUnbalancedDelim;
72pub use math_unbalanced_env::MathUnbalancedEnv;
73pub use orphan_reference_link::OrphanReferenceLink;
74pub use stray_dollar::StrayDollar;
75pub use subscript_damage::SubscriptDamage;
76pub use table_pipe_spacing::TablePipeSpacing;
77pub use trailing_whitespace::TrailingWhitespace;
78pub use unbalanced_backtick::UnbalancedBacktick;
79pub use unicodeable_subscript::UnicodeableSubscript;
80
81pub const NAMES: &[&str] = &[
90 "unbalanced-backtick",
91 "math/unbalanced-delim",
92 "math/unbalanced-env",
93 "math/unbalanced-braces",
94 "math/render-compat",
95 "adjacent-code-no-space",
96 "heading-punctuation",
97 "orphan-reference-link",
98 "duplicate-link-label",
99 "bare-url",
100 "trailing-whitespace",
101 "inconsistent-list-marker",
102 "table-pipe-spacing",
103 "list-tightness-flipped",
104 "duplicate-heading",
105 "unicodeable-subscript",
106 "info-string-typo",
107 "stray-dollar",
108 "latex-command",
109 "escaped-emphasis",
110 "subscript-damage",
111];
112
113pub fn names() -> impl Iterator<Item = &'static str> {
117 NAMES.iter().copied()
118}
119
120fn all_boxed() -> Vec<Box<dyn LintRule>> {
123 vec![
124 Box::new(UnbalancedBacktick),
125 Box::new(MathUnbalancedDelim),
126 Box::new(MathUnbalancedEnv),
127 Box::new(MathUnbalancedBraces),
128 Box::new(RenderCompat::new()),
129 Box::new(AdjacentCodeNoSpace),
130 Box::new(HeadingPunctuation),
131 Box::new(OrphanReferenceLink),
132 Box::new(DuplicateLinkLabel),
133 Box::new(BareUrl),
134 Box::new(TrailingWhitespace),
135 Box::new(InconsistentListMarker),
136 Box::new(TablePipeSpacing),
137 Box::new(ListTightnessFlipped),
138 Box::new(DuplicateHeading),
139 Box::new(UnicodeableSubscript),
140 Box::new(InfoStringTypo::new()),
141 Box::new(StrayDollar),
142 Box::new(LatexCommand),
143 Box::new(EscapedEmphasis),
144 Box::new(SubscriptDamage),
145 ]
146}
147
148#[must_use]
150pub fn all() -> RuleSet {
151 let mut rs = RuleSet::new();
152 for rule in all_boxed() {
153 let _unused = rs.add(rule);
159 }
160 rs
161}
162
163#[must_use]
165pub fn defaults() -> RuleSet {
166 let mut rs = RuleSet::new();
167 for rule in all_boxed() {
168 if rule.is_default() {
169 let _unused = rs.add(rule);
172 }
173 }
174 rs
175}
176
177#[must_use]
181pub fn by_name(name: &str) -> Option<Box<dyn LintRule>> {
182 all_boxed().into_iter().find(|r| r.name() == name)
183}
184
185#[cfg(test)]
186mod tests {
187 use super::{all, by_name, defaults};
188
189 #[test]
190 fn defaults_excludes_opt_in() {
191 let rs = defaults();
192 assert!(rs.contains("unbalanced-backtick"));
193 assert!(rs.contains("heading-punctuation"));
194 assert!(!rs.contains("stray-dollar"));
195 assert!(!rs.contains("latex-command"));
196 assert!(!rs.contains("escaped-emphasis"));
197 assert!(!rs.contains("subscript-damage"));
198 }
199
200 #[test]
201 fn all_includes_everything() {
202 let rs = all();
203 assert!(rs.contains("stray-dollar"));
204 assert!(rs.contains("subscript-damage"));
205 assert!(rs.contains("math/unbalanced-delim"));
206 assert!(rs.contains("math/unbalanced-env"));
207 assert!(rs.contains("math/unbalanced-braces"));
208 assert!(rs.contains("math/render-compat"));
209 assert!(rs.contains("table-pipe-spacing"));
210 assert!(rs.len() == 21);
211 }
212
213 #[test]
214 fn by_name_known() {
215 assert!(by_name("unbalanced-backtick").is_some());
216 assert!(by_name("escaped-emphasis").is_some());
217 assert!(by_name("does-not-exist").is_none());
218 }
219
220 #[test]
221 fn names_match_all_boxed() {
222 let from_rules: std::collections::BTreeSet<String> =
223 super::all_boxed().iter().map(|r| r.name().to_owned()).collect();
224 let from_const: std::collections::BTreeSet<String> = super::NAMES.iter().map(|s| (*s).to_owned()).collect();
225 assert_eq!(from_rules, from_const, "stdlib::NAMES drift");
226 }
227}