diff --git a/Rakefile b/Rakefile index d35bab68e58d91bef4041a834f73349c4af89570..37f2148e642fd58c07d70d9b39e98a00f81316e0 100644 --- a/Rakefile +++ b/Rakefile @@ -170,6 +170,8 @@ class JsDuckRunner "--categories", "#{@sdk_dir}/extjs/docs/categories.json", "--output", "#{@out_dir}", "--builtin-classes", + "--images", "#{@sdk_dir}/extjs/docs/resources", + "--images", "#{@sdk_dir}/platform/docs/resources", "#{@sdk_dir}/extjs/src", "#{@sdk_dir}/platform/src", "#{@sdk_dir}/platform/core/src", @@ -182,6 +184,7 @@ class JsDuckRunner "--footer", "Ext JS 4.0 Docs - Generated with JSDuck revison #{revision}", "--ignore-global", "--no-warnings", + "--images", "#{@ext_dir}/docs/doc-resources", "--output", "#{@out_dir}", "#{@ext_dir}/src", ] @@ -201,6 +204,7 @@ class JsDuckRunner "--videos", "#{@sdk_dir}/touch/doc-resources/videos.json", "--output", "#{@out_dir}", "--external=google.maps.Map,google.maps.LatLng", + "--images", "#{@sdk_dir}/touch/doc-resources", "#{@sdk_dir}/touch/resources/themes/stylesheets/sencha-touch/default", ] @@ -223,6 +227,7 @@ class JsDuckRunner "--examples", "#{@sdk_dir}/touch/docs/examples.json", "--output", "#{@out_dir}", "--external=google.maps.Map,google.maps.LatLng", + "--images", "#{@sdk_dir}/touch/docs/resources", "#{@sdk_dir}/touch/resources/themes/stylesheets/sencha-touch/default", ] @@ -242,7 +247,7 @@ class JsDuckRunner "--videos", "#{@animator_dir}/docs/videos.json", "--guides", "#{@animator_dir}/docs/guides.json", "--examples", "#{@animator_dir}/docs/examples/examples.json", - "--output", "#{@out_dir}" + "--output", "#{@out_dir}", ] end @@ -334,33 +339,6 @@ class JsDuckRunner ] end - # Copy over the images that SDK documentation links to - def copy_sdk_images - system "cp -r #{@sdk_dir}/extjs/docs/resources #{@out_dir}/doc-resources" - system "cp -r #{@sdk_dir}/platform/docs/resources/* #{@out_dir}/doc-resources" - end - - # Copy over the images that Ext4 documentation links to - def copy_ext4_images - system "cp -r #{@ext_dir}/docs/doc-resources #{@out_dir}/doc-resources" - end - - # Copy over the images that Sencha Touch documentation links to. - def copy_touch_images - system "cp -r #{@sdk_dir}/touch/doc-resources #{@out_dir}/doc-resources" - end - - # Copy over the images that Sencha Touch documentation links to. - def copy_touch2_images - system "cp -r #{@sdk_dir}/touch/docs/resources #{@out_dir}/doc-resources" - system "cp -r #{@sdk_dir}/touch/build #{@out_dir}/touch" - end - - # Copy over the images that Animator documentation links to. - def copy_animator_images - system "cp -r #{@animator_dir}/docs/resources #{@out_dir}/doc-resources" - end - # Copy over SDK examples def copy_sdk_examples system "mkdir #{@out_dir}/extjs/builds" @@ -375,6 +353,11 @@ class JsDuckRunner system "cp -r #{@animator_dir}/docs/examples #{@out_dir}/extjs" end + # Copy over Sencha Touch + def copy_touch2_build + system "cp -r #{@sdk_dir}/touch/build #{@out_dir}/touch" + end + def run # Pass multiple arguments to system, so we'll take advantage of the built-in escaping system(*["ruby", "bin/jsduck"].concat(@options)) @@ -409,8 +392,6 @@ task :sdk, [:mode] => :sass do |t, args| runner.add_google_analytics if mode == "live" runner.run - runner.copy_sdk_images - runner.copy_sdk_examples if mode == "export" || mode == "live" end @@ -427,8 +408,6 @@ task :ext4, [:mode] => :sass do |t, args| runner.add_debug if mode == "debug" runner.add_seo runner.run - - runner.copy_ext4_images end desc "Run JSDuck on Sencha Touch (for internal use at Sencha)\n" + @@ -444,8 +423,6 @@ task :touch, [:mode] => :sass do |t, args| runner.add_debug if mode == "debug" runner.add_seo if mode == "debug" || mode == "live" runner.run - - runner.copy_touch_images end desc "Run JSDuck on Sencha Touch 2 (for internal use at Sencha)\n" + @@ -462,7 +439,7 @@ task :touch2, [:mode] => :sass do |t, args| runner.add_seo if mode == "debug" || mode == "live" runner.run - runner.copy_touch2_images + runner.copy_touch2_build end desc "Run JSDuck on Sencha Animator (for internal use at Sencha)\n" + @@ -480,7 +457,6 @@ task :animator, [:mode] => :sass do |t, args| runner.add_seo if mode == "debug" || mode == "live" runner.run - runner.copy_animator_images runner.copy_animator_examples end diff --git a/bin/compare b/bin/compare index 16ac0bc9f615f5acbab32c2fc5db964ae0677e12..22a85b340c03e6fba9fede778639cd28ac7e881e 100755 --- a/bin/compare +++ b/bin/compare @@ -81,7 +81,7 @@ old_classes.each_pair do |name, cls| end # do HTML output -title = "Comparison of Ext 3.4.0 and Ext 4.0.6" +title = "Comparison of Ext 4.0.7 and Ext 4.1.0" #title = "Comparison of Touch 1.1.1 and Touch 2.0.0" html = [] html << <<-EOHTML @@ -111,32 +111,34 @@ EOHTML html << "" diff --git a/lib/jsduck/app.rb b/lib/jsduck/app.rb index cc71967706f16e5c5cdb4a0e1322c5aaa31378c3..9a16d6503a0342326bc68f51b496765b9bdeefd7 100644 --- a/lib/jsduck/app.rb +++ b/lib/jsduck/app.rb @@ -19,6 +19,7 @@ require 'jsduck/guides' require 'jsduck/videos' require 'jsduck/examples' require 'jsduck/categories' +require 'jsduck/images' require 'jsduck/json_duck' require 'jsduck/lint' require 'fileutils' @@ -49,6 +50,8 @@ module JsDuck Aliases.new(@relations).resolve_all Lint.new(@relations).run + @images = Images.new(@opts.images) + @welcome = Welcome.new if @opts.welcome @timer.time(:parsing) { @welcome.parse(@opts.welcome) } @@ -103,6 +106,7 @@ module JsDuck @timer.time(:generating) { @guides.write(@opts.output_dir+"/guides") } @timer.time(:generating) { @videos.write(@opts.output_dir+"/videos") } @timer.time(:generating) { @examples.write(@opts.output_dir+"/examples") } + @timer.time(:generating) { @images.copy(@opts.output_dir+"/images") } end @timer.report @@ -150,16 +154,22 @@ module JsDuck # Formats each class def format_classes - formatter = ClassFormatter.new(@relations, get_doc_formatter) + doc_formatter = get_doc_formatter + doc_formatter.img_path = "images" + class_formatter = ClassFormatter.new(@relations, doc_formatter) # Don't format types when exporting - formatter.include_types = !@opts.export + class_formatter.include_types = !@opts.export # Format all doc-objects in parallel - formatted_docs = @parallel.map(@relations.classes) do |cls| - formatter.format(cls.internal_doc) + formatted_classes = @parallel.map(@relations.classes) do |cls| + { + :doc => class_formatter.format(cls.internal_doc), + :images => doc_formatter.images + } end # Then merge the data back to classes sequentially - formatted_docs.each do |doc| - @relations[doc[:name]].internal_doc = doc + formatted_classes.each do |cls| + @relations[cls[:doc][:name]].internal_doc = cls[:doc] + cls[:images].each {|img| @images.add(img) } end end diff --git a/lib/jsduck/categories.rb b/lib/jsduck/categories.rb index 690d1f63cfdcceee541e35a1fae37d07d6fe1a1c..a55604d95201fc46227e0b91e80cd0ead6bc63a1 100644 --- a/lib/jsduck/categories.rb +++ b/lib/jsduck/categories.rb @@ -13,7 +13,7 @@ module JsDuck # Parses categories in JSON file def parse(path) - @categories = JsonDuck.read(path)["categories"] + @categories = JsonDuck.read(path) # Perform expansion on all class names containing * wildcard @categories.each do |cat| diff --git a/lib/jsduck/doc_formatter.rb b/lib/jsduck/doc_formatter.rb index d14841ae61f6c31401796c0ff70e503a34583bf2..ac52f05c44170a93902b654e669db3ee44fa71fd 100644 --- a/lib/jsduck/doc_formatter.rb +++ b/lib/jsduck/doc_formatter.rb @@ -33,6 +33,13 @@ module JsDuck # passed in a filename attr_accessor :get_example + # This will hold list of all image paths gathered from {@img} tags. + attr_accessor :images + + # Base path to prefix images from {@img} tags. + # Defaults to no prefix. + attr_accessor :img_path + # Sets up instance to work in context of particular class, so # that when {@link #blah} is encountered it knows that # Context#blah is meant. @@ -57,6 +64,7 @@ module JsDuck @doc_context = {} @max_length = 120 @relations = {} + @images = [] @link_tpl = '%a' @img_tpl = '%a' @example_tpl = '
%a
' @@ -167,10 +175,11 @@ module JsDuck # applies the image template def img(url, alt_text) + @images << url @img_tpl.gsub(/(%\w)/) do case $1 when '%u' - url + @img_path ? (@img_path + "/" + url) : url when '%a' CGI.escapeHTML(alt_text||"") else diff --git a/lib/jsduck/guides.rb b/lib/jsduck/guides.rb index 6583bc48b41a367386d47d817bd9162859a2850a..6ceacece311d26d786ff4023d21a0e80bc9e3607 100644 --- a/lib/jsduck/guides.rb +++ b/lib/jsduck/guides.rb @@ -49,9 +49,9 @@ module JsDuck FileUtils.cp_r(in_dir, out_dir) @formatter.doc_context = {:filename => guide_file, :linenr => 0} - html = @formatter.format(IO.read(guide_file)) name = File.basename(in_dir) - html.gsub!(/ html, :title => guide["title"]}) end diff --git a/lib/jsduck/images.rb b/lib/jsduck/images.rb new file mode 100644 index 0000000000000000000000000000000000000000..cd194015ed042ea5e056dc50dcdd32a779606a1c --- /dev/null +++ b/lib/jsduck/images.rb @@ -0,0 +1,72 @@ +require "jsduck/logger" +require "fileutils" + +module JsDuck + + # Looks up images from directories specified through --images option. + class Images + def initialize(paths) + @paths = scan_for_images(paths) + @images = {} + end + + # Scans each path for image files, building a hash of paths where + # each path points to a hash of image files found in that path. + def scan_for_images(paths) + map = {} + paths.each do |path| + # Scans directory for image files + map[path] = {} + Dir[path+"/**/*.{png,jpg,jpeg,gif}"].each do |img| + map[path][img] = false + end + end + map + end + + # Adds relative image path of an image + def add(filename) + unless @images[filename] + @images[filename] = true + end + end + + # Copys over images to given output dir + def copy(output_dir) + @images.each_key do |img| + unless copy_img(img, output_dir) + Logger.instance.warn("Image #{img} not found") + end + end + report_unused + end + + # Attempts to copy one image, returns true on success + def copy_img(img, output_dir) + @paths.each_pair do |path, map| + filename = path + "/" + img + if map.has_key?(filename) + dest = output_dir + "/" + img + FileUtils.makedirs(File.dirname(dest)) + FileUtils.cp(filename, dest) + Logger.instance.log("Copy #{filename} to #{dest} ...") + # mark file as used. + map[filename] = true + return true + end + end + return false + end + + # Report unused images + def report_unused + @paths.each_pair do |path, map| + map.each_pair do |img, used| + Logger.instance.warn("Image #{img} not used") unless used + end + end + end + + end + +end diff --git a/lib/jsduck/options.rb b/lib/jsduck/options.rb index 264a14d06e40e42bc16f6b426164c312d85d3d49..6f953afa25280e1d83a543c46913a3ac683c3138 100644 --- a/lib/jsduck/options.rb +++ b/lib/jsduck/options.rb @@ -26,6 +26,7 @@ module JsDuck attr_accessor :categories_path attr_accessor :inline_examples_dir attr_accessor :pretty_json + attr_accessor :images attr_accessor :link_tpl attr_accessor :img_tpl attr_accessor :export @@ -87,10 +88,11 @@ module JsDuck @categories_path = nil @inline_examples_dir = nil @pretty_json = false + @images = [] @link_tpl = '%a' # Note that we wrap image template inside

