jsduck 3.0.pre → 3.0.pre2

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.
data/lib/jsduck/merger.rb CHANGED
@@ -113,8 +113,7 @@ module JsDuck
113
113
  :mixins => detect_list(:mixins, doc_map, code),
114
114
  :alternateClassNames => detect_list(:alternateClassNames, doc_map, code),
115
115
  :xtypes => detect_xtypes(doc_map, code),
116
- :author => detect_author(doc_map),
117
- :docauthor => detect_docauthor(doc_map),
116
+ :meta => detect_meta(doc_map),
118
117
  :singleton => detect_singleton(doc_map, code),
119
118
  :requires => detect_list(:requires, doc_map, code),
120
119
  :uses => detect_list(:uses, doc_map, code),
@@ -144,6 +143,7 @@ module JsDuck
144
143
  :doc => detect_doc(docs),
145
144
  :params => detect_params(docs, code),
146
145
  :return => detect_return(doc_map, name == "constructor" ? "Object" : "undefined"),
146
+ :template => !!doc_map[:template],
147
147
  }, doc_map)
148
148
  end
149
149
 
@@ -166,9 +166,10 @@ module JsDuck
166
166
  :owner => detect_owner(doc_map) || owner,
167
167
  :type => detect_type(:cfg, doc_map, code),
168
168
  :doc => detect_doc(docs),
169
- :optional => detect_optional(:cfg, doc_map),
169
+ :required => detect_required(:cfg, doc_map),
170
170
  :default => detect_default(:cfg, doc_map, code),
171
171
  :properties => detect_subproperties(docs, :cfg),
172
+ :accessor => !!doc_map[:accessor],
172
173
  }, doc_map)
173
174
  end
174
175
 
@@ -208,7 +209,7 @@ module JsDuck
208
209
 
209
210
  # Detects properties common for each doc-object and adds them
210
211
  def add_shared(hash, doc_map)
