jsduck 0.5 → 0.6
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.
- 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
|