mdl 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -2
  3. data/CHANGELOG.md +45 -0
  4. data/README.md +1 -0
  5. data/docs/RULES.md +116 -6
  6. data/docs/configuration.md +16 -1
  7. data/docs/creating_rules.md +7 -0
  8. data/lib/mdl.rb +26 -9
  9. data/lib/mdl/cli.rb +60 -9
  10. data/lib/mdl/doc.rb +5 -1
  11. data/lib/mdl/rules.rb +80 -6
  12. data/lib/mdl/ruleset.rb +16 -7
  13. data/lib/mdl/style.rb +6 -0
  14. data/lib/mdl/styles/default.rb +2 -1
  15. data/lib/mdl/styles/relaxed.rb +1 -0
  16. data/lib/mdl/version.rb +1 -1
  17. data/mdl.gemspec +1 -1
  18. data/test/fixtures/default_mdlrc +1 -0
  19. data/test/fixtures/dir_with_md_and_markdown/bar.markdown +1 -0
  20. data/test/fixtures/dir_with_md_and_markdown/foo.md +1 -0
  21. data/test/fixtures/mdlrc_disable_rules +1 -0
  22. data/test/fixtures/mdlrc_disable_tags +1 -0
  23. data/test/fixtures/mdlrc_enable_rules +1 -0
  24. data/test/fixtures/mdlrc_enable_tags +1 -0
  25. data/test/fixtures/my_ruleset.rb +6 -0
  26. data/test/rule_tests/blockquote_spaces.md +6 -4
  27. data/test/rule_tests/bulleted_list_2_space_indent_style.rb +1 -0
  28. data/test/rule_tests/code_block_dollar_fence.md +29 -0
  29. data/test/rule_tests/default_test_style.rb +4 -0
  30. data/test/rule_tests/fenced_code_with_nesting.md +73 -0
  31. data/test/rule_tests/fenced_code_without_blank_lines_style.rb +1 -0
  32. data/test/rule_tests/first_line_top_level_header_atx.md +3 -0
  33. data/test/rule_tests/first_line_top_level_header_atx_style.rb +2 -0
  34. data/test/rule_tests/first_line_top_level_header_setext.md +4 -0
  35. data/test/rule_tests/first_line_top_level_header_setext_style.rb +2 -0
  36. data/test/rule_tests/headers_good_setext_with_atx.md +7 -0
  37. data/test/rule_tests/headers_good_setext_with_atx_style.rb +2 -0
  38. data/test/rule_tests/hr_style_dashes_style.rb +1 -0
  39. data/test/rule_tests/hr_style_long_style.rb +1 -0
  40. data/test/rule_tests/hr_style_stars_style.rb +1 -0
  41. data/test/rule_tests/incorrect_bullet_style_asterisk_style.rb +1 -0
  42. data/test/rule_tests/incorrect_bullet_style_dash_style.rb +1 -0
  43. data/test/rule_tests/incorrect_bullet_style_plus_style.rb +1 -0
  44. data/test/rule_tests/long_lines_100_style.rb +1 -0
  45. data/test/rule_tests/long_lines_code.md +38 -0
  46. data/test/rule_tests/long_lines_code_style.rb +3 -0
  47. data/test/rule_tests/no_first_line_header.md +1 -0
  48. data/test/rule_tests/no_first_line_header_style.rb +1 -0
  49. data/test/rule_tests/no_first_line_top_level_header.md +1 -0
  50. data/test/rule_tests/no_first_line_top_level_header_style.rb +1 -0
  51. data/test/rule_tests/ordered_list_item_prefix_ordered_style.rb +1 -0
  52. data/test/rule_tests/spaces_after_list_marker_style.rb +1 -0
  53. data/test/rule_tests/trailing_spaces_br_style.rb +1 -0
  54. data/test/test_cli.rb +205 -0
  55. data/test/test_ruledocs.rb +8 -1
  56. data/test/test_rules.rb +4 -2
  57. metadata +55 -7
@@ -4,6 +4,7 @@ module MarkdownLint
4
4
 
5
5
  def initialize(id, description, block)
6
6
  @id, @description = id, description
7
+ @aliases = []
7
8
  @tags = []
8
9
  @params = {}
9
10
  instance_eval &block
@@ -20,28 +21,36 @@ module MarkdownLint
20
21
  @tags
