jsduck 4.0.beta2 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,5 @@
1
1
  require 'jsduck/esprima'
2
+ require 'jsduck/logger'
2
3
 
3
4
  module JsDuck
4
5
 
@@ -155,7 +156,7 @@ module JsDuck
155
156
  properties = NODE_TYPES[node["type"]]
156
157
 
157
158
  unless properties
158
- puts "Unknown node type: "+node["type"]
159
+ Logger.instance.fatal("Unknown node type: "+node["type"])
159
160
  exit(1)
160
161
  end
161
162
 
@@ -1,4 +1,5 @@
1
1
  require 'jsduck/io'
2
+ require 'jsduck/logger'
2
3
  require 'json'
3
4
 
4
5
  module JsDuck
@@ -37,7 +38,7 @@ module JsDuck
37
38
  begin
38
39
  self.parse(JsDuck::IO.read(filename))
39
40
  rescue
40
- puts "Oh noes! #{filename} is not a valid JSON file."
41
+ Logger.instance.fatal("#{filename} is not a valid JSON file")
41
42
  exit(1)
42
43
  end
43
44
  end
@@ -57,7 +57,7 @@ module JsDuck
57
57
  # Prints log message with optional filename appended
58
58
  def log(msg, filename=nil)
59
59
  if @verbose
60
- puts msg + " " + format(filename) + "..."
60
+ $stderr.puts paint(:green, msg) + " " + format(filename) + " ..."
61
61
  end
62
62
  end
63
63
 
@@ -77,7 +77,7 @@ module JsDuck
77
77
 
78
78
  # get documentation for all warnings
79
79
  def doc_warnings
80
- @warning_docs.map {|w| " #{@warnings[w[0]] ? '+' : '-'}#{w[0]} - #{w[1]}" } + [" "]
80
+ @warning_docs.map {|w| " #{@warnings[w[0]] ? '+' : '-'}#{w[0]} - #{w[1]}" }
81
81
  end
82
82
 
83
83
  # Prints warning message.
@@ -92,7 +92,7 @@ module JsDuck
92
92
  #
93
93
  # Optionally filename and line number will be inserted to message.
94
94
  def warn(type, msg, filename=nil, line=nil)
95
- msg = "Warning: " + format(filename, line) + " " + msg
95
+ msg = paint(:yellow, "Warning: ") + format(filename, line) + " " + msg
96
96
 
97
97
  if type == nil || @warnings[type]
98
98
  if !@shown_warnings[msg]
@@ -115,16 +115,49 @@ module JsDuck
115
115
  out += ":#{line}:"
116
116
  end
117
117
  end
118
- out
118
+ paint(:magenta, out)
119
119
  end
120
120
 
121
121
  # Prints fatal error message with backtrace.
122
122
  # The error param should be $! from resque block.
123
- def fatal(msg, error)
124
- puts "#{msg}: #{error}"
125
- puts
126
- puts "Here's a full backtrace:"
127
- puts error.backtrace
123
+ def fatal(msg)
124
+ $stderr.puts paint(:red, "Error: ") + msg
125
+ end
126
+
127
+ # Prints fatal error message with backtrace.
128
+ # The error param should be $! from resque block.
129
+ def fatal_backtrace(msg, error)
130
+ $stderr.puts paint(:red, "Error: ") + "#{msg}: #{error}"
131
+ $stderr.puts
132
+ $stderr.puts "Here's a full backtrace:"
133
+ $stderr.puts error.backtrace
134
+ end
135
+
136
+ private
137
+
138
+ COLORS = {
139
+ :black => "\e[30m",
140
+ :red => "\e[31m",
141
+ :green => "\e[32m",
142
+ :yellow => "\e[33m",
143
+ :blue => "\e[34m",
144
+ :magenta => "\e[35m",
145
+ :cyan => "\e[36m",
146
+ :white => "\e[37m",
147
+ }
148
+
149
+ CLEAR = "\e[0m"
150
+
151
+ # Helper for doing colored output in UNIX terminal
152
+ #
153
+ # Only does color output when STDERR is attached to TTY
154
+ # i.e. is not piped/redirected.
155
+ def paint(color_name, msg)
156
+ if OS.windows? || !$stderr.tty?
157
+ msg
158
+ else
159
+ COLORS[color_name] + msg + CLEAR
160
+ end
128
161
  end
129
162
  end
130
163
 
