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
@@ -1,58 +0,0 @@
1
- require 'jsduck/html'
2
- require 'jsduck/logger'
3
-
4
- module JsDuck
5
-
6
- # Implementation of inline tag {@video}
7
- class InlineVideo
8
- def initialize(opts={})
9
- @templates = {
10
- "html5" => '<video src="%u">%a</video>',
11
- "vimeo" => [
12
- '<p><object width="640" height="360">',
13
- '<param name="allowfullscreen" value="true" />',
14
- '<param name="allowscriptaccess" value="always" />',
15
- '<param name="flashvars" value="api=1" />',
16
- '<param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=%u&amp;server=vimeo.com&amp;color=4CC208&amp;fullscreen=1" />',
17
- '<embed src="http://vimeo.com/moogaloop.swf?clip_id=%u&amp;server=vimeo.com&amp;color=4CC208&amp;fullscreen=1" ',
18
- 'type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="640" height="360"></embed>',
19
- '</object></p>',
20
- ].join
21
- }
22
-
23
- @re = /\{@video\s+(\w+)\s+(\S*?)(?:\s+(.+?))?\}/m
24
- end
25
-
26
- # Takes StringScanner instance.
27
- #
28
- # Looks for inline tag at the current scan pointer position, when
29
- # found, moves scan pointer forward and performs the apporpriate
30
- # replacement.
31
- def replace(input, doc_context)
32
- if input.check(@re)
33
- input.scan(@re).sub(@re) { apply_tpl($1, $2, $3, doc_context) }
34
- else
35
- false
36
- end
37
- end
38
-
39
- # applies the video template of the specified type
40
- def apply_tpl(type, url, alt_text, ctx)
41
- unless @templates.has_key?(type)
42
- Logger.instance.warn(nil, "Unknown video type #{type}", ctx[:filename], ctx[:linenr])
43
- end
44
-
45
- @templates[type].gsub(/(%\w)/) do
46
- case $1
47
- when '%u'
48
- url
49
- when '%a'
50
- HTML.escape(alt_text||"")
51
- else
52
- $1
53
- end
54
- end
55
- end
56
- end
57
-
58
- end
@@ -1,30 +0,0 @@
1
- module JsDuck
2
-
3
- # A helper to use instead the builtin IO class to read files in
4
- # correct encoding.
5
- #
6
- # By default in Ruby 1.9 the encoding is auto-detected, which can
7
- # have surprising results. So in here we read in all files in UTF-8
8
- # (the default) or in some other encoding specified through --encoding
9
- # option and convert it to UTF-8 internally.
10
- class IO
11
- @@encoding = "UTF-8"
12
-
13
- # Sets the external encoding to be used for reading files.
14
- # When it's different from UTF-8, the input will be converted to UTF-8.
15
- def self.encoding=(e)
16
- if e =~ /^UTF-8$/i
17
- @@encoding = e
18
- else
19
- @@encoding = e+":UTF-8"
20
- end
21
- end
22
-
23
- # Reads given filename into string
24
- def self.read(filename)
25
- File.open(filename, "r:"+@@encoding) {|f| f.read }
26
- end
27
-
28
- end
29
-
30
- end
@@ -1,52 +0,0 @@
1
- require 'jsduck/io'
2
- require 'jsduck/logger'
3
- require 'json'
4
-
5
- module JsDuck
6
-
7
- # Wrapper around the json gem for use in JsDuck.
8
- #
9
- # The main benefit of it is that we have a central place for
10
- # controlling how the JSON is created (pretty-formatted or not).
11
- class JsonDuck
12
- @@pretty = false
13
-
14
- # Set to true to turn on pretty-formatting of JSON
15
- def self.pretty=(pretty)
16
- @@pretty = pretty
17
- end
18
-
19
- # Turns object into JSON, places it inside JavaScript that calls the
20
- # given callback name, and writes the result to file.
21
- def self.write_jsonp(filename, callback_name, data)
22
- jsonp = "Ext.data.JsonP." + callback_name + "(" + self.generate(data) + ");"
23
- File.open(filename, 'w') {|f| f.write(jsonp) }
24
- end
25
-
26
- # Turns object into JSON and writes inside a file
27
- def self.write_json(filename, data)
28
- File.open(filename, 'w') {|f| f.write(self.generate(data)) }
29
- end
30
-
31
- # Generates JSON from object
32
- def self.generate(data)
33
- @@pretty ? JSON.pretty_generate(data) : JSON.generate(data)
34
- end
35
-
36
- # Reads and parses JSON from file
37
- def self.read(filename)
38
- begin
39
- self.parse(JsDuck::IO.read(filename))
40
- rescue
41
- Logger.instance.fatal("#{filename} is not a valid JSON file")
42
- exit(1)
43
- end
44
- end
45
-
46
- # Parses JSON string
47
- def self.parse(string)
48
- JSON.parse(string)
49
- end
50
- end
51
-
52
- end
@@ -1,251 +0,0 @@
1
- require 'strscan'
2
-
3
- module JsDuck
4
-
5
- # Tokenizes JavaScript code into lexical tokens.
6
- #
7
- # Each token has a type and value.
8
- # Types and possible values for them are as follows:
9
- #
10
- # - :number -- 25
11
- # - :string -- "Hello world"
12
- # - :ident -- "foo"
13
- # - :regex -- "/abc/i"
14
- # - :operator -- "+"
15
- # - :doc_comment -- "/** My comment */"
16
- #
17
- # Plus a separate types for all keywords: :if, :while, :function, ...
18
- # For keywords the type and value are the same.
19
- #
20
- # Notice that doc-comments are recognized as tokens while normal
21
- # comments are ignored just as whitespace.
22
- #
23
- class Lexer
24
- # Input can be either a String or StringScanner.
25
- #
26
- # In the latter case we ensure that only #next will advance the
27
- # scanpointer of StringScanner - this allows context-switching
28
- # while parsing some string. Specifically we need this feature to
29
- # parse some JavaScript inside doc-comments.
30
- def initialize(input)
31
- @input = input.is_a?(StringScanner) ? input : StringScanner.new(input)
32
- @buffer = []
33
- end
34
-
35
- # Tests if given pattern matches the tokens that follow at current
36
- # position.
37
- #
38
- # Takes list of strings and symbols. Symbols are compared to
39
- # token type, while strings to token value. For example:
40
- #
41
- # look(:ident, "=", :regex)
42
- #
43
- def look(*tokens)
44
- buffer_tokens(tokens.length)
45
- i = 0
46
- tokens.all? do |t|
47
- tok = @buffer[i]
48
- i += 1
49
- if !tok
50
- false
51
- elsif t.instance_of?(Symbol)
52
- tok[:type] == t
53
- else
54
- tok[:value] == t
55
- end
56
- end
57
- end
58
-
59
- # Returns the value of next token, moving the current token cursor
60
- # also to next token.
61
- #
62
- # When full=true, returns full token as hash like so:
63
- #
64
- # {:type => :ident, :value => "foo"}
65
- #
66
- # For doc-comments the full token also contains the field :linenr,
67
- # pointing to the line where the doc-comment began.
68
- #
69
- def next(full=false)
70
- buffer_tokens(1)
71
- tok = @buffer.shift
72
- # advance the scanpointer to the position after this token
73
- @input.pos = tok[:pos]
74
- full ? tok : tok[:value]
75
- end
76
-
77
- # True when no more tokens.
78
- def empty?
79
- buffer_tokens(1)
80
- return !@buffer.first
81
- end
82
-
83
- # Ensures next n tokens are read in buffer
84
- #
85
- # At the end of buffering the initial position scanpointer is
86
- # restored. Only the #next method will advance the scanpointer in
87
- # a way that's visible outside this class.
88
- def buffer_tokens(n)
89
- prev_pos = @input.pos
90
- @input.pos = @buffer.last[:pos] if @buffer.last
91
- (n - @buffer.length).times do
92
- @previous_token = tok = next_token
93
- if tok
94
- # remember scanpointer position after each token
95
- tok[:pos] = @input.pos
96
- @buffer << tok
97
- end
98
- end
99
- @input.pos = prev_pos
100
- end
101
-
102
- # Parses out next token from input stream.
103
- #
104
- # For efficency we look for tokens in order of frequency in
105
- # JavaScript source code:
106
- #
107
- # - first check for most common operators.
108
- # - then for identifiers and keywords.
109
- # - then strings
110
- # - then comments
111
- #
112
- # The remaining token types are less frequent, so these are left
113
- # to the end.
114
- #
115
- def next_token
116
- while !@input.eos? do
117
- skip_white
118
- if @input.check(/[.(),;={}:]/)
119
- return {
120
- :type => :operator,
121
- :value => @input.scan(/./)
122
- }
123
- elsif @input.check(/[a-zA-Z_$]/)
124
- value = @input.scan(/[$\w]+/)
125
- kw = KEYWORDS[value]
126
- return {
127
- :type => kw || :ident,
128
- :value => kw || value
129
- }
130
- elsif @input.check(/'/)
131
- return {
132
- :type => :string,
133
- :value => @input.scan(/'([^'\\]|\\.)*('|\Z)/m).gsub(/\A'|'\Z/m, "")
134
- }
135
- elsif @input.check(/"/)
136
- return {
137
- :type => :string,
138
- :value => @input.scan(/"([^"\\]|\\.)*("|\Z)/m).gsub(/\A"|"\Z/m, "")
139
- }
140
- elsif @input.check(/\//)
141
- # Several things begin with dash:
142
- # - comments, regexes, division-operators
143
- if @input.check(/\/\*\*[^\/]/)
144
- return {
145
- :type => :doc_comment,
146
- # Calculate current line number, starting with 1
147
- :linenr => @input.string[0...@input.pos].count("\n") + 1,
148
- :value => @input.scan_until(/\*\/|\Z/).sub(/\A\/\*\*/, "").sub(/\*\/\Z/, "")
149
- }
150
- elsif @input.check(/\/\*/)
151
- # skip multiline comment
152
- @input.scan_until(/\*\/|\Z/)
153
- elsif @input.check(/\/\//)
154
- # skip line comment
155
- @input.scan_until(/\n|\Z/)
156
- elsif regex?
157
- return {
158
- :type => :regex,
159
- :value => @input.scan(META_REGEX)
160
- }
161
- else
162
- return {
163
- :type => :operator,
164
- :value => @input.scan(/\//)
165
- }
166
- end
167
- elsif @input.check(/[0-9]+/)
168
- nr = @input.scan(/[0-9]+(\.[0-9]*)?/)
169
- return {
170
- :type => :number,
171
- :value => nr
172
- }
173
- elsif @input.check(/./)
174
- return {
175
- :type => :operator,
176
- :value => @input.scan(/./)
177
- }
178
- end
179
- end
180
- end
181
-
182
- # A slash "/" is a division operator if it follows:
183
- # - identifier
184
- # - the "this" keyword
185
- # - number
186
- # - closing bracket )
187
- # - closing square-bracket ]
188
- # Otherwise it's a beginning of regex
189
- def regex?
190
- if @previous_token
191
- type = @previous_token[:type]
192
- value = @previous_token[:value]
193
- if type == :ident || type == :number
194
- return false
195
- elsif type == :this
196
- return false
197
- elsif type == :operator && (value == ")" || value == "]")
198
- return false
199
- end
200
- end
201
- return true
202
- end
203
-
204
- def skip_white
205
- @input.scan(/\s+/)
206
- end
207
-
208
- # A regex to match a regex
209
- META_REGEX = %r{
210
- / (?# beginning )
211
- (
212
- [^/\[\\] (?# any character except \ / [ )
213
- |
214
- \\. (?# an escaping \ followed by any character )
215
- |
216
- \[ ([^\]\\]|\\.)* \] (?# [...] containing any characters including / )
217
- (?# except \ ] which have to be escaped )
218
- )*
219
- (/[gim]*|\Z) (?# ending + modifiers )
220
- }x
221
-
222
- KEYWORDS = {
223
- "break" => :break,
224
- "case" => :case,
225
- "catch" => :catch,
226
- "continue" => :continue,
227
- "default" => :default,
228
- "delete" => :delete,
229
- "do" => :do,
230
- "else" => :else,
231
- "finally" => :finally,
232
- "for" => :for,
233
- "function" => :function,
234
- "if" => :if,
235
- "in" => :in,
236
- "instanceof" => :instanceof,
237
- "new" => :new,
238
- "return" => :return,
239
- "switch" => :switch,
240
- "this" => :this,
241
- "throw" => :throw,
242
- "try" => :try,
243
- "typeof" => :typeof,
244
- "var" => :var,
245
- "void" => :void,
246
- "while" => :while,
247
- "with" => :with,
248
- }
249
- end
250
-
251
- end
@@ -1,19 +0,0 @@
1
- module JsDuck
2
- # A class that does nothing.
3
- # Responds to all methods by returning self, unless a hash passed to
4
- # constructor.
5
- # See: http://en.wikipedia.org/wiki/Null_Object_pattern
6
- class NullObject
7
- # Optionally takes a hash of method_name => return_value pairs,
8
- # making it return those values for those methods, sort of like
9
- # OpenStruct, but for all other methods self is still returned and
10
- # any number of arguments is accepted.
11
- def initialize(methods={})
12
- @methods = methods
13
- end
14
-
15
- def method_missing(meth, *args, &block)
16
- @methods.has_key?(meth) ? @methods[meth] : self
17
- end
18
- end
19
- end
@@ -1,11 +0,0 @@
1
- require 'rbconfig'
2
-
3
- module JsDuck
4
-
5
- # Simple helper class to detect operating system
6
- class OS
7
- def self.windows?
8
- RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
9
- end
10
- end
11
- end
@@ -1,32 +0,0 @@
1
- require 'parallel'
2
-
3
- module JsDuck
4
-
5
- # Wrapper around the parallel gem that falls back to simple
6
- # Array#map and Array#each when :in_processes => 0 specified.
7
- class ParallelWrap
8
- @@in_processes = nil
9
-
10
- # Sets globally the nr of processes to use.
11
- def self.in_processes=(n)
12
- @@in_processes = n
13
- end
14
-
15
- def self.each(arr, &block)
16
- if @@in_processes == 0
17
- arr.each &block
18
- else
19
- Parallel.each(arr, {:in_processes => @@in_processes}, &block)
20
- end
21
- end
22
-
23
- def self.map(arr, &block)
24
- if @@in_processes == 0
25
- arr.map &block
26
- else
27
- Parallel.map(arr, {:in_processes => @@in_processes}, &block)
28
- end
29
- end
30
- end
31
-
32
- end