jsduck 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -165,7 +165,7 @@ JsDuck has some strong opinions, so some things are intentionally
165
165
  missing.
166
166
 
167
167
  * Support for Markdown in comments
168
- * More things infered from the code
168
+ * More things inferred from the code
169
169
  * No XML configuration file, just command line options
170
170
  * Class documentation header doesn't separately list Package and Class -
171
171
  these are IMHO redundant.
@@ -174,18 +174,17 @@ missing.
174
174
  * Ext.Component has a component icon too, not only its descendants
175
175
 
176
176
 
177
- Missing features
178
- ----------------
177
+ Missing features and TODO
178
+ -------------------------
179
179
 
180
- It's still in early beta, so several things supported by ext-doc are
181
- currently missing:
180
+ * Search, not just searching from official ExtJS documentation.
182
181
 
183
- * Links from documentation to source code
184
- * List of subclasses
185
- * Tree of parent classes
186
- * Syntax highlighting of code examples
187
- * Search, not just searching from official ExtJS documentation
188
- * Support for custom @tags
182
+ * Support for custom @tags. Ext-doc supports this, I personally have
183
+ never used this feature, so I'm thinking it's not really needed.
184
+
185
+ * Speed improvements. JsDuck is clearly slower than ext-doc, but I
186
+ haven't so far done almost no optimizations, so there should be some
187
+ pretty low-hanging fruits to pick.
189
188
 
190
189
 
191
190
  Copying
@@ -195,3 +194,14 @@ JsDuck is distributed under the terms of the GNU General Public License version
195
194
 
