From d930eb88b671fa6e5573fe7342bcdda87501bdb7 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 19 Sep 2019 11:09:05 +0200 Subject: Add table of contents to about page (#11885) Move public domain blocks information to about page --- app/lib/toc_generator.rb | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 app/lib/toc_generator.rb (limited to 'app/lib/toc_generator.rb') diff --git a/app/lib/toc_generator.rb b/app/lib/toc_generator.rb new file mode 100644 index 000000000..c6e179557 --- /dev/null +++ b/app/lib/toc_generator.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +class TOCGenerator + TARGET_ELEMENTS = %w(h1 h2 h3 h4 h5 h6).freeze + LISTED_ELEMENTS = %w(h2 h3).freeze + + class Section + attr_accessor :depth, :title, :children, :anchor + + def initialize(depth, title, anchor) + @depth = depth + @title = title + @children = [] + @anchor = anchor + end + + delegate :<<, to: :children + end + + def initialize(source_html) + @source_html = source_html + @processed = false + @target_html = '' + @headers = [] + @slugs = Hash.new { |h, k| h[k] = 0 } + end + + def html + parse_and_transform unless @processed + @target_html + end + + def toc + parse_and_transform unless @processed + @headers + end + + private + + def parse_and_transform + return if @source_html.blank? + + parsed_html = Nokogiri::HTML.fragment(@source_html) + + parsed_html.traverse do |node| + next unless TARGET_ELEMENTS.include?(node.name) + + anchor = node.text.parameterize + @slugs[anchor] += 1 + anchor = "#{anchor}-#{@slugs[anchor]}" if @slugs[anchor] > 1 + + node['id'] = anchor + + next unless LISTED_ELEMENTS.include?(node.name) + + depth = node.name[1..-1] + latest_section = @headers.last + + if latest_section.nil? || latest_section.depth >= depth + @headers << Section.new(depth, node.text, anchor) + else + latest_section << Section.new(depth, node.text, anchor) + end + end + + @target_html = parsed_html.to_s + @processed = true + end +end -- cgit From 73a5ef03b2ea175a24c33257638f46f71d22b95a Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Sat, 21 Sep 2019 00:13:45 +0900 Subject: Respect original ID with ToC (#11895) --- app/lib/toc_generator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/lib/toc_generator.rb') diff --git a/app/lib/toc_generator.rb b/app/lib/toc_generator.rb index c6e179557..351675a5c 100644 --- a/app/lib/toc_generator.rb +++ b/app/lib/toc_generator.rb @@ -45,7 +45,7 @@ class TOCGenerator parsed_html.traverse do |node| next unless TARGET_ELEMENTS.include?(node.name) - anchor = node.text.parameterize + anchor = node['id'] || node.text.parameterize @slugs[anchor] += 1 anchor = "#{anchor}-#{@slugs[anchor]}" if @slugs[anchor] > 1 -- cgit From 67bef15e53a77b6f1557fdd0efa65f3e916c20df Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Tue, 24 Sep 2019 00:25:10 +0900 Subject: Add fallback section ID with ToC (#11941) --- app/lib/toc_generator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/lib/toc_generator.rb') diff --git a/app/lib/toc_generator.rb b/app/lib/toc_generator.rb index 351675a5c..0c8f766ca 100644 --- a/app/lib/toc_generator.rb +++ b/app/lib/toc_generator.rb @@ -45,7 +45,7 @@ class TOCGenerator parsed_html.traverse do |node| next unless TARGET_ELEMENTS.include?(node.name) - anchor = node['id'] || node.text.parameterize + anchor = node['id'] || node.text.parameterize.presence || 'sec' @slugs[anchor] += 1 anchor = "#{anchor}-#{@slugs[anchor]}" if @slugs[anchor] > 1 -- cgit