21
22
  end
22
23
 
24
+ def aliases(*a)
25
+ @aliases.concat(a)
26
+ @aliases
27
+ end
28
+
23
29
  def params(p = nil)
24
30
  @params.update(p) unless p.nil?
25
31
  @params
26
32
  end
33
+
27
34
  end
28
35
 
29
36
  class RuleSet
30
37
  attr_reader :rules
31
38
 
39
+ def initialize
40
+ @rules = {}
41
+ end
42
+
32
43
  def rule(id, description, &block)
33
- @rules = {} if @rules.nil?
34
44
  @rules[id] = Rule.new(id, description, block)
35
45
  end
36
46
 
37
- def self.load_default
38
- self.load(File.expand_path("../rules.rb", __FILE__))
47
+ def load(rules_file)
48
+ instance_eval(File.read(rules_file), rules_file)
49
+ @rules
39
50
  end
40
51
 
41
- def self.load(rules_file)
42
- ruleset = new
43
- ruleset.instance_eval(File.read(rules_file), rules_file)
44
- ruleset.rules
52
+ def load_default
53
+ load(File.expand_path("../rules.rb", __FILE__))
45
54
  end
46
55
  end
47
56
  end
@@ -6,11 +6,15 @@ module MarkdownLint
6
6
 
7
7
  def initialize(all_rules)
8
8
  @tagged_rules = {}
9
+ @aliases = {}
9
10
  all_rules.each do |id, r|
10
11
  r.tags.each do |t|
11
12
  @tagged_rules[t] ||= Set.new
12
13
  @tagged_rules[t] << id
13
14
  end
15
+ r.aliases.each do |a|
16
+ @aliases[a] = id
17
+ end
14
18
  end
15
19
  @all_rules = all_rules
16
20
  @rules = Set.new
@@ -21,11 +25,13 @@ module MarkdownLint
21
25
  end
22
26
 
23
27
  def rule(id, params={})
28
+ id = @aliases[id] if @aliases[id]
24
29
  @rules << id
25
30
  @all_rules[id].params(params)
26
31
  end
27
32
 
28
33
  def exclude_rule(id)
34
+ id = @aliases[id] if @aliases[id]
29
35
  @rules.delete(id)
30
36
  end
31
37
 
@@ -1,3 +1,4 @@
1
1
  all
2
2
 
3
- exclude_rule 'MD040' # Fenced code blocks should have a language specified
3
+ exclude_rule 'fenced-code-language' # Fenced code blocks should have a language specified
4
+ exclude_rule 'first-line-h1' # First line in file should be a top level header
@@ -7,3 +7,4 @@ exclude_rule 'MD007' # List indentation
7
7
  exclude_rule 'MD033' # Inline HTML
8
8
  exclude_rule 'MD034' # Bare URL used
9
9
  exclude_rule 'MD040' # Fenced code blocks should have a language specified
10
+ exclude_rule 'MD041' # First line in file should be a top level header
@@ -1,3 +1,3 @@
1
1
  module MarkdownLint
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.required_ruby_version = '>= 1.9.2'
22
22
 
23
- spec.add_dependency 'kramdown', '~> 1.5', '>= 1.5.0'
23
+ spec.add_dependency 'kramdown', '~> 1.8', '>= 1.8.0'
24
24
  spec.add_dependency 'mixlib-config', '~> 2.1', '>= 2.1.0'
25
25
  spec.add_dependency 'mixlib-cli', '~> 1.5', '>= 1.5.0'
26
26
 
@@ -0,0 +1 @@
1
+ # Blank .mdlrc
@@ -0,0 +1 @@
1
+ ## Second Header First
@@ -0,0 +1 @@
1
+ ## Second Header First
@@ -0,0 +1 @@
1
+ rules "~MD001", "~MD002"
@@ -0,0 +1 @@
1
+ tags "ul", "~indentation"
@@ -0,0 +1 @@
1
+ rules "MD001", "MD002"
@@ -0,0 +1 @@
1
+ tags "headers", "whitespace"
@@ -0,0 +1,6 @@
1
+ rule "MY001", "Documents must start with Hello World" do
2
+ tags :opinionated
3
+ check do |doc|
4
+ [1] if doc.lines[0] != "Hello World"
5
+ end
6
+ end
@@ -10,12 +10,14 @@ This tests other things embedded in the blockquote:
10
10
  > *foo* {MD027}