@@ -0,0 +1,109 @@
1
+ require 'optparse'
2
+
3
+ module JsDuck
4
+
5
+ # JSDuck version of OptionParser
6
+ #
7
+ # Enhanced with ability to output options help in two ways:
8
+ #
9
+ # - short list of all options (with the built-in #help method)
10
+ # - long description of one option (with the added #help_single method)
11
+ #
12
+ class OptionParser < ::OptionParser
13
+ def initialize
14
+ @full_options_index = {}
15
+ super
16
+ end
17
+
18
+ # Override the #on method to do some pre-processing on its
19
+ # parameters before passing them to the original #on method.
20
+ #
21
+ # Options are defined as usual:
22
+ #
23
+ # opts.on("-v", "--version", Type, "First line of description.",
24
+ # "Second line of description.",
25
+ # "Third line of description.")
26
+ #
27
+ # But only the first line of description will be passed to
28
+ # original #on method - meaning that #help method will also only
29
+ # list this first line.
30
+ #
31
+ # The remaining lines are saved to a separate place and can be
32
+ # retrieved through asking for full docs for an option with
33
+ # #help_single method.
34
+ #
35
+ def on(*opts, &block)
36
+ core = []
37
+ keys = []
38
+ desc = []
39
+
40
+ desc_started = false
41
+ opts.each do |o|
42
+ if desc_started
43
+ desc << o
44
+ elsif String === o
45
+ if o =~ /^-/
46
+ core << o
47
+ keys << o
48
+ else
49
+ core << o
50
+ desc << o
51
+ desc_started = true
52
+ end
53
+ else
54
+ core << o
55
+ end
56
+ end
57
+
58
+ full = {:keys => keys, :desc => desc}
59
+
60
+ keys.each do |op|
61
+ each_index_key(op) {|k| @full_options_index[k] = full }
62
+ end
63
+
64
+ super(*core, &block)
65
+ end
66
+
67
+ # Helper that turns option name like --images=PATH into list of
68
+ # keys by which we index the options:
69
+ #
70
+ # "--images=PATH" --> ["--images", "images"]
71
+ #
72
+ # For options containing "[no-]" all the alternative forms are expanded:
73
+ #
74
+ # "--[no-]seo" --> ["--[no-]seo", "[no-]seo", "--seo", "seo", "--no-seo", "no-seo"]
75
+ #
76
+ def each_index_key(option_name)
77
+ key = option_name.sub(/\[?=.*/, '')
78
+ plain_key = key.sub(/^-*/, '')
79
+ [key, plain_key].each do |k|
80
+ yield k
81
+ if k =~ /\[no-\]/
82
+ yield k.sub(/\[no-\]/, '')
83
+ yield k.sub(/\[no-\]/, 'no-')
84
+ end
85
+ end
86
+ end
87
+
88
+ # Returns long help text for a single option.
89
+ def help_single(option_name)
90
+ o = @full_options_index[option_name] || {:keys => [option_name], :desc => ["No such option. See --help=help"]}
91
+
92
+ r = []
93
+
94
+ r << ""
95
+ r << " " + o[:keys].join(", ")
96
+ r << ""
97
+
98
+ o[:desc].each do |line|
99
+ r << " " + line
100
+ end
101
+
102
+ r << ""
103
+ r << ""
104
+
105
+ return r.join("\n")
106
+ end
107
+ end
108
+
109
+ end
@@ -1,4 +1,4 @@
1
- require 'optparse'
1
+ require 'jsduck/option_parser'
2
2
  require 'jsduck/meta_tag_registry'
3
3
  require 'jsduck/logger'
4
4
  require 'jsduck/json_duck'
@@ -12,6 +12,7 @@ module JsDuck
12
12
  attr_accessor :output_dir
13
13
  attr_accessor :ignore_global
14
14
  attr_accessor :external_classes
15
+ attr_accessor :ext4_events
15
16
 
16
17
  # Customizing output
17
18
  attr_accessor :title
@@ -45,6 +46,7 @@ module JsDuck
45
46
  attr_accessor :touch_examples_ui
46
47
  attr_accessor :ext_namespaces
47
48
  attr_accessor :imports
49
+ attr_accessor :new_since
48
50
 
49
51
  def initialize
50
52
  @input_files = []
@@ -74,13 +76,14 @@ module JsDuck
74
76
  # Special anything-goes type
75
77
  "Mixed",
76
78
  ]
79
+ @ext4_events = nil
77
80
  @meta_tag_paths = []
78
81
 
79
- @version = "4.0.beta2"
82
+ @version = "4.0.0"
80
83
 
81
84
  # Customizing output
82
- @title = "Ext JS - Sencha Docs"
83
- @header = "<strong>Ext JS</strong> Sencha Docs"
85
+ @title = "Documentation - JSDuck"
86
+ @header = "<strong>Documentation</strong> JSDuck"
84
87
  @footer = "Generated with <a href='https://github.com/senchalabs/jsduck'>JSDuck</a> #{@version}."
85
88
  @head_html = ""
86
89
  @body_html = ""
@@ -114,6 +117,7 @@ module JsDuck
114
117
  @touch_examples_ui = false
115
118
  @ext_namespaces = ["Ext"]
116
119
  @imports = []
120
+ @new_since = nil
117
121
 
118
122
  # enable all warnings except :link_auto
