jsduck 5.0.0.beta2 → 5.0.0.beta3

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.
Files changed (71) hide show
  1. data/Rakefile +14 -4
  2. data/bin/jsduck +3 -1
  3. data/jsduck.gemspec +2 -2
  4. data/lib/jsduck/app.rb +8 -0
  5. data/lib/jsduck/assets.rb +3 -0
  6. data/lib/jsduck/batch_processor.rb +2 -0
  7. data/lib/jsduck/categories/class_name.rb +2 -26
  8. data/lib/jsduck/categories/factory.rb +5 -43
  9. data/lib/jsduck/columns.rb +56 -0
  10. data/lib/jsduck/doc/delimited_parser.rb +105 -0
  11. data/lib/jsduck/doc/scanner.rb +2 -1
  12. data/lib/jsduck/doc/standard_tag_parser.rb +37 -71
  13. data/lib/jsduck/guide_anchors.rb +32 -0
  14. data/lib/jsduck/guide_toc.rb +49 -0
  15. data/lib/jsduck/guides.rb +14 -32
  16. data/lib/jsduck/inline/video.rb +2 -8
  17. data/lib/jsduck/js/ast.rb +13 -305
  18. data/lib/jsduck/js/class.rb +245 -0
  19. data/lib/jsduck/js/event.rb +34 -0
  20. data/lib/jsduck/js/fires.rb +42 -0
  21. data/lib/jsduck/js/method.rb +94 -0
  22. data/lib/jsduck/js/method_calls.rb +40 -0
  23. data/lib/jsduck/js/node.rb +29 -0
  24. data/lib/jsduck/js/property.rb +64 -0
  25. data/lib/jsduck/js/{function.rb → returns.rb} +8 -3
  26. data/lib/jsduck/js/scoped_traverser.rb +42 -0
  27. data/lib/jsduck/logger.rb +13 -1
  28. data/lib/jsduck/merger.rb +34 -27
  29. data/lib/jsduck/news.rb +128 -0
  30. data/lib/jsduck/options.rb +59 -2
  31. data/lib/jsduck/params_merger.rb +47 -0
  32. data/lib/jsduck/process/accessors.rb +8 -2
  33. data/lib/jsduck/process/fires.rb +71 -0
  34. data/lib/jsduck/process/importer.rb +19 -1
  35. data/lib/jsduck/render/class.rb +11 -4
  36. data/lib/jsduck/render/signature_util.rb +14 -0
  37. data/lib/jsduck/tag/alias.rb +0 -20
  38. data/lib/jsduck/tag/alternate_class_names.rb +0 -5
  39. data/lib/jsduck/tag/cfg.rb +30 -5
  40. data/lib/jsduck/tag/class.rb +45 -2
  41. data/lib/jsduck/tag/css_mixin.rb +8 -4
  42. data/lib/jsduck/tag/css_var.rb +26 -5
  43. data/lib/jsduck/tag/default.rb +2 -8
  44. data/lib/jsduck/tag/enum.rb +7 -10
  45. data/lib/jsduck/tag/event.rb +12 -4
  46. data/lib/jsduck/tag/extends.rb +0 -6
  47. data/lib/jsduck/tag/fires.rb +53 -0
  48. data/lib/jsduck/tag/icons/cfg.png +0 -0
  49. data/lib/jsduck/tag/icons/css_mixin.png +0 -0
  50. data/lib/jsduck/tag/icons/css_var.png +0 -0
  51. data/lib/jsduck/tag/icons/event.png +0 -0
  52. data/lib/jsduck/tag/icons/method.png +0 -0
  53. data/lib/jsduck/tag/icons/property.png +0 -0
  54. data/lib/jsduck/tag/member_tag.rb +130 -0
  55. data/lib/jsduck/tag/method.rb +44 -4
  56. data/lib/jsduck/tag/param.rb +8 -60
  57. data/lib/jsduck/tag/property.rb +28 -5
  58. data/lib/jsduck/tag/tag.rb +3 -75
  59. data/lib/jsduck/tag/type.rb +1 -11
  60. data/lib/jsduck/tag_registry.rb +6 -48
  61. data/lib/jsduck/web/css.rb +8 -1
  62. data/lib/jsduck/web/data.rb +2 -1
  63. data/lib/jsduck/web/index_html.rb +1 -0
  64. data/lib/jsduck/web/member_icons.rb +43 -0
  65. data/lib/jsduck/web/search.rb +3 -2
  66. data/lib/jsduck/web/writer.rb +8 -0
  67. metadata +31 -27
  68. data/lib/jsduck/docs_code_comparer.rb +0 -44
  69. data/lib/jsduck/render/signature.rb +0 -94
  70. data/lib/jsduck/tag/autodetected.rb +0 -21
  71. data/lib/jsduck/tag/name.rb +0 -36
