diff options
author | Akihiro Nakashima <shibamu@gmail.com> | 2017-08-18 16:09:10 +0900 |
---|---|---|
committer | Robert Speicher <rspeicher@gmail.com> | 2017-09-06 12:48:25 -0400 |
commit | 2a055c23c27f85db4bc56f07dccca642fc264d57 (patch) | |
tree | 576331a4f422299dcc7dcf7219356e60883b2f3f /lib/banzai | |
parent | 10fd3542225e161de0c82442304a0881ccecc774 (diff) | |
download | gitlab-ce-2a055c23c27f85db4bc56f07dccca642fc264d57.tar.gz |
Fix indentation level in Wiki's TOC items to regard header level
Diffstat (limited to 'lib/banzai')
-rw-r--r-- | lib/banzai/filter/table_of_contents_filter.rb | 47 |
1 files changed, 43 insertions, 4 deletions
diff --git a/lib/banzai/filter/table_of_contents_filter.rb b/lib/banzai/filter/table_of_contents_filter.rb index 8e7084f2543..8cb860c5a92 100644 --- a/lib/banzai/filter/table_of_contents_filter.rb +++ b/lib/banzai/filter/table_of_contents_filter.rb @@ -15,6 +15,7 @@ module Banzai # `li` child elements. class TableOfContentsFilter < HTML::Pipeline::Filter PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u + HeaderNode = Struct.new(:level, :href, :text, :children, :parent) def call return doc if context[:no_header_anchors] @@ -23,6 +24,10 @@ module Banzai headers = Hash.new(0) + # root node of header-tree + header_root = HeaderNode.new(0, nil, nil, [], nil) + current_header = header_root + doc.css('h1, h2, h3, h4, h5, h6').each do |node| text = node.text @@ -38,12 +43,38 @@ module Banzai # namespace detection will be automatically handled via javascript (see issue #22781) namespace = "user-content-" href = "#{id}#{uniq}" - push_toc(href, text) + + level = node.name[1].to_i # get this header level + if level == current_header.level + # same as previous + parent = current_header.parent + elsif level > current_header.level + # larger (weaker) than previous + parent = current_header + else + # smaller (stronger) than previous + # search parent + parent = current_header + parent = parent.parent while parent.level >= level + end + + # create header-node and push as child + header_node = HeaderNode.new(level, href, text, [], parent) + parent.children.push(header_node) + current_header = header_node + header_content.add_previous_sibling(anchor_tag("#{namespace}#{href}", href)) end end - result[:toc] = %Q{<ul class="section-nav">\n#{result[:toc]}</ul>} unless result[:toc].empty? + # extract header-tree + if header_root.children.length > 0 + result[:toc] = %Q{<ul class="section-nav">\n} + header_root.children.each do |child| + push_toc(child) + end + result[:toc] << '</ul>' + end doc end @@ -54,8 +85,16 @@ module Banzai %Q{<a id="#{id}" class="anchor" href="##{href}" aria-hidden="true"></a>} end - def push_toc(href, text) - result[:toc] << %Q{<li><a href="##{href}">#{text}</a></li>\n} + def push_toc(header_node) + result[:toc] << %Q{<li><a href="##{header_node.href}">#{header_node.text}</a>} + if header_node.children.length > 0 + result[:toc] << '<ul>' + header_node.children.each do |child| + push_toc(child) + end + result[:toc] << '</ul>' + end + result[:toc] << '</li>\n' end end end |