119
123
  Logger.instance.set_warning(:all, true)
@@ -138,178 +142,386 @@ module JsDuck
138
142
  end
139
143
 
140
144
  def create_option_parser
141
- optparser = OptionParser.new do | opts |
142
- opts.banner = "Usage: jsduck [options] files/dirs...\n\n"
145
+ optparser = JsDuck::OptionParser.new do | opts |
146
+ opts.banner = "Usage: jsduck [options] files/dirs..."
147
+ opts.separator ""
148
+ opts.separator "For example:"
149
+ opts.separator ""
150
+ opts.separator " # Documentation for builtin JavaScript classes like Array and String"
151
+ opts.separator " jsduck --output output/dir --builtin-classes"
152
+ opts.separator ""
153
+ opts.separator " # Documentation for your own JavaScript"
154
+ opts.separator " jsduck --output output/dir input-file.js some/input/dir"
155
+ opts.separator ""
156
+ opts.separator "The main options:"
157
+ opts.separator ""
143
158
 
144
159
  opts.on('-o', '--output=PATH',
145
- "Directory to output all this amazing documentation.",
146
- "This option MUST be specified (unless --stdout).",
147
- "Use dash '-' to write docs to STDOUT (only export).", " ") do |path|
160
+ "Directory to write all this documentation.",
161
+ "",
162
+ "This option is REQUIRED. When the directory exists,",
163
+ "it will be overwritten. Give dash '-' as argument",
164
+ "to write docs to STDOUT (works only with --export).") do |path|
148
165
  @output_dir = path == "-" ? :stdout : canonical(path)
149
166
  end
150
167
 
151
- opts.on('--ignore-global', "Turns off the creation of global class.", " ") do
152
- @ignore_global = true
153
- end
154
-
155
- opts.on('--external=Foo,Bar,Baz', Array,
156
- "Declares list of external classes. These classes",
157
- "will then not generate warnings when used in type",
158
- "definitions or inherited from.", " ") do |classes|
159
- @external_classes += classes
168
+ opts.on('--export=TYPE',
169
+ "Exports docs in JSON.",
170
+ "",
171
+ "TYPE is one of:",
172
+ "",
173
+ "- full - full class docs.",
174
+ "- api - only class- and member names.",
175
+ "- examples - extracts inline examples from classes.") do |format|
176
+ @export = format.to_sym
160
177
  end
161
178
 
162
179
  opts.on('--builtin-classes',
163
- "Includes docs for JavaScript builtin classes.", " ") do
180
+ "Includes docs for JavaScript builtins.",
181
+ "",
182
+ "Docs for the following classes are included:",
183
+ "",
184
+ "- Array",
185
+ "- Boolean",
186
+ "- Date",
187
+ "- Function",
188
+ "- Number",
189
+ "- Object",
190
+ "- RegExp",
191
+ "- String") do
164
192
  read_filenames(@root_dir + "/js-classes")
165
193
  end
166
194
 
167
- opts.on('--meta-tags=PATH',
168
- "Path to Ruby file or directory with custom",
169
- "meta-tag implementations.", " ") do |path|
170
- @meta_tag_paths << canonical(path)
195
+ opts.on('--seo', "Enables SEO-friendly print version.",
196
+ "",
197
+ "Instead of index.html creates index.php that will serve",
198
+ "the regular docs, print-friendly docs, and search-engine-",
199
+ "friendly docs (the latter two are pretty much the same).") do
200
+ @seo = true
171
201
  end
172
202
 
173
- opts.on('--encoding=NAME', "Input encoding (defaults to UTF-8).", " ") do |encoding|
174
- JsDuck::IO.encoding = encoding
203
+ opts.on('--config=PATH',
204
+ "Loads config options from JSON file.",
205
+ "",
206
+ "An alternative to listing all options on command line.",
207
+ "",
208
+ "See also: https://github.com/senchalabs/jsduck/wiki/Config-file") do |path|
209
+ path = canonical(path)
210
+ if File.exists?(path)
211
+ config = read_json_config(path)
212
+ else
213
+ Logger.instance.fatal("The config file #{path} doesn't exist")
214
+ exit(1)
215
+ end
216
+ # treat paths inside JSON config relative to the location of
217
+ # config file. When done, switch back to current working dir.
218
+ @working_dir = File.dirname(path)
219
+ optparser.parse!(config).each {|fname| read_filenames(canonical(fname)) }
220
+ @working_dir = nil
175
221
  end
176
222
 
177
- opts.on('-v', '--verbose', "This will fill up your console.", " ") do
178
- Logger.instance.verbose = true
223
+ opts.on('--encoding=NAME', "Input encoding (defaults to UTF-8).") do |encoding|
224
+ JsDuck::IO.encoding = encoding
179
225
  end
180
226
 
227
+ opts.separator ""
181
228
  opts.separator "Customizing output:"