11
11
  > **bar** {MD027}
12
12
  > "Baz" {MD027}
13
- > *foo*
14
- > **bar**
15
- > 'baz'
13
+ > `qux` {MD027}
14
+ > *foo* more text
15
+ > **bar** more text
16
+ > 'baz' more text
17
+ > `qux` more text
16
18
 
17
19
  Test the first line being indented too much:
18
20
 
19
21
  > Foo {MD027}
20
22
  > Bar {MD027}
21
- > Baz
23
+ > Baz
@@ -1,2 +1,3 @@
1
1
  all
2
2
  rule 'MD007', :indent => 4
3
+ exclude_rule "MD041"
@@ -0,0 +1,29 @@
1
+ # header
2
+
3
+ ```fence
4
+ $ code
5
+ ```
6
+
7
+ text
8
+
9
+ ```fence
10
+ $ code
11
+ ```
12
+
13
+ text
14
+
15
+ ```fence
16
+ $ code
17
+ $ code
18
+ ```
19
+
20
+ text
21
+
22
+ ```fence
23
+ $ code
24
+ $ code
25
+ ```
26
+
27
+ text
28
+
29
+ {MD014:3} {MD014:9} {MD014:15} {MD014:22}
@@ -0,0 +1,4 @@
1
+ # Default style file for rule tests
2
+ all
3
+
4
+ exclude_rule "MD041"
@@ -0,0 +1,73 @@
1
+ # header
2
+
3
+ text
4
+ ```fence {MD031}
5
+ code
6
+ ``` {MD031}
7
+ text
8
+ ~~~fence {MD031}
9
+ code
10
+ ~~~ {MD031}
11
+ text
12
+ ```fence {MD031}
13
+ ~~~fence
14
+ code
15
+ ~~~
16
+ ``` {MD031}
17
+ text
18
+ ~~~fence {MD031}
19
+ ```fence
20
+ code
21
+ ```
22
+ ~~~ {MD031}
23
+ text
24
+ ```fence {MD031}
25
+
26
+ ~~~fence
27
+ code
28
+ ~~~
29
+
30
+ ``` {MD031}
31
+ text
32
+ ~~~fence {MD031}
33
+
34
+ ```fence
35
+ code
36
+ ```
37
+
38
+ ~~~ {MD031}
39
+ text
40
+ ```fence {MD031}
41
+ code
42
+ ~~~
43
+ ``` {MD031}
44
+ text
45
+ ~~~fence {MD031}
46
+ code
47
+ ```
48
+ ~~~ {MD031}
49
+ text
50
+ ````fence {MD031}
51
+ ```fence
52
+ code
53
+ ```
54
+ ```` {MD031}
55
+ text
56
+ ~~~~fence {MD031}
57
+ ~~~fence
58
+ code
59
+ ~~~
60
+ ~~~~ {MD031}
61
+ text
62
+ ````fence {MD031}
63
+ ```fence
64
+ code
65
+ ```
66
+ ````` {MD031}
67
+ text
68
+ ~~~~fence {MD031}
69
+ ~~~fence
70
+ code
71
+ ~~~
72
+ ~~~~~ {MD031}
73
+ text
@@ -1,2 +1,3 @@
1
1
  all
2
2
  exclude_rule "MD040"
3
+ exclude_rule "MD041"
@@ -0,0 +1,3 @@
1
+ # First line is a top level header
2
+
3
+ This shouldn't trigger MD041
@@ -0,0 +1,2 @@
1
+ # Only test MD041 here
2
+ rule "MD041"
@@ -0,0 +1,4 @@
1
+ First line top level header
2
+ ===========================
3
+
4
+ This shouldn't trigger MD041
@@ -0,0 +1,2 @@
1
+ # Only test MD041 here
2
+ rule "MD041"
@@ -0,0 +1,7 @@
1
+ Header 1
2
+ ========
3
+
4
+ Header 2
5
+ --------
6
+
7
+ ### Header 3
@@ -0,0 +1,2 @@
1
+ all
2
+ rule 'MD003', :style => :setext_with_atx
@@ -1,2 +1,3 @@
1
1
  all
2
2
  rule "MD035", :style => "---"
