Commit d952c52f authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Allow linking to named anchors inside guides.

Created GuideAchors class which transforms the hashes in links
and ID-s in anchors so they don't interfere with Docs app #!-navigation.

Relaxed the pattern matching of guide URL-s in Docs app and added
support for navigating to <a name="..."> anchors.
parent 4b30aab4
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
module JsDuck

  # Transforms in-page links so they won't break docs app #!-navigation.
  #
  # For example a link to "#automation" in testing guide will be
  # replaced with "#!/guide/testing-section-automation" and the link
  # target ID will be transformed into "testing-section-automation".
  class GuideAnchors

    def self.transform(html, guide_name)
      html.gsub(/(<a\s+(?:[^<>]*\s+)?href=['"]#)([^!].*?)(['"])/i) do |m|
        "#{$1}!/guide/#{guide_name}-section-#{$2}#{$3}"

      end.gsub(/(<a\s+(?:[^<>]*\s+)?name=['"])(.*?)(['"])/i) do |m|
        $1 + transform_id($2, guide_name) + $3

      end.gsub(/(<\w+\s+(?:[^<>]*\s+)?id=['"])(.*?)(['"])/i) do |m|
        $1 + transform_id($2, guide_name) + $3
      end
    end

    def self.transform_id(id, guide_name)
      if id =~ /^#{guide_name}-section-/
        id
      else
        "#{guide_name}-section-#{id}"
      end
    end

  end

end
+2 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ require 'jsduck/util/null_object'
require 'jsduck/logger'
require 'jsduck/grouped_asset'
require 'jsduck/guide_toc'
require 'jsduck/guide_anchors'
require 'jsduck/img/dir'
require 'fileutils'

@@ -69,6 +70,7 @@ module JsDuck
      @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 = GuideAnchors.transform(html, guide['name'])

      # Report unused images (but ignore the icon files)
      @formatter.images.get("icon.png")
+54 −0
Original line number Diff line number Diff line
require "jsduck/guide_anchors"

describe JsDuck::GuideAnchors do

  def transform(html)
    JsDuck::GuideAnchors.transform(html, "myguide")
  end

  it "transforms anchor links" do
    transform("<a href='#blah'>label</a>").should ==
      "<a href='#!/guide/myguide-section-blah'>label</a>"
  end

  it "transforms anchor links in fuzzier HTML" do
    transform("<a\n class='blah' href=\"#blah\"\n>label</a>").should ==
      "<a\n class='blah' href=\"#!/guide/myguide-section-blah\"\n>label</a>"
  end

  it "transforms anchor links in longer HTML" do
    transform("Some\nlong\ntext\nhere...\n\n <a href='#blah'>label</a>").should ==
      "Some\nlong\ntext\nhere...\n\n <a href='#!/guide/myguide-section-blah'>label</a>"
  end

  it "doesn't transform normal links" do
    transform("<a href='http://example.com'>label</a>").should ==
      "<a href='http://example.com'>label</a>"
  end

  it "doesn't transform docs-app #! links " do
    transform("<a href='#!/api/Ext.Base'>Ext.Base</a>").should ==
      "<a href='#!/api/Ext.Base'>Ext.Base</a>"
  end

  it "transforms anchors" do
    transform("<a name='blah'>target</a>").should ==
      "<a name='myguide-section-blah'>target</a>"
  end

  it "doesn't transforms anchors already in target format" do
    transform("<a name='myguide-section-blah'>target</a>").should ==
      "<a name='myguide-section-blah'>target</a>"
  end

  it "transforms ID-s" do
    transform("<h1 id='blah'>target</h1>").should ==
      "<h1 id='myguide-section-blah'>target</h1>"
  end

  it "doesn't ID-s already in target format" do
    transform("<h1 id='myguide-section-blah'>target</h1>").should ==
      "<h1 id='myguide-section-blah'>target</h1>"
  end

end
+1 −1
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ Ext.define('Docs.controller.Guides', {
    loadGuide: function(url, noHistory) {
        Ext.getCmp('card-panel').layout.setActiveItem('guide');
        Ext.getCmp('treecontainer').showTree('guidetree');
        var m = url.match(/^#!\/guide\/(.*?)(-section-[0-9]+)?$/);
        var m = url.match(/^#!\/guide\/(.*?)(-section-.*)?$/);
        var name = m[1];
        var section = m[2];
        url = "#!/guide/"+name; // ignore section in URL
+9 −2
Original line number Diff line number Diff line
@@ -28,9 +28,16 @@ Ext.define('Docs.view.guides.Container', {
    /**
     * Scrolls the specified element into view
     *
     * @param {String} el  The element to scroll to.
     * @param {String} id  The element to scroll to.
     * Either ID of the element of anchor name.
     */
    scrollToEl: function(el) {
    scrollToEl: function(id) {
        var el = Ext.get(id);

        if (!el) {
            el = Ext.get(Ext.query("a[name='"+id+"']")[0]);
        }

        this.scrollToView(el, {
            highlight: true,
            offset: -100