182
229
  opts.separator ""
183
230
 
184
231
  opts.on('--title=TEXT',
185
232
  "Custom title text for the documentation.",
186
- "Defaults to 'Ext JS - Sencha Docs'", " ") do |text|
233
+ "",
234
+ "Defaults to 'Documentation - JSDuck'",
235
+ "",
236
+ "The title will be used both inside <title> and in",
237
+ "the header of the page. Inside page header the left",
238
+ "part (from ' - ' separator) will be shown in bold.") do |text|
187
239
  @title = text
188
240
  @header = text.sub(/^(.*?) +- +/, "<strong>\\1 </strong>")
189
241
  end
190
242
 
191
243
  opts.on('--footer=TEXT',
192
244
  "Custom footer text for the documentation.",
193
- "Defaults to: 'Generated with JSDuck {VERSION}.'", " ") do |text|
245
+ "",
246
+ "Defaults to: 'Generated with JSDuck {VERSION}.'",
247
+ "",
248
+ "'{VERSION}' is a placeholder that will get substituted",
249
+ "with the current version of JSDuck. See --version.") do |text|
194
250
  @footer = text.gsub(/\{VERSION\}/, @version)
195
251
  end
196
252
 
197
- opts.on('--head-html=HTML', "HTML to append to the <head> section of index.html.", " ") do |html|
253
+ opts.on('--head-html=HTML',
254
+ "HTML for the <head> section of index.html.",
255
+ "",
256
+ "Useful for adding extra <style> and other tags.",
257
+ "",
258
+ "This option can be used repeatedly to append several",
259
+ "things to the header.") do |html|
198
260
  @head_html += html
199
261
  end
200
262
 
201
- opts.on('--body-html=HTML', "HTML to append to the <body> section index.html.", " ") do |html|
263
+ opts.on('--body-html=HTML',
264
+ "HTML for the <body> section of index.html.",
265
+ "",
266
+ "Useful for adding extra markup to the page.",
267
+ "",
268
+ "This option can be used repeatedly to append several",
269
+ "things to the body.") do |html|
202
270
  @body_html += html
203
271
  end
204
272
 
205
273
  opts.on('--welcome=PATH',
206
- "Path to HTML file with content for welcome page.", " ") do |path|
274
+ "HTML file with content for welcome page.",
275
+ "",
276
+ "It should only contain the <body> part of a HTML page.",
277
+ "",
278
+ "See also: https://github.com/senchalabs/jsduck/wiki/Welcome-page") do |path|
207
279
  @welcome = canonical(path)
208
280
  end
209
281
 
210
282
  opts.on('--guides=PATH',
211
- "Path to JSON file describing the guides. The file",
212
- "should be in a dir containing the actual guides.",
213
- "A guide is a dir containing README.md, icon.png,",
214
- "and other images referenced by the README.md file.", " ") do |path|
283
+ "JSON file describing the guides.",
284
+ "",
285
+ "The file should be in a dir containing the actual guides.",
286
+ "A guide is a dir containing README.md, icon.png, and",
287
+ "other images referenced by the README.md file.",
288
+ "",
289
+ "See also: https://github.com/senchalabs/jsduck/wiki/Guides") do |path|
215
290
  @guides = canonical(path)
216
291
  end
217
292
 
218
293
  opts.on('--videos=PATH',
219
- "Path to JSON file describing the videos.", " ") do |path|
294
+ "JSON file describing the videos.",
295
+ "",
296
+ "See also: https://github.com/senchalabs/jsduck/wiki/Videos") do |path|
220
297
  @videos = canonical(path)
221
298
  end
222
299
 
223
300
  opts.on('--examples=PATH',
224
- "Path JSON file describing the examples.", " ") do |path|
301
+ "JSON file describing the examples.",
302
+ "",
303
+ "See also: https://github.com/senchalabs/jsduck/wiki/Examples") do |path|
225
304
  @examples = canonical(path)
226
305
  end
227
306
 
228
307
  opts.on('--categories=PATH',
229
- "Path to JSON file which defines categories for classes.", " ") do |path|
308
+ "JSON file defining categories for classes.",
309
+ "",
310
+ "Without this option the classes will be categorized",
311
+ "based on how they are namespaced.",
312
+ "",
313
+ "See also: https://github.com/senchalabs/jsduck/wiki/Categories") do |path|
230
314
  @categories_path = canonical(path)
231
315
  end
232
316
 
233
317
  opts.on('--no-source',
234
- "Turns off the output of source files.", " ") do
318
+ "Turns off the output of source files.") do
235
319
  @source = false
236
320
  end
237
321
 
