diff --git a/lib/jsduck/examples.rb b/lib/jsduck/examples.rb index 30380d9b9f242b1ac7387cb5d5f89b2c4ab4818d..257e9b49296e428302b94de9b0eb7ab568dd5e09 100644 --- a/lib/jsduck/examples.rb +++ b/lib/jsduck/examples.rb @@ -20,7 +20,7 @@ module JsDuck @groups = Util::Json.read(filename) @opts = opts fix_examples_data - build_map_by_name("Two examples have the same name", filename) + build_map_by_name end # Prefix all relative URL-s in examples list with path given in --examples-base-url diff --git a/lib/jsduck/grouped_asset.rb b/lib/jsduck/grouped_asset.rb index 53ddc200a2c7a05481029b0a2bd0abb795f7950d..6b6b2f55ac04c727b280dd868137e2b9d0d277d4 100644 --- a/lib/jsduck/grouped_asset.rb +++ b/lib/jsduck/grouped_asset.rb @@ -10,20 +10,10 @@ module JsDuck class GroupedAsset # Should be called from constructor after @groups have been read in, # and after it's been ensured that all items in groupes have names. - # - # Prints warning when there is a duplicate item within a group. - # The warning message should say something like "duplicate " - def build_map_by_name(warning_msg, filename) + def build_map_by_name @map_by_name = {} - @groups.each do |group| - group_map = {} - group["items"].each do |item| - if group_map[item["name"]] - Logger.instance.warn(:dup_asset, "#{warning_msg} '#{item['name']}'", filename) - end - @map_by_name[item["name"]] = item - group_map[item["name"]] = item - end + each_item do |item| + @map_by_name[item["name"]] = item end end @@ -33,9 +23,30 @@ module JsDuck end # Iterates over all items in all groups - def each_item - @groups.each do |group| - group["items"].each {|item| yield item } + def each_item(group=nil, &block) + group = group || @groups + + group.each do |item| + if item["items"] + each_item(item["items"], &block) + else + block.call(item) + end + end + end + + def map_items(group=nil, &block) + group = group || @groups + + group.map do |item| + if item["items"] + { + "title" => item["title"], + "items" => map_items(item["items"], &block) + } + else + block.call(item) + end end end diff --git a/lib/jsduck/guides.rb b/lib/jsduck/guides.rb index c9edb9856ca2a197cf09e31a8ef51cde5a4afc4c..2c5a527de86d44490bf01157be66c4654edd2579 100644 --- a/lib/jsduck/guides.rb +++ b/lib/jsduck/guides.rb @@ -24,9 +24,10 @@ module JsDuck def initialize(filename, formatter, opts) @path = File.dirname(filename) @groups = Util::Json.read(filename) - build_map_by_name("Two guides have the same name", filename) @formatter = formatter @opts = opts + build_map_by_name + load_all_guides end # Writes all guides to given dir in JsonP format @@ -35,23 +36,16 @@ module JsDuck each_item {|guide| write_guide(guide, dir) } end - # Modified each_item that also loads HTML for each guide - def each_item - super do |guide| - # Load the guide if not loaded - guide[:html] = load_guide(guide) if guide[:html] == nil - # Pass guide to block if it was successfully loaded. - yield guide if guide[:html] + def load_all_guides + each_item do |guide| + guide[:html] = load_guide(guide) end end # Modified to_array that excludes the :html from guide nodes def to_array - @groups.map do |group| - { - "title" => group["title"], - "items" => group["items"].map {|g| Hash[g.select {|k, v| k != :html }] } - } + map_items do |item| + Hash[item.select {|k, v| k != :html }] end end @@ -141,7 +135,7 @@ module JsDuck [ "

#{group['title']}

