jsduck 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +6 -0
- data/jsduck.gemspec +2 -2
- data/lib/jsduck/aggregator.rb +18 -11
- data/lib/jsduck/app.rb +9 -5
- data/lib/jsduck/class.rb +18 -6
- data/lib/jsduck/doc_parser.rb +14 -0
- data/lib/jsduck/event_table.rb +1 -1
- data/lib/jsduck/merger.rb +19 -1
- data/lib/jsduck/page.rb +9 -1
- data/lib/jsduck/parser.rb +85 -1
- metadata +4 -4
data/README.md
CHANGED
@@ -195,6 +195,12 @@ JsDuck was developed by [Rene Saarsoo](http://triin.net).
|
|
195
195
|
Changelog
|
196
196
|
---------
|
197
197
|
|
198
|
+
* 0.4 - Ext4 support
|
199
|
+
* Support for Ext.define() syntax from ExtJS 4.
|
200
|
+
* Showing @xtype and @author information on generated pages.
|
201
|
+
* Showing filename and line number in warnings.
|
202
|
+
* Fix for event showing the same doc as method with same name.
|
203
|
+
|
198
204
|
* 0.3 - Performance improvements
|
199
205
|
* Significant peed improvements - most importantly utilizing
|
200
206
|
multiple CPU-s (if available) to speed things up. On my 4-core
|
data/jsduck.gemspec
CHANGED
@@ -2,8 +2,8 @@ Gem::Specification.new do |s|
|
|
2
2
|
s.required_rubygems_version = ">= 1.3.7"
|
3
3
|
|
4
4
|
s.name = 'jsduck'
|
5
|
-
s.version = '0.
|
6
|
-
s.date = '2011-02-
|
5
|
+
s.version = '0.4'
|
6
|
+
s.date = '2011-02-28'
|
7
7
|
s.summary = "Simple JavaScript Duckumentation generator"
|
8
8
|
s.description = "Better ext-doc like JavaScript documentation generator for ExtJS"
|
9
9
|
s.homepage = "https://github.com/nene/jsduck"
|
data/lib/jsduck/aggregator.rb
CHANGED
@@ -24,21 +24,28 @@ module JsDuck
|
|
24
24
|
def aggregate(input, filename="", html_filename="")
|
25
25
|
@current_class = nil
|
26
26
|
input.each do |docset|
|
27
|
-
doc = docset[:comment]
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
doc = @merger.merge(docset[:comment], docset[:code])
|
28
|
+
|
29
|
+
add_source_data(doc, {
|
30
|
+
:filename => filename,
|
31
|
+
:html_filename => html_filename,
|
32
|
+
:linenr => docset[:linenr],
|
33
|
+
})
|
34
|
+
|
35
|
+
register(doc)
|
31
36
|
end
|
32
37
|
end
|
33
38
|
|
34
|
-
#
|
35
|
-
|
36
|
-
|
37
|
-
doc[:
|
39
|
+
# Links doc-object to source code where it came from.
|
40
|
+
def add_source_data(doc, src)
|
41
|
+
doc[:href] = src[:html_filename] + "#line-" + src[:linenr].to_s
|
42
|
+
doc[:filename] = src[:filename]
|
43
|
+
doc[:linenr] = src[:linenr]
|
44
|
+
# class-level doc-comment can contain constructor and config
|
45
|
+
# options, link those to the same location in source.
|
38
46
|
if doc[:tagname] == :class
|
39
|
-
doc[:
|
40
|
-
doc[:
|
41
|
-
doc[:method].each {|method| method[:href] = href }
|
47
|
+
doc[:cfg].each {|cfg| add_source_data(cfg, src) }
|
48
|
+
doc[:method].each {|method| add_source_data(method, src) }
|
42
49
|
end
|
43
50
|
doc
|
44
51
|
end
|
data/lib/jsduck/app.rb
CHANGED
@@ -50,8 +50,8 @@ module JsDuck
|
|
50
50
|
puts "Parsing #{fname} ..." if @verbose
|
51
51
|
code = IO.read(fname)
|
52
52
|
{
|
53
|
-
:
|
54
|
-
:
|
53
|
+
:filename => fname,
|
54
|
+
:html_filename => File.basename(src.write(code, fname)),
|
55
55
|
:data => Parser.new(code).parse,
|
56
56
|
}
|
57
57
|
end
|
@@ -61,8 +61,8 @@ module JsDuck
|
|
61
61
|
def aggregate(parsed_files)
|
62
62
|
agr = Aggregator.new
|
63
63
|
parsed_files.each do |file|
|
64
|
-
puts "Aggregating #{file[:
|
65
|
-
agr.aggregate(file[:data],
|
64
|
+
puts "Aggregating #{file[:filename]} ..." if @verbose
|
65
|
+
agr.aggregate(file[:data], file[:filename], file[:html_filename])
|
66
66
|
end
|
67
67
|
agr.result
|
68
68
|
end
|
@@ -75,7 +75,11 @@ module JsDuck
|
|
75
75
|
if d[:tagname] == :class
|
76
76
|
classes[d[:name]] = Class.new(d, classes)
|
77
77
|
else
|
78
|
-
|
78
|
+
type = d[:tagname].to_s
|
79
|
+
name = d[:name]
|
80
|
+
file = d[:filename]
|
81
|
+
line = d[:linenr]
|
82
|
+
puts "Warning: Ignoring #{type}: #{name} in #{file} line #{line}"
|
79
83
|
end
|
80
84
|
end
|
81
85
|
classes.values
|
data/lib/jsduck/class.rb
CHANGED
@@ -18,6 +18,12 @@ module JsDuck
|
|
18
18
|
@doc[:extends] ? @classes[@doc[:extends]] : nil
|
19
19
|
end
|
20
20
|
|
21
|
+
# Returns array of mixin class instances.
|
22
|
+
# Returns empty array if no mixins
|
23
|
+
def mixins
|
24
|
+
@doc[:mixins] ? @doc[:mixins].collect {|classname| @classes[classname] } : []
|
25
|
+
end
|
26
|
+
|
21
27
|
# Returns true when this class inherits from the specified class.
|
22
28
|
# Also returns true when the class itself is the one we are asking about.
|
23
29
|
def inherits_from?(class_name)
|
@@ -51,9 +57,9 @@ module JsDuck
|
|
51
57
|
ms
|
52
58
|
end
|
53
59
|
|
54
|
-
# Returns hash of public members of class (and parent classes
|
55
|
-
# Members are methods, properties, cfgs,
|
56
|
-
# is
|
60
|
+
# Returns hash of public members of class (and of parent classes
|
61
|
+
# and mixin classes). Members are methods, properties, cfgs,
|
62
|
+
# events (member type is specified through 'type' parameter).
|
57
63
|
#
|
58
64
|
# When parent and child have members with same name,
|
59
65
|
# member from child overrides tha parent member.
|
@@ -61,11 +67,17 @@ module JsDuck
|
|
61
67
|
# We also set :member property to each member to the full class
|
62
68
|
# name where it belongs, so one can tell them apart afterwards.
|
63
69
|
def members_hash(type)
|
64
|
-
|
70
|
+
all_members = parent ? parent.members_hash(type) : {}
|
71
|
+
|
72
|
+
mixins.each do |mix|
|
73
|
+
all_members.merge!(mix.members_hash(type))
|
74
|
+
end
|
75
|
+
|
65
76
|
@doc[type].each do |m|
|
66
|
-
|
77
|
+
all_members[m[:name]] = m if !m[:private]
|
67
78
|
end
|
68
|
-
|
79
|
+
|
80
|
+
all_members
|
69
81
|
end
|
70
82
|
|
71
83
|
# A way to access full class name with similar syntax to
|
data/lib/jsduck/doc_parser.rb
CHANGED
@@ -90,10 +90,15 @@ module JsDuck
|
|
90
90
|
at_xtype
|
91
91
|
elsif look(/@member\b/)
|
92
92
|
at_member
|
93
|
+
elsif look(/@author\b/)
|
94
|
+
at_author
|
93
95
|
elsif look(/@static\b/)
|
94
96
|
boolean_at_tag(/@static/, :static)
|
95
97
|
elsif look(/@(private|ignore|hide|protected)\b/)
|
96
98
|
boolean_at_tag(/@(private|ignore|hide|protected)/, :private)
|
99
|
+
elsif look(/@markdown\b/)
|
100
|
+
# this is detected just to be ignored
|
101
|
+
boolean_at_tag(/@markdown/, :markdown)
|
97
102
|
elsif look(/@/)
|
98
103
|
@current_tag[:doc] += @input.scan(/@/)
|
99
104
|
elsif look(/[^@]/)
|
@@ -207,6 +212,15 @@ module JsDuck
|
|
207
212
|
skip_white
|
208
213
|
end
|
209
214
|
|
215
|
+
# matches @author some name ... newline
|
216
|
+
def at_author
|
217
|
+
match(/@author/)
|
218
|
+
add_tag(:author)
|
219
|
+
skip_horiz_white
|
220
|
+
@current_tag[:name] = @input.scan(/.*$/)
|
221
|
+
skip_white
|
222
|
+
end
|
223
|
+
|
210
224
|
# Used to match @private, @ignore, @hide, ...
|
211
225
|
def boolean_at_tag(regex, propname)
|
212
226
|
match(regex)
|
data/lib/jsduck/event_table.rb
CHANGED
data/lib/jsduck/merger.rb
CHANGED
@@ -33,7 +33,7 @@ module JsDuck
|
|
33
33
|
:method
|
34
34
|
elsif doc_map[:property] || doc_map[:type]
|
35
35
|
:property
|
36
|
-
elsif code[:type] == :
|
36
|
+
elsif code[:type] == :ext_define
|
37
37
|
:class
|
38
38
|
elsif code[:type] == :assignment && class_name?(*code[:left])
|
39
39
|
:class
|
@@ -109,7 +109,9 @@ module JsDuck
|
|
109
109
|
:name => detect_name(:class, doc_map, code, :full_name),
|
110
110
|
:doc => detect_doc(docs),
|
111
111
|
:extends => detect_extends(doc_map, code),
|
112
|
+
:mixins => detect_mixins(doc_map, code),
|
112
113
|
:xtype => detect_xtype(doc_map),
|
114
|
+
:author => detect_author(doc_map),
|
113
115
|
:singleton => !!doc_map[:singleton],
|
114
116
|
:private => !!doc_map[:private],
|
115
117
|
}
|
@@ -176,6 +178,8 @@ module JsDuck
|
|
176
178
|
code[:name]
|
177
179
|
elsif code[:type] == :assignment
|
178
180
|
name_type == :full_name ? code[:left].join(".") : code[:left].last
|
181
|
+
elsif code[:type] == :ext_define
|
182
|
+
name_type == :full_name ? code[:name] : code[:name].split(/\./).last
|
179
183
|
else
|
180
184
|
""
|
181
185
|
end
|
@@ -215,6 +219,16 @@ module JsDuck
|
|
215
219
|
doc_map[:extends].first[:extends]
|
216
220
|
elsif code[:type] == :assignment && code[:right] && code[:right][:type] == :ext_extend
|
217
221
|
code[:right][:extend].join(".")
|
222
|
+
elsif code[:type] == :ext_define
|
223
|
+
code[:extend]
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def detect_mixins(doc_map, code)
|
228
|
+
if code[:type] == :ext_define && code[:mixins]
|
229
|
+
code[:mixins]
|
230
|
+
else
|
231
|
+
[]
|
218
232
|
end
|
219
233
|
end
|
220
234
|
|
@@ -222,6 +236,10 @@ module JsDuck
|
|
222
236
|
doc_map[:xtype] ? doc_map[:xtype].first[:name] : nil
|
223
237
|
end
|
224
238
|
|
239
|
+
def detect_author(doc_map)
|
240
|
+
doc_map[:author] ? doc_map[:author].first[:name] : nil
|
241
|
+
end
|
242
|
+
|
225
243
|
def detect_params(docs, code)
|
226
244
|
implicit = detect_implicit_params(code)
|
227
245
|
explicit = detect_explicit_params(docs)
|
data/lib/jsduck/page.rb
CHANGED
@@ -51,8 +51,11 @@ module JsDuck
|
|
51
51
|
[
|
52
52
|
"<table cellspacing='0'>",
|
53
53
|
abstract_row("Extends:", @cls.parent ? class_link(@cls.parent.full_name) : "Object"),
|
54
|
+
@cls.mixins.length > 0 ? abstract_row("Mixins:", mixins) : "",
|
54
55
|
abstract_row("Defind In:", file_link),
|
55
56
|
@subclasses[@cls] ? abstract_row("Subclasses:", subclasses) : "",
|
57
|
+
@cls[:xtype] ? abstract_row("xtype:", @cls[:xtype]) : "",
|
58
|
+
@cls[:author] ? abstract_row("Author:", @cls[:author]) : "",
|
56
59
|
"</table>",
|
57
60
|
].join("\n")
|
58
61
|
end
|
@@ -63,7 +66,7 @@ module JsDuck
|
|
63
66
|
end
|
64
67
|
|
65
68
|
def file_link
|
66
|
-
"<a href='source/#{@cls[:href]}'>#{@cls[:filename]}</a>"
|
69
|
+
"<a href='source/#{@cls[:href]}'>#{File.basename(@cls[:filename])}</a>"
|
67
70
|
end
|
68
71
|
|
69
72
|
def subclasses
|
@@ -71,6 +74,11 @@ module JsDuck
|
|
71
74
|
subs.collect {|cls| class_link(cls.full_name, cls.short_name) }.join(", ")
|
72
75
|
end
|
73
76
|
|
77
|
+
def mixins
|
78
|
+
mixs = @cls.mixins.sort {|a, b| a.full_name <=> b.full_name }
|
79
|
+
mixs.collect {|cls| class_link(cls.full_name, cls.short_name) }.join(", ")
|
80
|
+
end
|
81
|
+
|
74
82
|
def abstract_row(label, info)
|
75
83
|
"<tr><td class='label'>#{label}</td><td class='hd-info'>#{info}</td></tr>"
|
76
84
|
end
|
data/lib/jsduck/parser.rb
CHANGED
@@ -67,12 +67,15 @@ module JsDuck
|
|
67
67
|
# The following is a recursive-descent parser for JavaScript that
|
68
68
|
# can possibly follow a doc-comment
|
69
69
|
|
70
|
-
# <code-block> := <function> | <var-declaration> | <
|
70
|
+
# <code-block> := <function> | <var-declaration> | <ext-define> |
|
71
|
+
# <assignment> | <property-literal>
|
71
72
|
def code_block
|
72
73
|
if look("function")
|
73
74
|
function
|
74
75
|
elsif look("var")
|
75
76
|
var_declaration
|
77
|
+
elsif look("Ext", ".", "define", "(", :string)
|
78
|
+
ext_define
|
76
79
|
elsif look(:ident, ":") || look(:string, ":")
|
77
80
|
property_literal
|
78
81
|
elsif look(",", :ident, ":") || look(",", :string, ":")
|
@@ -175,6 +178,87 @@ module JsDuck
|
|
175
178
|
}
|
176
179
|
end
|
177
180
|
|
181
|
+
# <ext-define> := "Ext" "." "define" "(" <string> "," <ext-define-cfg>
|
182
|
+
def ext_define
|
183
|
+
name = match("Ext", ".", "define", "(", :string)
|
184
|
+
|
185
|
+
if look(",", "{")
|
186
|
+
match(",")
|
187
|
+
cfg = ext_define_cfg
|
188
|
+
else
|
189
|
+
cfg = {}
|
190
|
+
end
|
191
|
+
|
192
|
+
cfg[:type] = :ext_define
|
193
|
+
cfg[:name] = name
|
194
|
+
|
195
|
+
cfg
|
196
|
+
end
|
197
|
+
|
198
|
+
# <ext-define-cfg> := "{" ( <extend> | <mixins> | <?> )*
|
199
|
+
def ext_define_cfg
|
200
|
+
match("{")
|
201
|
+
cfg = {}
|
202
|
+
found = true
|
203
|
+
while found
|
204
|
+
found = false
|
205
|
+
if look("extend", ":", :string)
|
206
|
+
cfg[:extend] = ext_define_extend
|
207
|
+
found = true
|
208
|
+
elsif look("mixins", ":", "{")
|
209
|
+
cfg[:mixins] = ext_define_mixins
|
210
|
+
found = true
|
211
|
+
elsif look(:ident, ":")
|
212
|
+
match(:ident, ":")
|
213
|
+
if look(:string) || look(:number) || look(:regex) ||
|
214
|
+
look("true") || look("false") ||
|
215
|
+
look("null") || look("undefined")
|
216
|
+
# Some key with literal value -- ignore
|
217
|
+
@lex.next
|
218
|
+
found = true
|
219
|
+
elsif look("[")
|
220
|
+
# Some key with array of strings -- ignore
|
221
|
+
found = array_of_strings
|
222
|
+
end
|
223
|
+
end
|
224
|
+
match(",") if look(",")
|
225
|
+
end
|
226
|
+
cfg
|
227
|
+
end
|
228
|
+
|
229
|
+
# <ext-define-extend> := "extend" ":" <string>
|
230
|
+
def ext_define_extend
|
231
|
+
match("extend", ":", :string)
|
232
|
+
end
|
233
|
+
|
234
|
+
# <ext-define-mixins> := "mixins" ":" "{" [ <ident> ":" <string> ","? ]* "}"
|
235
|
+
def ext_define_mixins
|
236
|
+
match("mixins", ":", "{")
|
237
|
+
mixins = []
|
238
|
+
while look(:ident, ":", :string)
|
239
|
+
mixins << match(:ident, ":", :string)
|
240
|
+
match(",") if look(",")
|
241
|
+
end
|
242
|
+
match("}") if look("}")
|
243
|
+
mixins
|
244
|
+
end
|
245
|
+
|
246
|
+
# <array-of-strings> := "[" [ <string> ","? ]* "]"
|
247
|
+
def array_of_strings
|
248
|
+
match("[")
|
249
|
+
while look(:string)
|
250
|
+
match(:string)
|
251
|
+
match(",") if look(",")
|
252
|
+
end
|
253
|
+
|
254
|
+
if look("]")
|
255
|
+
match("]")
|
256
|
+
true
|
257
|
+
else
|
258
|
+
false
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
178
262
|
# <property-literal> := ( <ident> | <string> ) ":" <expression>
|
179
263
|
def property_literal
|
180
264
|
left = look(:ident) ? match(:ident) : match(:string)
|
metadata
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsduck
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: "0.
|
8
|
+
- 4
|
9
|
+
version: "0.4"
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Rene Saarsoo
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-02-
|
17
|
+
date: 2011-02-28 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|