jsduck 4.0.1 → 4.1.1

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 (91) hide show
  1. data/Rakefile +14 -0
  2. data/esprima/esprima.js +210 -85
  3. data/jsduck.gemspec +3 -3
  4. data/lib/jsduck/accessors.rb +10 -8
  5. data/lib/jsduck/aggregator.rb +7 -7
  6. data/lib/jsduck/app.rb +24 -164
  7. data/lib/jsduck/app_data.rb +2 -4
  8. data/lib/jsduck/assets.rb +5 -2
  9. data/lib/jsduck/ast.rb +9 -4
  10. data/lib/jsduck/batch_formatter.rb +54 -0
  11. data/lib/jsduck/batch_parser.rb +106 -0
  12. data/lib/jsduck/categories.rb +5 -6
  13. data/lib/jsduck/class.rb +77 -239
  14. data/lib/jsduck/class_doc_expander.rb +0 -5
  15. data/lib/jsduck/class_formatter.rb +14 -10
  16. data/lib/jsduck/class_name.rb +23 -0
  17. data/lib/jsduck/class_writer.rb +9 -8
  18. data/lib/jsduck/doc_ast.rb +5 -6
  19. data/lib/jsduck/doc_formatter.rb +61 -272
  20. data/lib/jsduck/enum.rb +4 -4
  21. data/lib/jsduck/esprima.rb +10 -4
  22. data/lib/jsduck/examples.rb +5 -5
  23. data/lib/jsduck/export_writer.rb +62 -0
  24. data/lib/jsduck/exporter/app.rb +62 -0
  25. data/lib/jsduck/exporter/examples.rb +58 -0
  26. data/lib/jsduck/exporter/full.rb +60 -0
  27. data/lib/jsduck/file_categories.rb +7 -4
  28. data/lib/jsduck/function_ast.rb +99 -0
  29. data/lib/jsduck/grouped_asset.rb +27 -16
  30. data/lib/jsduck/guide_writer.rb +8 -7
  31. data/lib/jsduck/guides.rb +31 -29
  32. data/lib/jsduck/icons.rb +12 -1
  33. data/lib/jsduck/images.rb +3 -3
  34. data/lib/jsduck/importer.rb +7 -7
  35. data/lib/jsduck/index_html.rb +20 -6
  36. data/lib/jsduck/inherit_doc.rb +9 -12
  37. data/lib/jsduck/inline/example.rb +42 -0
  38. data/lib/jsduck/inline/img.rb +55 -0
  39. data/lib/jsduck/inline/link.rb +227 -0
  40. data/lib/jsduck/inline/video.rb +67 -0
  41. data/lib/jsduck/inline_examples.rb +7 -7
  42. data/lib/jsduck/js_parser.rb +5 -4
  43. data/lib/jsduck/lint.rb +14 -2
  44. data/lib/jsduck/logger.rb +5 -6
  45. data/lib/jsduck/members_index.rb +132 -0
  46. data/lib/jsduck/merger.rb +3 -9
  47. data/lib/jsduck/options.rb +39 -41
  48. data/lib/jsduck/override.rb +3 -7
  49. data/lib/jsduck/relations.rb +9 -9
  50. data/lib/jsduck/renderer.rb +3 -3
  51. data/lib/jsduck/return_values.rb +72 -0
  52. data/lib/jsduck/search_data.rb +16 -20
  53. data/lib/jsduck/shortener.rb +58 -0
  54. data/lib/jsduck/signature_renderer.rb +1 -2
  55. data/lib/jsduck/source/file.rb +98 -0
  56. data/lib/jsduck/source/file_parser.rb +72 -0
  57. data/lib/jsduck/source/writer.rb +89 -0
  58. data/lib/jsduck/tag/aside.rb +1 -1
  59. data/lib/jsduck/tag/since.rb +1 -1
  60. data/lib/jsduck/template_dir.rb +2 -2
  61. data/lib/jsduck/util/html.rb +27 -0
  62. data/lib/jsduck/util/io.rb +32 -0
  63. data/lib/jsduck/util/json.rb +60 -0
  64. data/lib/jsduck/util/null_object.rb +23 -0
  65. data/lib/jsduck/util/os.rb +14 -0
  66. data/lib/jsduck/util/parallel.rb +34 -0
  67. data/lib/jsduck/util/singleton.rb +35 -0
  68. data/lib/jsduck/util/stdout.rb +33 -0
  69. data/lib/jsduck/videos.rb +5 -5
  70. data/lib/jsduck/web_writer.rb +79 -0
  71. data/lib/jsduck/welcome.rb +6 -6
  72. data/spec/class_factory.rb +20 -0
  73. metadata +32 -20
  74. data/lib/jsduck/api_exporter.rb +0 -48
  75. data/lib/jsduck/app_exporter.rb +0 -60
  76. data/lib/jsduck/examples_exporter.rb +0 -56
  77. data/lib/jsduck/full_exporter.rb +0 -35
  78. data/lib/jsduck/html.rb +0 -25
  79. data/lib/jsduck/inline_img.rb +0 -53
  80. data/lib/jsduck/inline_video.rb +0 -58
  81. data/lib/jsduck/io.rb +0 -30
  82. data/lib/jsduck/json_duck.rb +0 -52
  83. data/lib/jsduck/lexer.rb +0 -251
  84. data/lib/jsduck/null_object.rb +0 -19
  85. data/lib/jsduck/os.rb +0 -11
  86. data/lib/jsduck/parallel_wrap.rb +0 -32
  87. data/lib/jsduck/source_file.rb +0 -97
  88. data/lib/jsduck/source_file_parser.rb +0 -70
  89. data/lib/jsduck/source_writer.rb +0 -87
  90. data/lib/jsduck/stats.rb +0 -103
  91. data/lib/jsduck/stdout.rb +0 -31
