Commit 74f8ef26 authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Create human-readable TOC links.

Instead of numeric myguide-section-3 we now get derive heading ID-s
from heading text.  For example: myguide-section-getting-started

Also added testsuite for GuideToc.
parent d952c52f
Loading
Loading
Loading
Loading
+24 −20
Original line number Diff line number Diff line
@@ -8,36 +8,40 @@ module JsDuck
    # Inserts table of contents at the top of guide HTML by looking
    # for <h2> elements.
    def self.inject(html, guide_name)
      toc = [
        "<div class='toc'>\n",
        "<p><strong>Contents</strong></p>\n",
        "<ol>\n",
      ]

      toc = []
      new_html = []
      i = 0

      html.each_line do |line|
        if line =~ /^<h2>(.*)<\/h2>$/
          i += 1
          text = Util::HTML.strip_tags($1)
          toc << "<li><a href='#!/guide/#{guide_name}-section-#{i}'>#{text}</a></li>\n"
          new_html << "<h2 id='#{guide_name}-section-#{i}'>#{text}</h2>\n"
        if line =~ /^\s*<(h[1-6])>(.*?)<\/h[1-6]>$/
          tag = $1
          text = Util::HTML.strip_tags($2)
          id = guide_name + "-section-" + title_to_id(text)
          if tag == "h2"
            toc << "<li><a href='#!/guide/#{id}'>#{text}</a></li>\n"
          end
          new_html << "<#{tag} id='#{id}'>#{text}</#{tag}>\n"
        else
          new_html << line
        end
      end

      toc << "</ol>\n"
      toc << "</div>\n"

      # Inject TOC below first heading if at least 2 items in TOC
      if i >= 2
        new_html.insert(1, toc)
      if toc.length >= 2
        new_html.insert(1, [
            "<div class='toc'>\n",
            "<p><strong>Contents</strong></p>\n",
            "<ol>\n",
            toc,
            "</ol>\n",
            "</div>\n",
        ])
      end

      new_html.flatten.join
      else
        html
    end

    def self.title_to_id(title)
      title.downcase.gsub(/[^\w]+/, "-")
    end

  end

spec/guide_toc_spec.rb

0 → 100644
+65 −0
Original line number Diff line number Diff line
require "jsduck/guide_toc"

describe JsDuck::GuideToc do

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

  it "adds no toc section when no headings" do
    inject("blah").should_not =~ /<div class='toc'>/
  end

  it "adds no toc section when less than two H2 headings" do
    inject(<<-EOHTML).should_not =~ /<div class='toc'>/
      <h2>Chapter A</h2>
    EOHTML
  end

  it "adds toc section when at least two H2 headings" do
    inject(<<-EOHTML).should =~ /<div class='toc'>/
      <h2>Chapter A</h2>
      <h2>Chapter B</h2>
    EOHTML
  end

  it "adds ID-s to H2 headings" do
    inject(<<-EOHTML).should =~ /<h2 id='myguide-section-my-chapter'>My Chapter/
      <h2>My Chapter</h2>
      <h2>Another Chapter</h2>
    EOHTML
  end

  it "links to headings from TOC" do
    inject(<<-EOHTML).should =~ /<a href='#!\/guide\/myguide-section-my-chapter'>/
      <h2>My Chapter</h2>
      <h2>Another Chapter</h2>
    EOHTML
  end

  it "adds ID-s to H2 headings even when no TOC" do
    inject(<<-EOHTML).should =~ /<h2 id='myguide-section-my-chapter'>My Chapter/
      <h2>My Chapter</h2>
    EOHTML
  end

  it "ignores HTML in headings" do
    inject(<<-EOHTML).should =~ /<h2 id='myguide-section-my-chapter'>My Chapter/
      <h2>My <span>Chapter</span></h2>
    EOHTML
  end

  it "adds ID-s also all H* headings" do
    inject(<<-EOHTML).should =~ /<h5 id='myguide-section-my-chapter'>My Chapter/
      <h5>My Chapter</h5>
    EOHTML
  end

  it "doesn't include any other headings besides H2 to TOC" do
    inject(<<-EOHTML).should_not =~ /<a href='#!\/guide\/myguide-section-my-chapter'>/
      <h3>My Chapter</h3>
      <h5>Another Chapter</h5>
    EOHTML
  end

end