jsduck 3.4.1 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
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