211
- return hash.merge({
212
+ hash.merge!({
212
213
  :private => !!doc_map[:private],
213
214
  :protected => !!doc_map[:protected],
214
215
  :static => !!doc_map[:static],
@@ -216,6 +217,12 @@ module JsDuck
216
217
  :deprecated => detect_deprecated(doc_map),
217
218
  :alias => doc_map[:alias] ? doc_map[:alias].first : nil,
218
219
  })
220
+ hash[:id] = create_member_id(hash)
221
+ return hash
222
+ end
223
+
224
+ def create_member_id(m)
225
+ "#{m[:static] ? 'static-' : ''}#{m[:tagname]}-#{m[:name]}"
219
226
  end
220
227
 
221
228
  def detect_name(tagname, doc_map, code, name_type = :last_name)
@@ -265,7 +272,9 @@ module JsDuck
265
272
 
266
273
  def detect_extends(doc_map, code)
267
274
  if doc_map[:extends]
268
- doc_map[:extends].first[:extends]
275
+ cls = doc_map[:extends].first[:extends]
276
+ # Ignore extending of the Object class
277
+ cls == "Object" ? nil : cls
269
278
  elsif code[:type] == :assignment && code[:right] && code[:right][:type] == :ext_extend
270
279
  code[:right][:extend].join(".")
271
280
  elsif code[:type] == :ext_define
@@ -291,9 +300,9 @@ module JsDuck
291
300
  return explicit_name == "" || explicit_name == implicit_name
292
301
  end
293
302
 
294
- def detect_optional(tagname, doc_map)
303
+ def detect_required(tagname, doc_map)
295
304
  main_tag = doc_map[tagname] ? doc_map[tagname].first : {}
296
- return main_tag[:optional] != false
305
+ return main_tag[:optional] == false
297
306
  end
298
307
 
299
308
  # for detecting mixins and alternateClassNames
@@ -309,20 +318,26 @@ module JsDuck
309
318
 
310
319
  def detect_xtypes(doc_map, code)
311
320
  if doc_map[:xtype]
312
- doc_map[:xtype].map {|tag| tag[:name] }
321
+ {"widget" => doc_map[:xtype].map {|tag| tag[:name] } }
313
322
  elsif code[:alias]
314
- code[:alias].find_all {|a| a =~ /^widget\./ }.map {|a| a.sub(/^widget\./, "") }
323
+ xtypes = {}
324
+ code[:alias].each do |a|
325
+ if a =~ /^(\w+)\.(\w+)$/
326
+ if xtypes[$1]
327
+ xtypes[$1] << $2
328
+ else
329
+ xtypes[$1] = [$2]
330
+ end
331
+ end
332
+ end
333
+ xtypes
315
334
  else
316
- []
335
+ {}
317
336
  end
318
337
  end
319
338
 
320
- def detect_author(doc_map)
321
- doc_map[:author] ? doc_map[:author].first[:name] : nil
322
- end
323
-
324
- def detect_docauthor(doc_map)
325
- doc_map[:docauthor] ? doc_map[:docauthor].first[:name] : nil
339
+ def detect_meta(doc_map)
340
+ doc_map[:meta] ? doc_map[:meta].map {|tag| {:name => tag[:name], :content => tag[:content]} } : []
326
341
  end
327
342
 
328
343
  def detect_deprecated(doc_map)
@@ -9,6 +9,7 @@ module JsDuck
9
9
  attr_accessor :output_dir
10
10
  attr_accessor :ignore_global
11
11
  attr_accessor :external_classes
12
+ attr_accessor :meta_tags
12
13
  attr_accessor :warnings
13
14
  attr_accessor :verbose
14
15
 
@@ -36,6 +37,7 @@ module JsDuck
36
37
  attr_accessor :template_links
37
38
  attr_accessor :extjs_path
38
39
  attr_accessor :local_storage_db
40
+ attr_accessor :ext_namespaces
39
41
 
40
42
  def initialize
41
43
  @input_files = []
@@ -63,15 +65,19 @@ module JsDuck
63
65
  "CSSStyleRule",
64
66
  "Event",
65
67
  ]
68
+ @meta_tags = [
69
+ {:name => "author", :title => "Author", :strip => / *<.*?> */},
70
+ {:name => "docauthor", :title => "Documentation author", :strip => / *<.*?> */},
71
+ ]
66
72
 
67
73
  @warnings = true
68
74
  @verbose = false
69
- @version = "3.0.pre"
75
+ @version = "3.0.pre2"
70
76
 
71
77
  # Customizing output
72
78
  @title = "Sencha Docs - Ext JS"
73
79
  @header = "<strong>Sencha Docs</strong> Ext JS"
74
- @footer = 'Generated with <a href="https://github.com/senchalabs/jsduck">JSDuck</a> #{@version}.'
80
+ @footer = "Generated with <a href='https://github.com/senchalabs/jsduck'>JSDuck</a> #{@version}."
75
81
  @head_html = ""
76
82
  @body_html = ""
77
83
  @welcome = nil
@@ -90,10 +96,18 @@ module JsDuck
90
96
 
91
97
  # Debugging
92
98
  @processes = nil
93
- @template_dir = File.dirname(File.dirname(File.dirname(__FILE__))) + "/template-min"
99
+ @root_dir = File.dirname(File.dirname(File.dirname(__FILE__)))
100
+ @template_dir = @root_dir + "/template-min"
94
101
  @template_links = false
95
102
  @extjs_path = "extjs/ext-all.js"
96
103
  @local_storage_db = "docs"
104
+ @ext_namespaces = ["Ext"]
105
+ end
106
+
107
+ # Make options object behave like hash.
108
+ # This allows us to substitute it with hash in unit tests.
109
+ def [](key)
110
+ send(key)
97
111
  end
98
112
 
99
113
  def parse!(argv)
@@ -107,8 +121,8 @@ module JsDuck
107
121
 
108
122
  opts.on('-o', '--output=PATH',
109
123
  "Directory to output all this amazing documentation.",
110
- "This option MUST be specified.", " ") do |path|
111
- @output_dir = path
124
+ "This option MUST be specified (unless --stdout).", " ") do |path|
125
+ @output_dir = canonical(path)
112
126
  end
