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

Table of Contents for each guide.

For each guide a TOC is created from all H2 headings.

A bit of twaking to get linking to those sections working.  So one can just refer
to each section from within the guide or from outside of it like so:

    #!/guide/guide_name-section-3
parent 2553f2f8
Loading
Loading
Loading
Loading
+24 −1
Original line number Diff line number Diff line
@@ -55,11 +55,34 @@ module JsDuck
      @formatter.doc_context = {:filename => guide_file, :linenr => 0}
      name = File.basename(in_dir)
      @formatter.img_path = "guides/#{name}"
      html = @formatter.format(IO.read(guide_file))
      html = add_toc(guide, @formatter.format(IO.read(guide_file)))

      JsonDuck.write_jsonp(out_dir+"/README.js", name, {:guide => html, :title => guide["title"]})
    end

    # Creates table of contents at the top of guide by looking for <h2> elements in HTML.
    def add_toc(guide, html)
      toc = [
        "<p><strong>Contents</strong></p>",
        "<ul class='toc'>",
      ]
      new_html = []
      i = 0
      html.each_line do |line|
        if line =~ /^<h2>(.*)<\/h2>$/
          i += 1
          toc << "<li><a href='#!/guide/#{guide['name']}-section-#{i}'>#{$1}</a></li>"
          new_html << "<h2 id='#{guide['name']}-section-#{i}'>#{$1}</h2>"
        else
          new_html << line
        end
      end
      toc << "</ul>"
      # Inject TOC at below first heading
      new_html.insert(1, toc)
      new_html.flatten.join
    end

    # Returns all guides as array
    def to_array
      @guides
+21 −11
Original line number Diff line number Diff line
@@ -18,6 +18,10 @@ Ext.define('Docs.controller.Guides', {
        {
            ref: 'tree',
            selector: '#guidetree'
        },
        {
            ref: 'guide',
            selector: '#guide'
        }
    ],

@@ -56,9 +60,15 @@ Ext.define('Docs.controller.Guides', {
            },
            '#guide': {
                afterrender: function(cmp) {
                    cmp.el.addListener('scroll', function(cmp, el) {
                    cmp.el.addListener('click', function(event, el) {
                        this.setScrollState(this.activeUrl, el.scrollTop);
                    }, this);
                    cmp.el.addListener('click', function(event, el) {
                        this.handleUrlClick(el.href, event);
                    }, this, {
                        preventDefault: true,
                        delegate: 'ul.toc > li > a'
                    });
                }
            }
        });
@@ -96,12 +106,15 @@ Ext.define('Docs.controller.Guides', {
    loadGuide: function(url, noHistory) {
        Ext.getCmp('card-panel').layout.setActiveItem('guide');
        Ext.getCmp('treecontainer').showTree('guidetree');
        var name = url.match(/^#!\/guide\/(.*)$/)[1];
        var m = url.match(/^#!\/guide\/(.*?)(-section-[0-9]+)?$/);
        var name = m[1];
        var section = m[2];
        url = "#!/guide/"+name; // ignore section in URL

        noHistory || Docs.History.push(url);

        if (this.cache[name]) {
            this.showGuide(this.cache[name], url, name);
            this.showGuide(this.cache[name], url, name, section);
        }
        else {
            this.cache[name] = "in-progress";
@@ -110,7 +123,7 @@ Ext.define('Docs.controller.Guides', {
                callbackName: name,
                success: function(json) {
                    this.cache[name] = json;
                    this.showGuide(json, url, name);
                    this.showGuide(json, url, name, section);
                },
                failure: function(response, opts) {
                    this.cache[name] = false;
@@ -126,9 +139,10 @@ Ext.define('Docs.controller.Guides', {
     *
     * @param {Object} json Guide json
     * @param {String} url URL of the guide
     * @param {Boolean} name Name of the guide
     * @param {String} name Name of the guide
     * @param {String} [section] Section name
     */
    showGuide: function(json, url, name) {
    showGuide: function(json, url, name, section) {
        var reRendered = false;

        if (json === "in-progress") {
@@ -143,13 +157,9 @@ Ext.define('Docs.controller.Guides', {
            reRendered = true;
        }
        this.activeUrl = url;
        this.scrollContent();
        section ? this.getGuide().scrollToEl(name+section) : this.getGuide().scrollToTop();
        this.fireEvent('showGuide', name, { reRendered: reRendered });
        this.getTree().selectUrl(url);
    },

    scrollContent: function() {
        Ext.get('guide').scrollTo('top', this.getScrollState(this.activeUrl));
    }

});
+22 −0
Original line number Diff line number Diff line
@@ -19,6 +19,28 @@ Ext.define('Docs.view.guides.Container', {
        this.callParent(arguments);
    },

    /**
     * Scrolls the specified element into view
     *
     * @param {String} id  ID of elemnt to scroll to.
     */
    scrollToEl: function(id) {
        var el = Ext.get(id);
        if (el) {
            var scrollOffset = el.getY() - 100;
            var currentScroll = this.getEl().getScroll()['top'];
            this.getEl().scrollTo('top', currentScroll + scrollOffset);
            el.highlight();
        }
    },

    /**
     * Scrolls guide to the top
     */
    scrollToTop: function() {
        this.getEl().scrollTo('top');
    },

    /**
     * Loads guide into the page.
     * @param {Object} guide