mdlint/rules/
md012.rs

1use crate::parser::flatten_nodes_with_content;
2use crate::rules::extensions::VecExt;
3use crate::ruleset::{RuleResult, RuleResultDetails};
4use comrak::nodes::AstNode;
5
6pub(crate) fn check<'a>(root: &'a AstNode<'a>) -> RuleResult {
7    // multimple blanklines in code blocks should be valid
8    let mut details: Vec<RuleResultDetails> = Vec::new();
9    let nodes = flatten_nodes_with_content(root);
10    nodes.iter().enumerate().for_each(|(i, n)| {
11        if i == 0 {
12            return;
13        }
14        let curr = n.data.borrow();
15        let prev_end_line = nodes[i - 1].data.borrow().end_line;
16        let curr_start_line = curr.start_line;
17        if curr_start_line - prev_end_line > 2 {
18            details.push(RuleResultDetails::from_node(&curr));
19        }
20    });
21
22    RuleResult::new(
23        "MD012",
24        "no-multiple-blanks",
25        "Multiple consecutive blank lines",
26        details.to_option(),
27    )
28}
29
30#[cfg(test)]
31mod test {
32
33    use super::*;
34    use crate::parser::get_ast;
35    use crate::rules::common_tests;
36    use typed_arena::Arena;
37
38    #[test]
39    fn it_does_not_have_details_if_all_ok() {
40        common_tests::all_ok("fixtures/md012/md012_ok.md", Box::new(check));
41    }
42
43    #[test]
44    fn it_has_details_if_ko() {
45        let arena = Arena::new();
46        let root = get_ast("fixtures/md012/md012_ko.md", &arena);
47        let result = check(root);
48        assert!(result.details.is_some());
49        let details = result.details.unwrap();
50        assert_eq!(details.len(), 3);
51        let first = &details[0];
52        assert_eq!(first.line, 4);
53        assert_eq!(first.column, 1);
54        let second = &details[1];
55        assert_eq!(second.line, 9);
56        assert_eq!(second.column, 1);
57        assert_eq!(second.content, "This is another line\n");
58        let third = &details[2];
59        assert_eq!(third.line, 21);
60        assert_eq!(third.column, 3);
61        assert_eq!(third.content, "item two\n");
62    }
63}