238
- opts.on('--pretty-json', "Turn on pretty-printing of JSON.", " ") do
239
- @pretty_json = true
240
- end
241
-
242
322
  opts.on('--images=PATH',
243
- "Search path for including images referenced by",
244
- "{@img} tag. Several paths can be specified by",
245
- "using the option multiple times.", " ") do |path|
323
+ "Path for images referenced by {@img} tag.",
324
+ "",
325
+ "Several paths can be specified by using the option",
326
+ "multiple times. This option only applies to {@img}",
327
+ "tags used in API (classes/members) documentation.",
328
+ "Images used in guides must be located inside the",
329
+ "directory of the specific guide.") do |path|
246
330
  @images << canonical(path)
247
331
  end
248
332
 
333
+ opts.on('--tests',
334
+ "Creates page for testing inline examples.") do
335
+ @tests = true
336
+ end
337
+
338
+ opts.on('--stats',
339
+ "Creates page with all kinds of statistics.") do
340
+ @stats = true
341
+ end
342
+
343
+ opts.on('--import=VERSION:PATH',
344
+ "Imports docs generating @since & @new.",
345
+ "",
346
+ "For example:",
347
+ "",
348
+ " --import='1.0:/path/to/first/version'",
349
+ " --import='2.0:/path/to/second/version'",
350
+ " --import='3.0",
351
+ "",
352
+ "Several versions can be imported using the option multiple",
353
+ "times. The last version must always be the current one",
354
+ "without the :PATH portion.",
355
+ "",
356
+ "JSDuck will then check in which version every class/member",
357
+ "first appears in and tag it with an appropriate @since tag.",
358
+ "Things appearing only in the latest version will also get",
359
+ "a @new tag (unless --new-since option is used).",
360
+ "",
361
+ "See also: https://github.com/senchalabs/jsduck/wiki/@since") do |v|
362
+ if v =~ /\A(.*?):(.*)\Z/
363
+ @imports << {:version => $1, :path => canonical($2)}
364
+ else
365
+ @imports << {:version => v}
366
+ end
367
+ end
368
+
369
+ opts.on('--new-since=VERSION',
370
+ "Since when to label items with @new tag.",
371
+ "",
372
+ "The VERSION must be one of the version names defined",
373
+ "with --import option.",
374
+ "",
375
+ "Defaults to the last version listed by --import.") do |v|
376
+ @new_since = v
377
+ end
378
+
379
+ opts.separator ""
380
+ opts.separator "Tweaking:"
381
+ opts.separator ""
382
+
383
+ opts.on('--meta-tags=PATH',
384
+ "Path to custom meta-tag implementations.",
385
+ "",
386
+ "Can be a path to single Ruby file or a directory.",
387
+ "",
388
+ "This option can be used repeatedly to include multiple",
389
+ "meta tags from different places.",
390
+ "",
391
+ "See also: https://github.com/senchalabs/jsduck/wiki/Custom-tags") do |path|
392
+ @meta_tag_paths << canonical(path)
393
+ end
394
+
395
+ opts.on('--ignore-global',
396
+ "Turns off the creation of 'global' class.",
397
+ "",
398
+ "The 'global' class gets created when members that",
399
+ "don't belong to any class are found - all these",
400
+ "members will be placed into the 'global' class.",
401
+ "",
402
+ "Using this option won't suppress the warning that's",
403
+ "given when global members are found. For that you",
404
+ "need to additionally use --warnings=-global") do
405
+ @ignore_global = true
406
+ end
407
+
408
+ opts.on('--external=Foo,Bar,Baz', Array,
409
+ "Declares list of external classes.",
410
+ "",
411
+ "These classes will then no more generate warnings",
412
+ "when used in type definitions or inherited from.",
413
+ "",
414
+ "Multiple classes can be given in comma-separated list,",
415
+ "or by using the option repeatedly.") do |classes|
416
+ @external_classes += classes
417
+ end
418
+
419
+ opts.on('--[no-]ext4-events',
420
+ "Forces Ext4 options param on events.",
421
+ "",
422
+ "In Ext JS 4 and Sencha Touch 2 all event handlers are",
423
+ "passed an additional options object at the end of the",
424
+ "parameters list. This options object is skipped in the",
425
+ "documentation of Ext4/Touch2 events, so it needs to be",
426
+ "appended by JSDuck.",
427
+ "",
428
+ "The default is to auto-detect if we're using Ext JS 4",
429
+ "or Sencha Touch 2 based on whether the code defines",
430
+ "classes using Ext.define(), and only then append the",
431
+ "options parameter. This should work most of the time.",
432
+ "",
433
+ "Use this option to override the auto-detection.") do |e|
434
+ @ext4_events = e
435
+ end
436
+
437
+ opts.on('--examples-base-url=URL',
438
+ "Base URL for examples with relative URL-s.",
439
+ " ",
440
+ "Defaults to: 'extjs-build/examples/'") do |path|
441
+ @examples_base_url = path
442
+ end
443
+
249
444
  opts.on('--link=TPL',
250
445
  "HTML template for replacing {@link}.",
446
+ "",
251
447
  "Possible placeholders:",
448
+ "",
252
449
  "%c - full class name (e.g. 'Ext.Panel')",
253
450
  "%m - class member name prefixed with member type",
254
451
  " (e.g. 'method-urlEncode')",
255
452
  "%# - inserts '#' if member name present",
256
453
  "%- - inserts '-' if member name present",
257
454
  "%a - anchor text for link",
258
- "Default is: '<a href=\"#!/api/%c%-%m\" rel=\"%c%-%m\" class=\"docClass\">%a</a>'", " ") do |tpl|
455
+ "",
456
+ "Defaults to: '<a href=\"#!/api/%c%-%m\" rel=\"%c%-%m\" class=\"docClass\">%a</a>'") do |tpl|
259
457
  @link_tpl = tpl
