mdl 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,8 +5,8 @@ require 'kramdown/parser/gfm'
5
5
 
6
6
  module Kramdown
7
7
  module Parser
8
+ # modified parser class - see comment above
8
9
  class MarkdownLint < Kramdown::Parser::Kramdown
9
-
10
10
  def initialize(source, options)
11
11
  super
12
12
  i = @block_parsers.index(:codeblock_fenced)
@@ -1,4 +1,4 @@
1
- rule "MD001", "Header levels should only increment by one level at a time" do
1
+ rule 'MD001', 'Header levels should only increment by one level at a time' do
2
2
  tags :headers
3
3
  aliases 'header-increment'
4
4
  check do |doc|
@@ -6,26 +6,26 @@ rule "MD001", "Header levels should only increment by one level at a time" do
6
6
  old_level = nil
7
7
  errors = []
8
8
  headers.each do |h|
9
- if old_level and h[:level] > old_level + 1
10
- errors << h[:location]
11
- end
9
+ errors << h[:location] if old_level && (h[:level] > old_level + 1)
12
10
  old_level = h[:level]
13
11
  end
14
12
  errors
15
13
  end
16
14
  end
17
15
 
18
- rule "MD002", "First header should be a top level header" do
16
+ rule 'MD002', 'First header should be a top level header' do
19
17
  tags :headers
20
18
  aliases 'first-header-h1'
21
19
  params :level => 1
22
20
  check do |doc|
23
21
  first_header = doc.find_type(:header).first
24
- [first_header[:location]] if first_header and first_header[:level] != @params[:level]
22
+ if first_header && (first_header[:level] != @params[:level])
23
+ [first_header[:location]]
24
+ end
25
25
  end
26
26
  end
27
27
 
28
- rule "MD003", "Header style" do
28
+ rule 'MD003', 'Header style' do
29
29
  # Header styles are things like ### and adding underscores
30
30
  # See http://daringfireball.net/projects/markdown/syntax#header
31
31
  tags :headers
@@ -37,47 +37,54 @@ rule "MD003", "Header style" do
37
37
  if headers.empty?
38
38
  nil
39
39
  else
40
- if @params[:style] == :consistent
41
- doc_style = doc.header_style(headers.first)
42
- else
43
- doc_style = @params[:style]
44
- end
40
+ doc_style = if @params[:style] == :consistent
41
+ doc.header_style(headers.first)
42
+ else
43
+ @params[:style]
44
+ end
45
45
  if doc_style == :setext_with_atx
46
- headers.map { |h| doc.element_linenumber(h) \
47
- unless doc.header_style(h) == :setext or \
48
- (doc.header_style(h) == :atx and \
49
- h.options[:level] > 2) }.compact
46
+ headers.map do |h|
47
+ doc.element_linenumber(h) \
48
+ unless (doc.header_style(h) == :setext) || \
49
+ ((doc.header_style(h) == :atx) && \
50
+ (h.options[:level] > 2))
51
+ end.compact
50
52
  else
51
- headers.map { |h| doc.element_linenumber(h) \
52
- if doc.header_style(h) != doc_style }.compact
53
+ headers.map do |h|
54
+ doc.element_linenumber(h) \
55
+ if doc.header_style(h) != doc_style
56
+ end.compact
53
57
  end
54
58
  end
55
59
  end
56
60
  end
57
61
 
58
- rule "MD004", "Unordered list style" do
62
+ rule 'MD004', 'Unordered list style' do
59
63
  tags :bullet, :ul
60
64
  aliases 'ul-style'
61
65
  # :style can be one of :consistent, :asterisk, :plus, :dash
62
66
  params :style => :consistent
63
67
  check do |doc|
64
- bullets = doc.find_type_elements(:ul).map {|l|
65
- doc.find_type_elements(:li, false, l.children)}.flatten
68
+ bullets = doc.find_type_elements(:ul).map do |l|
69
+ doc.find_type_elements(:li, false, l.children)
70
+ end.flatten
66
71
  if bullets.empty?
67
72
  nil
68
73
  else
69
- if @params[:style] == :consistent
70
- doc_style = doc.list_style(bullets.first)
71
- else
72
- doc_style = @params[:style]
73
- end
74
- bullets.map { |b| doc.element_linenumber(b) \
75
- if doc.list_style(b) != doc_style }.compact
74
+ doc_style = if @params[:style] == :consistent
75
+ doc.list_style(bullets.first)
76
+ else
77
+ @params[:style]
78
+ end
79
+ bullets.map do |b|
80
+ doc.element_linenumber(b) \
81
+ if doc.list_style(b) != doc_style
82
+ end.compact
76
83
  end