113
127
 
114
128
  opts.on('--ignore-global', "Turns off the creation of global class.", " ") do
@@ -122,6 +136,20 @@ module JsDuck
122
136
  @external_classes += classes
123
137
  end
124
138
 
139
+ opts.on('--builtin-classes',
140
+ "Includes docs for JavaScript builtin classes.", " ") do
141
+ read_filenames(@root_dir + "/js-classes")
142
+ end
143
+
144
+ opts.on('--meta-tags @name=Title,...', Array,
145
+ "Defines custom meta-data tags in addition to",
146
+ "@author and @docauthor. Experimantal!", " ") do |tags|
147
+ tags.each do |t|
148
+ t = t.split(/=/)
149
+ @meta_tags << {:name => t[0].sub(/^@/, ""), :title => t[1]}
150
+ end
151
+ end
152
+
125
153
  opts.on('--no-warnings', "Turns off warnings.", " ") do
126
154
  @warnings = false
127
155
  end
@@ -156,7 +184,7 @@ module JsDuck
156
184
 
157
185
  opts.on('--welcome=PATH',
158
186
  "Path to HTML file with content for welcome page.", " ") do |path|
159
- @welcome = path
187
+ @welcome = canonical(path)
160
188
  end
161
189
 
162
190
  opts.on('--guides=PATH',
@@ -164,26 +192,26 @@ module JsDuck
164
192
  "should be in a dir containing the actual guides.",
165
193
  "A guide is a dir containing README.md, icon.png,",
166
194
  "and other images referenced by the README.md file.", " ") do |path|
167
- @guides = path
195
+ @guides = canonical(path)
168
196
  end
169
197
 
170
198
  opts.on('--videos=PATH',
171
199
  "Path to JSON file describing the videos.", " ") do |path|
172
- @videos = path
200
+ @videos = canonical(path)
173
201
  end
174
202
 
175
203
  opts.on('--examples=PATH',
176
204
  "Path JSON file describing the examples.", " ") do |path|
177
- @examples = path
205
+ @examples = canonical(path)
178
206
  end
179
207
 
180
208
  opts.on('--categories=PATH',
181
209
  "Path to JSON file which defines categories for classes.", " ") do |path|
182
- @categories_path = path
210
+ @categories_path = canonical(path)
183
211
  end
184
212
 
185
213
  opts.on('--inline-examples=PATH', "Path to inline examples directory.", " ") do |path|
186
- @inline_examples_dir = path
214
+ @inline_examples_dir = canonical(path)
187
215
  end
188
216
 
189
217
  opts.on('--pretty-json', "Turn on pretty-printing of JSON.", " ") do
@@ -237,7 +265,7 @@ module JsDuck
237
265
 
238
266
  opts.on('--template=PATH',
239
267
  "Directory containing doc-browser UI template.", " ") do |path|
240
- @template_dir = path
268
+ @template_dir = canonical(path)
241
269
  end
242
270
 