260
458
  end
261
459
 
262
460
  opts.on('--img=TPL',
263
461
  "HTML template for replacing {@img}.",
462
+ "",
264
463
  "Possible placeholders:",
464
+ "",
265
465
  "%u - URL from @img tag (e.g. 'some/path.png')",
266
466
  "%a - alt text for image",
267
- "Default is: '<p><img src=\"%u\" alt=\"%a\"></p>'", " ") do |tpl|
467
+ "",
468
+ "Defaults to: '<p><img src=\"%u\" alt=\"%a\"></p>'") do |tpl|
268
469
  @img_tpl = tpl
269
470
  end
270
471
 
271
- opts.on('--export=TYPE',
272
- "Exports docs in JSON. TYPE is one of:",
273
- "* full - full class docs.",
274
- "* api - only class- and member names.",
275
- "* examples - extracts inline examples from classes.", " ") do |format|
276
- @export = format.to_sym
277
- end
278
-
279
- opts.on('--seo', "Creates index.php that handles search engine traffic.", " ") do
280
- @seo = true
281
- end
282
-
283
472
  opts.on('--eg-iframe=PATH',
284
- "An HTML file to use inside an iframe",
285
- "to display inline examples.", " ") do |path|
473
+ "HTML file used to display inline examples.",
474
+ "",
475
+ "The file will be used inside <iframe> that renders the",
476
+ "example. Not just any HTML file will work - it needs to",
477
+ "define loadInlineExample function that will be called",
478
+ "with the example code.",
479
+ "",
480
+ "See also: https://github.com/senchalabs/jsduck/wiki/Inline-examples") do |path|
286
481
  @eg_iframe = canonical(path)
287
482
  end
288
483
 
289
- opts.on('--examples-base-url=URL',
290
- "Base URL for examples with relative URL-s.", " ") do |path|
291
- @examples_base_url = path
292
- end
293
-
294
- opts.on('--tests', "Creates page for testing inline examples.", " ") do
295
- @tests = true
484
+ opts.on('--ext-namespaces=Ext,Foo', Array,
485
+ "Additional Ext JS namespaces to recognize.",
486
+ "",
487
+ "Defaults to 'Ext'",
488
+ "",
489
+ "Useful when using Ext JS in sandbox mode where instead",
490
+ "of Ext.define() your code contains YourNs.define().",
491
+ "In such case pass --ext-namespaces=Ext,YourNS option",
492
+ "and JSDuck will recognize both Ext.define() and",
493
+ "YourNs.define() plus few other things that depend on",
494
+ "Ext namespace like Ext.emptyFn.") do |ns|
495
+ @ext_namespaces = ns
296
496
  end
297
497
 
298
- opts.on('--stats',
299
- "Creates page with all kinds of statistics. Experimental!", " ") do
300
- @stats = true
498
+ opts.on('--touch-examples-ui',
499
+ "Turns on phone/tablet UI for examples.",
500
+ "",
501
+ "This is a very Sencha Touch 2 docs specific option.",
502
+ "Effects both normal- and inline-examples.") do
503
+ @touch_examples_ui = true
301
504
  end
302
505
 
506
+ opts.separator ""
303
507
  opts.separator "Debugging:"
304
508
  opts.separator ""
305
509
 
510
+ opts.on('-v', '--verbose',
511
+ "Turns on excessive logging.",
512
+ "",
513
+ "Log messages are writted to STDERR.") do
514
+ Logger.instance.verbose = true
515
+ end
516
+
306
517
  opts.on('--warnings=+A,-B,+C', Array,
307
518
  "Turns warnings selectively on/off.",
308
- " ",
519
+ "",
309
520
  " +all - to turn on all warnings",
310
- " ",
311
- "By default these warnings are turned +on/-off:",
312
- " ",
521
+ "",
522
+ "List of all available warning types:",
523
+ "(Those with '+' in front of them default to on)",
524
+ "",
313
525
  *Logger.instance.doc_warnings) do |warnings|
314
526
  warnings.each do |op|
315
527
  if op =~ /^([-+]?)(.*)$/
