jsduck 3.7.0 → 3.8.0

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.
@@ -1,3 +1,4 @@
1
+ require 'jsduck/io'
1
2
  require 'json'
2
3
 
3
4
  module JsDuck
@@ -33,7 +34,7 @@ module JsDuck
33
34
 
34
35
  # Reads and parses JSON from file
35
36
  def self.read(filename)
36
- self.parse(IO.read(filename))
37
+ self.parse(JsDuck::IO.read(filename))
37
38
  end
38
39
 
39
40
  # Parses JSON string
@@ -1,6 +1,7 @@
1
1
  require 'optparse'
2
2
  require 'jsduck/meta_tag_registry'
3
3
  require 'jsduck/logger'
4
+ require 'jsduck/io'
4
5
 
5
6
  module JsDuck
6
7
 
@@ -163,11 +164,8 @@ module JsDuck
163
164
  @meta_tag_paths << canonical(path)
164
165
  end
165
166
 
166
- opts.on('--no-warnings',
167
- "Turns off all warnings.",
168
- "(Deprecated, use --warnings=-all instead.)", " ") do
169
- Logger.instance.warn(nil, "--no-warnings is deprecated. Use --warnings=-all instead.")
170
- Logger.instance.set_warning(:all, false)
167
+ opts.on('--encoding=NAME', "Input encoding (defaults to UTF-8).", " ") do |encoding|
168
+ JsDuck::IO.encoding = encoding
171
169
  end
172
170
 
173
171
  opts.on('-v', '--verbose', "This will fill up your console.", " ") do
@@ -260,7 +258,7 @@ module JsDuck
260
258
  "Possible placeholders:",
261
259
  "%u - URL from @img tag (e.g. 'some/path.png')",
262
260
  "%a - alt text for image",
263
- "Default is: '<p><img src=\"doc-resources/%u\" alt=\"%a\"></p>'", " ") do |tpl|
261
+ "Default is: '<p><img src=\"%u\" alt=\"%a\"></p>'", " ") do |tpl|
264
262
  @img_tpl = tpl
265
263
  end
266
264
 