@@ -0,0 +1,47 @@
1
+ require "jsduck/logger"
2
+ require "jsduck/merger"
3
+
4
+ module JsDuck
5
+ # Performs the merging of :params field.
6
+ # Used by Method, Event and CssMixin members.
7
+ class ParamsMerger
8
+ # Ensures the existance of params array.
9
+ # Defaults type of each parameter to "Object".
10
+ # Logs warnings for inconsistencies between params in code and in docs.
11
+ def self.merge(h, docs, code)
12
+ h[:params] = [] unless h[:params]
13
+
14
+ h[:params].each do |p|
15
+ p[:type] = "Object" unless p[:type]
16
+ end
17
+
18
+ check_consistency(docs, code, h[:files].first)
19
+ end
20
+
21
+ def self.check_consistency(docs, code, file)
22
+ explicit = docs[:params] || []
23
+ implicit = JsDuck::Merger.can_be_autodetected?(docs, code) ? (code[:params] || []) : []
24
+ ex_len = explicit.length
25
+ im_len = implicit.length
26
+
27
+ if ex_len == 0 || im_len == 0
28
+ # Skip when either no implicit or explicit params
29
+ elsif ex_len != im_len && explicit.last[:type] =~ /\.\.\.$/
30
+ # Skip when vararg params are in play.
31
+ elsif ex_len < im_len
32
+ # Warn when less parameters documented than found from code.
33
+ JsDuck::Logger.warn(:param_count, "Detected #{im_len} params, but only #{ex_len} documented.", file)
34
+ elsif ex_len > im_len
35
+ # Warn when more parameters documented than found from code.
36
+ JsDuck::Logger.warn(:param_count, "Detected #{im_len} params, but #{ex_len} documented.", file)
37
+ elsif implicit.map {|p| p[:name] } != explicit.map {|p| p[:name] }
38
+ # Warn when parameter names don't match up.
39
+ ex_names = explicit.map {|p| p[:name] }
40
+ im_names = implicit.map {|p| p[:name] }
41
+ str = ex_names.zip(im_names).map {|p| ex, im = p; ex == im ? ex : (ex||"")+"/"+(im||"") }.join(", ")
42
+ JsDuck::Logger.warn(:param_count, "Documented and auto-detected params don't match: #{str}", file)
43
+ end
44
+ end
45
+
46
+ end
47
+ end
@@ -127,9 +127,15 @@ module JsDuck
127
127
  end
128
128
 
129
129
  # Copy over from @cfg all the fields that aren't already present.
130
- # Except :type and :default which don't make sense for methods and events.
131
130
  def add_shared(hash, cfg)
132
- ignored_fields = [:type, :default, :accessor, :evented]
131
+ ignored_fields = [
132
+ # These don't make sense for methods and events.
133
+ :type, :default,
134
+ # It's the config that's tagged with these, don't propagate them to methods/events.
135
+ :accessor, :evented,
136
+ # The :doc field get auto-created and we don't want any other docs.
137
+ :inheritdoc, :localdoc,
138
+ ]
133
139
 
134
140
  cfg.each_pair do |key, value|
135
141
  hash[key] = value unless ignored_fields.include?(key) || hash[key]