@@ -320,117 +532,81 @@ module JsDuck
320
532
  end
321
533
  end
322
534
 
323
- # For debugging it's often useful to set --processes=0 to get deterministic results.
324
535
  opts.on('-p', '--processes=COUNT',
325
536
  "The number of parallel processes to use.",
326
- OS::windows? ? "Defaults to off in Windows." : "Defaults to the number of processors/cores.",
327
- "Set to 0 to disable parallel processing completely.", " ") do |count|
537
+ "",
538
+ "Defaults to the number of processors/cores.",
539
+ "",
540
+ "Set to 0 to disable parallel processing completely.",
541
+ "This is often useful in debugging to get deterministic",
542
+ "results.",
543
+ "",
544
+ "In Windows this option is disabled.") do |count|
328
545
  @processes = count.to_i
329
546
  end
330
547
 
548
+ opts.on('--pretty-json',
549
+ "Turns on pretty-printing of JSON.",
550
+ "",
551
+ "This is useful when studying the JSON files generated",
552
+ "by --export option. But the option effects any JSON",
553
+ "that gets generated, so it's also useful when debugging",
554
+ "the resource files generated for the docs app.") do
555
+ @pretty_json = true
556
+ end
557
+
331
558
  opts.on('--template=PATH',
332
- "Directory containing doc-browser UI template.", " ") do |path|
559
+ "Dir containing the UI template files.",
560
+ "",
561
+ "Useful when developing the template files.") do |path|
333
562
  @template_dir = canonical(path)
334
563
  end
335
564
 
336
565
  opts.on('--template-links',
337
- "Instead of copying template files, create symbolic",
338
- "links. Useful for template files development.",
339
- "Only works on platforms supporting symbolic links.", " ") do
566
+ "Creates symlinks to UI template files.",
567
+ "",
568
+ "Useful for template files development.",
569
+ "Only works on platforms supporting symbolic links.") do
340
570
  @template_links = true
341
571
  end
342
572
 
343
573
  opts.on('--extjs-path=PATH',
344
- "Path for main ExtJS JavaScript file. Useful for specifying",
345
- "something different than extjs/ext.js", " ") do |path|
574
+ "Path for main ExtJS JavaScript file.",
575
+ "",
576
+ "This is the ExtJS file that's used by the docs app UI.",
577
+ "",
578
+ "Defaults to extjs/ext-all.js",
579
+ "",
580
+ "Useful for switching to extjs/ext-all-debug.js in development.") do |path|
346
581
  @extjs_path = path # NB! must be relative path
347
582
  end
348
583
 
349
584
  opts.on('--local-storage-db=NAME',
350
585
  "Prefix for LocalStorage database names.",
351
- "Defaults to 'docs'.", " ") do |name|
586
+ "",
587
+ "Defaults to 'docs'") do |name|
352
588
  @local_storage_db = name
353
589
  end
354
590
 
355
- opts.on('--touch-examples-ui',
356
- "Use phone/tablet UI for examples.", " ") do
357
- @touch_examples_ui = true
358
- end
359
-
360
- opts.on('--ext-namespaces=Ext,Foo', Array,
361
- "Namespace(s) of ExtJS. Defaults to 'Ext'.", " ") do |ns|
362
- @ext_namespaces = ns
363
- end
364
-
365
- opts.on('--import=VERSION:PATH',
366
- "Imports docs of a particular version generating @since tags.",
367
- "Several versions can be imported using the option multiple times.",
368
- "To specify the current version, leave the :PATH portion off.", " ") do |v|
369
- if v =~ /\A(.*?):(.*)\Z/
370
- @imports << {:version => $1, :path => canonical($2)}
371
- else
372
- @imports << {:version => v}
373
- end
374
- end
375
-
376
- opts.on('--config=PATH',
377
- "Loads config options from JSON file.", " ") do |path|
378
- path = canonical(path)
379
- if File.exists?(path)
380
- config = read_json_config(path)
381
- else
382
- puts "Oh noes! The config file #{path} doesn't exist."
383
- exit(1)
384
- end
385
- # treat paths inside JSON config relative to the location of
386
- # config file. When done, switch back to current working dir.
387
- @working_dir = File.dirname(path)
388
- optparser.parse!(config).each {|fname| read_filenames(canonical(fname)) }
389
- @working_dir = nil
390
- end
391
-
392
- opts.on('-h', '--help[=full]',
393
- "Short help or --help=full for all available options.", " ") do |v|
394
- if v == 'full'
395
- puts opts
591
+ opts.on('-h', '--help[=--some-option]',
592
+ "Use --help=--option for help on option.",
593
+ "",
594
+ "For example To get help on --processes option any of the",
595
+ "following will work:",
596
+ "",
597
+ " --help=--processes",
598
+ " --help=processes",
599
+ " --help=-p",
600
+ " --help=p") do |v|
601
+ if v
602
+ puts opts.help_single(v)
396
603
  else
