jsduck 3.0.pre2 → 3.0.pre3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +14 -7
- data/Rakefile +277 -24
- data/bin/compare +163 -0
- data/bin/stats +92 -0
- data/jsduck.gemspec +3 -3
- data/lib/jsduck/accessors.rb +64 -8
- data/lib/jsduck/aggregator.rb +10 -6
- data/lib/jsduck/aliases.rb +3 -2
- data/lib/jsduck/app.rb +51 -44
- data/lib/jsduck/author_tag.rb +11 -0
- data/lib/jsduck/categories.rb +14 -8
- data/lib/jsduck/class.rb +2 -1
- data/lib/jsduck/class_formatter.rb +5 -4
- data/lib/jsduck/doc_author_tag.rb +11 -0
- data/lib/jsduck/doc_formatter.rb +17 -37
- data/lib/jsduck/doc_parser.rb +39 -11
- data/lib/jsduck/exporter.rb +11 -0
- data/lib/jsduck/guides.rb +3 -3
- data/lib/jsduck/images.rb +72 -0
- data/lib/jsduck/js_parser.rb +20 -4
- data/lib/jsduck/lexer.rb +2 -8
- data/lib/jsduck/lint.rb +3 -2
- data/lib/jsduck/logger.rb +24 -5
- data/lib/jsduck/merger.rb +38 -8
- data/lib/jsduck/meta_tag.rb +49 -0
- data/lib/jsduck/meta_tag_loader.rb +48 -0
- data/lib/jsduck/options.rb +37 -25
- data/lib/jsduck/os.rb +11 -0
- data/lib/jsduck/renderer.rb +37 -34
- data/lib/jsduck/search_data.rb +1 -1
- data/lib/jsduck/source_file.rb +13 -8
- data/template-min/app.js +1 -1
- data/template-min/{egIframe.html → extIframe.html} +3 -4
- data/template-min/extjs/ext-all-debug.js +3107 -2026
- data/template-min/extjs/ext-all.js +1 -1
- data/template-min/extjs/resources/css/ext-all.css +1 -1
- data/template-min/resources/css/app.css +1 -1
- data/template-min/resources/images/down-arr.png +0 -0
- data/template-min/resources/images/gettingstarted.jpg +0 -0
- data/template-min/resources/images/ipad-l.jpg +0 -0
- data/template-min/resources/images/ipad-p.jpg +0 -0
- data/template-min/resources/images/iphone-l.jpg +0 -0
- data/template-min/resources/images/iphone-p.jpg +0 -0
- data/template-min/resources/images/iphone-small-l.jpg +0 -0
- data/template-min/resources/images/iphone-small-p.jpg +0 -0
- data/template-min/resources/images/link-arrow-next.png +0 -0
- data/template-min/template.html +5 -1
- data/template-min/touch-welcome.html +122 -0
- data/template-min/touchIframe.html +85 -0
- data/template-min/welcome.html +2 -0
- metadata +25 -8
- data/lib/jsduck/page.rb +0 -118
- data/lib/jsduck/timer.rb +0 -44
data/lib/jsduck/doc_formatter.rb
CHANGED
@@ -29,9 +29,12 @@ module JsDuck
|
|
29
29
|
# Default value: '<img src="%u" alt="%a"/>'
|
30
30
|
attr_accessor :img_tpl
|
31
31
|
|
32
|
-
#
|
33
|
-
|
34
|
-
|
32
|
+
# This will hold list of all image paths gathered from {@img} tags.
|
33
|
+
attr_accessor :images
|
34
|
+
|
35
|
+
# Base path to prefix images from {@img} tags.
|
36
|
+
# Defaults to no prefix.
|
37
|
+
attr_accessor :img_path
|
35
38
|
|
36
39
|
# Sets up instance to work in context of particular class, so
|
37
40
|
# that when {@link #blah} is encountered it knows that
|
@@ -57,13 +60,12 @@ module JsDuck
|
|
57
60
|
@doc_context = {}
|
58
61
|
@max_length = 120
|
59
62
|
@relations = {}
|
63
|
+
@images = []
|
60
64
|
@link_tpl = '<a href="%c%#%m">%a</a>'
|
61
65
|
@img_tpl = '<img src="%u" alt="%a"/>'
|
62
|
-
@example_tpl = '<pre class="inline-example"><code>%a</code></pre>'
|
63
66
|
@link_re = /\{@link\s+(\S*?)(?:\s+(.+?))?\}/m
|
64
67
|
@img_re = /\{@img\s+(\S*?)(?:\s+(.+?))?\}/m
|
65
|
-
@
|
66
|
-
@example_annotation_re = /<pre><code>@example( +[^\n]*)?\s+/m
|
68
|
+
@example_annotation_re = /<pre><code>\s*@example( +[^\n]*)?\s+/m
|
67
69
|
end
|
68
70
|
|
69
71
|
# Replaces {@link} and {@img} tags, auto-generates links for
|
@@ -74,8 +76,6 @@ module JsDuck
|
|
74
76
|
#
|
75
77
|
# Replaces {@img path/to/image.jpg Alt text} with HTML from @img_tpl.
|
76
78
|
#
|
77
|
-
# Replaces {@example path/to/example.js} with source from that file.
|
78
|
-
#
|
79
79
|
# Adds 'inline-example' class to code examples beginning with @example.
|
80
80
|
#
|
81
81
|
# Additionally replaces strings recognized as ClassNames with
|
@@ -89,11 +89,12 @@ module JsDuck
|
|
89
89
|
out += replace_link_tag(s.scan(@link_re))
|
90
90
|
elsif s.check(@img_re)
|
91
91
|
out += replace_img_tag(s.scan(@img_re))
|
92
|
-
elsif s.check(@example_re)
|
93
|
-
out += replace_example_tag(s.scan(@example_re))
|
94
92
|
elsif s.check(@example_annotation_re)
|
95
|
-
|
96
|
-
|
93
|
+
# Match possible classnames following @example and add them
|
94
|
+
# as CSS classes inside <pre> element.
|
95
|
+
s.scan(@example_annotation_re) =~ @example_annotation_re
|
96
|
+
css_classes = ($1 || "").strip
|
97
|
+
out += "<pre class='inline-example #{css_classes}'><code>"
|
97
98
|
elsif s.check(/[{<]/)
|
98
99
|
out += s.scan(/[{<]/)
|
99
100
|
else
|
@@ -129,10 +130,10 @@ module JsDuck
|
|
129
130
|
file = @doc_context[:filename]
|
130
131
|
line = @doc_context[:linenr]
|
131
132
|
if !@relations[cls]
|
132
|
-
Logger.instance.warn("#{
|
133
|
+
Logger.instance.warn("#{input} links to non-existing class", file, line)
|
133
134
|
text
|
134
135
|
elsif member && !get_member(cls, member, type)
|
135
|
-
Logger.instance.warn("#{
|
136
|
+
Logger.instance.warn("#{input} links to non-existing member", file, line)
|
136
137
|
text
|
137
138
|
else
|
138
139
|
link(cls, member, text, type)
|
@@ -144,10 +145,6 @@ module JsDuck
|
|
144
145
|
input.sub(@img_re) { img($1, $2) }
|
145
146
|
end
|
146
147
|
|
147
|
-
def replace_example_tag(input)
|
148
|
-
input.sub(@example_re) { example($1) }
|
149
|
-
end
|
150
|
-
|
151
148
|
def replace_class_names(input)
|
152
149
|
input.gsub(/(\A|\s)([A-Z][A-Za-z0-9.]*[A-Za-z0-9])(?:(#)([A-Za-z0-9]+))?([.,]?(?:\s|\Z))/m) do
|
153
150
|
before = $1
|
@@ -167,10 +164,11 @@ module JsDuck
|
|
167
164
|
|
168
165
|
# applies the image template
|
169
166
|
def img(url, alt_text)
|
167
|
+
@images << url
|
170
168
|
@img_tpl.gsub(/(%\w)/) do
|
171
169
|
case $1
|
172
170
|
when '%u'
|
173
|
-
url
|
171
|
+
@img_path ? (@img_path + "/" + url) : url
|
174
172
|
when '%a'
|
175
173
|
CGI.escapeHTML(alt_text||"")
|
176
174
|
else
|
@@ -179,24 +177,6 @@ module JsDuck
|
|
179
177
|
end
|
180
178
|
end
|
181
179
|
|
182
|
-
# Replaces example template with example read from file
|
183
|
-
def example(path)
|
184
|
-
@example_tpl.gsub(/(%\w)/) do
|
185
|
-
case $1
|
186
|
-
when '%a'
|
187
|
-
if @get_example
|
188
|
-
CGI.escapeHTML(@get_example.call(path))
|
189
|
-
else
|
190
|
-
file = @doc_context[:filename]
|
191
|
-
line = @doc_context[:linenr]
|
192
|
-
Logger.instance.warn("--examples not specified, but {@example} found in #{file} line #{line}.")
|
193
|
-
end
|
194
|
-
else
|
195
|
-
$1
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
180
|
# applies the link template
|
201
181
|
def link(cls, member, anchor_text, type=nil)
|
202
182
|
# Use the canonical class name for link (not some alternateClassName)
|
data/lib/jsduck/doc_parser.rb
CHANGED
@@ -30,7 +30,7 @@ module JsDuck
|
|
30
30
|
|
31
31
|
@meta_tags_map = {}
|
32
32
|
(meta_tags || []).each do |tag|
|
33
|
-
@meta_tags_map[tag
|
33
|
+
@meta_tags_map[tag.name] = tag
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -136,6 +136,8 @@ module JsDuck
|
|
136
136
|
boolean_at_tag(/@protected/, :protected)
|
137
137
|
elsif look(/@accessor\b/)
|
138
138
|
boolean_at_tag(/@accessor/, :accessor)
|
139
|
+
elsif look(/@evented\b/)
|
140
|
+
boolean_at_tag(/@evented/, :evented)
|
139
141
|
elsif look(/@template\b/)
|
140
142
|
boolean_at_tag(/@template/, :template)
|
141
143
|
elsif look(/@markdown\b/)
|
@@ -146,12 +148,9 @@ module JsDuck
|
|
146
148
|
boolean_at_tag(/@abstract/, :abstract)
|
147
149
|
elsif look(/@/)
|
148
150
|
@input.scan(/@/)
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
skip_horiz_white
|
153
|
-
@current_tag[:content] = @input.scan(/.*$/)
|
154
|
-
skip_white
|
151
|
+
tag = @meta_tags_map[look(/\w+/)]
|
152
|
+
if tag
|
153
|
+
meta_at_tag(tag)
|
155
154
|
else
|
156
155
|
@current_tag[:doc] += "@"
|
157
156
|
end
|
@@ -161,6 +160,24 @@ module JsDuck
|
|
161
160
|
end
|
162
161
|
end
|
163
162
|
|
163
|
+
# Matches the given meta-tag
|
164
|
+
def meta_at_tag(tag)
|
165
|
+
prev_tag = @current_tag
|
166
|
+
|
167
|
+
add_tag(:meta)
|
168
|
+
@current_tag[:name] = match(/\w+/)
|
169
|
+
skip_horiz_white
|
170
|
+
|
171
|
+
# Fors singleline tags, scan to the end of line and finish the
|
172
|
+
# tag. For multiline tags we leave the tag open for :doc
|
173
|
+
# addition just like with built-in multiline tags.
|
174
|
+
unless tag.multiline
|
175
|
+
@current_tag[:doc] = @input.scan(/.*$/).strip
|
176
|
+
skip_white
|
177
|
+
@current_tag = prev_tag
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
164
181
|
# matches @class name ...
|
165
182
|
def at_class
|
166
183
|
match(/@class/)
|
@@ -354,7 +371,7 @@ module JsDuck
|
|
354
371
|
end
|
355
372
|
end
|
356
373
|
|
357
|
-
# matches: <ident-chain> | "[" <ident-chain> [ "=" <
|
374
|
+
# matches: <ident-chain> | "[" <ident-chain> [ "=" <default-value> ] "]"
|
358
375
|
def maybe_name_with_default
|
359
376
|
skip_horiz_white
|
360
377
|
if look(/\[/)
|
@@ -364,7 +381,7 @@ module JsDuck
|
|
364
381
|
if look(/=/)
|
365
382
|
match(/=/)
|
366
383
|
skip_horiz_white
|
367
|
-
@current_tag[:default] =
|
384
|
+
@current_tag[:default] = default_value
|
368
385
|
end
|
369
386
|
skip_horiz_white
|
370
387
|
match(/\]/)
|
@@ -408,9 +425,20 @@ module JsDuck
|
|
408
425
|
end
|
409
426
|
end
|
410
427
|
|
411
|
-
|
428
|
+
# attempts to match javascript literal,
|
429
|
+
# when it fails grabs anything up to closing "]"
|
430
|
+
def default_value
|
431
|
+
start_pos = @input.pos
|
412
432
|
lit = JsLiteralParser.new(@input).literal
|
413
|
-
lit
|
433
|
+
if lit && look(/ *\]/)
|
434
|
+
# When lital matched and there's nothing after it up to the closing "]"
|
435
|
+
JsLiteralBuilder.new.to_s(lit)
|
436
|
+
else
|
437
|
+
# Otherwise reset parsing position to where we started
|
438
|
+
# and rescan up to "]" using simple regex.
|
439
|
+
@input.pos = start_pos
|
440
|
+
match(/[^\]]*/)
|
441
|
+
end
|
414
442
|
end
|
415
443
|
|
416
444
|
# matches {...} and returns text inside brackets
|
data/lib/jsduck/exporter.rb
CHANGED
@@ -29,6 +29,7 @@ module JsDuck
|
|
29
29
|
cls.delete(:doc)
|
30
30
|
cls[:members] = compact_members_group(cls[:members])
|
31
31
|
cls[:statics] = compact_members_group(cls[:statics])
|
32
|
+
cls[:files] = compact_files(cls[:files])
|
32
33
|
cls
|
33
34
|
end
|
34
35
|
|
@@ -47,6 +48,16 @@ module JsDuck
|
|
47
48
|
end
|
48
49
|
m_copy
|
49
50
|
end
|
51
|
+
|
52
|
+
# Remove full path from filename for privacy considerations as the
|
53
|
+
# path can reveal information about the system where JSDuck was
|
54
|
+
# run. The docs app doesn't need to have this information.
|
55
|
+
def compact_files(files)
|
56
|
+
files.map do |f|
|
57
|
+
{:filename => File.basename(f[:filename]), :href => f[:href]}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
50
61
|
end
|
51
62
|
|
52
63
|
end
|
data/lib/jsduck/guides.rb
CHANGED
@@ -44,14 +44,14 @@ module JsDuck
|
|
44
44
|
guide_file = in_dir + "/README.md"
|
45
45
|
return Logger.instance.warn("README.md not found in #{in_dir}") unless File.exists?(guide_file)
|
46
46
|
|
47
|
-
Logger.instance.log("Writing guide
|
47
|
+
Logger.instance.log("Writing guide", out_dir)
|
48
48
|
# Copy the whole guide dir over
|
49
49
|
FileUtils.cp_r(in_dir, out_dir)
|
50
50
|
|
51
51
|
@formatter.doc_context = {:filename => guide_file, :linenr => 0}
|
52
|
-
html = @formatter.format(IO.read(guide_file))
|
53
52
|
name = File.basename(in_dir)
|
54
|
-
|
53
|
+
@formatter.img_path = "guides/#{name}"
|
54
|
+
html = @formatter.format(IO.read(guide_file))
|
55
55
|
|
56
56
|
JsonDuck.write_jsonp(out_dir+"/README.js", name, {:guide => html, :title => guide["title"]})
|
57
57
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "jsduck/logger"
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
module JsDuck
|
5
|
+
|
6
|
+
# Looks up images from directories specified through --images option.
|
7
|
+
class Images
|
8
|
+
def initialize(paths)
|
9
|
+
@paths = scan_for_images(paths)
|
10
|
+
@images = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
# Scans each path for image files, building a hash of paths where
|
14
|
+
# each path points to a hash of image files found in that path.
|
15
|
+
def scan_for_images(paths)
|
16
|
+
map = {}
|
17
|
+
paths.each do |path|
|
18
|
+
# Scans directory for image files
|
19
|
+
map[path] = {}
|
20
|
+
Dir[path+"/**/*.{png,jpg,jpeg,gif}"].each do |img|
|
21
|
+
map[path][img] = false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
map
|
25
|
+
end
|
26
|
+
|
27
|
+
# Adds relative image path of an image
|
28
|
+
def add(filename)
|
29
|
+
unless @images[filename]
|
30
|
+
@images[filename] = true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Copys over images to given output dir
|
35
|
+
def copy(output_dir)
|
36
|
+
@images.each_key do |img|
|
37
|
+
unless copy_img(img, output_dir)
|
38
|
+
Logger.instance.warn("Image not found.", img)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
report_unused
|
42
|
+
end
|
43
|
+
|
44
|
+
# Attempts to copy one image, returns true on success
|
45
|
+
def copy_img(img, output_dir)
|
46
|
+
@paths.each_pair do |path, map|
|
47
|
+
filename = path + "/" + img
|
48
|
+
if map.has_key?(filename)
|
49
|
+
dest = output_dir + "/" + img
|
50
|
+
Logger.instance.log("Copying image", dest)
|
51
|
+
FileUtils.makedirs(File.dirname(dest))
|
52
|
+
FileUtils.cp(filename, dest)
|
53
|
+
# mark file as used.
|
54
|
+
map[filename] = true
|
55
|
+
return true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
return false
|
59
|
+
end
|
60
|
+
|
61
|
+
# Report unused images
|
62
|
+
def report_unused
|
63
|
+
@paths.each_pair do |path, map|
|
64
|
+
map.each_pair do |img, used|
|
65
|
+
Logger.instance.warn("Image not used.", img) unless used
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
data/lib/jsduck/js_parser.rb
CHANGED
@@ -234,7 +234,7 @@ module JsDuck
|
|
234
234
|
end
|
235
235
|
|
236
236
|
# <ext-define-cfg> := "{" ( <extend> | <mixins> | <alternate-class-name> | <alias> |
|
237
|
-
# <requires> | <uses> | <singleton> | <?> )*
|
237
|
+
# <xtype> | <requires> | <uses> | <singleton> | <?> )*
|
238
238
|
def ext_define_cfg
|
239
239
|
match("{")
|
240
240
|
cfg = {}
|
@@ -249,6 +249,8 @@ module JsDuck
|
|
249
249
|
cfg[:alternateClassNames] = found
|
250
250
|
elsif found = ext_define_alias
|
251
251
|
cfg[:alias] = found
|
252
|
+
elsif found = ext_define_xtype
|
253
|
+
cfg[:xtype] = found
|
252
254
|
elsif found = ext_define_requires
|
253
255
|
cfg[:requires] = found
|
254
256
|
elsif found = ext_define_uses
|
@@ -270,12 +272,18 @@ module JsDuck
|
|
270
272
|
end
|
271
273
|
end
|
272
274
|
|
273
|
-
# <mixins> := "mixins" ":" <object-literal>
|
275
|
+
# <mixins> := "mixins" ":" [ <object-literal> | <array-literal> ]
|
274
276
|
def ext_define_mixins
|
275
|
-
if look("mixins", ":"
|
277
|
+
if look("mixins", ":")
|
276
278
|
match("mixins", ":")
|
277
279
|
lit = literal
|
278
|
-
lit && lit[:
|
280
|
+
if lit && lit[:type] == :object
|
281
|
+
lit[:value].map {|x| x[:value][:value] }
|
282
|
+
elsif lit && lit[:type] == :array
|
283
|
+
lit[:value].map {|x| x[:value] }
|
284
|
+
else
|
285
|
+
nil
|
286
|
+
end
|
279
287
|
end
|
280
288
|
end
|
281
289
|
|
@@ -295,6 +303,14 @@ module JsDuck
|
|
295
303
|
end
|
296
304
|
end
|
297
305
|
|
306
|
+
# <xtype> := "xtype" ":" <string-or-list>
|
307
|
+
def ext_define_xtype
|
308
|
+
if look("xtype", ":")
|
309
|
+
match("xtype", ":")
|
310
|
+
string_or_list
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
298
314
|
# <requires> := "requires" ":" <string-or-list>
|
299
315
|
def ext_define_requires
|
300
316
|
if look("requires", ":")
|
data/lib/jsduck/lexer.rb
CHANGED
@@ -118,8 +118,8 @@ module JsDuck
|
|
118
118
|
:type => :operator,
|
119
119
|
:value => @input.scan(/./)
|
120
120
|
}
|
121
|
-
elsif @input.check(/[a-zA-Z_]/)
|
122
|
-
value = @input.scan(
|
121
|
+
elsif @input.check(/[a-zA-Z_$]/)
|
122
|
+
value = @input.scan(/[$\w]+/)
|
123
123
|
return {
|
124
124
|
:type => KEYWORDS[value] ? :keyword : :ident,
|
125
125
|
:value => value
|
@@ -167,12 +167,6 @@ module JsDuck
|
|
167
167
|
:type => :number,
|
168
168
|
:value => nr
|
169
169
|
}
|
170
|
-
elsif @input.check(/\$/)
|
171
|
-
value = @input.scan(/\$\w*/)
|
172
|
-
return {
|
173
|
-
:type => :ident,
|
174
|
-
:value => value
|
175
|
-
}
|
176
170
|
elsif @input.check(/./)
|
177
171
|
return {
|
178
172
|
:type => :operator,
|
data/lib/jsduck/lint.rb
CHANGED
@@ -75,8 +75,9 @@ module JsDuck
|
|
75
75
|
end
|
76
76
|
|
77
77
|
# Prints warning + filename and linenumber from doc-context
|
78
|
-
def warn(msg,
|
79
|
-
|
78
|
+
def warn(msg, member)
|
79
|
+
context = member[:files][0]
|
80
|
+
Logger.instance.warn(msg, context[:filename], context[:linenr])
|
80
81
|
end
|
81
82
|
|
82
83
|
end
|
data/lib/jsduck/logger.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'singleton'
|
2
|
+
require 'jsduck/os'
|
2
3
|
|
3
4
|
module JsDuck
|
4
5
|
|
@@ -15,9 +16,11 @@ module JsDuck
|
|
15
16
|
@shown_warnings = {}
|
16
17
|
end
|
17
18
|
|
18
|
-
# Prints log message
|
19
|
-
def log(msg)
|
20
|
-
|
19
|
+
# Prints log message with optional filename appended
|
20
|
+
def log(msg, filename=nil)
|
21
|
+
if @verbose
|
22
|
+
puts msg + " " + format(filename) + "..."
|
23
|
+
end
|
21
24
|
end
|
22
25
|
|
23
26
|
# Prints warning message.
|
@@ -25,12 +28,28 @@ module JsDuck
|
|
25
28
|
# Ignores duplicate warnings - only prints the first one.
|
26
29
|
# Works best when --processes=0, but it reduces the amount of
|
27
30
|
# warnings greatly also when run multiple processes.
|
28
|
-
|
31
|
+
#
|
32
|
+
# Optionally filename and line number will be inserted to message.
|
33
|
+
def warn(msg, filename=nil, line=nil)
|
34
|
+
msg = "Warning: " + format(filename, line) + " " + msg
|
35
|
+
|
29
36
|
if @warnings && !@shown_warnings[msg]
|
30
|
-
$stderr.puts
|
37
|
+
$stderr.puts msg
|
31
38
|
@shown_warnings[msg] = true
|
32
39
|
end
|
33
40
|
end
|
41
|
+
|
42
|
+
# Formats filename and line number for output
|
43
|
+
def format(filename=nil, line=nil)
|
44
|
+
out = ""
|
45
|
+
if filename
|
46
|
+
out = OS::windows? ? filename.gsub('/', '\\') : filename
|
47
|
+
if line
|
48
|
+
out += ":#{line}:"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
out
|
52
|
+
end
|
34
53
|
end
|
35
54
|
|
36
55
|
end
|
data/lib/jsduck/merger.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'jsduck/logger'
|
2
|
+
|
1
3
|
module JsDuck
|
2
4
|
|
3
5
|
# Takes data from doc-comment and code that follows it and combines
|
@@ -6,6 +8,15 @@ module JsDuck
|
|
6
8
|
#
|
7
9
|
# The main method merge() produces a hash as a result.
|
8
10
|
class Merger
|
11
|
+
# Allow passing in filename and line for error reporting
|
12
|
+
attr_accessor :filename
|
13
|
+
attr_accessor :linenr
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@filename = ""
|
17
|
+
@linenr = 0
|
18
|
+
end
|
19
|
+
|
9
20
|
def merge(docs, code)
|
10
21
|
case detect_doc_type(docs, code)
|
11
22
|
when :class
|
@@ -170,6 +181,7 @@ module JsDuck
|
|
170
181
|
:default => detect_default(:cfg, doc_map, code),
|
171
182
|
:properties => detect_subproperties(docs, :cfg),
|
172
183
|
:accessor => !!doc_map[:accessor],
|
184
|
+
:evented => !!doc_map[:evented],
|
173
185
|
}, doc_map)
|
174
186
|
end
|
175
187
|
|
@@ -222,7 +234,9 @@ module JsDuck
|
|
222
234
|
end
|
223
235
|
|
224
236
|
def create_member_id(m)
|
225
|
-
|
237
|
+
# Sanitize $ in member names with something safer
|
238
|
+
name = m[:name].gsub(/\$/, 'S-')
|
239
|
+
"#{m[:static] ? 'static-' : ''}#{m[:tagname]}-#{name}"
|
226
240
|
end
|
227
241
|
|
228
242
|
def detect_name(tagname, doc_map, code, name_type = :last_name)
|
@@ -319,10 +333,17 @@ module JsDuck
|
|
319
333
|
def detect_xtypes(doc_map, code)
|
320
334
|
if doc_map[:xtype]
|
321
335
|
{"widget" => doc_map[:xtype].map {|tag| tag[:name] } }
|
322
|
-
elsif code[:alias]
|
336
|
+
elsif code[:xtype] || code[:alias]
|
323
337
|
xtypes = {}
|
324
|
-
code[:
|
325
|
-
if
|
338
|
+
(code[:xtype] || []).each do |a|
|
339
|
+
if xtypes["widget"]
|
340
|
+
xtypes["widget"] << a
|
341
|
+
else
|
342
|
+
xtypes["widget"] = [a]
|
343
|
+
end
|
344
|
+
end
|
345
|
+
(code[:alias] || []).each do |a|
|
346
|
+
if a =~ /^([\w.]+)\.(\w+)$/
|
326
347
|
if xtypes[$1]
|
327
348
|
xtypes[$1] << $2
|
328
349
|
else
|
@@ -337,7 +358,12 @@ module JsDuck
|
|
337
358
|
end
|
338
359
|
|
339
360
|
def detect_meta(doc_map)
|
340
|
-
|
361
|
+
meta = {}
|
362
|
+
(doc_map[:meta] || []).map do |tag|
|
363
|
+
meta[tag[:name]] = [] unless meta[tag[:name]]
|
364
|
+
meta[tag[:name]] << tag[:doc]
|
365
|
+
end
|
366
|
+
meta
|
341
367
|
end
|
342
368
|
|
343
369
|
def detect_deprecated(doc_map)
|
@@ -407,8 +433,12 @@ module JsDuck
|
|
407
433
|
if it[:name] =~ /^(.+)\.([^.]+)$/
|
408
434
|
it[:name] = $2
|
409
435
|
parent = index[$1]
|
410
|
-
|
411
|
-
|
436
|
+
if parent
|
437
|
+
parent[:properties] = [] unless parent[:properties]
|
438
|
+
parent[:properties] << it
|
439
|
+
else
|
440
|
+
Logger.instance.warn("Ignoring subproperty #{$1}.#{$2}, no parent found with name '#{$1}'.", @filename, @linenr)
|
441
|
+
end
|
412
442
|
else
|
413
443
|
items << it
|
414
444
|
end
|
@@ -429,7 +459,7 @@ module JsDuck
|
|
429
459
|
# Combines :doc-s of most tags
|
430
460
|
# Ignores tags that have doc comment themselves and subproperty tags
|
431
461
|
def detect_doc(docs)
|
432
|
-
ignore_tags = [:param, :return]
|
462
|
+
ignore_tags = [:param, :return, :meta]
|
433
463
|
doc_tags = docs.find_all { |tag| !ignore_tags.include?(tag[:tagname]) && !subproperty?(tag) }
|
434
464
|
doc_tags.map { |tag| tag[:doc] }.compact.join(" ")
|
435
465
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module JsDuck
|
2
|
+
|
3
|
+
# Abstract base class for all meta tag implementations.
|
4
|
+
#
|
5
|
+
# Child classes must define value for @name attribute. They can
|
6
|
+
# also provide @multiline, and override #to_html method.
|
7
|
+
class MetaTag
|
8
|
+
# Name of the tag (required)
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
# True to include all lines up to next @tag as part of this meta-tag
|
12
|
+
attr_reader :multiline
|
13
|
+
|
14
|
+
# Override this to transform the content of meta-tag to HTML to be
|
15
|
+
# included into documentation.
|
16
|
+
#
|
17
|
+
# It gets passed an array of contents gathered from all meta-tags
|
18
|
+
# of given type. It should return an HTML string to inject into
|
19
|
+
# document. For help in that it can use the #format method to
|
20
|
+
# easily support Markdown and {@link/img} tags inside the contents
|
21
|
+
# of meta-tag.
|
22
|
+
#
|
23
|
+
# By default the method returns nil, which means the tag will not
|
24
|
+
# be rendered at all.
|
25
|
+
def to_html(contents)
|
26
|
+
end
|
27
|
+
|
28
|
+
# This is used to inject the formatter object for #markdown method
|
29
|
+
attr_accessor :formatter
|
30
|
+
|
31
|
+
# Helper method to format the text in standard JsDuck way.
|
32
|
+
# This means running it through Markdown engine and expanding
|
33
|
+
# {@link} and {@img} tags.
|
34
|
+
def format(text)
|
35
|
+
@formatter.format(text)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns all descendants of MetaTag class.
|
39
|
+
def self.descendants
|
40
|
+
result = []
|
41
|
+
ObjectSpace.each_object(::Class) do |cls|
|
42
|
+
result << cls if cls < self
|
43
|
+
end
|
44
|
+
result
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "jsduck/meta_tag"
|
2
|
+
require 'jsduck/author_tag'
|
3
|
+
require 'jsduck/doc_author_tag'
|
4
|
+
|
5
|
+
module JsDuck
|
6
|
+
|
7
|
+
# Loads user-defined meta-tags
|
8
|
+
class MetaTagLoader
|
9
|
+
# instatiates builtin meta tags
|
10
|
+
def initialize
|
11
|
+
@classes = MetaTag.descendants
|
12
|
+
@meta_tags = @classes.map {|cls| cls.new }
|
13
|
+
end
|
14
|
+
|
15
|
+
# Loads user-defined meta-tags from given paths.
|
16
|
+
# Returns list of meta-tag instances.
|
17
|
+
def load(paths)
|
18
|
+
paths.each do |path|
|
19
|
+
if File.directory?(path)
|
20
|
+
Dir[path+"/**/*.rb"].each do |file|
|
21
|
+
require(file)
|
22
|
+
init_remaining
|
23
|
+
end
|
24
|
+
else
|
25
|
+
require(path)
|
26
|
+
init_remaining
|
27
|
+
end
|
28
|
+
end
|
29
|
+
@meta_tags
|
30
|
+
end
|
31
|
+
|
32
|
+
# Instantiates meta tag classes that haven't been instantiated
|
33
|
+
# already. This is called after each meta-tags file is loaded so
|
34
|
+
# that the list of meta-tags will be in order specified from
|
35
|
+
# command line.
|
36
|
+
def init_remaining
|
37
|
+
MetaTag.descendants.each do |cls|
|
38
|
+
if !@classes.include?(cls)
|
39
|
+
@classes << cls
|
40
|
+
newtag = cls.new
|
41
|
+
@meta_tags = @meta_tags.find_all {|t| t.name != newtag.name }
|
42
|
+
@meta_tags << newtag
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|