@@ -0,0 +1,71 @@
1
+ require 'jsduck/logger'
2
+
3
+ module JsDuck
4
+ module Process
5
+
6
+ # Expands lists of fired events to take into account events fired
7
+ # by all the methods that get called by a method.
8
+ class Fires
9
+ def initialize(relations)
10
+ @relations = relations
11
+ # Map of methods for which all @fires tags have been detected.
12
+ # So we don't repeat the resolving.
13
+ @detected = {}
14
+ # Map of methods that we're currently resolving.
15
+ # So we don't recurse into infinity.
16
+ @call_chain = {}
17
+ end
18
+
19
+ # Populates @fires tags with additional events.
20
+ def process_all!
21
+ @relations.each do |cls|
22
+ cls.find_members(:tagname => :method, :static => false).each do |m|
23
+ @call_chain = {m[:name] => true}
24
+ detect_fires(cls, m)
25
+ end
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def detect_fires(cls, m)
32
+ if m[:autodetected][:fires] && m[:method_calls] && !detected?(m)
33
+ m[:fires] = events_from_methods(cls, m[:method_calls]).concat(m[:fires] || []).sort.uniq
34
+ mark_detected(m)
35
+ end
36
+
37
+ m[:fires]
38
+ end
39
+
40
+ def mark_detected(m)
41
+ @detected[m[:owner]] = {} unless @detected[m[:owner]]
42
+ @detected[m[:owner]][m[:name]] = true
43
+ end
44
+
45
+ def detected?(m)
46
+ cls = @detected[m[:owner]]
47
+ cls && cls[m[:name]]
48
+ end
49
+
50
+ def events_from_methods(cls, methods)
51
+ events = []
52
+
53
+ methods.each do |name|
54
+ if !@call_chain[name]
55
+ @call_chain[name] = true
56
+ m = cls.find_members(:tagname => :method, :name => name, :static => false)[0]
57
+ if m
58
+ fires = detect_fires(cls, m)
59
+ events.concat(fires) if fires
60
+ end
61
+ @call_chain[name] = false
62
+ end
63
+ end
64
+
65
+ events.sort.uniq
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+ end
@@ -28,9 +28,11 @@ module JsDuck
28
28
 
29
29
  # Reads in data from all .json files in directory
30
30
  def read(ver)
31
+ ensure_correct_format(ver[:path])
32
+
31
33
  # Map list of files into pairs of (classname, members-hash)
32
34
  pairs = Util::Parallel.map(Dir[ver[:path] + "/*.json"]) do |filename|
33
- JsDuck::Logger.log("Importing #{ver[:version]}", filename)
35
+ Logger.log("Importing #{ver[:version]}", filename)
34
36
  json = Util::Json.read(filename)
35
37
  [json["name"], members_id_index(json)]
36
38
  end
@@ -39,6 +41,22 @@ module JsDuck
39
41
  return Hash[ pairs ]
40
42
  end
41
43
 
44
+ def ensure_correct_format(path)
45
+ # Read first JSON file in import dir
46
+ json = Util::Json.read(Dir[path + "/*.json"].first)
47
+
48
+ unless correct_format?(json)
49
+ Logger.fatal("Bad format for importing: #{path}")
50
+ Logger.fatal("Export format changed in 5.0.0 beta 2.")
51
+ Logger.fatal("Maybe you forgot to re-generate the exports with new JSDuck.")
52
+ exit(1)
53
+ end
54
+ end
55
+
56
+ def correct_format?(json)
57
+ json["members"].is_a?(Array)
58
+ end
59
+
42
60
  # creates index of all class members
43
61
  def members_id_index(json)
44
62
  index = {}
@@ -1,6 +1,6 @@
1
- require 'jsduck/render/signature'
2
1
  require 'jsduck/render/tags'
3
2
  require 'jsduck/render/sidebar'
3
+ require 'jsduck/tag_registry'
4
4
 
5
5
  module JsDuck
6
6
  module Render
@@ -13,7 +13,6 @@ module JsDuck
13
13
 
14
14
  def render(cls)
15
15
  @cls = cls
16
- @signature = Render::Signature.new(cls)
17
16
 
18
17
  return [
19
18
  "<div>",
@@ -122,8 +121,8 @@ module JsDuck
122
121
  "<br/>",
123
122
  @opts.source ? "<a href='source/#{m[:files][0][:href]}' target='_blank' class='view-source'>view source</a>" : "",
124
123
  "</div>",
125
- # method params signature or property type signature
126
- @signature.render(m),
124
+ render_member_signature(m),
125
+ render_tag_signature(m),
127
126
  "</div>",
128
127
  # short and long descriptions
129
128
  "<div class='description'>",
@@ -138,6 +137,14 @@ module JsDuck
138
137
  ]
139
138
  end
140
139
 
140
+ def render_member_signature(m)
141
+ TagRegistry.get_by_name(m[:tagname]).to_html(m, @cls)
142
+ end
143
+
144
+ def render_tag_signature(m)
145
+ Render::Tags.render_signature(m)
146
+ end
147
+
141
148
  end
142
149
 
143
150
  end
@@ -0,0 +1,14 @@
1
+ module JsDuck
2
+ module Render
3
+
4
+ # Helper method for rendering the link in method/property signature
5
+ class SignatureUtil
6
+
7
+ def self.link(class_name, member_id, text)
8
+ "<a href='#!/api/#{class_name}-#{member_id}' class='name expandable'>#{text}</a>"
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+ end
@@ -9,7 +9,6 @@ module JsDuck::Tag
9
9
  @repeatable = true