77
84
  end
78
85
  end
79
86
 
80
- rule "MD005", "Inconsistent indentation for list items at the same level" do
87
+ rule 'MD005', 'Inconsistent indentation for list items at the same level' do
81
88
  tags :bullet, :ul, :indentation
82
89
  aliases 'list-indent'
83
90
  check do |doc|
@@ -97,29 +104,30 @@ rule "MD005", "Inconsistent indentation for list items at the same level" do
97
104
  end
98
105
  end
99
106
 
100
- rule "MD006", "Consider starting bulleted lists at the beginning of the line" do
107
+ rule 'MD006', 'Consider starting bulleted lists at the beginning of the line' do
101
108
  # Starting at the beginning of the line means that indendation for each
102
109
  # bullet level can be identical.
103
110
  tags :bullet, :ul, :indentation
104
111
  aliases 'ul-start-left'
105
112
  check do |doc|
106
- doc.find_type(:ul, false).select{
107
- |e| doc.indent_for(doc.element_line(e)) != 0 }.map{ |e| e[:location] }
113
+ doc.find_type(:ul, false).reject do |e|
114
+ doc.indent_for(doc.element_line(e)) == 0
115
+ end.map { |e| e[:location] }
108
116
  end
109
117
  end
110
118
 
111
- rule "MD007", "Unordered list indentation" do
119
+ rule 'MD007', 'Unordered list indentation' do
112
120
  tags :bullet, :ul, :indentation
113
121
  aliases 'ul-indent'
114
122
  params :indent => 2
115
123
  check do |doc|
116
- indents = []
117
124
  errors = []
118
- indents = doc.find_type(:ul).map {
119
- |e| [doc.indent_for(doc.element_line(e)), doc.element_linenumber(e)] }
125
+ indents = doc.find_type(:ul).map do |e|
126
+ [doc.indent_for(doc.element_line(e)), doc.element_linenumber(e)]
127
+ end
120
128
  curr_indent = indents[0][0] unless indents.empty?
121
129
  indents.each do |indent, linenum|
122
- if indent > curr_indent and indent - curr_indent != @params[:indent]
130
+ if (indent > curr_indent) && (indent - curr_indent != @params[:indent])
123
131
  errors << linenum
124
132
  end
125
133
  curr_indent = indent
@@ -128,7 +136,7 @@ rule "MD007", "Unordered list indentation" do
128
136
  end
129
137
  end
130
138
 
131
- rule "MD009", "Trailing spaces" do
139
+ rule 'MD009', 'Trailing spaces' do
132
140
  tags :whitespace
133
141
  aliases 'no-trailing-spaces'
134
142
  params :br_spaces => 0
@@ -141,7 +149,7 @@ rule "MD009", "Trailing spaces" do
141
149
  end
142
150
  end
143
151
 
144
- rule "MD010", "Hard tabs" do
152
+ rule 'MD010', 'Hard tabs' do
145
153
  tags :whitespace, :hard_tab
146
154
  aliases 'no-hard-tabs'
147
155
  check do |doc|
@@ -149,7 +157,7 @@ rule "MD010", "Hard tabs" do
149
157
  end
150
158
  end
151
159
 
152
- rule "MD011", "Reversed link syntax" do
160
+ rule 'MD011', 'Reversed link syntax' do
153
161
  tags :links
154
162
  aliases 'no-reversed-links'
155
163
  check do |doc|
@@ -157,39 +165,47 @@ rule "MD011", "Reversed link syntax" do
157
165
  end
158
166
  end
159
167
 
160
- rule "MD012", "Multiple consecutive blank lines" do
168
+ rule 'MD012', 'Multiple consecutive blank lines' do
161
169
  tags :whitespace, :blank_lines
162
170
  aliases 'no-multiple-blanks'
163
171
  check do |doc|
164
172
  # Every line in the document that is part of a code block. Blank lines
165
173
  # inside of a code block are acceptable.
166
- codeblock_lines = doc.find_type_elements(:codeblock).map{
167
- |e| (doc.element_linenumber(e)..
168
- doc.element_linenumber(e) + e.value.lines.count).to_a }.flatten
174
+ codeblock_lines = doc.find_type_elements(:codeblock).map do |e|
175
+ (doc.element_linenumber(e)..
176
+ doc.element_linenumber(e) + e.value.lines.count).to_a
177
+ end.flatten
169
178
  blank_lines = doc.matching_lines(/^\s*$/)
170
- cons_blank_lines = blank_lines.each_cons(2).select{
171
- |p, n| n - p == 1}.map{|p, n| n}
179
+ cons_blank_lines = blank_lines.each_cons(2).select do |p, n|
180
+ n - p == 1
181
+ end.map { |_p, n| n }
172
182
  cons_blank_lines - codeblock_lines
