jsduck 0.5 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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(cls)
9
- @formatter = DocFormatter.new()
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> : #{param[:type]}",
23
+ "<code>#{param[:name]}</code> : #{type}",
28
24
  "<div class='sub-desc'>#{doc}</div>",
29
25
  "</li>",
30
26
  ].join("")
@@ -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
- list << member_node(m, cls)
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 => detect_mixins(doc_map, code),
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
- def detect_mixins(doc_map, code)
228
- if code[:type] == :ext_define && code[:mixins]
229
- code[:mixins]
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)
@@ -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(@cls)
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.css_class = 'docClass'
25
- @formatter.url_template = 'output/%cls%.html'
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("Defind In:", file_link),
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"
@@ -34,6 +34,10 @@ module JsDuck
34
34
  @lookup[classname]
35
35
  end
36
36
 
37
+ def each(&block)
38
+ @classes.each(&block)
39
+ end
40
+
37
41
  def reg_subclasses(cls)
38
42
  if !cls.parent
39
43
  # do nothing
@@ -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
- # Formats JavaScript source into HTML page. Inside the HTML every
6
- # source code line will be marked with ID, so that it can be linked
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
- # formatter can be either :format_page or :format_pre; with the
14
- # first one the whole HTML page is created, otherwise just a
15
- # contents of <pre> element.
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
- @formatter = formatter
13
+ @wrapper = wrapper
19
14
  end
20
15
 
21
- # Converts source to HTML and writes into file in output
22
- # directory. It returns the name of the file that it wrote.
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') {|f| f.write(self.send(@formatter, source)) }
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 full source for HTML page
44
- def format_page(source)
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">#{format_pre(source)}</pre>
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