Commit 93537d4c authored by Scott Whittaker's avatar Scott Whittaker
Browse files

Add guide-toc-level option to customize guide TOCs

The new `--guide-toc-level` option, which defaults to 2, controls what
heading levels will appear in guides' tables of contents. Specifying
`--guide-toc-level=N` will result in headings at or above <hN> being
included in all guides' TOCs. Choosing a `guide-toc-level` of 1 disables
the TOC entirely.
parent 0c871b2b
Loading
Loading
Loading
Loading
+14 −13
Original line number Diff line number Diff line
@@ -6,25 +6,26 @@ module JsDuck
  class GuideToc

    # Inserts table of contents at the top of guide HTML by looking
    # for <h2> or <h3> elements.
    def self.inject(html, guide_name)
    # for headings at or below the specified maximum level.
    def self.inject(html, guide_name, max_level)
      toc = []
      new_html = []
      i = 0
      j = 0

      # Count the number of heading increments we've seen so far; use one fewer
      # than max_level, since <h1> tags don't go in the TOC.
      heading_counts = Array.new(max_level - 1) { 0 }

      html.each_line do |line|
        if line =~ /^\s*<(h[1-6])>(.*?)<\/h[1-6]>$/
        if line =~ /^\s*<(h([1-6]))>(.*?)<\/h[1-6]>$/
          tag = $1
          text = Util::HTML.strip_tags($2)
          level = $2.to_i - 1 # ignore <h1>
          text = Util::HTML.strip_tags($3)
          id = guide_name + "-section-" + title_to_id(text)
          if tag == "h2"
            i += 1
            j = 0
            toc << "#{i}. <a href='#!/guide/#{id}'>#{text}</a><br/>\n"
          elsif tag == "h3"
            j += 1
            toc << "#{i}.#{j}. <a href='#!/guide/#{id}'>#{text}</a><br/>\n"
          if (1...max_level).include? level
            heading_counts[level - 1] += 1
            (level...heading_counts.length).each { |i| heading_counts[i] = 0 }
            prefix = heading_counts.slice(0...level).join('.')
            toc << "#{prefix}. <a href='#!/guide/#{id}'>#{text}</a><br/>\n"
          end
          new_html << "<#{tag} id='#{id}'>#{text}</#{tag}>\n"
        else
+1 −1
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ module JsDuck
      @formatter.doc_context = {:filename => guide[:filename], :linenr => 0}
      @formatter.images = Img::Dir.new(guide["url"], "guides/#{guide["name"]}")
      html = @formatter.format(Util::IO.read(guide[:filename]))
      html = GuideToc.inject(html, guide['name'])
      html = GuideToc.inject(html, guide['name'], @opts.guide_toc_level)
      html = GuideAnchors.transform(html, guide['name'])

      # Report unused images (but ignore the icon files)
+17 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ module JsDuck
    attr_accessor :message
    attr_accessor :welcome
    attr_accessor :guides
    attr_accessor :guide_toc_level
    attr_accessor :videos
    attr_accessor :examples
    attr_accessor :categories_path
@@ -112,6 +113,7 @@ module JsDuck
      @message = ""
      @welcome = nil
      @guides = nil
      @guide_toc_level = 2
      @videos = nil
      @examples = nil
      @categories_path = nil
@@ -393,6 +395,21 @@ module JsDuck
          @guides = canonical(path)
        end

        opts.on('--guide-toc-level=LEVEL',
          "The maximum heading level to include in guides' tables of contents.",
          "",
          "Values between 1 and 6 are allowed. Choosing 1 hides the table of ",
          "contents.",
          "",
          "The default is 2, indicating that only <h2>-level headings will ",
          "be included in the table of contents.") do |level|
          @guide_toc_level = level.to_i
          if !(1..6).include? @guide_toc_level
            Logger.fatal("Unsupported guide-toc-level: '#{level}'")
            exit(1)
          end
        end

        opts.on('--videos=PATH',
          "JSON file describing the videos.",
          "",
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ require "jsduck/guide_toc"
describe JsDuck::GuideToc do

  def inject(html)
    JsDuck::GuideToc.inject(html, "myguide")
    JsDuck::GuideToc.inject(html, "myguide", 2)
  end

  it "adds no toc section when no headings" do