173
183
  end
174
184
  end
175
185
 
176
- rule "MD013", "Line length" do
186
+ rule 'MD013', 'Line length' do
177
187
  tags :line_length
178
188
  aliases 'line-length'
179
189
  params :line_length => 80, :code_blocks => true, :tables => true
180
190
  check do |doc|
181
191
  # Every line in the document that is part of a code block.
182
- codeblock_lines = doc.find_type_elements(:codeblock).map{
183
- |e| (doc.element_linenumber(e)..
184
- doc.element_linenumber(e) + e.value.lines.count).to_a }.flatten
192
+ codeblock_lines = doc.find_type_elements(:codeblock).map do |e|
193
+ (doc.element_linenumber(e)..
194
+ doc.element_linenumber(e) + e.value.lines.count).to_a
195
+ end.flatten
185
196
  # Every line in the document that is part of a table.
186
197
  locations = doc.elements
187
- .map { |e| [e.options[:location], e] }
188
- .reject { |l, _| l.nil? }
189
- table_lines = locations.map.with_index {
190
- |(l, e), i| (i + 1 < locations.size ?
191
- (l..locations[i+1].first - 1) :
192
- (l..doc.lines.count)).to_a if e.type == :table }.flatten
198
+ .map { |e| [e.options[:location], e] }
199
+ .reject { |l, _| l.nil? }
200
+ table_lines = locations.map.with_index do |(l, e), i|
201
+ if e.type == :table
202
+ if i + 1 < locations.size
203
+ (l..locations[i + 1].first - 1).to_a
204
+ else
205
+ (l..doc.lines.count).to_a
206
+ end
207
+ end
208
+ end.flatten
193
209
  overlines = doc.matching_lines(/^.{#{@params[:line_length]}}.*\s/)
194
210
  overlines -= codeblock_lines unless params[:code_blocks]
195
211
  overlines -= table_lines unless params[:tables]
@@ -197,18 +213,18 @@ rule "MD013", "Line length" do
197
213
  end
198
214
  end
199
215
 
200
- rule "MD014", "Dollar signs used before commands without showing output" do
216
+ rule 'MD014', 'Dollar signs used before commands without showing output' do
201
217
  tags :code
202
218
  aliases 'commands-show-output'
203
219
  check do |doc|
204
- doc.find_type_elements(:codeblock).select{
205
- |e| not e.value.empty? and
206
- not e.value.split(/\n+/).map{|l| l.match(/^\$\s/)}.include?(nil)
207
- }.map{|e| doc.element_linenumber(e)}
220
+ doc.find_type_elements(:codeblock).select do |e|
221
+ !e.value.empty? and
222
+ !e.value.split(/\n+/).map { |l| l.match(/^\$\s/) }.include?(nil)
223
+ end.map { |e| doc.element_linenumber(e) }
208
224
  end
209
225
  end
210
226
 
211
- rule "MD018", "No space after hash on atx style header" do
227
+ rule 'MD018', 'No space after hash on atx style header' do
212
228
  tags :headers, :atx, :spaces
213
229
  aliases 'no-missing-space-atx'
214
230
  check do |doc|
@@ -218,7 +234,7 @@ rule "MD018", "No space after hash on atx style header" do
218
234
  end
219
235
  end
220
236
 
221
- rule "MD019", "Multiple spaces after hash on atx style header" do
237
+ rule 'MD019', 'Multiple spaces after hash on atx style header' do
222
238
  tags :headers, :atx, :spaces
223
239
  aliases 'no-multiple-space-atx'
224
240
  check do |doc|
@@ -228,7 +244,7 @@ rule "MD019", "Multiple spaces after hash on atx style header" do
228
244
  end
229
245
  end
230
246
 
231
- rule "MD020", "No space inside hashes on closed atx style header" do
247
+ rule 'MD020', 'No space inside hashes on closed atx style header' do
232
248
  tags :headers, :atx_closed, :spaces
233
249
  aliases 'no-missing-space-closed-atx'
234
250
  check do |doc|
@@ -240,7 +256,7 @@ rule "MD020", "No space inside hashes on closed atx style header" do
240
256
  end
241
257
  end
242
258
 
243
- rule "MD021", "Multiple spaces inside hashes on closed atx style header" do
259
+ rule 'MD021', 'Multiple spaces inside hashes on closed atx style header' do
244
260
  tags :headers, :atx_closed, :spaces
245
261
  aliases 'no-multiple-space-closed-atx'
246
262
  check do |doc|
@@ -252,7 +268,7 @@ rule "MD021", "Multiple spaces inside hashes on closed atx style header" do
252
268
  end
253
269
  end
254
270
 
255
- rule "MD022", "Headers should be surrounded by blank lines" do
271
+ rule 'MD022', 'Headers should be surrounded by blank lines' do
256
272
  tags :headers, :blank_lines
257
273
  aliases 'blanks-around-headers'
258
274
  check do |doc|
@@ -261,13 +277,11 @@ rule "MD022", "Headers should be surrounded by blank lines" do
261
277
  header_bad = false
262
278
  linenum = doc.element_linenumber(h)
263
279
  # Check previous line
264
- if linenum > 1 and not doc.lines[linenum - 2].empty?
265
- header_bad = true
266
- end
280
+ header_bad = true if (linenum > 1) && !doc.lines[linenum - 2].empty?
267
281
  # Check next line
268
282
  next_line_idx = doc.header_style(h) == :setext ? linenum + 1 : linenum
269
283
  next_line = doc.lines[next_line_idx]
270
- header_bad = true if not next_line.nil? and not next_line.empty?
284
+ header_bad = true if !next_line.nil? && !next_line.empty?
271
285
  errors << linenum if header_bad
272
286
  end
273
287
  # Kramdown requires that headers start on a block boundary, so in most
@@ -275,16 +289,14 @@ rule "MD022", "Headers should be surrounded by blank lines" do
275
289
  # to check regular text and pick out headers ourselves too
276
290
  doc.find_type_elements(:p, false).each do |p|
277
291
  linenum = doc.element_linenumber(p)
278
- text = p.children.select { |e| e.type == :text }.map {|e| e.value }.join
292
+ text = p.children.select { |e| e.type == :text }.map(&:value).join
279
293
  lines = text.split("\n")
280
- prev_lines = ["", ""]
294
+ prev_lines = ['', '']
281
295
  lines.each do |line|
282
296
  # First look for ATX style headers without blank lines before
283
- if line.match(/^\#{1,6}/) and not prev_lines[1].empty?
284
- errors << linenum
285
- end
297
+ errors << linenum if line.match(/^\#{1,6}/) && !prev_lines[1].empty?
286
298
  # Next, look for setext style
287
- if line.match(/^(-+|=+)\s*$/) and not prev_lines[0].empty?
299
+ if line.match(/^(-+|=+)\s*$/) && !prev_lines[0].empty?
288
300
  errors << linenum - 1
289
301
  end
290
302
  linenum += 1
@@ -296,7 +308,7 @@ rule "MD022", "Headers should be surrounded by blank lines" do
296
308
  end
297
309
  end
298
310
 
299
- rule "MD023", "Headers must start at the beginning of the line" do
311
+ rule 'MD023', 'Headers must start at the beginning of the line' do
300
312
  tags :headers, :spaces
301
313
  aliases 'header-start-left'
302
314
  check do |doc|
@@ -311,14 +323,12 @@ rule "MD023", "Headers must start at the beginning of the line" do
311
323
  doc.find_type_elements(:p, false).each do |p|
312
324
  linenum = doc.element_linenumber(p)
313
325
  lines = doc.extract_text(p)
314
- prev_line = ""
326
+ prev_line = ''
315
327
  lines.each do |line|
316
328
  # First look for ATX style headers
317
- if line.match(/^\s+\#{1,6}/)
318
- errors << linenum
319
- end
329
+ errors << linenum if line.match(/^\s+\#{1,6}/)
320
330
  # Next, look for setext style
321
- if line.match(/^\s+(-+|=+)\s*$/) and not prev_line.empty?
331
+ if line.match(/^\s+(-+|=+)\s*$/) && !prev_line.empty?
322
332
  errors << linenum - 1
323
333
  end
324
334
  linenum += 1
@@ -329,7 +339,7 @@ rule "MD023", "Headers must start at the beginning of the line" do
329
339
  end
330
340
  end
331
341
 
332
- rule "MD024", "Multiple headers with the same content" do
342
+ rule 'MD024', 'Multiple headers with the same content' do
333
343
  tags :headers
334
344
  aliases 'no-duplicate-header'
335
345
  params :allow_different_nesting => false
@@ -357,8 +367,8 @@ rule "MD024", "Multiple headers with the same content" do
357
367
  stack.pop
358
368
  elsif current_level < level
359
369
  stack.push([text])
360
- else
361
- same_nesting_duplicates.add(header) if stack.last.include?(text)
370
+ elsif stack.last.include?(text)
371
+ same_nesting_duplicates.add(header)
362
372
  end
363
373
 
364
374
  current_level = level
@@ -371,30 +381,34 @@ rule "MD024", "Multiple headers with the same content" do
371
381
  end
372
382
  end
373
383
 
374
- rule "MD025", "Multiple top level headers in the same document" do
384
+ rule 'MD025', 'Multiple top level headers in the same document' do
375
385
  tags :headers
376
386
  aliases 'single-h1'
377
387
  params :level => 1
378
388
  check do |doc|
379
- headers = doc.find_type(:header, false).select { |h| h[:level] == params[:level] }
380
- if not headers.empty? and doc.element_linenumber(headers[0]) == 1
389
+ headers = doc.find_type(:header, false).select do |h|
390
+ h[:level] == params[:level]
391
+ end
392
+ if !headers.empty? && (doc.element_linenumber(headers[0]) == 1)
381
393
  headers[1..-1].map { |h| doc.element_linenumber(h) }
382
394
  end
383
395
  end
384
396
  end
385
397
 
386
- rule "MD026", "Trailing punctuation in header" do
398
+ rule 'MD026', 'Trailing punctuation in header' do
387
399
  tags :headers
388
400
  aliases 'no-trailing-punctuation'
389
401
  params :punctuation => '.,;:!?'
390
402
  check do |doc|
391
- doc.find_type(:header).select {
392
- |h| h[:raw_text].match(/[#{params[:punctuation]}]$/) }.map {
393
- |h| doc.element_linenumber(h) }
403
+ doc.find_type(:header).select do |h|
404
+ h[:raw_text].match(/[#{params[:punctuation]}]$/)
405
+ end.map do |h|
406
+ doc.element_linenumber(h)
407
+ end
394
408
  end
395
409
  end
396
410
 
397
- rule "MD027", "Multiple spaces after blockquote symbol" do
411
+ rule 'MD027', 'Multiple spaces after blockquote symbol' do
398
412
  tags :blockquote, :whitespace, :indentation
399
413
  aliases 'no-multiple-space-blockquote'
400
414
  check do |doc|
@@ -403,7 +417,7 @@ rule "MD027", "Multiple spaces after blockquote symbol" do
403
417
  linenum = doc.element_linenumber(e)
404
418
  lines = doc.extract_text(e, /^\s*> /)
405
419
  lines.each do |line|
406
- errors << linenum if line.start_with?(" ")
420
+ errors << linenum if line.start_with?(' ')
407
421
  linenum += 1
408
422
  end
409
423
  end
@@ -411,7 +425,7 @@ rule "MD027", "Multiple spaces after blockquote symbol" do
411
425
  end
412
426
  end
413
427
 
414
- rule "MD028", "Blank line inside blockquote" do
428
+ rule 'MD028', 'Blank line inside blockquote' do
415
429
  tags :blockquote, :whitespace
416
430
  aliases 'no-blanks-blockquote'
417
431
  check do |doc|
@@ -420,7 +434,7 @@ rule "MD028", "Blank line inside blockquote" do
420
434
  elements.each do |e|
421
435
  prev.shift
422
436
  prev << e.type
423
- if prev == [:blockquote, :blank, :blockquote]
437
+ if prev == %i{blockquote blank blockquote}
424
438
  # The current location is the start of the second blockquote, so the
425
439
  # line before will be a blank line in between the two, or at least the
426
440
  # lowest blank line if there are more than one.
@@ -435,42 +449,49 @@ rule "MD028", "Blank line inside blockquote" do
435
449
  end
436
450
  end
437
451
 
438
- rule "MD029", "Ordered list item prefix" do
452
+ rule 'MD029', 'Ordered list item prefix' do
439
453
  tags :ol
440
454
  aliases 'ol-prefix'
441
455
  # Style can be :one or :ordered
442
456
  params :style => :one
443
457
  check do |doc|
444
- if params[:style] == :ordered
445
- doc.find_type_elements(:ol).map { |l|
446
- doc.find_type_elements(:li, false, l.children).map.with_index { |i, idx|
447
- doc.element_linenumber(i) \
448
- unless doc.element_line(i).strip.start_with?("#{idx+1}. ")
449
- }
450
- }.flatten.compact
451
- elsif params[:style] == :one
452
- doc.find_type_elements(:ol).map { |l|
453
- doc.find_type_elements(:li, false, l.children) }.flatten.map { |i|
454
- doc.element_linenumber(i) \
455
- unless doc.element_line(i).strip.start_with?('1. ') }.compact
458
+ case params[:style]
459
+ when :ordered
460
+ doc.find_type_elements(:ol).map do |l|
461
+ doc.find_type_elements(:li, false, l.children)
462
+ .map.with_index do |i, idx|
463
+ unless doc.element_line(i).strip.start_with?("#{idx + 1}. ")
464
+ doc.element_linenumber(i)
465
+ end
466
+ end
467
+ end.flatten.compact
468
+ when :one
469
+ doc.find_type_elements(:ol).map do |l|
470
+ doc.find_type_elements(:li, false, l.children)
471
+ end.flatten.map do |i|
472
+ unless doc.element_line(i).strip.start_with?('1. ')
473
+ doc.element_linenumber(i)
474
+ end
475
+ end.compact
456
476
  end
457
477
  end
458
478
  end
459
479
 
460
- rule "MD030", "Spaces after list markers" do
480
+ rule 'MD030', 'Spaces after list markers' do
461
481
  tags :ol, :ul, :whitespace
462
482
  aliases 'list-marker-space'
463
483
  params :ul_single => 1, :ol_single => 1, :ul_multi => 1, :ol_multi => 1
464
484
  check do |doc|
465
485
  errors = []
466
- doc.find_type_elements([:ul, :ol]).each do |l|
486
+ doc.find_type_elements(%i{ul ol}).each do |l|
467
487
  list_type = l.type.to_s
468
488
  items = doc.find_type_elements(:li, false, l.children)
469
489
  # The entire list is to use the multi-paragraph spacing rule if any of
470
490
  # the items in it have multiple paragraphs/other block items.
471
- srule = items.map { |i| i.children.length }.max > 1 ? "multi" : "single"
491
+ srule = items.map { |i| i.children.length }.max > 1 ? 'multi' : 'single'
472
492
  items.each do |i|
473
- actual_spaces = doc.element_line(i).gsub(/^> /,'').match(/^\s*\S+(\s+)/)[1].length
493
+ actual_spaces = doc.element_line(i).gsub(/^> /, '')
494
+ .match(/^\s*\S+(\s+)/)[1].length
474
495
  required_spaces = params["#{list_type}_#{srule}".to_sym]
475
496
  errors << doc.element_linenumber(i) if required_spaces != actual_spaces
476
497
  end
@@ -479,7 +500,7 @@ rule "MD030", "Spaces after list markers" do
479
500
  end
480
501
  end
481
502
 
482
- rule "MD031", "Fenced code blocks should be surrounded by blank lines" do
503
+ rule 'MD031', 'Fenced code blocks should be surrounded by blank lines' do
483
504
  tags :code, :blank_lines
484
505
  aliases 'blanks-around-fences'
485
506
  check do |doc|
@@ -488,23 +509,29 @@ rule "MD031", "Fenced code blocks should be surrounded by blank lines" do
488
509
  # blocks without surrounding whitespace, so examine the lines directly.
489
510
  in_code = false
490
511
  fence = nil
491
- lines = [ "" ] + doc.lines + [ "" ]
512
+ lines = [''] + doc.lines + ['']
492
513
  lines.each_with_index do |line, linenum|
493
514
  line.strip.match(/^(`{3,}|~{3,})/)
494
- if $1 and (not in_code or $1.slice(0, fence.length) == fence)
495
- fence = in_code ? nil : $1
496
- in_code = !in_code
497
- if (in_code and not lines[linenum - 1].empty?) or
498
- (not in_code and not lines[linenum + 1].empty?)
499
- errors << linenum
500
- end
515
+ unless Regexp.last_match(1) &&
516
+ (
517
+ !in_code ||
518
+ (Regexp.last_match(1).slice(0, fence.length) == fence)
519
+ )
520
+ next
521
+ end
522
+
523
+ fence = in_code ? nil : Regexp.last_match(1)
524
+ in_code = !in_code
525
+ if (in_code && !lines[linenum - 1].empty?) ||
526
+ (!in_code && !lines[linenum + 1].empty?)
527
+ errors << linenum
501
528
  end
502
529
  end
503
530
  errors
504
531
  end
505
532
  end
506
533
 
507
- rule "MD032", "Lists should be surrounded by blank lines" do
534
+ rule 'MD032', 'Lists should be surrounded by blank lines' do
508
535
  tags :bullet, :ul, :ol, :blank_lines
509
536
  aliases 'blanks-around-lists'
510
537
  check do |doc|
@@ -514,21 +541,24 @@ rule "MD032", "Lists should be surrounded by blank lines" do
514
541
  in_list = false
515
542
  in_code = false
516
543
  fence = nil
517
- prev_line = ""
544
+ prev_line = ''
518
545
  doc.lines.each_with_index do |line, linenum|
519
546
  next if line.strip == '{:toc}'
520
- if not in_code
521
- list_marker = line.strip.match(/^([\*\+\-]|(\d+\.))\s/)
522
- if list_marker and not in_list and not prev_line.match(/^($|\s)/)
547
+
548
+ unless in_code
549
+ list_marker = line.strip.match(/^([*+\-]|(\d+\.))\s/)
550
+ if list_marker && !in_list && !prev_line.match(/^($|\s)/)
523
551
  errors << linenum + 1
524
- elsif not list_marker and in_list and not line.match(/^($|\s)/)
552
+ elsif !list_marker && in_list && !line.match(/^($|\s)/)
525
553
  errors << linenum
526
554
  end
527
555
  in_list = list_marker
528
556
  end
529
557
  line.strip.match(/^(`{3,}|~{3,})/)
530
- if $1 and (not in_code or $1.slice(0, fence.length) == fence)
531
- fence = in_code ? nil : $1
558
+ if Regexp.last_match(1) && (
559
+ !in_code || (Regexp.last_match(1).slice(0, fence.length) == fence)
560
+ )
561
+ fence = in_code ? nil : Regexp.last_match(1)
532
562
  in_code = !in_code
533
563
  in_list = false
534
564
  end
@@ -538,7 +568,7 @@ rule "MD032", "Lists should be surrounded by blank lines" do
538
568
  end
539
569
  end
540
570
 
541
- rule "MD033", "Inline HTML" do
571
+ rule 'MD033', 'Inline HTML' do
542
572
  tags :html
543
573
  aliases 'no-inline-html'
544
574
  check do |doc|
@@ -546,15 +576,15 @@ rule "MD033", "Inline HTML" do
546
576
  end
547
577
  end
548
578
 
549
- rule "MD034", "Bare URL used" do
579
+ rule 'MD034', 'Bare URL used' do
550
580
  tags :links, :url
551
581
  aliases 'no-bare-urls'
552
582
  check do |doc|
553
- doc.matching_text_element_lines(/https?:\/\//)
583
+ doc.matching_text_element_lines(%r{https?://})
554
584
  end
555
585
  end
556
586
 
557
- rule "MD035", "Horizontal rule style" do
587
+ rule 'MD035', 'Horizontal rule style' do
558
588
  tags :hr
559
589
  aliases 'hr-style'
560
590
  params :style => :consistent
@@ -563,17 +593,19 @@ rule "MD035", "Horizontal rule style" do
563
593
  if hrs.empty?
564
594
  []
565
595
  else
566
- if params[:style] == :consistent
567
- doc_style = doc.element_line(hrs[0])
568
- else
569
- doc_style = params[:style]
570
- end
571
- doc.element_linenumbers(hrs.select{|e| doc.element_line(e) != doc_style})
596
+ doc_style = if params[:style] == :consistent
597
+ doc.element_line(hrs[0])
598
+ else
599
+ params[:style]
600
+ end
601
+ doc.element_linenumbers(
602
+ hrs.reject { |e| doc.element_line(e) == doc_style },
603
+ )
572
604
  end
573
605
  end
574
606
  end
575
607
 
576
- rule "MD036", "Emphasis used instead of a header" do
608
+ rule 'MD036', 'Emphasis used instead of a header' do
577
609
  tags :headers, :emphasis
578
610
  aliases 'no-emphasis-as-header'
579
611
  params :punctuation => '.,;:!?'
@@ -583,18 +615,20 @@ rule "MD036", "Emphasis used instead of a header" do
583
615
  errors = []
584
616
  doc.find_type_elements(:p, false).each do |p|
585
617
  next if p.children.length > 1
586
- next unless [:em, :strong].include?(p.children[0].type)
587
- lines = doc.extract_text(p.children[0], "", false)
618
+ next unless %i{em strong}.include?(p.children[0].type)
619
+
620
+ lines = doc.extract_text(p.children[0], '', false)
588
621
  next if lines.length > 1
589
622
  next if lines.empty?
590
623
  next if lines[0].match(/[#{params[:punctuation]}]$/)
624
+
591
625
  errors << doc.element_linenumber(p)
592
626
  end
593
627
  errors
594
628
  end
595
629
  end
596
630
 
597
- rule "MD037", "Spaces inside emphasis markers" do
631
+ rule 'MD037', 'Spaces inside emphasis markers' do
598
632
  tags :whitespace, :emphasis
599
633
  aliases 'no-space-in-emphasis'
600
634
  check do |doc|
@@ -606,54 +640,59 @@ rule "MD037", "Spaces inside emphasis markers" do
606
640
  end
607
641
  end
608
642
 
609
- rule "MD038", "Spaces inside code span elements" do
643
+ rule 'MD038', 'Spaces inside code span elements' do
610
644
  tags :whitespace, :code
611
645
  aliases 'no-space-in-code'
612
646
  check do |doc|
613
647
  # We only want to check single line codespan elements and not fenced code
614
648
  # block that happen to be parsed as code spans.
615
- doc.element_linenumbers(doc.find_type_elements(:codespan).select{
616
- |i| i.value.match(/(^\s|\s$)/) and not i.value.include?("\n")})
649
+ doc.element_linenumbers(
650
+ doc.find_type_elements(:codespan).select do |i|
651
+ i.value.match(/(^\s|\s$)/) and !i.value.include?("\n")
652
+ end,
653
+ )
617
654
  end
618
655
  end
619
656
 
620
- rule "MD039", "Spaces inside link text" do
657
+ rule 'MD039', 'Spaces inside link text' do
621
658
  tags :whitespace, :links
622
659
  aliases 'no-space-in-links'
623
660
  check do |doc|
624
661
  doc.element_linenumbers(
625
- doc.find_type_elements(:a).reject{|e|e.children.empty?}.select{|e|
662
+ doc.find_type_elements(:a).reject { |e| e.children.empty? }.select do |e|
626
663
  e.children.first.type == :text && e.children.last.type == :text and (
627
- e.children.first.value.start_with?(" ") or
628
- e.children.last.value.end_with?(" "))}
664
+ e.children.first.value.start_with?(' ') or
665
+ e.children.last.value.end_with?(' '))
666
+ end,
629
667
  )
630
668
  end
631
669
  end
632
670
 
633
- rule "MD040", "Fenced code blocks should have a language specified" do
671
+ rule 'MD040', 'Fenced code blocks should have a language specified' do
634
672
  tags :code, :language
635
673
  aliases 'fenced-code-language'
636
674
  check do |doc|
637
675
  # Kramdown parses code blocks with language settings as code blocks with
638
676
  # the class attribute set to language-languagename.
639
- doc.element_linenumbers(doc.find_type_elements(:codeblock).select{|i|
640
- not i.attr['class'].to_s.start_with?("language-") and
641
- not doc.element_line(i).start_with?(" ")})
677
+ doc.element_linenumbers(doc.find_type_elements(:codeblock).select do |i|
678
+ !i.attr['class'].to_s.start_with?('language-') and
679
+ !doc.element_line(i).start_with?(' ')
680
+ end)
642
681
  end
643
682
  end
644
683
 
645
- rule "MD041", "First line in file should be a top level header" do
684
+ rule 'MD041', 'First line in file should be a top level header' do
646
685
  tags :headers
647
686
  aliases 'first-line-h1'
648
687
  params :level => 1
649
688
  check do |doc|
650
689
  first_header = doc.find_type(:header).first
651
- [1] if first_header.nil? or first_header[:location] != 1 \
652
- or first_header[:level] != params[:level]
690
+ [1] if first_header.nil? || (first_header[:location] != 1) \
691
+ || (first_header[:level] != params[:level])
653
692
  end
654
693
  end
655
694
 
656
- rule "MD046", "Code block style" do
695
+ rule 'MD046', 'Code block style' do
657
696
  tags :code
658
697
  aliases 'code-block-style'
659
698
  params :style => :fenced
@@ -663,11 +702,11 @@ rule "MD046", "Code block style" do
663
702
  doc.find_type_elements(:codeblock).select do |i|
664
703
  # for consistent we determine the first one
665
704
  if style == :consistent
666
- if doc.element_line(i).start_with?(" ")
667
- style = :indented
668
- else
669
- style = :fenced
670
- end
705
+ style = if doc.element_line(i).start_with?(' ')
706
+ :indented
707
+ else
708
+ :fenced
709
+ end
671
710
  end
672
711
  if style == :fenced
673
712
  # if our parent is a list or a codeblock, we need to ignore
@@ -677,7 +716,7 @@ rule "MD046", "Code block style" do
677
716
  if parent
678
717
  parent.options.delete(:children)
679
718
  parent.options.delete(:parent)
680
- if [:li, :codeblock].include?(parent.type)
719
+ if %i{li codeblock}.include?(parent.type)
681
720
  linenum = doc.element_linenumbers([parent]).first
682
721
  indent = doc.indent_for(doc.lines[linenum - 1])
683
722
  ignored_spaces = indent + 4
@@ -686,9 +725,9 @@ rule "MD046", "Code block style" do
686
725
  start = ' ' * ignored_spaces
687
726
  doc.element_line(i).start_with?("#{start} ")
688
727
  else
689
- !doc.element_line(i).start_with?(" ")
728
+ !doc.element_line(i).start_with?(' ')
690
729
  end
691
- end
730
+ end,
692
731
  )
693
732
  end
694
733
  end