jsduck 4.0.beta2 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +0 -1
- data/README.md +40 -20
- data/Rakefile +2 -11
- data/esprima/esprima.js +3581 -0
- data/js-classes/String.js +1 -1
- data/jsduck.gemspec +3 -5
- data/lib/jsduck/aggregator.rb +6 -3
- data/lib/jsduck/app.rb +9 -5
- data/lib/jsduck/ast.rb +4 -2
- data/lib/jsduck/class.rb +11 -3
- data/lib/jsduck/css_parser.rb +3 -2
- data/lib/jsduck/doc_ast.rb +1 -0
- data/lib/jsduck/doc_formatter.rb +3 -3
- data/lib/jsduck/doc_parser.rb +10 -0
- data/lib/jsduck/esprima.rb +7 -9
- data/lib/jsduck/examples.rb +1 -1
- data/lib/jsduck/file_categories.rb +3 -3
- data/lib/jsduck/grouped_asset.rb +2 -2
- data/lib/jsduck/guides.rb +4 -4
- data/lib/jsduck/importer.rb +25 -6
- data/lib/jsduck/inherit_doc.rb +3 -0
- data/lib/jsduck/inline_video.rb +4 -4
- data/lib/jsduck/js_parser.rb +2 -1
- data/lib/jsduck/json_duck.rb +2 -1
- data/lib/jsduck/logger.rb +42 -9
- data/lib/jsduck/option_parser.rb +109 -0
- data/lib/jsduck/options.rb +352 -176
- data/lib/jsduck/override.rb +87 -0
- data/lib/jsduck/tag/chainable.rb +14 -0
- data/lib/jsduck/videos.rb +1 -1
- metadata +10 -10
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -45
- data/lib/jsduck/markdown.rb +0 -46
data/lib/jsduck/js_parser.rb
CHANGED
@@ -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
|
-
|
159
|
+
Logger.instance.fatal("Unknown node type: "+node["type"])
|
159
160
|
exit(1)
|
160
161
|
end
|
161
162
|
|
data/lib/jsduck/json_duck.rb
CHANGED
@@ -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
|
-
|
41
|
+
Logger.instance.fatal("#{filename} is not a valid JSON file")
|
41
42
|
exit(1)
|
42
43
|
end
|
43
44
|
end
|
data/lib/jsduck/logger.rb
CHANGED
@@ -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
|
124
|
-
puts "
|
125
|
-
|
126
|
-
|
127
|
-
|
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
|
data/lib/jsduck/options.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
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.
|
82
|
+
@version = "4.0.0"
|
80
83
|
|
81
84
|
# Customizing output
|
82
|
-
@title = "
|
83
|
-
@header = "<strong>
|
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
|
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
|
146
|
-
"
|
147
|
-
"
|
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('--
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
"
|
157
|
-
"
|
158
|
-
"
|
159
|
-
@
|
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
|
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('--
|
168
|
-
"
|
169
|
-
"
|
170
|
-
|
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('--
|
174
|
-
|
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('
|
178
|
-
|
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
|
-
"
|
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
|
-
"
|
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',
|
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',
|
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
|
-
"
|
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
|
-
"
|
212
|
-
"
|
213
|
-
"
|
214
|
-
"
|
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
|
-
"
|
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
|
-
"
|
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
|
-
"
|
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."
|
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
|
-
"
|
244
|
-
"
|
245
|
-
"
|
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
|
-
"
|
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
|
-
"
|
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
|
-
"
|
285
|
-
"
|
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('--
|
290
|
-
"
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
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('--
|
299
|
-
"
|
300
|
-
|
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
|
-
"
|
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
|
-
|
327
|
-
"
|
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
|
-
"
|
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
|
-
"
|
338
|
-
"
|
339
|
-
"
|
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.
|
345
|
-
"
|
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
|
-
"
|
586
|
+
"",
|
587
|
+
"Defaults to 'docs'") do |name|
|
352
588
|
@local_storage_db = name
|
353
589
|
end
|
354
590
|
|
355
|
-
opts.on('--
|
356
|
-
"Use
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
"
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
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.
|
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"
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
687
|
+
Logger.instance.fatal("Unknown export format: #{@export}")
|
512
688
|
exit(1)
|
513
689
|
elsif @output_dir != :stdout
|
514
690
|
if !@output_dir
|
515
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
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
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
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
|