jsduck 0.5 → 0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +30 -2
- data/bin/jsduck +24 -2
- data/jsduck.gemspec +2 -2
- data/lib/jsduck/aggregator.rb +53 -32
- data/lib/jsduck/app.rb +71 -22
- data/lib/jsduck/cfg_table.rb +2 -2
- data/lib/jsduck/class.rb +5 -0
- data/lib/jsduck/css_parser.rb +75 -0
- data/lib/jsduck/doc_formatter.rb +111 -20
- data/lib/jsduck/doc_parser.rb +64 -4
- data/lib/jsduck/event_table.rb +3 -3
- data/lib/jsduck/exporter.rb +11 -9
- data/lib/jsduck/inheritance_tree.rb +2 -7
- data/lib/jsduck/{parser.rb → js_parser.rb} +20 -4
- data/lib/jsduck/lexer.rb +1 -2
- data/lib/jsduck/long_params.rb +4 -8
- data/lib/jsduck/members.rb +15 -1
- data/lib/jsduck/merger.rb +50 -5
- data/lib/jsduck/method_table.rb +4 -8
- data/lib/jsduck/page.rb +20 -9
- data/lib/jsduck/property_table.rb +2 -2
- data/lib/jsduck/relations.rb +4 -0
- data/lib/jsduck/source_file.rb +101 -0
- data/lib/jsduck/{source_formatter.rb → source_writer.rb} +14 -27
- data/lib/jsduck/table.rb +12 -11
- data/template/resources/docs.js +43 -51
- metadata +8 -6
data/lib/jsduck/long_params.rb
CHANGED
@@ -1,15 +1,10 @@
|
|
1
|
-
require "jsduck/doc_formatter"
|
2
|
-
|
3
1
|
module JsDuck
|
4
2
|
|
5
3
|
# Renders method/event parameters list in long form
|
6
4
|
# for use in documentation body.
|
7
5
|
class LongParams
|
8
|
-
def initialize(
|
9
|
-
@formatter =
|
10
|
-
@formatter.context = cls.full_name
|
11
|
-
@formatter.css_class = 'docClass'
|
12
|
-
@formatter.url_template = 'output/%cls%.html'
|
6
|
+
def initialize(formatter)
|
7
|
+
@formatter = formatter
|
13
8
|
end
|
14
9
|
|
15
10
|
def render(params)
|
@@ -22,9 +17,10 @@ module JsDuck
|
|
22
17
|
|
23
18
|
def render_single(param)
|
24
19
|
doc = @formatter.format(param[:doc])
|
20
|
+
type = @formatter.replace(param[:type])
|
25
21
|
return [
|
26
22
|
"<li>",
|
27
|
-
"<code>#{param[:name]}</code> : #{
|
23
|
+
"<code>#{param[:name]}</code> : #{type}",
|
28
24
|
"<div class='sub-desc'>#{doc}</div>",
|
29
25
|
"</li>",
|
30
26
|
].join("")
|
data/lib/jsduck/members.rb
CHANGED
@@ -9,15 +9,29 @@ module JsDuck
|
|
9
9
|
def create(docs)
|
10
10
|
list = []
|
11
11
|
docs.each do |cls|
|
12
|
+
list << class_node(cls)
|
12
13
|
[:cfg, :property, :method, :event].each do |type|
|
13
14
|
cls.members(type).each do |m|
|
14
|
-
|
15
|
+
# skip inherited items and constructors
|
16
|
+
if m[:member] == cls.full_name && m[:name] != cls.short_name
|
17
|
+
list << member_node(m, cls)
|
18
|
+
end
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
18
22
|
list
|
19
23
|
end
|
20
24
|
|
25
|
+
# Creates structure representing one class
|
26
|
+
def class_node(cls)
|
27
|
+
return {
|
28
|
+
:cls => cls.full_name,
|
29
|
+
:member => cls.short_name,
|
30
|
+
:type => :cls,
|
31
|
+
:doc => short_desc(cls[:doc])
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
21
35
|
# Creates structure representing one member
|
22
36
|
def member_node(member, cls)
|
23
37
|
return {
|
data/lib/jsduck/merger.rb
CHANGED
@@ -18,6 +18,10 @@ module JsDuck
|
|
18
18
|
create_cfg(docs, code)
|
19
19
|
when :property
|
20
20
|
create_property(docs, code)
|
21
|
+
when :css_var
|
22
|
+
create_css_var(docs, code)
|
23
|
+
when :css_mixin
|
24
|
+
create_css_mixin(docs, code)
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
@@ -33,12 +37,16 @@ module JsDuck
|
|
33
37
|
:method
|
34
38
|
elsif doc_map[:property] || doc_map[:type]
|
35
39
|
:property
|
40
|
+
elsif doc_map[:css_var]
|
41
|
+
:css_var
|
36
42
|
elsif code[:type] == :ext_define
|
37
43
|
:class
|
38
44
|
elsif code[:type] == :assignment && class_name?(*code[:left])
|
39
45
|
:class
|
40
46
|
elsif code[:type] == :function && class_name?(code[:name])
|
41
47
|
:class
|
48
|
+
elsif code[:type] == :css_mixin
|
49
|
+
:css_mixin
|
42
50
|
elsif doc_map[:cfg]
|
43
51
|
:cfg
|
44
52
|
elsif code[:type] == :function
|
@@ -67,6 +75,8 @@ module JsDuck
|
|
67
75
|
end
|
68
76
|
result[:property] = []
|
69
77
|
result[:event] = []
|
78
|
+
result[:css_var] = []
|
79
|
+
result[:css_mixin] = []
|
70
80
|
result
|
71
81
|
end
|
72
82
|
|
@@ -109,9 +119,11 @@ module JsDuck
|
|
109
119
|
:name => detect_name(:class, doc_map, code, :full_name),
|
110
120
|
:doc => detect_doc(docs),
|
111
121
|
:extends => detect_extends(doc_map, code),
|
112
|
-
:mixins =>
|
122
|
+
:mixins => detect_list(:mixins, doc_map, code),
|
123
|
+
:alternateClassNames => detect_list(:alternateClassNames, doc_map, code),
|
113
124
|
:xtype => detect_xtype(doc_map),
|
114
125
|
:author => detect_author(doc_map),
|
126
|
+
:docauthor => detect_docauthor(doc_map),
|
115
127
|
:singleton => !!doc_map[:singleton],
|
116
128
|
:private => !!doc_map[:private],
|
117
129
|
}
|
@@ -168,13 +180,39 @@ module JsDuck
|
|
168
180
|
}
|
169
181
|
end
|
170
182
|
|
183
|
+
def create_css_var(docs, code)
|
184
|
+
doc_map = build_doc_map(docs)
|
185
|
+
return {
|
186
|
+
:tagname => :css_var,
|
187
|
+
:name => detect_name(:css_var, doc_map, code),
|
188
|
+
:member => detect_member(doc_map),
|
189
|
+
:type => detect_type(:css_var, doc_map, code),
|
190
|
+
:doc => detect_doc(docs),
|
191
|
+
:private => !!doc_map[:private],
|
192
|
+
:static => !!doc_map[:static],
|
193
|
+
}
|
194
|
+
end
|
195
|
+
|
196
|
+
def create_css_mixin(docs, code)
|
197
|
+
doc_map = build_doc_map(docs)
|
198
|
+
return {
|
199
|
+
:tagname => :css_mixin,
|
200
|
+
:name => detect_name(:css_mixin, doc_map, code),
|
201
|
+
:member => detect_member(doc_map),
|
202
|
+
:doc => detect_doc(docs),
|
203
|
+
:params => detect_params(docs, code),
|
204
|
+
:private => !!doc_map[:private],
|
205
|
+
:static => !!doc_map[:static],
|
206
|
+
}
|
207
|
+
end
|
208
|
+
|
171
209
|
def detect_name(tagname, doc_map, code, name_type = :last_name)
|
172
210
|
main_tag = doc_map[tagname] ? doc_map[tagname].first : {}
|
173
211
|
if main_tag[:name]
|
174
212
|
main_tag[:name]
|
175
213
|
elsif doc_map[:constructor]
|
176
214
|
"constructor"
|
177
|
-
elsif code[:type] == :function
|
215
|
+
elsif code[:type] == :function || code[:type] == :css_mixin
|
178
216
|
code[:name]
|
179
217
|
elsif code[:type] == :assignment
|
180
218
|
name_type == :full_name ? code[:left].join(".") : code[:left].last
|
@@ -224,9 +262,12 @@ module JsDuck
|
|
224
262
|
end
|
225
263
|
end
|
226
264
|
|
227
|
-
|
228
|
-
|
229
|
-
|
265
|
+
# for detecting mixins and alternateClassNames
|
266
|
+
def detect_list(type, doc_map, code)
|
267
|
+
if doc_map[type]
|
268
|
+
doc_map[type].map {|d| d[type] }.flatten
|
269
|
+
elsif code[:type] == :ext_define && code[type]
|
270
|
+
code[type]
|
230
271
|
else
|
231
272
|
[]
|
232
273
|
end
|
@@ -240,6 +281,10 @@ module JsDuck
|
|
240
281
|
doc_map[:author] ? doc_map[:author].first[:name] : nil
|
241
282
|
end
|
242
283
|
|
284
|
+
def detect_docauthor(doc_map)
|
285
|
+
doc_map[:docauthor] ? doc_map[:docauthor].first[:name] : nil
|
286
|
+
end
|
287
|
+
|
243
288
|
def detect_params(docs, code)
|
244
289
|
implicit = detect_implicit_params(code)
|
245
290
|
explicit = detect_explicit_params(docs)
|
data/lib/jsduck/method_table.rb
CHANGED
@@ -5,19 +5,15 @@ require 'jsduck/long_params'
|
|
5
5
|
module JsDuck
|
6
6
|
|
7
7
|
class MethodTable < Table
|
8
|
-
def initialize(cls, cache={})
|
9
|
-
super(cls, cache)
|
8
|
+
def initialize(cls, formatter, cache={})
|
9
|
+
super(cls, formatter, cache)
|
10
10
|
@type = :method
|
11
11
|
@id = @cls.full_name + "-methods"
|
12
12
|
@title = "Public Methods"
|
13
13
|
@column_title = "Method"
|
14
14
|
@row_class = "method-row"
|
15
15
|
@short_params = ShortParams.new
|
16
|
-
@long_params = LongParams.new(@
|
17
|
-
@formatter = DocFormatter.new()
|
18
|
-
@formatter.context = @cls.full_name
|
19
|
-
@formatter.css_class = 'docClass'
|
20
|
-
@formatter.url_template = 'output/%cls%.html'
|
16
|
+
@long_params = LongParams.new(@formatter)
|
21
17
|
end
|
22
18
|
|
23
19
|
def signature_suffix(item)
|
@@ -36,7 +32,7 @@ module JsDuck
|
|
36
32
|
end
|
37
33
|
|
38
34
|
def render_return(item)
|
39
|
-
type = item[:return][:type]
|
35
|
+
type = @formatter.replace(item[:return][:type])
|
40
36
|
doc = @formatter.format(item[:return][:doc])
|
41
37
|
if type == "void" && doc.length == 0
|
42
38
|
"<ul><li>void</li></ul>"
|
data/lib/jsduck/page.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'cgi'
|
1
2
|
require 'jsduck/doc_formatter'
|
2
3
|
require 'jsduck/inheritance_tree'
|
3
4
|
require 'jsduck/cfg_table'
|
@@ -21,8 +22,16 @@ module JsDuck
|
|
21
22
|
@cache = cache
|
22
23
|
@formatter = DocFormatter.new
|
23
24
|
@formatter.context = cls.full_name
|
24
|
-
@formatter.
|
25
|
-
@formatter.
|
25
|
+
@formatter.link_tpl = '<a href="output/%c.html%M" rel="%c%M" class="docClass">%a</a>'
|
26
|
+
@formatter.relations = relations
|
27
|
+
end
|
28
|
+
|
29
|
+
# Setters to override link and image templates
|
30
|
+
def link_tpl=(tpl)
|
31
|
+
@formatter.link_tpl = tpl
|
32
|
+
end
|
33
|
+
def img_tpl=(tpl)
|
34
|
+
@formatter.img_tpl = tpl
|
26
35
|
end
|
27
36
|
|
28
37
|
def to_html
|
@@ -33,17 +42,17 @@ module JsDuck
|
|
33
42
|
abstract,
|
34
43
|
description,
|
35
44
|
"<div class='hr'></div>",
|
36
|
-
CfgTable.new(@cls, @cache).to_html,
|
37
|
-
PropertyTable.new(@cls, @cache).to_html,
|
38
|
-
MethodTable.new(@cls, @cache).to_html,
|
39
|
-
EventTable.new(@cls, @cache).to_html,
|
45
|
+
CfgTable.new(@cls, @formatter, @cache).to_html,
|
46
|
+
PropertyTable.new(@cls, @formatter, @cache).to_html,
|
47
|
+
MethodTable.new(@cls, @formatter, @cache).to_html,
|
48
|
+
EventTable.new(@cls, @formatter, @cache).to_html,
|
40
49
|
"</div>",
|
41
50
|
].join("\n")
|
42
51
|
end
|
43
52
|
|
44
53
|
# only render the tree if class has at least one ancestor
|
45
54
|
def inheritance_tree
|
46
|
-
@cls.parent ? InheritanceTree.new(@cls).to_html : ""
|
55
|
+
@cls.parent ? InheritanceTree.new(@cls, @formatter).to_html : ""
|
47
56
|
end
|
48
57
|
|
49
58
|
def heading
|
@@ -53,13 +62,15 @@ module JsDuck
|
|
53
62
|
def abstract
|
54
63
|
[
|
55
64
|
"<table cellspacing='0'>",
|
65
|
+
boolean_row("Alternate names:", @cls[:alternateClassNames].join(", ")),
|
56
66
|
row("Extends:", extends_link),
|
57
67
|
classes_row("Mixins:", @cls.mixins),
|
58
|
-
row("
|
68
|
+
row("Defined In:", file_link),
|
59
69
|
classes_row("Subclasses:", @relations.subclasses(@cls)),
|
60
70
|
classes_row("Mixed into:", @relations.mixed_into(@cls)),
|
61
71
|
boolean_row("xtype:", @cls[:xtype]),
|
62
72
|
boolean_row("Author:", @cls[:author]),
|
73
|
+
boolean_row("Author of docs:", @cls[:docauthor]),
|
63
74
|
"</table>",
|
64
75
|
].join("\n")
|
65
76
|
end
|
@@ -92,7 +103,7 @@ module JsDuck
|
|
92
103
|
end
|
93
104
|
|
94
105
|
def boolean_row(label, item)
|
95
|
-
item ? row(label, item) : ""
|
106
|
+
(item && item != "") ? row(label, CGI.escapeHTML(item)) : ""
|
96
107
|
end
|
97
108
|
|
98
109
|
def row(label, info)
|
@@ -3,8 +3,8 @@ require 'jsduck/table'
|
|
3
3
|
module JsDuck
|
4
4
|
|
5
5
|
class PropertyTable < Table
|
6
|
-
def initialize(cls, cache={})
|
7
|
-
super(cls, cache)
|
6
|
+
def initialize(cls, formatter, cache={})
|
7
|
+
super(cls, formatter, cache)
|
8
8
|
@type = :property
|
9
9
|
@id = @cls.full_name + "-props"
|
10
10
|
@title = "Public Properties"
|
data/lib/jsduck/relations.rb
CHANGED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'jsduck/js_parser'
|
2
|
+
require 'jsduck/css_parser'
|
3
|
+
require 'jsduck/merger'
|
4
|
+
require "cgi"
|
5
|
+
|
6
|
+
module JsDuck
|
7
|
+
|
8
|
+
# Represents one JavaScript or CSS source file.
|
9
|
+
#
|
10
|
+
# The filename parameter determines whether it's parsed as
|
11
|
+
# JavaScript (the default) or CSS.
|
12
|
+
class SourceFile
|
13
|
+
attr_reader :filename
|
14
|
+
attr_reader :contents
|
15
|
+
attr_reader :docs
|
16
|
+
attr_reader :html_filename
|
17
|
+
|
18
|
+
def initialize(contents, filename="")
|
19
|
+
@contents = contents
|
20
|
+
@filename = filename
|
21
|
+
@html_filename = ""
|
22
|
+
@links = {}
|
23
|
+
|
24
|
+
merger = Merger.new
|
25
|
+
@docs = parse.map do |docset|
|
26
|
+
link(docset[:linenr], merger.merge(docset[:comment], docset[:code]))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# loops through each doc-object in file
|
31
|
+
def each(&block)
|
32
|
+
@docs.each(&block)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Sets the html filename of this file,
|
36
|
+
# updating also all doc-objects linking this file
|
37
|
+
def html_filename=(html_filename)
|
38
|
+
@html_filename = html_filename
|
39
|
+
@links.each_value do |line|
|
40
|
+
line.each do |doc|
|
41
|
+
doc[:html_filename] = @html_filename
|
42
|
+
doc[:href] = @html_filename + "#" + id(doc)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns source code as HTML with lines starting doc-comments specially marked.
|
48
|
+
def to_html
|
49
|
+
linenr = 0
|
50
|
+
return @contents.lines.map do |line|
|
51
|
+
linenr += 1;
|
52
|
+
line = CGI.escapeHTML(line)
|
53
|
+
# wrap the line in as many spans as there are links to this line number.
|
54
|
+
if @links[linenr]
|
55
|
+
@links[linenr].each do |doc|
|
56
|
+
line = "<span id='#{id(doc)}'>#{line}</span>"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
line
|
60
|
+
end.join()
|
61
|
+
end
|
62
|
+
|
63
|
+
def id(doc)
|
64
|
+
if doc[:tagname] == :class
|
65
|
+
doc[:name].gsub(/\./, '-')
|
66
|
+
else
|
67
|
+
# when creation of global class is skipped,
|
68
|
+
# this member property can be nil.
|
69
|
+
(doc[:member] || "global").gsub(/\./, '-') + "-" + doc[:tagname].to_s + "-" + doc[:name]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# Parses the file depending on filename as JS or CSS
|
76
|
+
def parse
|
77
|
+
if @filename =~ /\.s?css$/
|
78
|
+
CssParser.new(@contents).parse
|
79
|
+
else
|
80
|
+
JsParser.new(@contents).parse
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Creates two-way link between sourcefile and doc-object.
|
85
|
+
# If doc-object is class, links also the contained cfgs and constructor.
|
86
|
+
# Returns the modified doc-object after done.
|
87
|
+
def link(linenr, doc)
|
88
|
+
@links[linenr] = [] unless @links[linenr]
|
89
|
+
@links[linenr] << doc
|
90
|
+
doc[:filename] = @filename
|
91
|
+
doc[:linenr] = linenr
|
92
|
+
if doc[:tagname] == :class
|
93
|
+
doc[:cfg].each {|cfg| link(linenr, cfg) }
|
94
|
+
doc[:method].each {|method| link(linenr, method) }
|
95
|
+
end
|
96
|
+
doc
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -1,28 +1,25 @@
|
|
1
|
-
require "cgi"
|
2
|
-
|
3
1
|
module JsDuck
|
4
2
|
|
5
|
-
#
|
6
|
-
|
7
|
-
# from documentation.
|
8
|
-
class SourceFormatter
|
3
|
+
# Writes HTML JavaScript/CSS source into HTML file.
|
4
|
+
class SourceWriter
|
9
5
|
|
10
6
|
# Initializes SourceFormatter to the directory where
|
11
7
|
# HTML-formatted source files will be placed.
|
12
8
|
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
16
|
-
def initialize(output_dir, formatter = :format_page)
|
9
|
+
# Wrapper can be either :page or nil; with the first one the whole
|
10
|
+
# HTML page is created, otherwise source is left as is.
|
11
|
+
def initialize(output_dir, wrapper = :page)
|
17
12
|
@output_dir = output_dir
|
18
|
-
@
|
13
|
+
@wrapper = wrapper
|
19
14
|
end
|
20
15
|
|
21
|
-
#
|
22
|
-
#
|
16
|
+
# Writes HTML into file in output directory. It returns the name
|
17
|
+
# of the file that it wrote.
|
23
18
|
def write(source, filename)
|
24
19
|
fname = uniq_html_filename(filename)
|
25
|
-
File.open(fname, 'w')
|
20
|
+
File.open(fname, 'w') do |f|
|
21
|
+
f.write(@wrapper ? wrap_page(source) : source)
|
22
|
+
end
|
26
23
|
fname
|
27
24
|
end
|
28
25
|
|
@@ -40,8 +37,8 @@ module JsDuck
|
|
40
37
|
@output_dir + "/" + File.basename(filename, ".js") + (nr > 0 ? nr.to_s : "") + ".html"
|
41
38
|
end
|
42
39
|
|
43
|
-
# Returns
|
44
|
-
def
|
40
|
+
# Returns source wrapped inside HTML page
|
41
|
+
def wrap_page(source)
|
45
42
|
return <<-EOHTML
|
46
43
|
<!DOCTYPE html>
|
47
44
|
<html>
|
@@ -60,22 +57,12 @@ module JsDuck
|
|
60
57
|
</script>
|
61
58
|
</head>
|
62
59
|
<body onload="prettyPrint(); highlight();">
|
63
|
-
<pre class="prettyprint lang-js">#{
|
60
|
+
<pre class="prettyprint lang-js">#{source}</pre>
|
64
61
|
</body>
|
65
62
|
</html>
|
66
63
|
EOHTML
|
67
64
|
end
|
68
65
|
|
69
|
-
# Formats the contents of <pre>, wrapping each source code line
|
70
|
-
# inside <span>.
|
71
|
-
def format_pre(source)
|
72
|
-
i = 0
|
73
|
-
return source.lines.collect do |line|
|
74
|
-
i += 1
|
75
|
-
"<span id='line-#{i}'>#{CGI.escapeHTML(line)}</span>"
|
76
|
-
end.join()
|
77
|
-
end
|
78
|
-
|
79
66
|
end
|
80
67
|
|
81
68
|
end
|