10
10
  @ext_define_pattern = "alias"
11
11
  @ext_define_default = {:aliases => []}
12
- @merge_context = :class
13
12
  end
14
13
 
15
14
  # For backwards compatibility decide whether the @alias was used
@@ -39,24 +38,5 @@ module JsDuck::Tag
39
38
  cls[:aliases] += JsDuck::Js::Utils.make_string_list(ast)
40
39
  end
41
40
 
42
- def merge(h, docs, code)
43
- h[:aliases] = build_aliases_hash(docs[:aliases] || code[:aliases] || [])
44
- end
45
-
46
- # Given array of full alias names like "foo.bar", "foo.baz"
47
- # build hash like {"foo" => ["bar", "baz"]}
48
- def build_aliases_hash(aliases)
49
- hash={}
50
- aliases.each do |a|
51
- if a =~ /^([^.]+)\.(.+)$/
52
- if hash[$1]
53
- hash[$1] << $2
54
- else
55
- hash[$1] = [$2]
56
- end
57
- end
58
- end
59
- hash
60
- end
61
41
  end
62
42
  end
@@ -8,11 +8,6 @@ module JsDuck::Tag
8
8
  @repeatable = true
9
9
  @ext_define_pattern = "alternateClassName"
10
10
  @ext_define_default = {:alternateClassNames => []}
11
- @merge_context = :class
12
- end
13
-
14
- def merge(h, docs, code)
15
- h[@tagname] = docs[@tagname] || code[@tagname] || []
16
11
  end
17
12
  end
18
13
  end
@@ -1,18 +1,17 @@
1
- require "jsduck/tag/tag"
1
+ require "jsduck/tag/member_tag"
2
2
  require "jsduck/doc/subproperties"
3
3
 
4
4
  module JsDuck::Tag
5
- class Cfg < Tag
5
+ class Cfg < MemberTag
6
6
  def initialize
7
7
  @pattern = "cfg"
8
8
  @tagname = :cfg
9
9
  @repeatable = true