397
- puts opts.banner
398
- puts "For example:"
399
- puts
400
- puts " # Documentation for builtin JavaScript classes like Array and String"
401
- puts " jsduck --output output/dir --builtin-classes"
402
- puts
403
- puts " # Documentation for your own JavaScript"
404
- puts " jsduck --output output/dir input-file.js some/input/dir"
405
- puts
406
- puts "The main options:"
407
- puts
408
-
409
- show_help = false
410
- main_opts = [
411
- /--output/,
412
- /--builtin-classes/,
413
- /--encoding/,
414
- /--verbose/,
415
- /--help/,
416
- /--version/,
417
- ]
418
- opts.summarize([], opts.summary_width) do |helpline|
419
- if main_opts.any? {|re| helpline =~ re }
420
- puts helpline
421
- show_help = true
422
- elsif helpline =~ /^\s*$/ && show_help == true
423
- puts helpline
424
- show_help = false
425
- elsif show_help == true
426
- puts helpline
427
- end
428
- end
604
+ puts opts.help
429
605
  end
430
606
  exit
431
607
  end
432
608
 
433
- opts.on('--version', "Prints JSDuck version", " ") do
609
+ opts.on('--version', "Prints JSDuck version") do
434
610
  puts "JSDuck " + @version
435
611
  exit
436
612
  end
@@ -473,7 +649,7 @@ module JsDuck
473
649
  @input_files << fname
474
650
  end
475
651
  else
476
- Logger.instance.warn(nil, "File #{fname} not found")
652
+ Logger.instance.warn(nil, "File not found", fname)
477
653
  end
478
654
  end
479
655
 
@@ -502,35 +678,35 @@ module JsDuck
502
678
  # Runs checks on the options
503
679
  def validate
504
680
  if @input_files.length == 0 && !@welcome && !@guides && !@videos && !@examples
505
- puts "You should specify some input files, otherwise there's nothing I can do :("
681
+ Logger.instance.fatal("You should specify some input files, otherwise there's nothing I can do :(")
506
682
  exit(1)
507
683
  elsif @output_dir == :stdout && !@export
508
- puts "Output to STDOUT only works when using --export option."
684
+ Logger.instance.fatal("Output to STDOUT only works when using --export option")
509
685
  exit(1)
510
686
  elsif ![nil, :full, :api, :examples].include?(@export)
511
- puts "Unknown export format: #{@export}"
687
+ Logger.instance.fatal("Unknown export format: #{@export}")
512
688
  exit(1)
513
689
  elsif @output_dir != :stdout
514
690
  if !@output_dir
515
- puts "You should also specify an output directory, where I could write all this amazing documentation."
691
+ Logger.instance.fatal("You should also specify an output directory, where I could write all this amazing documentation")
516
692
  exit(1)
517
693
  elsif File.exists?(@output_dir) && !File.directory?(@output_dir)
518
- puts "Oh noes! The output directory is not really a directory at all :("
694
+ Logger.instance.fatal("The output directory is not really a directory at all :(")
519
695
  exit(1)
520
696
  elsif !File.exists?(File.dirname(@output_dir))
521
- puts "Oh noes! The parent directory for #{@output_dir} doesn't exist."
697
+ Logger.instance.fatal("The parent directory for #{@output_dir} doesn't exist")
522
698
  exit(1)
523
699
  elsif !@export && !File.exists?(@template_dir + "/extjs")
524
- puts "Oh noes! The template directory does not contain extjs/ directory :("
525
- puts "Please copy ExtJS over to template/extjs or create symlink."
526
- puts "For example:"
527
- puts " $ cp -r /path/to/ext-4.0.0 " + @template_dir + "/extjs"
700
+ Logger.instance.fatal("Oh noes! The template directory does not contain extjs/ directory :(")
701
+ Logger.instance.fatal("Please copy ExtJS over to template/extjs or create symlink.")
702
+ Logger.instance.fatal("For example:")
703
+ Logger.instance.fatal(" $ cp -r /path/to/ext-4.0.0 " + @template_dir + "/extjs")
528
704
  exit(1)
529
705
  elsif !@export && !File.exists?(@template_dir + "/resources/css")
530
- puts "Oh noes! CSS files for custom ExtJS theme missing :("
531
- puts "Please compile SASS files in template/resources/sass with compass."
532
- puts "For example:"
533
- puts " $ compass compile " + @template_dir + "/resources/sass"
706
+ Logger.instance.fatal("Oh noes! CSS files for custom ExtJS theme missing :(")
707
+ Logger.instance.fatal("Please compile SASS files in template/resources/sass with compass.")
708
+ Logger.instance.fatal("For example:")
709
+ Logger.instance.fatal(" $ compass compile " + @template_dir + "/resources/sass")
534
710
  exit(1)
535
711
  end
536
712
  end