jsduck 3.4.1 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -154,14 +154,6 @@ class JsDuckRunner
154
154
  @options += options
155
155
  end
156
156
 
157
- def add_relative_examples_path
158
- @options += ["--head-html", <<-EOHTML]
159
- <script type="text/javascript">
160
- Docs.exampleBaseUrl = "#{relative_sdk_path}examples/";
161
- </script>
162
- EOHTML
163
- end
164
-
165
157
  # Enables comments when CORS is supported by browser.
166
158
  # This excludes Opera and IE < 8.
167
159
  # We check explicitly for IE version to make sure the code works the
@@ -222,7 +214,7 @@ class JsDuckRunner
222
214
 
223
215
  def set_touch2_src
224
216
  relative_touch_path = "../"
225
- system("cp", "-r", "#{@sdk_dir}/touch/docs/welcome.html", "template-min/welcome.html")
217
+ system("cp", "-r", "#{@sdk_dir}/touch/docs/build-welcome.html", "template-min/welcome.html")
226
218
  system("cp", "-r", "#{@sdk_dir}/touch/docs/eg-iframe.html", "template-min/eg-iframe.html")
227
219
 
228
220
  ["template-min/eg-iframe.html", "template-min/welcome.html"].each do |file|
@@ -240,7 +232,6 @@ class JsDuckRunner
240
232
 
241
233
  head_html = <<-EOHTML
242
234
  <script type="text/javascript">
243
- Docs.exampleBaseUrl = "#{relative_touch_path}examples/";
244
235
  if (Ext.is.Phone) { window.location = "#{relative_touch_path}examples/"; }
245
236
  </script>
246
237
  EOHTML
@@ -248,7 +239,8 @@ class JsDuckRunner
248
239
  @options += [
249
240
  "--body-html", head_html,
250
241
  "--welcome", "template-min/welcome.html",
251
- "--eg-iframe", "template-min/eg-iframe.html"
242
+ "--eg-iframe", "template-min/eg-iframe.html",
243
+ "--examples-base-url", "#{relative_touch_path}examples/",
252
244
  ]
253
245
  end
254
246
 
@@ -475,7 +467,11 @@ task :touch2, [:mode] => :sass do |t, args|
475
467
  runner.add_options ["--output", OUT_DIR, "--config", "#{SDK_DIR}/touch/docs/config.json"]
476
468
  runner.add_debug if mode == "debug"
477
469
  runner.add_export_notice("touch/2-0") if mode == "export"
478
- runner.set_touch2_src if mode == "export"
470
+ if mode == "export"
471
+ runner.set_touch2_src
472
+ else
473
+ runner.add_options ["--examples-base-url", "touch/examples/"]
474
+ end
479
475
  runner.add_seo if mode == "debug" || mode == "live"
480
476
  runner.add_google_analytics if mode == "live"
481
477
  runner.add_comments('comments-touch-2') if mode == "debug" || mode == "live"
data/bin/compare CHANGED
@@ -36,12 +36,16 @@ def read_ignored_members(filename)
36
36
  map
37
37
  end
38
38
 
39
+ def normal_public_member?(m)
40
+ !m["private"] && !m["meta"]["protected"] && !m["meta"]["deprecated"] && !m["meta"]["removed"]
41
+ end
42
+
39
43
  # Gathers class members that are in cls1, but are missing in cls2
40
44
  # Ignoring members listed in ignored_members hash.
41
45
  def compare_classes(cls1, cls2, ignored_members)
42
46
  diff = []
43
47
  cls1["members"].each_pair do |group_name, group_items|
44
- group_items.find_all {|m1| !m1["private"] && !m1["meta"]["protected"] && m1["owner"] == cls1["name"] }.each do |m1|
48
+ group_items.find_all {|m1| normal_public_member?(m1) && m1["owner"] == cls1["name"] }.each do |m1|
45
49
  match = cls2["members"][group_name].find do |m2|
46
50
  m2["name"] == m1["name"] && !m2["meta"]["protected"] && !m2["private"]