3
+ exclude_rule "MD041"
@@ -1,2 +1,3 @@
1
1
  all
2
2
  rule "MD035", :style => "_____"
3
+ exclude_rule "MD041"
@@ -1,2 +1,3 @@
1
1
  all
2
2
  rule "MD035", :style => "***"
3
+ exclude_rule "MD041"
@@ -1,2 +1,3 @@
1
1
  all
2
2
  rule 'MD004', :style => :asterisk
3
+ exclude_rule "MD041"
@@ -1,2 +1,3 @@
1
1
  all
2
2
  rule 'MD004', :style => :dash
3
+ exclude_rule "MD041"
@@ -1,2 +1,3 @@
1
1
  all
2
2
  rule 'MD004', :style => :plus
3
+ exclude_rule "MD041"
@@ -1,2 +1,3 @@
1
1
  all
2
2
  rule 'MD013', :line_length => 100
3
+ exclude_rule "MD041"
@@ -0,0 +1,38 @@
1
+ This is a short line.
2
+
3
+ This is a very very very very very very very very very very very very very very very very very very very very long line. {MD013}
4
+
5
+ This is a short line.
6
+
7
+ ```text
8
+ Here is a short line in a code block.
9
+ Here is a very very very very very very very very very very very very very very very very very very very long line in a code block.
10
+ ```
11
+
12
+ This is a short line.
13
+
14
+ | First Header | Second Header | Third Header | Fourth Header | Fifth Header | Sixth Header |
15
+ | ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |
16
+ | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell |
17
+ | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell |
18
+ | ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |
19
+ | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell |
20
+ | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell |
21
+ | ============= | ============= | ============= | ============= | ============= | ============= |
22
+ | Footer Cell | Footer Cell | Footer Cell | Footer Cell | Footer Cell | Footer Cell |
23
+ {: rules="groups"}
24
+
25
+ This is a very very very very very very very very very very very very very very very very very very very very long line. {MD013}
26
+
27
+ Another line.
28
+
29
+ | First Header | Second Header | Third Header | Fourth Header | Fifth Header | Sixth Header |
30
+ | ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |
31
+ | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell |
32
+ | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell |
33
+ | ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |
34
+ | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell |
35
+ | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell | Content Cell |
36
+ | ============= | ============= | ============= | ============= | ============= | ============= |
37
+ | Footer Cell | Footer Cell | Footer Cell | Footer Cell | Footer Cell | Footer Cell |
38
+ {: rules="groups"}
@@ -0,0 +1,3 @@
1
+ all
2
+ rule 'MD013', :code_blocks => false, :tables => false
3
+ exclude_rule "MD041"
@@ -0,0 +1 @@
1
+ This is a file without a top level header {MD041}
@@ -0,0 +1 @@
1
+ ## Second level header {MD041} {MD002}
@@ -1,2 +1,3 @@
1
1
  all
2
2
  rule 'MD029', :style => :ordered
3
+ exclude_rule 'MD041'
@@ -1,3 +1,4 @@
1
1
  all
2
2
  rule "MD007", :indent => 4
3
3
  rule "MD030", :ul_multi => 3, :ol_multi => 2
4
+ exclude_rule "MD041"
@@ -1,2 +1,3 @@
1
1
  all
2
2
  rule 'MD009', :br_spaces => 2