@@ -0,0 +1,42 @@
1
+ module JsDuck
2
+ module Inline
3
+
4
+ # Implementation of @example tag.
5
+ #
6
+ # Looks for @example tag at the beginning of code blocks. When
7
+ # found, adds an "inline-example" CSS class to the <pre> element.
8
+ #
9
+ # Unlike other Inline:: classes this doesn't implement an
10
+ # {@example} tag as could be expected. But it fits nicely along
11
+ # with other inline tags as it's processed inside DocFormatter, so
12
+ # it mostly fits here along with the others.
13
+ #
14
+ class Example
15
+ # Constructor takes opts parameter for consistency with other
16
+ # JsDuck::Inline::* classes.
17
+ def initialize(opts={})
18
+ @re = /<pre><code>\s*@example( +[^\n]*)?\s+/m
19
+ end
20
+
21
+ # Takes StringScanner instance.
22
+ #
23
+ # Looks for "<pre><code>@example" at the current scan pointer
24
+ # position, when found, moves scan pointer forward and performs
25
+ # the apporpriate replacement.
26
+ def replace(input)
27
+ if input.check(@re)
28
+ # Match possible classnames following @example and add them
29
+ # as CSS classes inside <pre> element.
30
+ input.scan(@re) =~ @re
31
+ css_classes = ($1 || "").strip
32
+
33
+ return "<pre class='inline-example #{css_classes}'><code>"
34
+ else
35
+ false
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,55 @@
1
+ require 'jsduck/util/html'
2
+ require 'jsduck/logger'
3
+
4
+ module JsDuck
5
+ module Inline
6
+
7
+ # Implementation of inline tag {@img}
8
+ class Img
9
+ # Base path to prefix images from {@img} tags.
10
+ # Defaults to no prefix.
11
+ attr_accessor :base_path
12
+
13
+ # This will hold list of all image paths gathered from {@img} tags.
14
+ attr_accessor :images
15
+
16
+ def initialize(opts={})
17
+ @tpl = opts[:img_tpl] || '<img src="%u" alt="%a"/>'
18
+
19
+ @re = /\{@img\s+(\S*?)(?:\s+(.+?))?\}/m
20
+
21
+ @base_path = nil
22
+ @images = []
23
+ end
24
+
25
+ # Takes StringScanner instance.
26
+ #
27
+ # Looks for inline tag at the current scan pointer position, when
28
+ # found, moves scan pointer forward and performs the apporpriate
29
+ # replacement.
30
+ def replace(input)
31
+ if input.check(@re)
32
+ input.scan(@re).sub(@re) { apply_tpl($1, $2) }
33
+ else
34
+ false
35
+ end
36
+ end
37
+
38
+ # applies the image template
39
+ def apply_tpl(url, alt_text)
40
+ @images << url
41
+ @tpl.gsub(/(%\w)/) do
42
+ case $1
43
+ when '%u'
44
+ @base_path ? (@base_path + "/" + url) : url
45
+ when '%a'
46
+ Util::HTML.escape(alt_text||"")
47
+ else
48
+ $1
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,227 @@
1
+ require 'jsduck/util/html'
2
+ require 'jsduck/logger'
3
+
4
+ module JsDuck
5
+ module Inline
6
+
7
+ # Implementation of inline tag {@link}
8
+ #
9
+ # It also takes care of the auto-detection of links in text
10
+ # through the #create_magic_links method.
11
+ class Link
12
+ # Sets up instance to work in context of particular class, so
13
+ # that when {@link #blah} is encountered it knows that
14
+ # Context#blah is meant.
15
+ attr_accessor :class_context
16
+
17
+ # Sets up instance to work in context of particular doc object.
18
+ # Used for error reporting.
19
+ attr_accessor :doc_context
20
+
21
+ # JsDuck::Relations for looking up class names.
22
+ #
23
+ # When auto-creating class links from CamelCased names found from
24
+ # text, we check the relations object to see if a class with that
25
+ # name actually exists.
26
+ attr_accessor :relations
27
+
28
+ def initialize(opts={})
29
+ @class_context = ""
30
+ @doc_context = {}
31
+ @relations = {}
32
+
33
+ # Template HTML that replaces {@link Class#member anchor text}.
34
+ # Can contain placeholders:
35
+ #
36
+ # %c - full class name (e.g. "Ext.Panel")
37
+ # %m - class member name prefixed with member type (e.g. "method-urlEncode")
38
+ # %# - inserts "#" if member name present
39
+ # %- - inserts "-" if member name present
40
+ # %a - anchor text for link
41
+ @tpl = opts[:link_tpl] || '<a href="%c%#%m">%a</a>'
42
+
43
+ @re = /\{@link\s+(\S*?)(?:\s+(.+?))?\}/m
44
+ end
45
+
46
+ # Takes StringScanner instance.
47
+ #
48
+ # Looks for inline tag at the current scan pointer position, when
49
+ # found, moves scan pointer forward and performs the apporpriate
50
+ # replacement.
51
+ def replace(input)
52
+ if input.check(@re)
53
+ input.scan(@re).sub(@re) { apply_tpl($1, $2, $&) }
54
+ else
55
+ false
56
+ end
57
+ end
58
+
59
+ # applies the link template
60
+ def apply_tpl(target, text, full_link)
61
+ if target =~ /^(.*)#(static-)?(?:(cfg|property|method|event|css_var|css_mixin)-)?(.*)$/
62
+ cls = $1.empty? ? @class_context : $1
63
+ static = $2 ? true : nil
64
+ type = $3 ? $3.intern : nil
65
+ member = $4
66
+ else
67
+ cls = target
68
+ static = nil
69
+ type = false
70
+ member = false
71
+ end
72
+
73
+ # Construct link text
74
+ if text
75
+ text = text
76
+ elsif member
77
+ text = (cls == @class_context) ? member : (cls + "." + member)
78
+ else
79
+ text = cls
80
+ end
81
+
82
+ file = @doc_context[:filename]
83
+ line = @doc_context[:linenr]
84
+ if !@relations[cls]
85
+ Logger.warn(:link, "#{full_link} links to non-existing class", file, line)
86
+ return text
87
+ elsif member
88
+ ms = find_members(cls, {:name => member, :tagname => type, :static => static})
89
+ if ms.length == 0
90
+ Logger.warn(:link, "#{full_link} links to non-existing member", file, line)
91
+ return text
92
+ end
93
+
94
+ if ms.length > 1
95
+ # When multiple public members, see if there remains just
96
+ # one when we ignore the static members. If there's more,
97
+ # report ambiguity. If there's only static members, also
98
+ # report ambiguity.
99
+ instance_ms = ms.find_all {|m| !m[:meta][:static] }
100
+ if instance_ms.length > 1
101
+ alternatives = instance_ms.map {|m| "#{m[:tagname]} in #{m[:owner]}" }.join(", ")
102
+ Logger.warn(:link_ambiguous, "#{full_link} is ambiguous: "+alternatives, file, line)
103
+ elsif instance_ms.length == 0
104
+ static_ms = ms.find_all {|m| m[:meta][:static] }
105
+ alternatives = static_ms.map {|m| "static " + m[:tagname].to_s }.join(", ")
106
+ Logger.warn(:link_ambiguous, "#{full_link} is ambiguous: "+alternatives, file, line)
107
+ end
108
+ end
109
+
110
+ return link(cls, member, text, type, static)
111
+ else
112
+ return link(cls, false, text)
113
+ end
114
+ end
115
+
116
+ # Looks input text for patterns like:
117
+ #
118
+ # My.ClassName
119
+ # MyClass#method
120
+ # #someProperty
121
+ #
122
+ # and converts them to links, as if they were surrounded with
123
+ # {@link} tag. One notable exception is that Foo is not created to
124
+ # link, even when Foo class exists, but Foo.Bar is. This is to
125
+ # avoid turning normal words into links. For example:
126
+ #
127
+ # Math involves a lot of numbers. Ext JS is a JavaScript framework.
128
+ #
129
+ # In these sentences we don't want to link "Math" and "Ext" to the
130
+ # corresponding JS classes. And that's why we auto-link only
131
+ # class names containing a dot "."
132
+ #
133
+ def create_magic_links(input)
134
+ cls_re = "([A-Z][A-Za-z0-9.]*[A-Za-z0-9])"
135
+ member_re = "(?:#([A-Za-z0-9]+))"
136
+
137
+ input.gsub(/\b#{cls_re}#{member_re}?\b|#{member_re}\b/m) do
138
+ replace_magic_link($1, $2 || $3)
139
+ end
140
+ end
141
+
142
+ def replace_magic_link(cls, member)
143
+ if cls && member
144
+ if @relations[cls] && get_matching_member(cls, {:name => member})
145
+ return link(cls, member, cls+"."+member)
146
+ else
147
+ warn_magic_link("#{cls}##{member} links to non-existing " + (@relations[cls] ? "member" : "class"))
148
+ end
149
+ elsif cls && cls =~ /\./
150
+ if @relations[cls]
151
+ return link(cls, nil, cls)
152
+ else
153
+ cls2, member2 = split_to_cls_and_member(cls)
154
+ if @relations[cls2] && get_matching_member(cls2, {:name => member2})
155
+ return link(cls2, member2, cls2+"."+member2)
156
+ elsif cls =~ /\.(js|css|html|php)\Z/
157
+ # Ignore common filenames
158
+ else
159
+ warn_magic_link("#{cls} links to non-existing class")
160
+ end
161
+ end
162
+ elsif !cls && member
163
+ if get_matching_member(@class_context, {:name => member})
164
+ return link(@class_context, member, member)
165
+ elsif member =~ /\A([A-F0-9]{3}|[A-F0-9]{6})\Z/i || member =~ /\A[0-9]/
166
+ # Ignore HEX color codes and
167
+ # member names beginning with number
168
+ else
169
+ warn_magic_link("##{member} links to non-existing member")
170
+ end
171
+ end
172
+
173
+ return "#{cls}#{member ? '#' : ''}#{member}"
174
+ end
175
+
176
+ def split_to_cls_and_member(str)
177
+ parts = str.split(/\./)
178
+ return [parts.slice(0, parts.length-1).join("."), parts.last]
179
+ end
180
+
181
+ def warn_magic_link(msg)
182
+ Logger.warn(:link_auto, msg, @doc_context[:filename], @doc_context[:linenr])
183
+ end
184
+
185
+ # applies the link template
186
+ def link(cls, member, anchor_text, type=nil, static=nil)
187
+ # Use the canonical class name for link (not some alternateClassName)
188
+ cls = @relations[cls][:name]
189
+ # prepend type name to member name
190
+ member = member && get_matching_member(cls, {:name => member, :tagname => type, :static => static})
191
+
192
+ @tpl.gsub(/(%[\w#-])/) do
193
+ case $1
194
+ when '%c'
195
+ cls
196
+ when '%m'
197
+ member ? member[:id] : ""
198
+ when '%#'
199
+ member ? "#" : ""
200
+ when '%-'
201
+ member ? "-" : ""
202
+ when '%a'
203
+ Util::HTML.escape(anchor_text||"")
204
+ else
205
+ $1
206
+ end
207
+ end
208
+ end
209
+
210
+ def get_matching_member(cls, query)
211
+ ms = find_members(cls, query).find_all {|m| !m[:private] }
212
+ if ms.length > 1
213
+ instance_ms = ms.find_all {|m| !m[:meta][:static] }
214
+ instance_ms.length > 0 ? instance_ms[0] : ms.find_all {|m| m[:meta][:static] }[0]
215
+ else
216
+ ms[0]
217
+ end
218
+ end
219
+
220
+ def find_members(cls, query)
221
+ @relations[cls] ? @relations[cls].find_members(query) : []
222
+ end
223
+
224
+ end
225
+
226
+ end
227
+ end
@@ -0,0 +1,67 @@
1
+ require 'jsduck/util/html'
2
+ require 'jsduck/logger'
3
+
4
+ module JsDuck
5
+ module Inline
6
+
7
+ # Implementation of inline tag {@video}
8
+ class Video
9
+ # Sets up instance to work in context of particular doc object.
10
+ # Used for error reporting.
11
+ attr_accessor :doc_context
12
+
13
+ def initialize(opts={})
14
+ @doc_context = {}
15
+
16
+ @templates = {
17
+ "html5" => '<video src="%u">%a</video>',
18
+ "vimeo" => [
19
+ '<p><object width="640" height="360">',
20
+ '<param name="allowfullscreen" value="true" />',
21
+ '<param name="allowscriptaccess" value="always" />',
22
+ '<param name="flashvars" value="api=1" />',
23
+ '<param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=%u&amp;server=vimeo.com&amp;color=4CC208&amp;fullscreen=1" />',
24
+ '<embed src="http://vimeo.com/moogaloop.swf?clip_id=%u&amp;server=vimeo.com&amp;color=4CC208&amp;fullscreen=1" ',
25
+ 'type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="640" height="360"></embed>',
26
+ '</object></p>',
27
+ ].join
28
+ }
29
+
30
+ @re = /\{@video\s+(\w+)\s+(\S*?)(?:\s+(.+?))?\}/m
31
+ end
32
+
33
+ # Takes StringScanner instance.
34
+ #
35
+ # Looks for inline tag at the current scan pointer position, when
36
+ # found, moves scan pointer forward and performs the apporpriate
37
+ # replacement.
38
+ def replace(input)
39
+ if input.check(@re)
40
+ input.scan(@re).sub(@re) { apply_tpl($1, $2, $3) }
41
+ else
42
+ false
43
+ end
44
+ end
45
+
46
+ # applies the video template of the specified type
47
+ def apply_tpl(type, url, alt_text)
48
+ unless @templates.has_key?(type)
49
+ ctx = @doc_context
50
+ Logger.warn(nil, "Unknown video type #{type}", ctx[:filename], ctx[:linenr])
51
+ end
52
+
53
+ @templates[type].gsub(/(%\w)/) do
54
+ case $1
55
+ when '%u'
56
+ url
57
+ when '%a'
58
+ Util::HTML.escape(alt_text||"")
59
+ else
60
+ $1
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ end
67
+ end
@@ -1,5 +1,5 @@
1
- require 'jsduck/json_duck'
2
- require 'jsduck/html'
1
+ require 'jsduck/util/json'
2
+ require 'jsduck/util/html'
3
3
 
4
4
  module JsDuck
5
5
 
@@ -16,9 +16,9 @@ module JsDuck
16
16
  relations.each do |cls|
17
17
  extract(cls[:doc]).each_with_index do |ex, i|
18
18
  @examples << {
19
- :id => cls.full_name + "-" + i.to_s,
20
- :name => cls.full_name + " example #" + (i+1).to_s,
21
- :href => '#!/api/' + cls.full_name,
19
+ :id => cls[:name] + "-" + i.to_s,
20
+ :name => cls[:name] + " example #" + (i+1).to_s,
21
+ :href => '#!/api/' + cls[:name],
22
22
  :code => ex[:code],
23
23
  :options => ex[:options],
24
24
  }
@@ -47,7 +47,7 @@ module JsDuck
47
47
 
48
48
  # Writes all found examples to .js file
49
49
  def write(filename)
50
- JsonDuck.write_jsonp(filename, "__inline_examples__", @examples)
50
+ Util::Json.write_jsonp(filename, "__inline_examples__", @examples)
51
51
  end
52
52
 
53
53
  # Extracts inline examples from HTML
@@ -65,7 +65,7 @@ module JsDuck
65
65
  ex = s.scan_until(@end_example_re).sub(@end_example_re, '')
66
66
 
67
67
  examples << {
68
- :code => HTML.unescape(HTML.strip_tags(ex)),
68
+ :code => Util::HTML.unescape(Util::HTML.strip_tags(ex)),
69
69
  :options => options,
70
70
  }
71
71
  else
@@ -25,7 +25,7 @@ module JsDuck
25
25
  # }
26
26
  #
27
27
  def parse
28
- @ast = Esprima.instance.parse(@input)
28
+ @ast = Esprima.parse(@input)
29
29
 
30
30
  @ast["comments"] = merge_comments(@ast["comments"])
31
31
  locate_comments
@@ -62,10 +62,11 @@ module JsDuck
62
62
  end
63
63
 
64
64
  # Two comments can be merged if they are both line-comments and
65
- # they are separated only by whitespace (but no newlines)
65
+ # they are separated only by whitespace (only one newline at the
66
+ # end of the first comment is allowed)
66
67
  def mergeable?(c1, c2)
67
68
  if c1["type"] == "Line" && c2["type"] == "Line"
68
- /\A[ \t]*\Z/ =~ @input.slice((c1["range"][1])..(c2["range"][0]-1))
69
+ /\A(\r\n|\n|\r)?[ \t]*\Z/ =~ @input.slice((c1["range"][1])..(c2["range"][0]-1))
69
70
  else
70
71
  false
71
72
  end
@@ -156,7 +157,7 @@ module JsDuck
156
157
  properties = NODE_TYPES[node["type"]]
157
158
 
158
159
  unless properties
159
- Logger.instance.fatal("Unknown node type: "+node["type"])
160
+ Logger.fatal("Unknown node type: "+node["type"])
160
161
  exit(1)
161
162
  end
162
163