Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow "changelog-style" header organization #200

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions docs/RULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,8 @@ Tags: headers

Aliases: no-duplicate-header

Parameters: allow_different_nesting (boolean; default false)

This rule is triggered if there are multiple headers in the document that have
the same text:

Expand All @@ -502,6 +504,21 @@ Rationale: Some markdown parses generate anchors for headers based on the
header name, and having headers with the same content can cause problems with
this.

If the parameter `allow_different_nesting` is set to `true`, header duplication
under different nesting is allowed, like it usually happens in change logs:

# Change log

## 2.0.0

### Bug fixes

### Features

## 1.0.0

### Bug fixes

## MD025 - Multiple top level headers in the same document

Tags: headers
Expand Down
39 changes: 35 additions & 4 deletions lib/mdl/rules.rb
Original file line number Diff line number Diff line change
Expand Up @@ -332,11 +332,42 @@
rule "MD024", "Multiple headers with the same content" do
tags :headers
aliases 'no-duplicate-header'
params :allow_different_nesting => false
check do |doc|
header_content = Set.new
doc.find_type(:header).select do |h|
not header_content.add?(h[:raw_text])
end.map { |h| doc.element_linenumber(h) }
headers = doc.find_type(:header)
allow_different_nesting = params[:allow_different_nesting]

duplicates = headers.select do |h|
headers.any? do |e|
e[:location] < h[:location] &&
e[:raw_text] == h[:raw_text] &&
(allow_different_nesting == false || e[:level] != h[:level])
end
end.to_set

if allow_different_nesting
same_nesting_duplicates = Set.new
stack = []
current_level = 0
doc.find_type(:header).each do |header|
level = header[:level]
text = header[:raw_text]

if current_level > level
stack.pop
elsif current_level < level
stack.push([text])
else
same_nesting_duplicates.add(header) if stack.last.include?(text)
end

current_level = level
end

duplicates += same_nesting_duplicates
end

duplicates.map { |h| doc.element_linenumber(h) }
end
end

Expand Down
11 changes: 11 additions & 0 deletions test/rule_tests/header_duplicate_content_different_nesting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Change log

## 2.0.0

### Bug fixes

### Features

## 1.0.0

### Bug fixes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rule "MD024", :allow_different_nesting => true
13 changes: 13 additions & 0 deletions test/rule_tests/header_duplicate_content_no_different_nesting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Change log

## 2.0.0

### Bug fixes

### Features

## 1.0.0

### Bug fixes

{MD024:11}