3
+ exclude_rule "MD041"
@@ -0,0 +1,205 @@
1
+ require_relative 'setup_tests'
2
+ require 'open3'
3
+ require 'set'
4
+
5
+ class TestCli < Minitest::Test
6
+ def run_cli(args, stdin = "", mdlrc="default_mdlrc")
7
+ mdl_script = File.expand_path("../../bin/mdl", __FILE__)
8
+ # Load the mdlrc file from the text/fixtures/ directory
9
+ mdlrc = File.expand_path("../fixtures/#{mdlrc}", __FILE__)
10
+ result = {}
11
+ result[:stdout], result[:stderr], result[:status] = \
12
+ Open3.capture3(*(%W{bundle exec #{mdl_script} -c #{mdlrc}} + args.split),
13
+ :stdin_data => stdin)
14
+ result[:status] = result[:status].exitstatus
15
+ result
16
+ end
17
+
18
+ def assert_rules_enabled(result, rules, only_these_rules=false)
19
+ # Asserts that the given rules are enabled given the output of mdl -l
20
+ # If only_these_rules is set, then it asserts that the given rules and no
21
+ # others are enabled.
22
+ lines = result[:stdout].split("\n")
23
+ assert_equal("Enabled rules:", lines.first)
24
+ lines.shift
25
+ rules = rules.to_set
26
+ enabled_rules = lines.map{ |l| l.split(" ").first }.to_set
27
+ if only_these_rules
28
+ assert_equal(rules, enabled_rules)
29
+ else
30
+ assert_equal(Set.new, rules - enabled_rules)
31
+ end
32
+ end
33
+
34
+ def assert_rules_disabled(result, rules)
35
+ # Asserts that the given rules are _not_ enabled given the output of mdl -l
36
+ lines = result[:stdout].split("\n")
37
+ assert_equal("Enabled rules:", lines.first)
38
+ lines.shift
39
+ rules = rules.to_set
40
+ enabled_rules = lines.map{ |l| l.split(" ").first }.to_set
41
+ assert_equal(Set.new, rules & enabled_rules)
42
+ end
43
+
44
+ def assert_ran_ok(result)
45
+ assert_equal(0, result[:status])
46
+ assert_equal("", result[:stderr])
47
+ end
48
+
49
+ def test_help_text
50
+ result = run_cli("--help")
51
+ assert_match(/Usage: \S+ \[options\]/, result[:stdout])
52
+ assert_equal(0, result[:status])
53
+ end
54
+
55
+ def test_default_ruleset_loading
56
+ result = run_cli("-l")
57
+ assert_ran_ok(result)
58
+ assert_rules_enabled(result, ["MD001"])
59
+ end
60
+
61
+ def test_show_alias_rule_list
62
+ result = run_cli("-al")
63
+ assert_ran_ok(result)
64
+ assert_rules_enabled(result, ["header-increment"])
65
+ end
66
+
67
+ def test_show_alias_processing_file
68
+ result = run_cli("-a -r MD002", "## header2")
69
+ assert_equal(1, result[:status])
70
+ assert_equal("", result[:stderr])
71
+ assert_match(/^\(stdin\):1: first-header-h1/, result[:stdout])
72
+ end
73
+
74
+ def test_skipping_default_ruleset_loading
75
+ result = run_cli("-ld")
76
+ assert_rules_enabled(result, [], true)
77
+ end
78
+
79
+ def test_custom_ruleset_loading
80
+ my_ruleset = File.expand_path("../fixtures/my_ruleset.rb", __FILE__)
81
+ result = run_cli("-ldu #{my_ruleset}")
82
+ assert_rules_enabled(result, ["MY001"], true)
83
+ assert_ran_ok(result)
84
+ end
85
+
86
+ def test_show_alias_rule_without_alias
87
+ # Tests that when -a is given, but the rule doesn't have an alias, it
88
+ # prints the rule ID instead.
89
+ my_ruleset = File.expand_path("../fixtures/my_ruleset.rb", __FILE__)
90
+ result = run_cli("-ladu #{my_ruleset}")
91
+ assert_rules_enabled(result, ["MY001"], true)
92
+ assert_ran_ok(result)
93
+ end
94
+
95
+ def test_custom_ruleset_processing_success
96
+ my_ruleset = File.expand_path("../fixtures/my_ruleset.rb", __FILE__)
97
+ result = run_cli("-du #{my_ruleset}", "Hello World")
98
+ assert_equal("", result[:stdout])
99
+ assert_ran_ok(result)
100
+ end
101
+
102
+ def test_custom_ruleset_processing_failure
103
+ my_ruleset = File.expand_path("../fixtures/my_ruleset.rb", __FILE__)
104
+ result = run_cli("-du #{my_ruleset}", "Goodbye world")
105
+ assert_equal(1, result[:status])
106
+ assert_match(/^\(stdin\):1: MY001/, result[:stdout])
107
+ assert_equal("", result[:stderr])
108
+ end
109
+
110
+ def test_custom_ruleset_processing_failure_with_show_alias
111
+ # The custom rule doesn't have an alias, so the output should be identical
112
+ # to that without show_alias enabled.
113
+ my_ruleset = File.expand_path("../fixtures/my_ruleset.rb", __FILE__)
114
+ result = run_cli("-dau #{my_ruleset}", "Goodbye world")
115
+ assert_equal(1, result[:status])
116
+ assert_match(/^\(stdin\):1: MY001/, result[:stdout])
117
+ assert_equal("", result[:stderr])
118
+ end
119
+
120
+ def test_custom_ruleset_loading_with_default
121
+ my_ruleset = File.expand_path("../fixtures/my_ruleset.rb", __FILE__)
122
+ result = run_cli("-lu #{my_ruleset}")
123
+ assert_rules_enabled(result, ["MD001", "MY001"])
124
+ assert_ran_ok(result)
125
+ end
126
+
127
+ def test_rule_inclusion_cli
128
+ result = run_cli("-r MD001 -l")
129
+ assert_rules_enabled(result, ["MD001"], true)
130
+ assert_ran_ok(result)
131
+ end
132
+
133
+ def test_rule_exclusion_cli
134
+ result = run_cli("-r ~MD001 -l")
135
+ assert_rules_disabled(result, ["MD001"])
136
+ assert_ran_ok(result)
137
+ end
138
+
139
+ def test_rule_inclusion_with_exclusion_cli
140
+ result = run_cli("-r ~MD001,MD039 -l")
141
+ assert_rules_enabled(result, ["MD039"], true)
142
+ assert_ran_ok(result)
143
+ end
144
+
145
+ def test_tag_inclusion_cli
146
+ result = run_cli("-t headers -l")
147
+ assert_rules_enabled(result, ["MD001", "MD002", "MD003"])
148
+ assert_rules_disabled(result, ["MD004", "MD005", "MD006"])
149
+ assert_ran_ok(result)
150
+ end
151
+
152
+ def test_tag_exclusion_cli
153
+ result = run_cli("-t ~headers -l")
154
+ assert_ran_ok(result)
155
+ assert_rules_disabled(result, ["MD001", "MD002", "MD003"])
156
+ assert_rules_enabled(result, ["MD004", "MD005", "MD006"])
157
+ end
158
+
159
+ def test_rule_inclusion_config
160
+ result = run_cli("-l", "", "mdlrc_enable_rules")
161
+ assert_ran_ok(result)
162
+ assert_rules_enabled(result, ["MD001", "MD002"], true)
163
+ end
164
+
165
+ def test_rule_exclusion_config
166
+ result = run_cli("-l", "", "mdlrc_disable_rules")
167
+ assert_ran_ok(result)
168
+ assert_rules_disabled(result, ["MD001", "MD002"])
169
+ assert_rules_enabled(result, ["MD003", "MD004"])
170
+ end
171
+
172
+ def test_tag_inclusion_config
173
+ result = run_cli("-l", "", "mdlrc_enable_tags")
174
+ assert_ran_ok(result)
175
+ assert_rules_enabled(result, ["MD001", "MD002", "MD009", "MD010"])
176
+ assert_rules_disabled(result, ["MD004", "MD005"])
177
+ end
178
+
179
+ def test_tag_exclusion_config
180
+ result = run_cli("-l", "", "mdlrc_disable_tags")
181
+ assert_ran_ok(result)
182
+ assert_rules_enabled(result, ["MD004", "MD030", "MD032"])
183
+ assert_rules_disabled(result, ["MD001", "MD005"])
184
+ end
185
+
186
+ def test_rule_inclusion_alias_cli
187
+ result = run_cli("-l -r header-increment")
188
+ assert_ran_ok(result)
189
+ assert_rules_enabled(result, ["MD001"], true)
190
+ end
191
+
192
+ def test_rule_exclusion_alias_cli
193
+ result = run_cli("-l -r ~header-increment")
194
+ assert_ran_ok(result)
195
+ assert_rules_disabled(result, ["MD001"])
196
+ assert_rules_enabled(result, ["MD002"])
197
+ end
198
+
199
+ def test_directory_scanning
200
+ path = File.expand_path("./fixtures/dir_with_md_and_markdown", File.dirname(__FILE__))
201
+ result = run_cli("#{path}")
202
+ files_with_issues = result[:stdout].split("\n").map { |l| l.split(":")[0] }.sort
203
+ assert_equal(files_with_issues, ["#{path}/bar.markdown", "#{path}/foo.md"])
204
+ end
205
+ end