because {@img} often # appears inline within text, but that just looks ugly in HTML - @img_tpl = '

%a

' + @img_tpl = '

%a

' @export = nil @seo = false @@ -218,6 +220,13 @@ module JsDuck @pretty_json = true end + opts.on('--images=PATH', + "Search path for including images referenced by", + "{@img} tag. Several paths can be specified by", + "using the option multiple times.", " ") do |path| + @images << path + end + opts.on('--link=TPL', "HTML template for replacing {@link}.", "Possible placeholders:", diff --git a/lib/jsduck/page.rb b/lib/jsduck/page.rb deleted file mode 100644 index ed077fddbd10b8d4c79bb427e4d12637a3292b47..0000000000000000000000000000000000000000 --- a/lib/jsduck/page.rb +++ /dev/null @@ -1,118 +0,0 @@ -require 'cgi' -require 'jsduck/doc_formatter' -require 'jsduck/inheritance_tree' -require 'jsduck/cfg_table' -require 'jsduck/property_table' -require 'jsduck/method_table' -require 'jsduck/event_table' - -module JsDuck - - # Creates HTML documentation page for one class. - class Page - # Initializes doc page generator - # - # - cls : the Class object for which to generate documentation - # - relations : access to subclasses, mixins, etc - # - cache : cache for already generated HTML rows for class members - # - def initialize(cls, relations, cache = {}) - @cls = cls - @relations = relations - @cache = cache - @formatter = DocFormatter.new - @formatter.class_context = cls.full_name - @formatter.link_tpl = '%a' - @formatter.relations = relations - end - - # Setters to override link and image templates - def link_tpl=(tpl) - @formatter.link_tpl = tpl - end - def img_tpl=(tpl) - @formatter.img_tpl = tpl - end - - def to_html - [ - '
', - inheritance_tree, - heading, - abstract, - description, - "
", - CfgTable.new(@cls, @formatter, @cache).to_html, - PropertyTable.new(@cls, @formatter, @cache).to_html, - MethodTable.new(@cls, @formatter, @cache).to_html, - EventTable.new(@cls, @formatter, @cache).to_html, - "
", - ].join("\n") - end - - # only render the tree if class has at least one ancestor - def inheritance_tree - @cls.parent ? InheritanceTree.new(@cls, @formatter).to_html : "" - end - - def heading - "

