jsduck 4.0.beta2 → 4.0.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,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