196
195
  JsDuck was developed by [Rene Saarsoo](http://triin.net).
197
196
 
197
+
198
+ Changelog
199
+ ---------
200
+
201
+ * 0.2 - most features of ext-doc supported.
202
+ * Links from documentation to source code
203
+ * Syntax highlighting of code examples
204
+ * Tree of parent classes
205
+ * List of subclasses
206
+
207
+ * 0.1 - initial version.
@@ -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.1'
6
- s.date = '2010-12-27'
5
+ s.version = '0.2'
6
+ s.date = '2011-01-10'
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"
@@ -16,13 +16,34 @@ module JsDuck
16
16
  @merger = Merger.new
17
17
  end
18
18
 
19
- def parse(input)
19
+ # Parses chunk of JavaScript. The resulting documentation is
20
+ # accumulated inside this class and can be later accessed through
21
+ # #result method.
22
+ #
23
+ # - input the JavaScript source
24
+ # - filename name of the JS file where it came from
25
+ # - html_filename name of the HTML file where the source was saved.
26
+ #
27
+ def parse(input, filename="", html_filename="")
20
28
  @current_class = nil
21
29
  Parser.new(input).parse.each do |docset|
22
30
  doc = @doc_parser.parse(docset[:comment])
23
31
  code = docset[:code]
24
- register(@merger.merge(doc, code))
32
+ href = html_filename + "#line-" + docset[:linenr].to_s
33
+ register(add_href(@merger.merge(doc, code), href, filename))
34
+ end
35
+ end
36
+
37
+ # Tags doc-object with link to source code where it came from.
38
+ # For class we also store the name of the JavaScript file.
39
+ def add_href(doc, href, filename)
40
+ doc[:href] = href
41
+ if doc[:tagname] == :class
42
+ doc[:filename] = filename
43
+ doc[:cfg].each {|cfg| cfg[:href] = href }
44
+ doc[:method].each {|method| method[:href] = href }
25
45
  end
46
+ doc
26
47
  end
27
48
 
28
49
  # Registers documentation node either as class or as member of
@@ -1,8 +1,10 @@
1
1
  require 'rubygems'
2
2
  require 'jsduck/aggregator'
3
+ require 'jsduck/source_formatter'
3
4
  require 'jsduck/class'
4
5
  require 'jsduck/tree'
5
6
  require 'jsduck/tree_icons'
7
+ require 'jsduck/subclasses'
6
8
  require 'jsduck/page'
7
9
  require 'json'
8
10
  require 'fileutils'
@@ -26,8 +28,8 @@ module JsDuck
26
28
 
27
29
  # Call this after input parameters set
28
30
  def run
29
- classes = filter_classes(parse_files(@input_files))
30
31
  copy_template(@template_dir, @output_dir)
32
+ classes = filter_classes(parse_files(@input_files))
31
33
  write_tree(@output_dir+"/output/tree.js", classes)
32
34
  write_pages(@output_dir+"/output", classes)
33
35
  end
@@ -36,9 +38,12 @@ module JsDuck
36
38
  # documented items in all of those files.
37
39
  def parse_files(filenames)
38
40
  agr = Aggregator.new
39
- filenames.each do |name|
40
- puts "Parsing #{name} ..." if @verbose
41
- agr.parse(IO.read(name))
41
+ src = SourceFormatter.new(@output_dir + "/source")
42
+ filenames.each do |fname|
43
+ puts "Parsing #{fname} ..." if @verbose
44
+ code = IO.read(fname)
45
+ src_fname = src.write(code, fname)
46
+ agr.parse(code, File.basename(fname), File.basename(src_fname))
42
47
  end
43
48
  agr.result
44
49
  end
@@ -69,10 +74,11 @@ module JsDuck
69
74
 
70
75
  # Writes documentation page for each class
71
76
  def write_pages(path, docs)
77
+ subclasses = Subclasses.new(docs)
72
78
  docs.each do |cls|
73
79
  filename = path + "/" + cls[:name] + ".html"
74
80
  puts "Writing to #{filename} ..." if @verbose
75
- File.open(filename, 'w') {|f| f.write( Page.new(cls).to_html ) }
81
+ File.open(filename, 'w') {|f| f.write( Page.new(cls, subclasses).to_html ) }
76
82
  end
77
83
  end
78
84
 
@@ -83,6 +89,7 @@ module JsDuck
83
89
  end
84
90
  FileUtils.cp_r(template_dir, dir)
85
91
  FileUtils.mkdir(dir + "/output")
92
+ FileUtils.mkdir(dir + "/source")
86
93
  end
87
94
  end
88
95
 
@@ -0,0 +1,51 @@
1
+ module JsDuck
2
+
3
+ # Creates the inheritance tree shown on class documentation page.
4
+ class InheritanceTree
5
+ def initialize(cls)
6
+ @cls = cls
7
+ end
8
+
9
+ # Renders the tree using HTML <pre> element
10
+ def to_html
11
+ i = -1
12
+ html = ancestors(@cls).reverse.collect do |cls|
13
+ i += 1
14
+ make_indent(i) + make_link(cls)
15
+ end.join("\n")
16
+
17
+ return <<-EOHTML
18
+ <div class="inheritance res-block">
19
+ <pre class="res-block-inner">#{html}</pre>
20
+ </div>
21
+ EOHTML
22
+ end
23
+
24
+ # Returns array of the names of ancestor classes for given class.
25
+ # Including the name of the class itself.
26
+ # Example result when ascing ancestors of MyPanel might be:
27
+ #
28
+ # [MyPanel, Ext.Panel, Ext.Component, Ext.util.Observable]
29
+ #
30
+ def ancestors(cls)
31
+ cls.parent ? [cls] + ancestors(cls.parent) : [cls]
32
+ end
33
+
34
+ def make_indent(level)
35
+ if level > 0
36
+ (" " * level) + "<img src='resources/elbow-end.gif' alt=''>"
37
+ else
38
+ ""
39
+ end
40
+ end
41
+
42
+ def make_link(cls)
43
+ if cls == @cls
44
+ cls.short_name
45
+ else
46
+ "<a href='output/#{cls.full_name}.html' ext:cls='#{cls.full_name}'>#{cls.short_name}</a>"
47
+ end
48
+ end
49
+ end
50
+
51
+ end
@@ -53,6 +53,9 @@ module JsDuck
53
53
  #
54
54
  # {:type => :ident, :value => "foo"}
55
55
  #
56
+ # For doc-comments the full token also contains the field :linenr,
57
+ # pointing to the line where the doc-comment began.
58
+ #
56
59
  def next(full=false)
57
60
  tok = @tokens.shift
58
61
  full ? tok : tok[:value]
@@ -82,6 +85,8 @@ module JsDuck
82
85
  elsif @input.check(/\/\*\*/) then
83
86
  @tokens << {
84
87
  :type => :doc_comment,
88
+ # Calculate current line number, starting with 1
89
+ :linenr => @input.string[0...@input.pos].count("\n") + 1,
85
90
  :value => @input.scan_until(/\*\/|\Z/)
86
91
  }
87
92
  elsif @input.check(/"/) then
@@ -1,4 +1,5 @@
1
1
  require 'jsduck/doc_formatter'
2
+ require 'jsduck/inheritance_tree'
2
3
  require 'jsduck/cfg_table'
3
4
  require 'jsduck/property_table'
4
5
  require 'jsduck/method_table'
@@ -8,14 +9,16 @@ module JsDuck
8
9
 
9
10
  # Creates HTML documentation page for one class.
10
11
  class Page
11
- def initialize(cls)
12
+ def initialize(cls, subclasses = {})
12
13
  @cls = cls
14
+ @subclasses = subclasses
13
15
  @formatter = DocFormatter.new(cls.full_name)
14
16
  end
15
17
 
16
18
  def to_html
17
19
  [
18
20
  '<div class="body-wrap">',
21
+ inheritance_tree,
19
22
  heading,
20
23
  abstract,
21
24
  description,
@@ -28,20 +31,37 @@ module JsDuck
28
31
  ].join("\n")
29
32
  end
30
33
 
34
+ # only render the tree if class has at least one ancestor
35
+ def inheritance_tree
36
+ @cls.parent ? InheritanceTree.new(@cls).to_html : ""
37
+ end
38
+
31
39
  def heading
32
- "<h1>Class <a href='source/sample.html#cls-#{@cls.full_name}'>#{@cls.full_name}</a></h1>"
40
+ "<h1>Class <a href='source/#{@cls[:href]}'>#{@cls.full_name}</a></h1>"
33
41
  end
34
42
 
35
43
  def abstract
36
44
  [
37
45
  "<table cellspacing='0'>",
38
46
  abstract_row("Extends:", @cls.parent ? class_link(@cls.parent.full_name) : "Object"),
47
+ abstract_row("Defind In:", file_link),
48
+ @subclasses[@cls] ? abstract_row("Subclasses:", subclasses) : "",
39
49
  "</table>",
40
50
  ].join("\n")
41
51
  end
42
52
 
43
- def class_link(name)
44
- "<a href='output/#{name}.html' ext:cls='#{name}'>#{name}</a>"
53
+ def class_link(class_name, label=nil)
54
+ label = label || class_name
55
+ "<a href='output/#{class_name}.html' ext:cls='#{class_name}'>#{label}</a>"
56
+ end
57
+
58
+ def file_link
59
+ "<a href='source/#{@cls[:href]}'>#{@cls[:filename]}</a>"
60
+ end
61
+
62
+ def subclasses
63
+ subs = @subclasses[@cls].sort {|a, b| a.short_name <=> b.short_name }
64
+ subs.collect {|cls| class_link(cls.full_name, cls.short_name) }.join(", ")
45
65
  end
46
66
 
47
67
  def abstract_row(label, info)
@@ -9,9 +9,10 @@ module JsDuck
9
9
  end
10
10
 
11
11
  # Parses the whole JavaScript block and returns array where for
12
- # each doc-comment there is a hash of two values: the comment
13
- # itself as string and parsed structure of the code that
14
- # immediately follows the comment.
12
+ # each doc-comment there is a hash of three values: the comment
13
+ # itself as string, number of the line where the comment starts,
14
+ # and parsed structure of the code that immediately follows the
15
+ # comment.
15
16
  #
16
17
  # For example with the following JavaScript input:
17
18
  #
@@ -26,6 +27,7 @@ module JsDuck
26
27
  # [
27
28
  # {
28
29
  # :comment => "/**\n * @param {String} foo\n */",
30
+ # :linenr => 1,
29
31
  # :code => {
30
32
  # :type => :assignment,
31
33
  # :left => ["MyClass", "doIt"],
@@ -44,8 +46,10 @@ module JsDuck
44
46
  def parse
45
47
  while !@lex.empty? do
46
48
  if look(:doc_comment) then
49
+ comment = @lex.next(true)
47
50
  @docs << {
48
- :comment => match(:doc_comment),
51
+ :comment => comment[:value],
52
+ :linenr => comment[:linenr],
49
53
  :code => code_block
50
54
  }
51
55
  else
@@ -0,0 +1,76 @@
1
+ require "cgi"
2
+
3
+ module JsDuck
4
+
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
9
+
10
+ # Initializes SourceFormatter to the directory where
11
+ # HTML-formatted source files will be placed
12
+ def initialize(output_dir)
13
+ @output_dir = output_dir
14
+ end
15
+
16
+ # Converts source to HTML and writes into file in output
17
+ # directory. It returns the name of the file that it wrote.
18
+ def write(source, filename)
19
+ fname = uniq_html_filename(filename)
20
+ File.open(fname, 'w') {|f| f.write(format(source)) }
21
+ fname
22
+ end
23
+
24
+ def uniq_html_filename(filename)
25
+ fname = html_filename(filename)
26
+ nr = 1
27
+ while File.exists?(fname)
28
+ nr += 1
29
+ fname = html_filename(filename, nr)
30
+ end
31
+ fname
32
+ end
33
+
34
+ def html_filename(filename, nr=0)
35
+ @output_dir + "/" + File.basename(filename, ".js") + (nr > 0 ? nr.to_s : "") + ".html"
36
+ end
37
+
38
+ # Returns full source for HTML page
39
+ def format(source)
40
+ return <<-EOHTML
41
+ <!DOCTYPE html>
42
+ <html>
43
+ <head>
44
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
45
+ <title>The source code</title>
46
+ <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
47
+ <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
48
+ <style type="text/css">
49
+ .highlight { display: block; background-color: #ddd; }
50
+ </style>
51
+ <script type="text/javascript">
52
+ function highlight() {
53
+ document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
54
+ }
55
+ </script>
56
+ </head>
57
+ <body onload="prettyPrint(); highlight();">
58
+ <pre class="prettyprint lang-js">#{format_pre(source)}</pre>
59
+ </body>
60
+ </html>
61
+ EOHTML
62
+ end
63
+
64
+ # Formats the contents of <pre>, wrapping each source code line
65
+ # inside <span>.
66
+ def format_pre(source)
67
+ i = 0
68
+ return source.lines.collect do |line|
69
+ i += 1
70
+ "<span id='line-#{i}'>#{CGI.escapeHTML(line)}</span>"
71
+ end.join()
72
+ end
73
+
74
+ end
75
+
76
+ end
@@ -0,0 +1,27 @@
1
+ module JsDuck
2
+
3
+ # Provides information about direct descendants of particular class.
4
+ #
5
+ # The constructor is initialized with array of all available
6
+ # classes. Then through [] method subclasses of particlular class
7
+ # can be asked for.
8
+ class Subclasses
9
+ def initialize(classes)
10
+ @subs = {}
11
+ classes.each do |cls|
12
+ if !cls.parent
13
+ # do nothing
14
+ elsif @subs[cls.parent.full_name]
15
+ @subs[cls.parent.full_name] << cls
16
+ else
17
+ @subs[cls.parent.full_name] = [cls]
18
+ end
19
+ end
20
+ end
21
+
22
+ def [](cls)
23
+ @subs[cls.full_name]
24
+ end
25
+ end
26
+
27
+ end
@@ -55,7 +55,7 @@ module JsDuck
55
55
 
56
56
  def signature(item)
57
57
  id = @cls.full_name+ "-" + item[:name]
58
- src = "source/sample.html#" + id
58
+ src = "source/#{item[:href]}"
59
59
  return "<a id='#{id}'></a><b><a href='#{src}'>#{item[:name]}</a></b>" + signature_suffix(item)
60
60
  end
61
61
 
@@ -7,11 +7,13 @@
7
7
  <link rel="stylesheet" type="text/css" href="resources/css/xtheme-gray.css" />
8
8
  <link rel="stylesheet" type="text/css" href="resources/docs.css" />
9
9
  <link rel="stylesheet" type="text/css" href="resources/style.css" />
10
+ <link rel="stylesheet" type="text/css" href="resources/prettify/prettify.css" />
10
11
  <link rel="shortcut icon" href="resources/favicon.ico" />
11
12
  <link rel="icon" href="resources/favicon.ico" />
12
13
  <script type="text/javascript" src="resources/ext-base.js"></script>
13
14
  <script type="text/javascript" src="resources/ext-all.js"></script>
14
15
  <script type="text/javascript" src="resources/TabCloseMenu.js"></script>
16
+ <script type="text/javascript" src="resources/prettify/prettify.js"></script>
15
17
  <script type="text/javascript" src="resources/docs.js"></script>
16
18
  <script type="text/javascript" src="output/tree.js"></script>
17
19
  </head>
@@ -209,10 +209,16 @@ DocPanel = Ext.extend(Ext.Panel, {
209
209
  hlMember : function(member){
210
210
  var el = Ext.fly(this.cclass + '-' + member);
211
211
  if(el){
212
- if (tr = el.up('tr')) {
213
- tr.highlight('#cadaf9');
214
- }
212
+ var tr = el.up('tr');
213
+ tr && tr.highlight('#cadaf9');
215
214
  }
215
+ },
216
+
217
+ // Marks all code examples with "prettyprint" class.
218
+ // Then runs the prettify library on the whole document.
219
+ prettyPrint : function(){
220
+ Ext.select("pre > code", this.el).addClass("prettyprint lang-js");
221
+ prettyPrint();
216
222
  }
217
223
  });
218
224
 
@@ -314,12 +320,14 @@ Ext.extend(MainPanel, Ext.TabPanel, {
314
320
  tab.scrollToMember(member);
315
321
  }
316
322
  }else{
317
- var autoLoad = {url: href};
318
- if(member){
319
- autoLoad.callback = function(){
320
- Ext.getCmp(id).scrollToMember(member);
323
+ var autoLoad = {
324
+ url: href,
325
+ callback: function(){
326
+ var tab = Ext.getCmp(id);
327
+ tab.prettyPrint();
328
+ member && tab.scrollToMember(member);
321
329
  }
322
- }
330
+ };
323
331
  var p = this.add(new DocPanel({
324
332
  id: id,
325
333
  cclass : cls,
@@ -0,0 +1 @@
1
+ .str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun{color:#660}.pln{color:#000}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec{color:#606}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}@media print{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun{color:#440}.pln{color:#000}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}
@@ -0,0 +1,33 @@
1
+ window.PR_SHOULD_USE_CONTINUATION=true;window.PR_TAB_WIDTH=8;window.PR_normalizedHtml=window.PR=window.prettyPrintOne=window.prettyPrint=void 0;window._pr_isIE6=function(){var y=navigator&&navigator.userAgent&&navigator.userAgent.match(/\bMSIE ([678])\./);y=y?+y[1]:false;window._pr_isIE6=function(){return y};return y};
2
+ (function(){function y(b){return b.replace(L,"&amp;").replace(M,"&lt;").replace(N,"&gt;")}function H(b,f,i){switch(b.nodeType){case 1:var o=b.tagName.toLowerCase();f.push("<",o);var l=b.attributes,n=l.length;if(n){if(i){for(var r=[],j=n;--j>=0;)r[j]=l[j];r.sort(function(q,m){return q.name<m.name?-1:q.name===m.name?0:1});l=r}for(j=0;j<n;++j){r=l[j];r.specified&&f.push(" ",r.name.toLowerCase(),'="',r.value.replace(L,"&amp;").replace(M,"&lt;").replace(N,"&gt;").replace(X,"&quot;"),'"')}}f.push(">");
3
+ for(l=b.firstChild;l;l=l.nextSibling)H(l,f,i);if(b.firstChild||!/^(?:br|link|img)$/.test(o))f.push("</",o,">");break;case 3:case 4:f.push(y(b.nodeValue));break}}function O(b){function f(c){if(c.charAt(0)!=="\\")return c.charCodeAt(0);switch(c.charAt(1)){case "b":return 8;case "t":return 9;case "n":return 10;case "v":return 11;case "f":return 12;case "r":return 13;case "u":case "x":return parseInt(c.substring(2),16)||c.charCodeAt(1);case "0":case "1":case "2":case "3":case "4":case "5":case "6":case "7":return parseInt(c.substring(1),
4
+ 8);default:return c.charCodeAt(1)}}function i(c){if(c<32)return(c<16?"\\x0":"\\x")+c.toString(16);c=String.fromCharCode(c);if(c==="\\"||c==="-"||c==="["||c==="]")c="\\"+c;return c}function o(c){var d=c.substring(1,c.length-1).match(RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));c=[];for(var a=[],k=d[0]==="^",e=k?1:0,h=d.length;e<h;++e){var g=d[e];switch(g){case "\\B":case "\\b":case "\\D":case "\\d":case "\\S":case "\\s":case "\\W":case "\\w":c.push(g);
5
+ continue}g=f(g);var s;if(e+2<h&&"-"===d[e+1]){s=f(d[e+2]);e+=2}else s=g;a.push([g,s]);if(!(s<65||g>122)){s<65||g>90||a.push([Math.max(65,g)|32,Math.min(s,90)|32]);s<97||g>122||a.push([Math.max(97,g)&-33,Math.min(s,122)&-33])}}a.sort(function(v,w){return v[0]-w[0]||w[1]-v[1]});d=[];g=[NaN,NaN];for(e=0;e<a.length;++e){h=a[e];if(h[0]<=g[1]+1)g[1]=Math.max(g[1],h[1]);else d.push(g=h)}a=["["];k&&a.push("^");a.push.apply(a,c);for(e=0;e<d.length;++e){h=d[e];a.push(i(h[0]));if(h[1]>h[0]){h[1]+1>h[0]&&a.push("-");
6
+ a.push(i(h[1]))}}a.push("]");return a.join("")}function l(c){for(var d=c.source.match(RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g")),a=d.length,k=[],e=0,h=0;e<a;++e){var g=d[e];if(g==="(")++h;else if("\\"===g.charAt(0))if((g=+g.substring(1))&&g<=h)k[g]=-1}for(e=1;e<k.length;++e)if(-1===k[e])k[e]=++n;for(h=e=0;e<a;++e){g=d[e];if(g==="("){++h;if(k[h]===undefined)d[e]="(?:"}else if("\\"===
7
+ g.charAt(0))if((g=+g.substring(1))&&g<=h)d[e]="\\"+k[h]}for(h=e=0;e<a;++e)if("^"===d[e]&&"^"!==d[e+1])d[e]="";if(c.ignoreCase&&r)for(e=0;e<a;++e){g=d[e];c=g.charAt(0);if(g.length>=2&&c==="[")d[e]=o(g);else if(c!=="\\")d[e]=g.replace(/[a-zA-Z]/g,function(s){s=s.charCodeAt(0);return"["+String.fromCharCode(s&-33,s|32)+"]"})}return d.join("")}for(var n=0,r=false,j=false,q=0,m=b.length;q<m;++q){var t=b[q];if(t.ignoreCase)j=true;else if(/[a-z]/i.test(t.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,
8
+ ""))){r=true;j=false;break}}var p=[];q=0;for(m=b.length;q<m;++q){t=b[q];if(t.global||t.multiline)throw Error(""+t);p.push("(?:"+l(t)+")")}return RegExp(p.join("|"),j?"gi":"g")}function Y(b){var f=0;return function(i){for(var o=null,l=0,n=0,r=i.length;n<r;++n)switch(i.charAt(n)){case "\t":o||(o=[]);o.push(i.substring(l,n));l=b-f%b;for(f+=l;l>=0;l-=16)o.push(" ".substring(0,l));l=n+1;break;case "\n":f=0;break;default:++f}if(!o)return i;o.push(i.substring(l));return o.join("")}}function I(b,
9
+ f,i,o){if(f){b={source:f,c:b};i(b);o.push.apply(o,b.d)}}function B(b,f){var i={},o;(function(){for(var r=b.concat(f),j=[],q={},m=0,t=r.length;m<t;++m){var p=r[m],c=p[3];if(c)for(var d=c.length;--d>=0;)i[c.charAt(d)]=p;p=p[1];c=""+p;if(!q.hasOwnProperty(c)){j.push(p);q[c]=null}}j.push(/[\0-\uffff]/);o=O(j)})();var l=f.length;function n(r){for(var j=r.c,q=[j,z],m=0,t=r.source.match(o)||[],p={},c=0,d=t.length;c<d;++c){var a=t[c],k=p[a],e=void 0,h;if(typeof k==="string")h=false;else{var g=i[a.charAt(0)];
10
+ if(g){e=a.match(g[1]);k=g[0]}else{for(h=0;h<l;++h){g=f[h];if(e=a.match(g[1])){k=g[0];break}}e||(k=z)}if((h=k.length>=5&&"lang-"===k.substring(0,5))&&!(e&&typeof e[1]==="string")){h=false;k=P}h||(p[a]=k)}g=m;m+=a.length;if(h){h=e[1];var s=a.indexOf(h),v=s+h.length;if(e[2]){v=a.length-e[2].length;s=v-h.length}k=k.substring(5);I(j+g,a.substring(0,s),n,q);I(j+g+s,h,Q(k,h),q);I(j+g+v,a.substring(v),n,q)}else q.push(j+g,k)}r.d=q}return n}function x(b){var f=[],i=[];if(b.tripleQuotedStrings)f.push([A,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
11
+ null,"'\""]);else b.multiLineStrings?f.push([A,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):f.push([A,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);b.verbatimStrings&&i.push([A,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);if(b.hashComments)if(b.cStyleComments){f.push([C,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"]);i.push([A,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,
12
+ null])}else f.push([C,/^#[^\r\n]*/,null,"#"]);if(b.cStyleComments){i.push([C,/^\/\/[^\r\n]*/,null]);i.push([C,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}b.regexLiterals&&i.push(["lang-regex",RegExp("^"+Z+"(/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/)")]);b=b.keywords.replace(/^\s+|\s+$/g,"");b.length&&i.push([R,RegExp("^(?:"+b.replace(/\s+/g,"|")+")\\b"),null]);f.push([z,/^\s+/,null," \r\n\t\u00a0"]);i.push([J,/^@[a-z_$][a-z_$@0-9]*/i,null],[S,/^@?[A-Z]+[a-z][A-Za-z_$@0-9]*/,
13
+ null],[z,/^[a-z_$][a-z_$@0-9]*/i,null],[J,/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],[E,/^.[^\s\w\.$@\'\"\`\/\#]*/,null]);return B(f,i)}function $(b){function f(D){if(D>r){if(j&&j!==q){n.push("</span>");j=null}if(!j&&q){j=q;n.push('<span class="',j,'">')}var T=y(p(i.substring(r,D))).replace(e?d:c,"$1&#160;");e=k.test(T);n.push(T.replace(a,s));r=D}}var i=b.source,o=b.g,l=b.d,n=[],r=0,j=null,q=null,m=0,t=0,p=Y(window.PR_TAB_WIDTH),c=/([\r\n ]) /g,
14
+ d=/(^| ) /gm,a=/\r\n?|\n/g,k=/[ \r\n]$/,e=true,h=window._pr_isIE6();h=h?b.b.tagName==="PRE"?h===6?"&#160;\r\n":h===7?"&#160;<br>\r":"&#160;\r":"&#160;<br />":"<br />";var g=b.b.className.match(/\blinenums\b(?::(\d+))?/),s;if(g){for(var v=[],w=0;w<10;++w)v[w]=h+'</li><li class="L'+w+'">';var F=g[1]&&g[1].length?g[1]-1:0;n.push('<ol class="linenums"><li class="L',F%10,'"');F&&n.push(' value="',F+1,'"');n.push(">");s=function(){var D=v[++F%10];return j?"</span>"+D+'<span class="'+j+'">':D}}else s=h;
15
+ for(;;)if(m<o.length?t<l.length?o[m]<=l[t]:true:false){f(o[m]);if(j){n.push("</span>");j=null}n.push(o[m+1]);m+=2}else if(t<l.length){f(l[t]);q=l[t+1];t+=2}else break;f(i.length);j&&n.push("</span>");g&&n.push("</li></ol>");b.a=n.join("")}function u(b,f){for(var i=f.length;--i>=0;){var o=f[i];if(G.hasOwnProperty(o))"console"in window&&console.warn("cannot override language handler %s",o);else G[o]=b}}function Q(b,f){b&&G.hasOwnProperty(b)||(b=/^\s*</.test(f)?"default-markup":"default-code");return G[b]}
16
+ function U(b){var f=b.f,i=b.e;b.a=f;try{var o,l=f.match(aa);f=[];var n=0,r=[];if(l)for(var j=0,q=l.length;j<q;++j){var m=l[j];if(m.length>1&&m.charAt(0)==="<"){if(!ba.test(m))if(ca.test(m)){f.push(m.substring(9,m.length-3));n+=m.length-12}else if(da.test(m)){f.push("\n");++n}else if(m.indexOf(V)>=0&&m.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g,' $1="$2$3$4"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/)){var t=m.match(W)[2],p=1,c;c=j+1;a:for(;c<q;++c){var d=l[c].match(W);if(d&&
17
+ d[2]===t)if(d[1]==="/"){if(--p===0)break a}else++p}if(c<q){r.push(n,l.slice(j,c+1).join(""));j=c}else r.push(n,m)}else r.push(n,m)}else{var a;p=m;var k=p.indexOf("&");if(k<0)a=p;else{for(--k;(k=p.indexOf("&#",k+1))>=0;){var e=p.indexOf(";",k);if(e>=0){var h=p.substring(k+3,e),g=10;if(h&&h.charAt(0)==="x"){h=h.substring(1);g=16}var s=parseInt(h,g);isNaN(s)||(p=p.substring(0,k)+String.fromCharCode(s)+p.substring(e+1))}}a=p.replace(ea,"<").replace(fa,">").replace(ga,"'").replace(ha,'"').replace(ia," ").replace(ja,
18
+ "&")}f.push(a);n+=a.length}}o={source:f.join(""),h:r};var v=o.source;b.source=v;b.c=0;b.g=o.h;Q(i,v)(b);$(b)}catch(w){if("console"in window)console.log(w&&w.stack?w.stack:w)}}var A="str",R="kwd",C="com",S="typ",J="lit",E="pun",z="pln",P="src",V="nocode",Z=function(){for(var b=["!","!=","!==","#","%","%=","&","&&","&&=","&=","(","*","*=","+=",",","-=","->","/","/=",":","::",";","<","<<","<<=","<=","=","==","===",">",">=",">>",">>=",">>>",">>>=","?","@","[","^","^=","^^","^^=","{","|","|=","||","||=",
19
+ "~","break","case","continue","delete","do","else","finally","instanceof","return","throw","try","typeof"],f="(?:^^|[+-]",i=0;i<b.length;++i)f+="|"+b[i].replace(/([^=<>:&a-z])/g,"\\$1");f+=")\\s*";return f}(),L=/&/g,M=/</g,N=/>/g,X=/\"/g,ea=/&lt;/g,fa=/&gt;/g,ga=/&apos;/g,ha=/&quot;/g,ja=/&amp;/g,ia=/&nbsp;/g,ka=/[\r\n]/g,K=null,aa=RegExp("[^<]+|<!--[\\s\\S]*?--\>|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>|</?[a-zA-Z](?:[^>\"']|'[^']*'|\"[^\"]*\")*>|<","g"),ba=/^<\!--/,ca=/^<!\[CDATA\[/,da=/^<br\b/i,W=/^<(\/?)([a-zA-Z][a-zA-Z0-9]*)/,
20
+ la=x({keywords:"break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof alignof align_union asm axiom bool concept concept_map const_cast constexpr decltype dynamic_cast explicit export friend inline late_check mutable namespace nullptr reinterpret_cast static_assert static_cast template typeid typename using virtual wchar_t where break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof abstract boolean byte extends final finally implements import instanceof null native package strictfp super synchronized throws transient as base by checked decimal delegate descending event fixed foreach from group implicit in interface internal into is lock object out override orderby params partial readonly ref sbyte sealed stackalloc string select uint ulong unchecked unsafe ushort var break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof debugger eval export function get null set undefined var with Infinity NaN caller delete die do dump elsif eval exit foreach for goto if import last local my next no our print package redo require sub undef unless until use wantarray while BEGIN END break continue do else for if return while and as assert class def del elif except exec finally from global import in is lambda nonlocal not or pass print raise try with yield False True None break continue do else for if return while alias and begin case class def defined elsif end ensure false in module next nil not or redo rescue retry self super then true undef unless until when yield BEGIN END break continue do else for if return while case done elif esac eval fi function in local set then until ",
21
+ hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true}),G={};u(la,["default-code"]);u(B([],[[z,/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],[C,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[E,/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup",
22
+ "htm","html","mxml","xhtml","xml","xsl"]);u(B([[z,/^[\s]+/,null," \t\r\n"],["atv",/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[E,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],
23
+ ["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);u(B([],[["atv",/^[\s\S]+/]]),["uq.val"]);u(x({keywords:"break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof alignof align_union asm axiom bool concept concept_map const_cast constexpr decltype dynamic_cast explicit export friend inline late_check mutable namespace nullptr reinterpret_cast static_assert static_cast template typeid typename using virtual wchar_t where ",
24
+ hashComments:true,cStyleComments:true}),["c","cc","cpp","cxx","cyc","m"]);u(x({keywords:"null true false"}),["json"]);u(x({keywords:"break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof abstract boolean byte extends final finally implements import instanceof null native package strictfp super synchronized throws transient as base by checked decimal delegate descending event fixed foreach from group implicit in interface internal into is lock object out override orderby params partial readonly ref sbyte sealed stackalloc string select uint ulong unchecked unsafe ushort var ",
25
+ hashComments:true,cStyleComments:true,verbatimStrings:true}),["cs"]);u(x({keywords:"break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof abstract boolean byte extends final finally implements import instanceof null native package strictfp super synchronized throws transient ",
26
+ cStyleComments:true}),["java"]);u(x({keywords:"break continue do else for if return while case done elif esac eval fi function in local set then until ",hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);u(x({keywords:"break continue do else for if return while and as assert class def del elif except exec finally from global import in is lambda nonlocal not or pass print raise try with yield False True None ",hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);
27
+ u(x({keywords:"caller delete die do dump elsif eval exit foreach for goto if import last local my next no our print package redo require sub undef unless until use wantarray while BEGIN END ",hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);u(x({keywords:"break continue do else for if return while alias and begin case class def defined elsif end ensure false in module next nil not or redo rescue retry self super then true undef unless until when yield BEGIN END ",hashComments:true,
28
+ multiLineStrings:true,regexLiterals:true}),["rb"]);u(x({keywords:"break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof debugger eval export function get null set undefined var with Infinity NaN ",cStyleComments:true,regexLiterals:true}),["js"]);u(B([],[[A,/^[\s\S]+/]]),
29
+ ["regex"]);window.PR_normalizedHtml=H;window.prettyPrintOne=function(b,f){var i={f:b,e:f};U(i);return i.a};window.prettyPrint=function(b){function f(){for(var t=window.PR_SHOULD_USE_CONTINUATION?j.now()+250:Infinity;q<o.length&&j.now()<t;q++){var p=o[q];if(p.className&&p.className.indexOf("prettyprint")>=0){var c=p.className.match(/\blang-(\w+)\b/);if(c)c=c[1];for(var d=false,a=p.parentNode;a;a=a.parentNode)if((a.tagName==="pre"||a.tagName==="code"||a.tagName==="xmp")&&a.className&&a.className.indexOf("prettyprint")>=
30
+ 0){d=true;break}if(!d){a=p;if(null===K){d=document.createElement("PRE");d.appendChild(document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />'));K=!/</.test(d.innerHTML)}if(K){d=a.innerHTML;if("XMP"===a.tagName)d=y(d);else{a=a;if("PRE"===a.tagName)a=true;else if(ka.test(d)){var k="";if(a.currentStyle)k=a.currentStyle.whiteSpace;else if(window.getComputedStyle)k=window.getComputedStyle(a,null).whiteSpace;a=!k||k==="pre"}else a=true;a||(d=d.replace(/(<br\s*\/?>)[\r\n]+/g,"$1").replace(/(?:[\r\n]+[ \t]*)+/g,
31
+ " "))}d=d}else{d=[];for(a=a.firstChild;a;a=a.nextSibling)H(a,d);d=d.join("")}d=d.replace(/(?:\r\n?|\n)$/,"");m={f:d,e:c,b:p};U(m);if(p=m.a){c=m.b;if("XMP"===c.tagName){d=document.createElement("PRE");for(a=0;a<c.attributes.length;++a){k=c.attributes[a];if(k.specified)if(k.name.toLowerCase()==="class")d.className=k.value;else d.setAttribute(k.name,k.value)}d.innerHTML=p;c.parentNode.replaceChild(d,c)}else c.innerHTML=p}}}}if(q<o.length)setTimeout(f,250);else b&&b()}for(var i=[document.getElementsByTagName("pre"),
32
+ document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],o=[],l=0;l<i.length;++l)for(var n=0,r=i[l].length;n<r;++n)o.push(i[l][n]);i=null;var j=Date;j.now||(j={now:function(){return(new Date).getTime()}});var q=0,m;f()};window.PR={combinePrefixPatterns:O,createSimpleLexer:B,registerLangHandler:u,sourceDecorator:x,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:C,PR_DECLARATION:"dec",PR_KEYWORD:R,PR_LITERAL:J,PR_NOCODE:V,PR_PLAIN:z,PR_PUNCTUATION:E,PR_SOURCE:P,PR_STRING:A,
33
+ PR_TAG:"tag",PR_TYPE:S}})()
@@ -120,6 +120,8 @@
120
120
  margin: 5px 0;
121
121
  overflow: hidden;
122
122
  line-height: 1px;
123
+ /* Force the line always below inheritance tree */
124
+ clear: both;
123
125
  }
124
126
 
125
127
 
@@ -251,22 +253,9 @@
251
253
  color: #000;
252
254
  line-height: 16px !important;
253
255
  }
254
- .body-wrap pre code b {
255
- font-weight: normal;
256
- color: #800080;
257
- }
258
- .body-wrap pre code em {
259
- font-weight: normal;
260
- color: #008080;
261
- background-color:#eee;
262
- }
263
- .body-wrap pre code i,
264
- .body-wrap pre code i b,
265
- .body-wrap pre code i em {
266
- font-weight: normal;
267
- font-style: normal;
268
- color: #999;
269
- }
256
+ .body-wrap pre code a {
257
+ text-decoration: underline !important;
258
+ }
270
259
 
271
260
  /* Hide long descriptions initially */
272
261
  /* When "expanded" class set, hide short and show long */
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: 9
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
- version: "0.1"
8
+ - 2
9
+ version: "0.2"
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: 2010-12-27 00:00:00 +02:00
17
+ date: 2011-01-10 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -67,6 +67,7 @@ files:
67
67
  - lib/jsduck/doc_formatter.rb
68
68
  - lib/jsduck/doc_parser.rb
69
69
  - lib/jsduck/event_table.rb
70
+ - lib/jsduck/inheritance_tree.rb
70
71
  - lib/jsduck/lexer.rb
71
72
  - lib/jsduck/long_params.rb
72
73
  - lib/jsduck/merger.rb
@@ -75,6 +76,8 @@ files:
75
76
  - lib/jsduck/parser.rb
76
77
  - lib/jsduck/property_table.rb
77
78
  - lib/jsduck/short_params.rb
79
+ - lib/jsduck/source_formatter.rb
80
+ - lib/jsduck/subclasses.rb
78
81
  - lib/jsduck/table.rb
79
82
  - lib/jsduck/tree.rb
80
83
  - lib/jsduck/tree_icons.rb
@@ -91,6 +94,7 @@ files:
91
94
  - template/resources/docs.css
92
95
  - template/resources/docs.gif
93
96
  - template/resources/docs.js
97
+ - template/resources/elbow-end.gif
94
98
  - template/resources/event.gif
95
99
  - template/resources/expand-all.gif
96
100
  - template/resources/expand-bg-over.gif
@@ -436,6 +440,8 @@ files:
436
440
  - template/resources/pkg-closed.gif
437
441
  - template/resources/pkg-open.gif
438
442
  - template/resources/pkg.gif
443
+ - template/resources/prettify/prettify.css
444
+ - template/resources/prettify/prettify.js
439
445
  - template/resources/prop.gif
440
446
  - template/resources/s.gif
441
447
  - template/resources/static.gif