243
271
  opts.on('--template-links',
@@ -250,7 +278,7 @@ module JsDuck
250
278
  opts.on('--extjs-path=PATH',
251
279
  "Path for main ExtJS JavaScript file. Useful for specifying",
252
280
  "something different than extjs/ext.js", " ") do |path|
253
- @extjs_path = path
281
+ @extjs_path = path # NB! must be relative path
254
282
  end
255
283
 
256
284
  opts.on('--local-storage-db=NAME',
@@ -259,8 +287,49 @@ module JsDuck
259
287
  @local_storage_db = name
260
288
  end
261
289
 
262
- opts.on('-h', '--help', "Prints this help message", " ") do
263
- puts opts
290
+ opts.on('--ext-namespaces=Ext,Foo', Array,
291
+ "Namespace(s) of ExtJS. Defaults to 'Ext'.", " ") do |ns|
292
+ @ext_namespaces = ns
293
+ end
294
+
295
+ opts.on('-h', '--help[=full]',
296
+ "Short help or --help=full for all available options.", " ") do |v|
297
+ if v == 'full'
298
+ puts opts
299
+ else
300
+ puts opts.banner
301
+ puts "For example:"
302
+ puts
303
+ puts " # Documentation for builtin JavaScript classes like Array and String"
304
+ puts " jsduck --output output/dir --builtin-classes"
305
+ puts
306
+ puts " # Documentation for your own JavaScript"
307
+ puts " jsduck --output output/dir input-file.js some/input/dir"
308
+ puts
309
+ puts "The main options:"
310
+ puts
311
+
312
+ show_help = false
313
+ main_opts = [
314
+ /--output/,
315
+ /--builtin-classes/,
316
+ /--no-warnings/,
317
+ /--verbose/,
318
+ /--help/,
319
+ /--version/,
320
+ ]
321
+ opts.summarize([], opts.summary_width) do |helpline|
322
+ if main_opts.any? {|re| helpline =~ re }
323
+ puts helpline
324
+ show_help = true
325
+ elsif helpline =~ /^\s*$/ && show_help == true
326
+ puts helpline
327
+ show_help = false
328
+ elsif show_help == true
329
+ puts helpline
330
+ end
331
+ end
332
+ end
264
333
  exit
265
334
  end
266
335
 
@@ -284,6 +353,15 @@ module JsDuck
284
353
  end
285
354
  end
286
355
 
356
+ # Converts relative path to full path
357
+ #
358
+ # Especially important for running on Windows where C:\foo\bar
359
+ # pathnames are converted to C:/foo/bar which ruby can work on
360
+ # more easily.
361
+ def canonical(path)
362
+ File.expand_path(path)
363
+ end
364
+
287
365
  # Runs checks on the options
288
366
  def validate
289
367
  if @input_files.length == 0
@@ -5,6 +5,10 @@ module JsDuck
5
5
  # Ruby-side implementation of class docs Renderer.
6
6
  # Uses PhantomJS to run Docs.Renderer JavaScript.
7
7
  class Renderer
8
+ def initialize(options={})
9
+ @options = options
10
+ end
11
+
8
12
  def render(cls)
9
13
  @cls = cls
10
14
 
@@ -14,6 +18,7 @@ module JsDuck
14
18
  "<div class='doc-contents'>",
15
19
  render_private_class_notice,
16
20
  @cls[:doc],
21
+ render_meta_data,
17
22
  "</div>",
18
23
  "<div class='members'>",
19
24
  render_member_sections,
@@ -31,6 +36,25 @@ module JsDuck
31
36
  ]
32
37
  end
33
38
 
39
+ def render_meta_data
40
+ return if !@cls[:meta] || @cls[:meta].length == 0
41
+
42
+ html = ["<ul class='meta-data'>"]
43
+
44
+ @options[:meta_tags].each do |meta|
45
+ title = meta[:title]
46
+ items = @cls[:meta].find_all {|m| m[:name] == meta[:name]}.map {|m| m[:content] }
47
+ content = meta[:strip] ? items.map {|m| m.gsub(meta[:strip], "") } : items
48
+ if items.length > 0
49
+ html << "<li><strong>#{CGI.escapeHTML(title)}:</strong> #{CGI.escapeHTML(content.join(', '))}</li>"
50
+ end
51
+ end
52
+
53
+ html << "</ul>"
54
+
55
+ html
56
+ end
57
+
34
58
  def render_hierarchy
35
59
  has_parents = @cls[:extends] && @cls[:extends] != "Object"
36
60
  has_alt_names = @cls[:alternateClassNames].length > 0
@@ -144,7 +168,7 @@ module JsDuck
144
168
  inherited = owner == @cls[:name] ? "not-inherited" : "inherited"
145
169
 
146
170
  return [
147
- "<div id='#{m[:tagname]}-#{m[:name]}' class='member #{first_child} #{inherited}'>",
171
+ "<div id='#{m[:id]}' class='member #{first_child} #{inherited}'>",
148
172
  # leftmost column: expand button
149
173
  "<a href='#' class='side #{expandable}'>",
150
174
  "<span>&nbsp;</span>",
@@ -201,11 +225,14 @@ module JsDuck
201
225
  if m[:deprecated]
202
226
  after += "<strong class='deprecated-signature'>deprecated</strong>"
203
227
  end
204
- if m[:tagname] == :cfg && !m[:optional]
228
+ if m[:required]
205
229
  after += "<strong class='required-signature'>required</strong>"
206
230
  end
231
+ if m[:template]
232
+ after += "<strong class='template-signature'>template</strong>"
233
+ end
207
234
 
208
- uri = "#!/api/#{m[:owner]}-#{m[:tagname]}-#{m[:name]}"
235
+ uri = "#!/api/#{m[:owner]}-#{m[:id]}"
209
236
 
210
237
  return [
211
238
  before,
@@ -237,6 +264,15 @@ module JsDuck
237
264
  ]
238
265
  end
239
266
 
267
+ if m[:template]
268
+ doc << [
269
+ "<div class='template'>",
270
+ "<p>This is a template method. A hook into the functionality of this class.",
271
+ "Feel free to override it in child classes.</p>",
272
+ "</div>",
273
+ ]
274
+ end
275
+
240
276
  doc << render_params_and_return(m)
241
277
 
242
278
  doc
@@ -297,6 +333,7 @@ module JsDuck
297
333
  end
298
334
 
299
335
  def render_return(ret)
336
+ return if ret[:type] == "undefined"
300
337
  return [
301
338
  "<h3 class='pa'>Returns</h3>",
302
339
  "<ul>",
@@ -10,11 +10,13 @@ module JsDuck
10
10
  list = []
11
11
  docs.each do |cls|
12
12
  list << class_node(cls)
13
- [:cfg, :property, :method, :event].each do |type|
14
- cls.members(type).each do |m|
15
- # skip inherited items and constructors
16
- if m[:owner] == cls.full_name && m[:name] != cls.short_name
17
- list << member_node(m, cls)
13
+ [:members, :statics].each do |group|
14
+ [:cfg, :property, :method, :event].each do |type|
15
+ cls.members(type, group).each do |m|
16
+ # skip inherited items and constructors
17
+ if m[:owner] == cls.full_name && m[:name] != cls.short_name
18
+ list << member_node(m, cls)
19
+ end
18
20
  end
19
21
  end
20
22
  end
@@ -38,6 +40,7 @@ module JsDuck
38
40
  :cls => cls.full_name,
39
41
  :member => member[:name],
40
42
  :type => member[:tagname],
43
+ :id => member[:id],
41
44
  }
42
45
  end
43
46
 
@@ -15,9 +15,10 @@ module JsDuck
15
15
  attr_reader :docs
16
16
  attr_reader :html_filename
17
17
 
18
- def initialize(contents, filename="")
18
+ def initialize(contents, filename="", options={})
19
19
  @contents = contents
20
20
  @filename = filename
21
+ @options = options
21
22
  @html_filename = ""
22
23
  @links = {}
23
24
 
@@ -69,7 +70,7 @@ module JsDuck
69
70
  else
70
71
  # when creation of global class is skipped,
71
72
  # this owner property can be nil.
72
- (doc[:owner] || "global").gsub(/\./, '-') + "-" + doc[:tagname].to_s + "-" + doc[:name]
73
+ (doc[:owner] || "global").gsub(/\./, '-') + "-" + doc[:id]
73
74
  end
74
75
  end
75
76
 
@@ -78,9 +79,9 @@ module JsDuck
78
79
  # Parses the file depending on filename as JS or CSS
79
80
  def parse
80
81
  if @filename =~ /\.s?css$/
81
- CssParser.new(@contents).parse
82
+ CssParser.new(@contents, @options).parse
82
83
  else
83
- JsParser.new(@contents).parse
84
+ JsParser.new(@contents, @options).parse
84
85
  end
85
86
  end
86
87