47
51
  end
@@ -68,22 +72,34 @@ def compare_classes(cls1, cls2, ignored_members)
68
72
  end
69
73
 
70
74
 
71
-
72
75
  old_classes = read_all_classes(ARGV[0], :ignore_private)
73
76
  new_classes = read_all_classes(ARGV[1])
74
77
  out_file = ARGV[2]
75
78
  ignored_members = ARGV[3] ? read_ignored_members(ARGV[3]) : {}
76
79
 
80
+ # Explicit remapping of classes
81
+ remap = {
82
+ "Array" => "Ext.Array",
83
+ "Date" => "Ext.Date",
84
+ "Function" => "Ext.Function",
85
+ "Number" => "Ext.Number",
86
+ "String" => "Ext.String",
87
+ "Ext.supports" => "Ext.feature.has",
88
+ }
89
+
77
90
  diff_data = []
78
91
  old_classes.each_pair do |name, cls|
92
+ # only go through classes, not alternate names
79
93
  if name == cls["name"]
80
- new_cls = new_classes[cls["name"]]
81
- # Remap classes like Array to Ext.Array
82
- new_cls = new_classes["Ext."+cls["name"]] unless new_cls
94
+ if remap[name]
95
+ new_cls = new_classes[remap[name]]
96
+ else
97
+ new_cls = new_classes[name]
98
+ end
83
99
 
84
100
  diff_data << {
85
101
  :name => cls["name"],
86
- :found => !!new_cls,
102
+ :found => !!new_cls || ignored_members[name],
87
103
  :new_name => new_cls && new_cls["name"],
88
104
  :diff => new_cls ? compare_classes(cls, new_cls, ignored_members) : [],
89
105
  }
data/jsduck.gemspec CHANGED
@@ -2,8 +2,8 @@ Gem::Specification.new do |s|
2
2
  s.required_rubygems_version = ">= 1.3.5"
3
3
 
4
4
  s.name = 'jsduck'
5
- s.version = '3.4.1'
6
- s.date = '2012-01-30'
5
+ s.version = '3.5.0'
6
+ s.date = '2012-02-15'
7
7
  s.summary = "Simple JavaScript Duckumentation generator"
8
8
  s.description = "Documentation generator for Sencha JS frameworks"
9
9
  s.homepage = "https://github.com/senchalabs/jsduck"