Class #{@cls.full_name}

" - end - - def abstract - [ - "", - boolean_row("Alternate names:", @cls[:alternateClassNames].join(", ")), - row("Extends:", extends_link), - classes_row("Mixins:", @cls.mixins), - row("Defined In:", file_link), - classes_row("Subclasses:", @relations.subclasses(@cls)), - classes_row("Mixed into:", @relations.mixed_into(@cls)), - boolean_row("xtype:", @cls[:xtype]), - boolean_row("Author:", @cls[:author]), - boolean_row("Author of docs:", @cls[:docauthor]), - "
", - ].join("\n") - end - - def class_link(class_name, label=nil) - label = label || class_name - @formatter.link(class_name, nil, label || class_name) - end - - def file_link - "#{File.basename(@cls[:filename])}" - end - - def extends_link - if @cls[:extends] - @relations[@cls[:extends]] ? class_link(@cls[:extends]) : @cls[:extends] - else - "Object" - end - end - - def classes_row(label, classes) - if classes.length > 0 - classes = classes.sort {|a, b| a.short_name <=> b.short_name } - html = classes.collect {|cls| class_link(cls.full_name, cls.short_name) }.join(", ") - row(label, html) - else - "" - end - end - - def boolean_row(label, item) - (item && item != "") ? row(label, CGI.escapeHTML(item)) : "" - end - - def row(label, info) - "#{label}#{info}" - end - - def description - "
#{@formatter.format(@cls[:doc])}
" - end - end - -end