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_data.sort! {|a, b| a[:name] <=> b[:name] }
diff_data.each do |cls|
- html << "- "
- if cls[:found]
- new_name = (cls[:new_name] == cls[:name] ? "" : " --> " + cls[:new_name])
- diff_count = cls[:diff].length > 0 ? "(#{cls[:diff].length} missing members)" : ""
- link = cls[:diff].length > 0 ? "#{cls[:name]}" : cls[:name]
- html << "
#{link} #{new_name} #{diff_count}
"
- if cls[:diff].length > 0
- html << ""
- cls[:diff].each do |m|
- html << "- "
- html << m[:type] + " " + m[:name]
- if m[:other]
- o = m[:other]
- stat = o[:static] ? 'static' : ''
- priv = o[:private] ? 'private' : ''
- prot = o[:protected] ? 'protected' : ''
- html << " (found #{stat} #{priv} #{prot} #{o[:type]} with the same name)"
+ if !cls[:found] || cls[:diff].length > 0
+ html << "
- "
+ if cls[:found]
+ new_name = (cls[:new_name] == cls[:name] ? "" : " --> " + cls[:new_name])
+ diff_count = cls[:diff].length > 0 ? "(#{cls[:diff].length} missing members)" : ""
+ link = cls[:diff].length > 0 ? "#{cls[:name]}" : cls[:name]
+ html << "
#{link} #{new_name} #{diff_count}
"
+ if cls[:diff].length > 0
+ html << ""
+ cls[:diff].each do |m|
+ html << "- "
+ html << m[:type] + " " + m[:name]
+ if m[:other]
+ o = m[:other]
+ stat = o[:static] ? 'static' : ''
+ priv = o[:private] ? 'private' : ''
+ prot = o[:protected] ? 'protected' : ''
+ html << " (found #{stat} #{priv} #{prot} #{o[:type]} with the same name)"
+ end
+ html << "
"
end
- html << "
"
+ html << "
"
end
- html << "
"
+ else
+ html << "" + cls[:name] + " not found
"
end
- else
- html << "" + cls[:name] + " not found
"
+ html << ""
end
- html << ""
end
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 = '
'
@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 = '

'
+ @img_tpl = '
'
@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
- ""
- 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