jsduck 4.0.1 → 4.1.1

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