", "", ] end.flatten.join("\n") @@ -153,6 +147,14 @@ module JsDuck EOHTML end + def flatten_subgroups(items) + result = [] + each_item(items) do |item| + result << item + end + result + end + # Extracts guide icon URL from guide hash def icon_url(guide) "guides/" + guide["name"] + "/icon.png" diff --git a/lib/jsduck/logger.rb b/lib/jsduck/logger.rb index a34ef2f4849eeae65a2b418feeb7ff34fa73837a..5be95f02367d64eebb2ab8eca390889038213a5c 100644 --- a/lib/jsduck/logger.rb +++ b/lib/jsduck/logger.rb @@ -25,7 +25,6 @@ module JsDuck [:no_doc, "Member or class without documentation"], [:dup_param, "Method has two parameters with the same name"], [:dup_member, "Class has two members with the same name"], - [:dup_asset, "Duplicate guide/video/example"], [:req_after_opt, "Required parameter comes after optional"], [:subproperty, "@param foo.bar where foo param doesn't exist"], [:sing_static, "Singleton class member marked as @static"], diff --git a/lib/jsduck/videos.rb b/lib/jsduck/videos.rb index fa28a799713646ecdab386c8fb0371144c16893f..3ec91606eff51bd68df27d00a2e9a7248bb3c085 100644 --- a/lib/jsduck/videos.rb +++ b/lib/jsduck/videos.rb @@ -18,7 +18,7 @@ module JsDuck def initialize(filename) @groups = Util::Json.read(filename) add_names_if_missing - build_map_by_name("Two videos have the same name", filename) + build_map_by_name end # Each video should have a name, which is used in URL to reference the video. diff --git a/template/app/view/GroupTree.js b/template/app/view/GroupTree.js index bf4cebad6c0baf9df5f1e25879e23c236021ffef..ca2bc5a5dce1063206acf7e3aad3e41954e1689a 100644 --- a/template/app/view/GroupTree.js +++ b/template/app/view/GroupTree.js @@ -25,19 +25,26 @@ Ext.define('Docs.view.GroupTree', { initComponent: function() { this.root = { - children: [], - text: 'Root' + text: 'Root', + children: this.buildTree(this.data) }; - Ext.Array.each(this.data, function(group) { - this.root.children.push({ - text: group.title, - expanded: true, - children: Ext.Array.map(group.items, this.convert), - iconCls: 'icon-pkg' - }); - }, this); - this.callParent(); + }, + + buildTree: function(items) { + return Ext.Array.map(items, function(item) { + if (item.items) { + return { + text: item.title, + expanded: true, + iconCls: 'icon-pkg', + children: this.buildTree(item.items) + }; + } + else { + return this.convert(item); + } + }, this); } }); diff --git a/template/app/view/ThumbList.js b/template/app/view/ThumbList.js index 2fee6d831c64d3fc4000a5c686fc3f68f8f2b55a..a0da045a3cdf662f919659f5b98de0e7f17d369e 100644 --- a/template/app/view/ThumbList.js +++ b/template/app/view/ThumbList.js @@ -47,13 +47,14 @@ Ext.define('Docs.view.ThumbList', { fields: ['id', 'title', 'items'] }); + // Can't just pass the #data config to store as in Ext 4.1 the // value of data config gets modified - each array element // gets replaced with a Model record. // // But we don't want to modify the items in the global // Docs.data... - this.store.loadData(this.data); + this.store.loadData(this.flattenSubgroups(this.data)); // Place itemTpl inside main template this.tpl = new Ext.XTemplate(Ext.Array.flatten([ @@ -90,6 +91,47 @@ Ext.define('Docs.view.ThumbList', { this.callParent(arguments); }, + // Given groups data with subgroups like this: + // + // - group A + // - subgroup AA + // - item 1 + // - item 2 + // - subgroup AB + // - item 3 + // - item 4 + // - group B + // - item 5 + // + // Eliminates the subgroups so we're left with: + // + // - group A + // - item 1 + // - item 2 + // - item 3 + // - item 4 + // - group B + // - item 5 + // + flattenSubgroups: function(data) { + function expand(item) { + if (item.items) { + return Ext.Array.map(item.items, expand); + } + else { + return item; + } + } + + return Ext.Array.map(data, function(group) { + return { + id: group.id, + title: group.title, + items: Ext.Array.flatten(Ext.Array.map(group.items, expand)) + }; + }); + }, + onContainerClick: function(e) { var group = e.getTarget('h2', 3, true);