10
10
  @member_type = {
11
- :name => :cfg,
12
- :category => :property_like,
13
11
  :title => "Config options",
14
12
  :toolbar_title => "Configs",
15
13
  :position => MEMBER_POS_CFG,
14
+ :icon => File.dirname(__FILE__) + "/icons/cfg.png",
16
15
  :subsections => [
17
16
  {:title => "Required config options", :filter => {:required => true}},
18
17
  {:title => "Optional config options", :filter => {:required => false}, :default => true},
@@ -22,7 +21,13 @@ module JsDuck::Tag
22
21
 
23
22
  # @cfg {Type} [name=default] (required) ...
24
23
  def parse_doc(p, pos)
25
- tag = p.standard_tag({:tagname => :cfg, :type => true, :name => true})
24
+ tag = p.standard_tag({
25
+ :tagname => :cfg,
26
+ :type => true,
27
+ :name => true,
28
+ :default => true,
29
+ :optional => true
30
+ })
26
31
  tag[:optional] = false if parse_required(p)
27
32
  tag[:doc] = :multiline
28
33
  tag
@@ -45,5 +50,25 @@ module JsDuck::Tag
45
50
  h[:properties] = nested[:properties]
46
51
  h[:name] = nested[:name]
47
52
  end
53
+
54
+ def process_code(code)
55
+ h = super(code)
56
+ h[:type] = code[:type]
57
+ h[:default] = code[:default]
58
+ h[:accessor] = code[:accessor]
59
+ h[:evented] = code[:evented]
60
+ h
61
+ end
62
+
63
+ # Do the merging of :type field
64
+ def merge(h, docs, code)
65
+ if h[:type] == nil
66
+ h[:type] = code[:tagname] == :method ? "Function" : "Object"
67
+ end
68
+ end
69
+
70
+ def to_html(cfg, cls)
71
+ member_link(cfg) + " : " + cfg[:html_type]
72
+ end
48
73
  end
49
74
  end
@@ -5,7 +5,6 @@ module JsDuck::Tag
5
5
  def initialize
6
6
  @pattern = "class"
7
7
  @tagname = :class
8
- @merge_context = :class
9
8
  end
10
9
 
11
10
  # @class name
@@ -20,9 +19,53 @@ module JsDuck::Tag
20
19
  h[:name] = tags[0][:name]
21
20
  end
22
21
 
23
- # Ensure the empty members array.
22
+ # Although class is not a member, it also has the auto-detected
23
+ # part from code. So this method gets called by Merger.
24
+ #
25
+ # If we did detect code as a class use all the auto-detected
26
+ # fields, otherwise use only the name field.
27
+ def process_code(code)
28
+ if code[:tagname] == :class
29
+ code
30
+ else
31
+ {:name => code[:name] }
32
+ end
33
+ end
34
+
24
35
  def merge(h, docs, code)
36
+ # Ensure the empty members array.
25
37
  h[:members] = []
38
+ # Ignore extending of the Object class
39
+ h[:extends] = nil if h[:extends] == "Object"
40
+ # Default alternateClassNames list to empty array
41
+ h[:alternateClassNames] = [] unless h[:alternateClassNames]
42
+ # Turn :aliases field into hash
43
+ h[:aliases] = build_aliases_hash(h[:aliases] || [])
44
+
45
+ # Takes the :enum always from docs, but the :doc_only can come
46
+ # from either code or docs.
47
+ if docs[:enum]
48
+ h[:enum] = docs[:enum]
49
+ h[:enum][:doc_only] = docs[:enum][:doc_only] || (code[:enum] && code[:enum][:doc_only])
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ # Given array of full alias names like "foo.bar", "foo.baz"
56
+ # build hash like {"foo" => ["bar", "baz"]}
57
+ def build_aliases_hash(aliases)
58
+ hash={}
59
+ aliases.each do |a|
60
+ if a =~ /^([^.]+)\.(.+)$/
61
+ if hash[$1]
62
+ hash[$1] << $2
63
+ else
64
+ hash[$1] = [$2]
65
+ end
66
+ end
67
+ end
68
+ hash
26
69
  end
27
70
  end
28
71
  end
@@ -1,17 +1,21 @@
1
- require "jsduck/tag/tag"
1
+ require "jsduck/tag/member_tag"
2
2
 
3
3
  module JsDuck::Tag
4
4
  # As of now there is no @css_mixin tag available in CSS files. This
5
5
  # class just exists to define that we have a member type called
6
6
  # :css_mixin.
7
- class CssMixin < Tag
7
+ class CssMixin < MemberTag
8
8
  def initialize
9
+ @tagname = :css_mixin
9
10
  @member_type = {
10
- :name => :css_mixin,
11
- :category => :method_like,
12
11
  :title => "CSS Mixins",
13
12
  :position => MEMBER_POS_CSS_MIXIN,
13
+ :icon => File.dirname(__FILE__) + "/icons/css_mixin.png"
14
14
  }
15
15
  end
16
+
17
+ def to_html(mixin, cls)
18
+ member_link(mixin) + member_params(mixin[:params])
19
+ end
16
20
  end
17
21
  end
@@ -1,22 +1,27 @@
1
- require "jsduck/tag/tag"
1
+ require "jsduck/tag/member_tag"
2
2
 
3
3
  module JsDuck::Tag
4
- class CssVar < Tag
4
+ class CssVar < MemberTag
5
5
  def initialize
6
6
  @pattern = "var"
7
7
  @tagname = :css_var
8
8
  @member_type = {
9
- :name => :css_var,
10
- :category => :property_like,
11
9
  :title => "CSS Variables",
12
10
  :toolbar_title => "CSS Vars",
13
11
  :position => MEMBER_POS_CSS_VAR,
12
+ :icon => File.dirname(__FILE__) + "/icons/css_var.png"
14
13
  }
15
14
  end
16
15
 
17
16
  # @var {Type} [name=default] ...
18
17
  def parse_doc(p, pos)
19
- p.standard_tag({:tagname => :css_var, :type => true, :name => true})
18
+ p.standard_tag({
19
+ :tagname => :css_var,
20
+ :type => true,
21
+ :name => true,
22
+ :default => true,
23
+ :optional => true
24
+ })
20
25
  end
21
26
 
22
27
  def process_doc(h, tags, pos)
@@ -25,5 +30,21 @@ module JsDuck::Tag
25
30
  h[:type] = p[:type]
26
31
  h[:default] = p[:default]
27
32
  end
33
+
34
+ def process_code(code)
35
+ h = super(code)
36
+ h[:type] = code[:type]
37
+ h[:default] = code[:default]
38
+ h
39
+ end
40
+
41
+ # Set default value for :type field
42
+ def merge(h, docs, code)
43
+ h[:type] = "Object" unless h[:type]
44
+ end
45
+
46
+ def to_html(var, cls)
47
+ member_link(var) + " : " + var[:html_type]
48
+ end
28
49
  end
29
50
  end