@@ -380,7 +378,7 @@ module JsDuck
380
378
  main_opts = [
381
379
  /--output/,
382
380
  /--builtin-classes/,
383
- /--no-warnings/,
381
+ /--encoding/,
384
382
  /--verbose/,
385
383
  /--help/,
386
384
  /--version/,
@@ -449,7 +447,7 @@ module JsDuck
449
447
 
450
448
  # Extracts files of first build in jsb file
451
449
  def extract_jsb_files(jsb_file)
452
- json = JSON.parse(IO.read(jsb_file))
450
+ json = JSON.parse(JsDuck::IO.read(jsb_file))
453
451
  basedir = File.dirname(jsb_file)
454
452
 
455
453
  return json["builds"][0]["packages"].map do |package_id|
@@ -4,11 +4,12 @@ module JsDuck
4
4
  # Creates list of all members in all classes that is used by the
5
5
  # searching feature in UI.
6
6
  class SearchData
7
- # Given list of class documentation objects returns an array of
8
- # hashes describing all the members.
9
- def create(docs)
7
+ # Given list of classes and other assets, returns an array of
8
+ # hashes describing the search data.
9
+ def create(classes, assets)
10
10
  list = []
11
- docs.each do |cls|
11
+
12
+ classes.each do |cls|
12
13
  list << class_node(cls)
13
14
 
14
15
  cls[:alternateClassNames].each do |name|
@@ -32,61 +33,96 @@ module JsDuck
32
33
  end
33
34
  end
34
35
  end
36
+
37
+ assets.guides.each_item {|g| list << guide_node(g) }
38
+
39
+ assets.videos.each_item {|v| list << video_node(v) }
40
+
41
+ assets.examples.each_item {|e| list << example_node(e) }
42
+
35
43
  list
36
44
  end
37
45
 
38
- # Creates structure representing one alias
46
+ private
47
+
39
48
  def alias_node(key, name, cls)
40
49
  return {
41
- :cls => alias_display_name(key)+": "+name,
42
- :member => name,
43
- :type => :class,
44
- :icon => cls.icon,
45
- :id => cls.full_name,
50
+ :name => name,
51
+ :fullName => alias_display_name(key)+": "+name,
52
+ :icon => cls.icon + "-redirect",
53
+ :url => "#!/api/" + cls.full_name,
46
54
  :meta => cls[:meta],
47
55
  :sort => 0,
48
56
  }
49
57
  end
50
58
 
51
- # Creates structure representing one class
52
59
  def class_node(cls)
53
60
  return {
54
- :cls => cls.full_name,
55
- :member => cls.short_name,
56
- :type => :class,
61
+ :name => cls.short_name,
62
+ :fullName => cls.full_name,
57
63
  :icon => cls.icon,
58
- :id => cls.full_name,
64
+ :url => "#!/api/" + cls.full_name,
59
65
  :meta => cls[:meta],
60
66
  :sort => 1,
61
67
  }
62
68
  end
63
69
 
64
- # Creates structure representing one alternate classname
65
70
  def alt_node(name, cls)
66
71
  return {
67
- :cls => name,
68
- :member => Class.short_name(name),
72
+ :name => Class.short_name(name),
73
+ :fullName => name,
69
74
  :type => :class,
70
- :icon => cls.icon,
71
- :id => cls.full_name,
75
+ :icon => cls.icon + "-redirect",
76
+ :url => "#!/api/" + cls.full_name,
72
77
  :meta => cls[:meta],
73
78
  :sort => 2,
74
79
  }
75
80
  end
76
81
 
77
- # Creates structure representing one member
78
82
  def member_node(member, cls)
79
83
  return {
80
- :cls => cls.full_name,
81
- :member => member[:name],
82
- :type => :member,
84
+ :name => member[:name],
85
+ :fullName => cls.full_name + "." + member[:name],
83
86
  :icon => "icon-" + member[:tagname].to_s,
84
- :id => cls.full_name + "-" + member[:id],
87
+ :url => "#!/api/" + cls.full_name + "-" + member[:id],
85
88
  :meta => member[:meta],
86
89
  :sort => 3,
87
90
  }
88
91
  end
89
92
 
93
+ def guide_node(guide)
94
+ return {
95
+ :name => guide["title"],
96
+ :fullName => "guide: " + guide["title"],
97
+ :icon => "icon-guide",
98
+ :url => "#!/guide/" + guide["name"],
99
+ :meta => {},
100
+ :sort => 4,
101
+ }
102
+ end
103
+
104
+ def video_node(video)
105
+ return {
106
+ :name => video["title"],
107
+ :fullName => "video: " + video["title"],
108
+ :icon => "icon-video",
109
+ :url => "#!/video/" + video["name"],
110
+ :meta => {},
111
+ :sort => 4,
112
+ }
113
+ end
114
+
115
+ def example_node(example)
116
+ return {
117
+ :name => example["title"],
118
+ :fullName => "example: " + example["title"],
119
+ :icon => "icon-example",
120
+ :url => "#!/example/" + example["name"],
121
+ :meta => {},
122
+ :sort => 4,
123
+ }
124
+ end
125
+
90
126
  # Some alias types are shown differently.
91
127
  # e.g. instead of "widget:" we show "xtype:"
92
128
  def alias_display_name(key)
@@ -3,9 +3,6 @@ require "jsduck/logger"
3
3
 
4
4
  module JsDuck::Tag
5
5
  # Implementation of @aside tag.
6
- #
7
- # To document members that were present in previous version but are
8
- # completely gone now. Other than that it behaves exactly like @deprecated.
9
6
  class Aside < JsDuck::MetaTag
10
7
  def initialize
11
8
  @name = "aside"
@@ -2,17 +2,40 @@ require 'strscan'
2
2
 
3
3
  module JsDuck
4
4
 
5
- # Validates the syntax of type definitions
5
+ # Validates the syntax of type definitions.
6
6
  #
7
- # Quick summary of supported types:
7
+ # The parser supports a combination of two syntaxes:
8
8
  #
9
- # - SomeType
10
- # - Name.spaced.Type
11
- # - Number[]
12
- # - String/RegExp
13
- # - Type...
9
+ # 1. Traditional type expressions found in ExtJS code:
14
10
  #
15
- # Details are covered in spec.
11
+ # SomeType
12
+ # Name.spaced.Type
13
+ # Number[]
14
+ # String/RegExp
15
+ # Type...
16
+ #
17
+ # 2. Google Closure Compiler Type Expressions:
18
+ #
19
+ # boolean
20
+ # Window
21
+ # goog.ui.Menu
22
+ #
23
+ # Array.<string>
24
+ # Object.<string, number>
25
+ #
26
+ # {myNum: number, myObject}
27
+ #
28
+ # (number|boolean)
29
+ # ?number
30
+ # !Object
31
+ # ...number
32
+ # *
33
+ #
34
+ # function(string, boolean): number
35
+ # function(new:goog.ui.Menu, string)
36
+ # function(this:goog.ui.Menu, string)
37
+ # function(?string=, number=)
38
+ # function(string, ...[number])
16
39
  #
17
40
  class TypeParser
18
41
  # Allows to check the type of error that was encountered.
@@ -29,22 +52,27 @@ module JsDuck
29
52
  def initialize(relations={}, formatter={})
30
53
  @relations = relations
31
54
  @formatter = formatter
55
+ @primitives = {
56
+ "boolean" => "Boolean",
57
+ "number" => "Number",
58
+ "string" => "String",
59
+ "null" => "null",
60
+ "undefined" => "undefined",
61
+ "void" => "void",
62
+ }
32
63
  end
33
64
 
65
+ # Parses the type definition
66
+ #
67
+ # <type> ::= <alteration-type>
68
+ #
34
69
  def parse(str)
35
70
  @input = StringScanner.new(str)
36
71
  @error = :syntax
37
72
  @out = []
38
73
 
39
- # Return immediately if base type doesn't match
40
- return false unless base_type
41
-
42
- # Go through enumeration of types, separated with "/"
43
- while @input.check(/\//)
44
- @out << @input.scan(/\//)
45
- # Fail if there's no base type after "/"
46
- return false unless base_type
47
- end
74
+ # Return immediately if the base type doesn't match
75
+ return false unless alteration_type
48
76
 
49
77
  # Concatenate all output
50
78
  @out = @out.join
@@ -53,34 +81,281 @@ module JsDuck
53
81
  return @input.eos?
54
82
  end
55
83
 
56
- # The basic type
84
+ private
85
+
86
+ #
87
+ # <alteration-type> ::= <varargs-type> [ ("/" | "|") <varargs-type> ]*
88
+ #
89
+ def alteration_type
90
+ skip_whitespace
91
+
92
+ # Return immediately if varargs-type doesn't match
93
+ return false unless varargs_type
94
+
95
+ skip_whitespace
96
+
97
+ # Go through enumeration of types, separated with "/" or "|"
98
+ while @input.check(/[\/|]/)
99
+ @out << @input.scan(/[\/|]/)
100
+
101
+ skip_whitespace
102
+ return false unless varargs_type
103
+ skip_whitespace
104
+ end
105
+
106
+ true
107
+ end
108
+
109
+ #
110
+ # <varargs-type> ::= "..." <null-type>
111
+ # | "..." "[" <null-type> "]"
112
+ # | <null-type> "..."
113
+ # | <null-type>
114
+ #
115
+ def varargs_type
116
+ if @input.scan(/\.\.\./)
117
+ varargs = true
118
+ @out << "..."
119
+ if @input.scan(/\[/)
120
+ varargs_bracketed = true
121
+ @out << "["
122
+ end
123
+ end
124
+
125
+ return false unless null_type
126
+
127
+ if !varargs
128
+ @out << "..." if @input.scan(/\.\.\./)
129
+ end
130
+
131
+ if varargs_bracketed
132
+ return false unless @input.scan(/\]/)
133
+ @out << "]"
134
+ end
135
+
136
+ true
137
+ end
138
+
139
+ #
140
+ # <null-type> ::= [ "?" | "!" ] <array-type>
141
+ #
142
+ # <array-type> ::= <atomic-type> [ "[]" ]*
143
+ #
144
+ # <atomic-type> ::= <union-type> | <record-type> | <function-type> | <type-name>
145
+ #
146
+ def null_type
147
+ if nullability = @input.scan(/[?!]/)
148
+ @out << nullability
149
+ end
150
+
151
+ if @input.check(/\(/)
152
+ return false unless union_type
153
+ elsif @input.check(/\{/)
154
+ return false unless record_type
155
+ elsif @input.check(/function\(/)
156
+ return false unless function_type
157
+ else
158
+ return false unless type_name
159
+ end
160
+
161
+ while @input.scan(/\[\]/)
162
+ @out << "[]"
163
+ end
164
+
165
+ true
166
+ end
167
+
168
+ #
169
+ # <union-type> ::= "(" <alteration-type> ")"
170
+ #
171
+ def union_type
172
+ @out << @input.scan(/\(/)
173
+
174
+ return false unless alteration_type
175
+
176
+ return false unless @input.scan(/\)/)
177
+ @out << ")"
178
+
179
+ true
180
+ end
181
+
182
+ #
183
+ # <record-type> ::= "{" <rtype-item> [ "," <rtype-item> ]* "}"
184
+ #
185
+ def record_type
186
+ @out << @input.scan(/\{/)
187
+
188
+ return false unless rtype_item
189
+
190
+ while @input.scan(/,/)
191
+ @out << ","
192
+ return false unless rtype_item
193
+ end
194
+
195
+ return false unless @input.scan(/\}/)
196
+ @out << "}"
197
+
198
+ true
199
+ end
200
+
201
+ #
202
+ # <rtype-item> ::= <ident> ":" <null-type>
203
+ # | <ident>
204
+ #
205
+ def rtype_item
206
+ skip_whitespace
207
+
208
+ key = @input.scan(/[a-zA-Z0-9_]+/)
209
+ return false unless key
210
+
211
+ skip_whitespace
212
+ if @input.scan(/:/)
213
+ @out << ":"
214
+ skip_whitespace
215
+ return false unless null_type
216
+ skip_whitespace
217
+ end
218
+
219
+ true
220
+ end
221
+
222
+ #
223
+ # <function-type> ::= "function(" <function-type-arguments> ")" [ ":" <null-type> ]
224
+ #
225
+ def function_type
226
+ @out << @input.scan(/function\(/)
227
+
228
+ skip_whitespace
229
+ if !@input.check(/\)/)
230
+ return false unless function_type_arguments
231
+ end
232
+
233
+ return false unless @input.scan(/\)/)
234
+ @out << ")"
235
+
236
+ skip_whitespace
237
+ if @input.scan(/:/)
238
+ @out << ":"
239
+ skip_whitespace
240
+ return false unless null_type
241
+ end
242
+
243
+ true
244
+ end
245
+
246
+ #
247
+ # <function-type-arguments> ::= <ftype-first-arg> [ "," <ftype-arg> ]*
57
248
  #
58
- # <ident> [ "." <ident> ]* [ "[]" ]* [ "..." ]
249
+ # <ftype-first-arg> ::= "new" ":" <type-name>
250
+ # | "this" ":" <type-name>
251
+ # | <ftype-arg>
59
252
  #
60
- # dot-separated identifiers followed by optional "[]"
61
- def base_type
62
- type = @input.scan(/[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)*/)
253
+ def function_type_arguments
254
+ skip_whitespace
255
+
256
+ # First argument is special
257
+ if s = @input.scan(/new\s*:\s*/)
258
+ @out << s
259
+ return false unless type_name
260
+ elsif s = @input.scan(/this\s*:\s*/)
261
+ @out << s
262
+ return false unless type_name
263
+ else
264
+ return false unless ftype_arg
265
+ end
266
+
267
+ skip_whitespace
268
+
269
+ # Go through additional arguments, separated with ","
270
+ while @input.check(/,/)
271
+ @out << @input.scan(/,/)
272
+ return false unless ftype_arg
273
+ end
63
274
 
64
- if !type
275
+ true
276
+ end
277
+
278
+ #
279
+ # <ftype-arg> ::= <alteration-type> [ "=" ]
280
+ #
281
+ def ftype_arg
282
+ return false unless alteration_type
283
+
284
+ # Each argument can be optional (ending with "=")
285
+ @out << "=" if @input.scan(/[=]/)
286
+ skip_whitespace
287
+
288
+ true
289
+ end
290
+
291
+ #
292
+ # <type-name> ::= <type-application> | "*"
293
+ #
294
+ # <type-application> ::= <ident-chain> [ "." "<" <type-arguments> ">" ]
295
+ #
296
+ # <type-arguments> ::= <alteration-type> [ "," <alteration-type> ]*
297
+ #
298
+ # <ident-chain> ::= <ident> [ "." <ident> ]*
299
+ #
300
+ # <ident> ::= [a-zA-Z0-9_]+
301
+ #
302
+ def type_name
303
+ name = @input.scan(/[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)*|\*/)
304
+
305
+ if !name
65
306
  return false
66
- elsif @relations[type]
67
- @out << @formatter.link(type, nil, type)
68
- elsif @relations.ignore?(type) || type == "undefined"
69
- @out << type
307
+ elsif @relations[name]
308
+ @out << @formatter.link(name, nil, name)
309
+ elsif @primitives[name]
310
+ if @relations[@primitives[name]]
311
+ @out << @formatter.link(@primitives[name], nil, name)
312
+ else
313
+ @out << name
314
+ end
315
+ elsif @relations.ignore?(name) || name == "*"
316
+ @out << name
70
317
  else
71
318
  @error = :name
72
319
  return false
73
320
  end
74
321
 
75
- while @input.scan(/\[\]/)
76
- @out << "[]"
322
+ # All type names besides * can be followed by .<arguments>
323
+ if name != "*" && @input.scan(/\.</)
324
+ return false unless type_arguments
325
+ return false unless @input.scan(/>/)
77
326
  end
78
327
 
79
- @out << "..." if @input.scan(/\.\.\./)
328
+ true
329
+ end
330
+
331
+ #
332
+ # <type-arguments> ::= <alteration-type> [ "," <alteration-type> ]*
333
+ #
334
+ def type_arguments
335
+ skip_whitespace
336
+
337
+ # First argument is required
338
+ return false unless alteration_type
339
+
340
+ skip_whitespace
341
+
342
+ # Go through additional arguments, separated with ","
343
+ while @input.check(/,/)
344
+ @out << @input.scan(/,/)
345
+
346
+ skip_whitespace
347
+ return false unless alteration_type
348
+ skip_whitespace
349
+ end
80
350
 
81
351
  true
82
352
  end
83
353
 
354
+ def skip_whitespace
355
+ ws = @input.scan(/\s*/)
356
+ @out << ws if ws
357
+ end
358
+
84
359
  end
85
360
 
86
361
  end