@@ -83,12 +83,7 @@ module JsDuck
83
83
  return add_shared({
84
84
  :tagname => :event,
85
85
  :name => name,
86
- :doc =>
87
- "Fires when the {@link ##{cfg[:id]}} configuration is changed by {@link #method-#{setter_name}}." +
88
- "\n\n" +
89
- "Note that this event is fired *before* the value of {@link ##{cfg[:id]}} has been updated, " +
90
- "and that you can return false from any listener to the #{name} event " +
91
- "to cancel the change.",
86
+ :doc => "Fires when the {@link ##{cfg[:id]}} configuration is changed by {@link #method-#{setter_name}}.",
92
87
  :params => [
93
88
  {
94
89
  :name => "this",
data/lib/jsduck/app.rb CHANGED
@@ -8,12 +8,7 @@ require 'jsduck/relations'
8
8
  require 'jsduck/inherit_doc'
9
9
  require 'jsduck/parallel_wrap'
10
10
  require 'jsduck/logger'
11
- require 'jsduck/welcome'
12
- require 'jsduck/guides'
13
- require 'jsduck/videos'
14
- require 'jsduck/examples'
15
- require 'jsduck/categories'
16
- require 'jsduck/images'
11
+ require 'jsduck/assets'
17
12
  require 'jsduck/json_duck'
18
13
  require 'jsduck/lint'
19
14
  require 'jsduck/template_dir'
@@ -48,12 +43,11 @@ module JsDuck
48
43
  InheritDoc.new(@relations).resolve_all
49
44
  Lint.new(@relations).run
50
45
 
51
- @images = Images.new(@opts.images)
52
- @welcome = Welcome.create(@opts.welcome)
53
- @guides = Guides.create(@opts.guides, DocFormatter.new(@relations, @opts))
54
- @videos = Videos.create(@opts.videos)
55
- @examples = Examples.create(@opts.examples)
56
- @categories = Categories.create(@opts.categories_path, DocFormatter.new(@relations, @opts), @relations)
46
+ # Initialize guides, videos, examples, ...
47
+ @assets = Assets.new(@relations, @opts)
48
+
49
+ # Give access to assets from all meta-tags
50
+ MetaTagRegistry.instance.assets = @assets
57
51
 
58
52
  if @opts.export
59
53
  format_classes
@@ -65,17 +59,9 @@ module JsDuck
65
59
  FileUtils.rm_rf(@opts.output_dir)
66
60
  TemplateDir.new(@opts).write
67
61
 
68
- index = IndexHtml.new(@opts)
69
- index.welcome = @welcome
70
- index.categories = @categories
71
- index.guides = @guides
72
- index.write
62
+ IndexHtml.new(@assets, @opts).write
73
63
 
74
- app_data = AppData.new(@relations, @opts)
75
- app_data.guides = @guides
76
- app_data.videos = @videos
77
- app_data.examples = @examples
78
- app_data.write(@opts.output_dir+"/data.js")
64
+ AppData.new(@relations, @assets, @opts).write(@opts.output_dir+"/data.js")
79
65
 
80
66
  # class-formatting is done in parallel which breaks the links
81
67
  # between source files and classes. Therefore it MUST to be done
@@ -87,10 +73,7 @@ module JsDuck
87
73
  cw = ClassWriter.new(AppExporter, @relations, @opts)
88
74
  cw.write(@opts.output_dir+"/output", ".js")
89
75
 
90
- @guides.write(@opts.output_dir+"/guides")
91
- @videos.write(@opts.output_dir+"/videos")
92
- @examples.write(@opts.output_dir+"/examples")
93
- @images.copy(@opts.output_dir+"/images")
76
+ @assets.write
94
77
  end
95
78
  end
96
79
 
@@ -160,7 +143,7 @@ module JsDuck
160
143
  # Then merge the data back to classes sequentially
161
144
  formatted_classes.each do |cls|
162
145
  @relations[cls[:doc][:name]].internal_doc = cls[:doc]
163
- cls[:images].each {|img| @images.add(img) }
146
+ cls[:images].each {|img| @assets.images.add(img) }
164
147
  end
165
148
  end
166
149
 
@@ -8,12 +8,9 @@ module JsDuck
8
8
 
9
9
  # Creates big JS file with data for Docs app.
10
10
  class AppData
11
- attr_accessor :guides
12
- attr_accessor :videos
13
- attr_accessor :examples
14
-
15
- def initialize(relations, opts)
11
+ def initialize(relations, assets, opts)
16
12
  @relations = relations
13
+ @assets = assets
17
14
  @opts = opts
18
15
  end
19
16
 
@@ -22,9 +19,9 @@ module JsDuck
22
19
  js = "Docs = " + JsonDuck.generate({
23
20
  :data => {
24
21
  :classes => Icons.new.create(@relations.classes),
25
- :guides => @guides.to_array,
26
- :videos => @videos.to_array,
27
- :examples => @examples.to_array,
22
+ :guides => @assets.guides.to_array,
23
+ :videos => @assets.videos.to_array,
24
+ :examples => @assets.examples.to_array,
28
25
  :search => SearchData.new.create(@relations.classes),
29
26
  :stats => @opts.stats ? Stats.new.create(@relations.classes) : [],
30
27
  :signatures => signatures,
@@ -0,0 +1,50 @@
1
+ require 'jsduck/images'
2
+ require 'jsduck/welcome'
3
+ require 'jsduck/guides'
4
+ require 'jsduck/videos'
5
+ require 'jsduck/examples'
6
+ require 'jsduck/categories'
7
+ require 'jsduck/doc_formatter'
8
+
9
+ module JsDuck
10
+
11
+ # Binds together: Welcome page, Categories, Images, Guides, Videos,
12
+ # Examples.
13
+ #
14
+ # Often we need to pass guides/videos/examples/... to several
15
+ # classes. Having all these assets together in here, means we just
16
+ # need to pass one value instead of 3 or more.
17
+ class Assets
18
+ attr_reader :images
19
+ attr_reader :welcome
20
+ attr_reader :guides
21
+ attr_reader :videos
22
+ attr_reader :examples
23
+ attr_reader :categories
24
+
25
+ def initialize(relations, opts)
26
+ @relations = relations
27
+ @opts = opts
28
+
29
+ @images = Images.new(@opts.images)
30
+ @welcome = Welcome.create(@opts.welcome)
31
+ @guides = Guides.create(@opts.guides, DocFormatter.new(@relations, @opts))
32
+ @videos = Videos.create(@opts.videos)
33
+ @examples = Examples.create(@opts.examples, @opts)
34
+ @categories = Categories.create(@opts.categories_path, DocFormatter.new(@relations, @opts), @relations)
35
+ end
36
+
37
+ # Writes out the assets that can be written out separately:
38
+ # guides, videos, examples, images.
39
+ #
40
+ # Welcome page and categories are written in JsDuck::IndexHtml
41
+ def write
42
+ @guides.write(@opts.output_dir+"/guides")
43
+ @videos.write(@opts.output_dir+"/videos")
44
+ @examples.write(@opts.output_dir+"/examples")
45
+ @images.copy(@opts.output_dir+"/images")
46
+ end
47
+
48
+ end
49
+
50
+ end
data/lib/jsduck/class.rb CHANGED
@@ -8,8 +8,16 @@ module JsDuck
8
8
  class Class
9
9
  attr_accessor :relations
10
10
 
11
- def initialize(doc)
11
+ # Creates JSDuck class.
12
+ #
13
+ # Pass true as second parameter to create a placeholder class.
14
+ def initialize(doc, class_exists=true)
12
15
  @doc = doc
16
+
17
+ # Wrap classname into custom string class that allows
18
+ # differenciating between existing and missing classes.
19
+ @doc[:name] = ClassNameString.new(@doc[:name], class_exists)
20
+
13
21
  @doc[:members] = Class.default_members_hash if !@doc[:members]
14
22
  @doc[:statics] = Class.default_members_hash if !@doc[:statics]
15
23
  @relations = nil
@@ -44,15 +52,25 @@ module JsDuck
44
52
  p ? p.superclasses + [p] : []
45
53
  end
46
54
 
47
- # Returns array of mixin class instances.
48
- # Returns empty array if no mixins
55
+ # Returns all direct mixins of this class. Same as #deps(:mixins).
49
56
  def mixins
50
- @doc[:mixins] ? @doc[:mixins].collect {|classname| lookup(classname) }.compact : []
57
+ deps(:mixins)
58
+ end
59
+
60
+ # Returns an array of class instances this class directly depends on.
61
+ # Possible types are:
62
+ #
63
+ # - :mixins
64
+ # - :requires
65
+ # - :uses
66
+ #
67
+ def deps(type)
68
+ @doc[type] ? @doc[type].collect {|classname| lookup(classname) } : []
51
69
  end
52
70
 
53
- # Returns all mixins this class and its parent classes
54
- def all_mixins
55
- mixins + (parent ? parent.all_mixins : [])
71
+ # Same ase #deps, but pulls out the dependencies from all parent classes.
72
+ def parent_deps(type)
73
+ parent ? parent.deps(type) + parent.parent_deps(type) : []
56
74
  end
57
75
 
58
76
  # Looks up class object by name
@@ -60,10 +78,18 @@ module JsDuck
60
78
  def lookup(classname)
61
79
  if @relations[classname]
62
80
  @relations[classname]
63
- elsif !@relations.ignore?(classname)
81
+ elsif @relations.ignore?(classname) || classname =~ /\*/
82
+ # Ignore explicitly ignored classes and classnames with
83
+ # wildcards in them. We could expand the wildcard, but that
84
+ # can result in a very long list of classes, like when
85
+ # somebody requires 'Ext.form.*', so for now we do the
86
+ # simplest thing and ignore it.
87
+ Class.new({:name => classname}, false)
88
+ else
64
89
  context = @doc[:files][0]
65
90
  Logger.instance.warn(:extend, "Class #{classname} not found", context[:filename], context[:linenr])
66
- nil
91
+ # Create placeholder class
92
+ Class.new({:name => classname}, false)
67
93
  end
68
94
  end
69
95
 
@@ -276,4 +302,21 @@ module JsDuck
276
302
  end
277
303
  end
278
304
 
305
+ # String class for classnames that has extra method #exists? which
306
+ # returns false when class with such name doesn't exist.
307
+ #
308
+ # This ability is used by JsDuck::Renderer, which only receives
309
+ # names of various classes but needs to only render existing classes
310
+ # as links.
311
+ class ClassNameString < String
312
+ def initialize(str, exists=true)
313
+ super(str)
314
+ @exists = exists
315
+ end
316
+
317
+ def exists?
318
+ @exists
319
+ end
320
+ end
321
+
279
322
  end
@@ -1,22 +1,51 @@
1
1
  require 'jsduck/json_duck'
2
2
  require 'jsduck/null_object'
3
+ require 'jsduck/grouped_asset'
3
4
 
4
5
  module JsDuck
5
6
 
6
7
  # Reads in examples JSON file
7
- class Examples
8
+ class Examples < GroupedAsset
8
9
  # Creates Examples object from filename.
9
- def self.create(filename)
10
+ def self.create(filename, opts)
10
11
  if filename
11
- Examples.new(filename)
12
+ Examples.new(filename, opts)
12
13
  else
13
- NullObject.new(:to_array => [])
14
+ NullObject.new(:to_array => [], :[] => nil)
14
15
  end
15
16
  end
16
17
 
17
18
  # Parses examples config file
18
- def initialize(filename)
19
- @examples = JsonDuck.read(filename)
19
+ def initialize(filename, opts)
20
+ @groups = JsonDuck.read(filename)
21
+ @opts = opts
22
+ fix_examples_data
23
+ build_map_by_name("Two examples have the same name")
24
+ end
25
+
26
+ # Prefix all relative URL-s in examples list with path given in --examples-base-url
27
+ #
28
+ # For backwards compatibility:
29
+ #
30
+ # - Create names for each example when not present
31
+ # - Create title from text
32
+ # - Create description from desc
33
+ #
34
+ def fix_examples_data
35
+ each_item do |ex|
36
+ unless ex["url"] =~ /^https?:\/\//
37
+ ex["url"] = @opts.examples_base_url + ex["url"]
38
+ ex["name"] = ex["url"] unless ex["name"]
39
+ unless ex["title"]
40
+ ex["title"] = ex["text"]
41
+ ex.delete("text")
42
+ end
43
+ unless ex["description"]
44
+ ex["description"] = ex["desc"]
45
+ ex.delete("desc")
46
+ end
47
+ end
48
+ end
20
49
  end
21
50
 
22
51
  # Writes examples JSON file to dir
@@ -24,12 +53,12 @@ module JsDuck
24
53
  FileUtils.mkdir(dir) unless File.exists?(dir)
25
54
  # Write the JSON to output dir, so it's available in released
26
55
  # version of docs and people can use it with JSDuck by themselves.
27
- JsonDuck.write_json(dir+"/examples.json", @examples)
56
+ JsonDuck.write_json(dir+"/examples.json", @groups)
28
57
  end
29
58
 
30
- # Returns all examples as array
31
- def to_array
32
- @examples
59
+ # Extracts example icon URL from example hash
60
+ def icon_url(example)
61
+ @opts.examples_base_url + example["icon"]
33
62
  end
34
63
 
35
64
  end