pdoc 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +34 -0
- data/Rakefile +46 -0
- data/bin/pdoc +58 -0
- data/lib/pdoc.rb +32 -0
- data/lib/pdoc/error.rb +4 -0
- data/lib/pdoc/generators.rb +6 -0
- data/lib/pdoc/generators/abstract_generator.rb +16 -0
- data/lib/pdoc/generators/html.rb +8 -0
- data/lib/pdoc/generators/html/helpers.rb +256 -0
- data/lib/pdoc/generators/html/page.rb +71 -0
- data/lib/pdoc/generators/html/syntax_highlighter.rb +41 -0
- data/lib/pdoc/generators/html/template.rb +37 -0
- data/lib/pdoc/generators/html/website.rb +194 -0
- data/lib/pdoc/generators/json.rb +15 -0
- data/lib/pdoc/generators/pythonesque.rb +105 -0
- data/lib/pdoc/models.rb +47 -0
- data/lib/pdoc/models/argument.rb +37 -0
- data/lib/pdoc/models/base.rb +107 -0
- data/lib/pdoc/models/callable.rb +19 -0
- data/lib/pdoc/models/class.rb +28 -0
- data/lib/pdoc/models/class_method.rb +18 -0
- data/lib/pdoc/models/class_property.rb +9 -0
- data/lib/pdoc/models/constant.rb +9 -0
- data/lib/pdoc/models/constructor.rb +14 -0
- data/lib/pdoc/models/container.rb +114 -0
- data/lib/pdoc/models/entity.rb +54 -0
- data/lib/pdoc/models/instance_method.rb +18 -0
- data/lib/pdoc/models/instance_property.rb +9 -0
- data/lib/pdoc/models/mixin.rb +10 -0
- data/lib/pdoc/models/namespace.rb +10 -0
- data/lib/pdoc/models/root.rb +27 -0
- data/lib/pdoc/models/section.rb +19 -0
- data/lib/pdoc/models/signature.rb +27 -0
- data/lib/pdoc/models/utility.rb +11 -0
- data/lib/pdoc/parser.rb +109 -0
- data/lib/pdoc/parser/argument_description_nodes.rb +21 -0
- data/lib/pdoc/parser/basic_nodes.rb +31 -0
- data/lib/pdoc/parser/description_nodes.rb +42 -0
- data/lib/pdoc/parser/documentation_nodes.rb +483 -0
- data/lib/pdoc/parser/ebnf_arguments_nodes.rb +58 -0
- data/lib/pdoc/parser/ebnf_expression_nodes.rb +227 -0
- data/lib/pdoc/parser/fragment.rb +55 -0
- data/lib/pdoc/parser/section_content_nodes.rb +19 -0
- data/lib/pdoc/parser/tags_nodes.rb +14 -0
- data/lib/pdoc/parser/treetop_files/argument_description.treetop +31 -0
- data/lib/pdoc/parser/treetop_files/basic.treetop +41 -0
- data/lib/pdoc/parser/treetop_files/description.treetop +7 -0
- data/lib/pdoc/parser/treetop_files/documentation.treetop +75 -0
- data/lib/pdoc/parser/treetop_files/ebnf_arguments.treetop +33 -0
- data/lib/pdoc/parser/treetop_files/ebnf_expression.treetop +70 -0
- data/lib/pdoc/parser/treetop_files/ebnf_javascript.treetop +54 -0
- data/lib/pdoc/parser/treetop_files/events.treetop +17 -0
- data/lib/pdoc/parser/treetop_files/section_content.treetop +8 -0
- data/lib/pdoc/parser/treetop_files/tags.treetop +31 -0
- data/lib/pdoc/runner.rb +110 -0
- data/lib/pdoc/treemaker.rb +94 -0
- data/pdoc.gemspec +31 -0
- data/templates/html/assets/images/pdoc/alias.png +0 -0
- data/templates/html/assets/images/pdoc/class.png +0 -0
- data/templates/html/assets/images/pdoc/class_deprecated.png +0 -0
- data/templates/html/assets/images/pdoc/class_method.png +0 -0
- data/templates/html/assets/images/pdoc/class_property.png +0 -0
- data/templates/html/assets/images/pdoc/constant.png +0 -0
- data/templates/html/assets/images/pdoc/constructor.png +0 -0
- data/templates/html/assets/images/pdoc/deprecated.png +0 -0
- data/templates/html/assets/images/pdoc/description.png +0 -0
- data/templates/html/assets/images/pdoc/information.png +0 -0
- data/templates/html/assets/images/pdoc/instance_method.png +0 -0
- data/templates/html/assets/images/pdoc/instance_property.png +0 -0
- data/templates/html/assets/images/pdoc/method.png +0 -0
- data/templates/html/assets/images/pdoc/method_deprecated.png +0 -0
- data/templates/html/assets/images/pdoc/mixin.png +0 -0
- data/templates/html/assets/images/pdoc/namespace.png +0 -0
- data/templates/html/assets/images/pdoc/property.png +0 -0
- data/templates/html/assets/images/pdoc/related_to.png +0 -0
- data/templates/html/assets/images/pdoc/search-background.png +0 -0
- data/templates/html/assets/images/pdoc/section-background.png +0 -0
- data/templates/html/assets/images/pdoc/section.png +0 -0
- data/templates/html/assets/images/pdoc/selected-section-background.png +0 -0
- data/templates/html/assets/images/pdoc/subclass.png +0 -0
- data/templates/html/assets/images/pdoc/superclass.png +0 -0
- data/templates/html/assets/images/pdoc/utility.png +0 -0
- data/templates/html/assets/javascripts/pdoc/application.js +478 -0
- data/templates/html/assets/javascripts/pdoc/prototype.js +4874 -0
- data/templates/html/assets/javascripts/pdoc/tabs.js +506 -0
- data/templates/html/assets/stylesheets/pdoc/api.css +677 -0
- data/templates/html/assets/stylesheets/pdoc/pygments.css +62 -0
- data/templates/html/helpers.rb +35 -0
- data/templates/html/index.erb +18 -0
- data/templates/html/item_index.js.erb +6 -0
- data/templates/html/layout.erb +67 -0
- data/templates/html/leaf.erb +22 -0
- data/templates/html/node.erb +30 -0
- data/templates/html/partials/class_relationships.erb +19 -0
- data/templates/html/partials/classes.erb +7 -0
- data/templates/html/partials/constructor.erb +5 -0
- data/templates/html/partials/description.erb +5 -0
- data/templates/html/partials/link_list.erb +1 -0
- data/templates/html/partials/method_signatures.erb +14 -0
- data/templates/html/partials/methodized_note.erb +9 -0
- data/templates/html/partials/mixins.erb +7 -0
- data/templates/html/partials/namespaces.erb +7 -0
- data/templates/html/partials/related_utilities.erb +5 -0
- data/templates/html/partials/relationships.erb +11 -0
- data/templates/html/partials/short_description_list.erb +7 -0
- data/templates/html/partials/title.erb +22 -0
- data/templates/html/section.erb +18 -0
- data/test/unit/parser/argument_description_test.rb +40 -0
- data/test/unit/parser/basic_test.rb +55 -0
- data/test/unit/parser/description_test.rb +34 -0
- data/test/unit/parser/documentation_test.rb +520 -0
- data/test/unit/parser/ebnf_arguments_test.rb +81 -0
- data/test/unit/parser/ebnf_expression_test.rb +382 -0
- data/test/unit/parser/ebnf_javascript_test.rb +37 -0
- data/test/unit/parser/events_test.rb +27 -0
- data/test/unit/parser/section_content_test.rb +44 -0
- data/test/unit/parser/tags_test.rb +39 -0
- data/test/unit/parser/test_fragment.rb +80 -0
- data/test/unit/parser_test_helper.rb +62 -0
- data/test/unit/runner/basic_test.rb +14 -0
- data/test/unit/templates/html_helpers_test.rb +25 -0
- metadata +222 -0
data/README.markdown
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
PDoc
|
2
|
+
====
|
3
|
+
|
4
|
+
PDoc is an inline comment parser and JavaScript documentation generator written in Ruby. It is designed for documenting [Prototype](http://prototypejs.org) and Prototype-based libraries.
|
5
|
+
|
6
|
+
PDoc uses [Treetop](http://treetop.rubyforge.org/), a Ruby-based DSL for text parsing and interpretation, and its own ActionView-inspired, ERB-based templating system for HTML generation. Other documentation generators (e.g., DocBook XML) are planned.
|
7
|
+
|
8
|
+
Unlike other inline-doc parsers, PDoc does not rely on the JavaScript source code at all; it only parses the comments. This approach, though slightly more verbose, is much better at generating consistent, reliable documentation, and avoids the headaches encountered when documenting highly dynamic languages.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
PDoc depends on Rake, your choice of markdown parser, and treetop, all of which can be obtained through RubyGems:
|
13
|
+
|
14
|
+
gem install rake bluecloth treetop
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
For hints on how to run PDoc on the command line, consult the built-in Rake tasks (in `Rakefile`) and the `PDoc::Runner` class (in `lib/pdoc/runner.rb`).
|
19
|
+
|
20
|
+
## How it works
|
21
|
+
|
22
|
+
The process of turning inline PDoc comments into a human-friendly document has two phases.
|
23
|
+
|
24
|
+
### Parsing phase
|
25
|
+
In this phase, the source files are scanned for PDoc comments, then parsed with the Ruby files generated from the Treetop language grammar. The product of this phase is a tree full of specialized classes, all of which inherit from `Treetop::Runtime::SyntaxNode`.
|
26
|
+
|
27
|
+
The root of the tree is an instance of `Documentation::Doc`. It comprises one or more instances of `Documentation::Section`; which in turn comprise language elements like namespaces, classes, constants, etc., all of which have class representations.
|
28
|
+
|
29
|
+
### Rendering phase
|
30
|
+
Next, PDoc asks a _generator_ how to translate this abstract tree into a hierarchical document. The default generator outputs organized HTML in a manner similar to [RDoc](http://rdoc.sourceforge.net/ "RDoc - Document Generator for Ruby Source")'s.
|
31
|
+
|
32
|
+
The HTML generator (`PDoc::Generators::Html`) has associated _templates_ (in the `templates` directory) that accept syntax nodes and echo their metadata onto the page using [ERB](http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/index.html "erb: Ruby Standard Library Documentation"). Templates are modular, so it's quite easy to apply a custom "skin" to one's documentation pages.
|
33
|
+
|
34
|
+
Furthermore, generators themselves are modular; PDoc can, theoretically, parse once and render to several different targets (HTML, [DocBook XML](http://www.docbook.org/ "DocBook.org"), CHM, PDF, even [ScriptDoc](http://www.scriptdoc.org/ "ScriptDoc.org: Dynamic Language Documentation").) We hope many such generators will exist in the future.
|
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'lib/pdoc'
|
3
|
+
|
4
|
+
desc "Builds the documentation"
|
5
|
+
task :build_doc do
|
6
|
+
PDoc.run({
|
7
|
+
:source_files => [File.join(File.dirname(__FILE__), "test", "fixtures", "ajax.js")],
|
8
|
+
:destination => OUTPUT_DIR,
|
9
|
+
:syntax_highlighter => :pygments,
|
10
|
+
:markdown_parser => :bluecloth,
|
11
|
+
:src_code_href => proc { |file, line|
|
12
|
+
"http://github.com/example/ex/#{file}##{line}"
|
13
|
+
},
|
14
|
+
:pretty_urls => false,
|
15
|
+
:bust_cache => true,
|
16
|
+
:name => 'Example JavaScript Framework',
|
17
|
+
:short_name => 'Ex',
|
18
|
+
:home_url => 'http://example.com',
|
19
|
+
:doc_url => 'http://example.com/api',
|
20
|
+
:version => "1.2.0",
|
21
|
+
:copyright_notice => 'This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share Alike 3.0 Unported License</a>.'
|
22
|
+
})
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Empties output directory"
|
26
|
+
task :remove_doc do
|
27
|
+
rm_rf Dir.glob(File.join(OUTPUT_DIR, "*"))
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Empties the output directory and builds the documentation."
|
31
|
+
task :doc => [:remove_doc, :build_doc]
|
32
|
+
|
33
|
+
desc "Runs all the unit tests."
|
34
|
+
task :test do
|
35
|
+
require 'rake/runtest'
|
36
|
+
Rake.run_tests '**/*_test.rb'
|
37
|
+
end
|
38
|
+
|
39
|
+
task :compile_parser do
|
40
|
+
require 'treetop'
|
41
|
+
compiler = Treetop::Compiler::GrammarCompiler.new
|
42
|
+
treetop_dir = File.expand_path(File.join(File.dirname(__FILE__), "lib", "pdoc", "parser", "treetop_files"))
|
43
|
+
Dir.glob(File.join(treetop_dir, "*.treetop")).each do |treetop_file_path|
|
44
|
+
compiler.compile(treetop_file_path)
|
45
|
+
end
|
46
|
+
end
|
data/bin/pdoc
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'oyster'
|
4
|
+
require File.dirname(__FILE__) + '/../lib/pdoc'
|
5
|
+
|
6
|
+
spec = Oyster.spec do
|
7
|
+
name "pdoc -- Inline comment parser and JavaScript documentation generator"
|
8
|
+
author "Tobie Langel <tobie.langel@gmail.com>"
|
9
|
+
|
10
|
+
synopsis <<-EOS
|
11
|
+
pdoc [-o OUTPUT_DIR] [-t TEMPLATE_DIR] SOURCE_FILES
|
12
|
+
pdoc [OPTIONS] -d SOURCE_DIRECTORY
|
13
|
+
EOS
|
14
|
+
|
15
|
+
string :directory,
|
16
|
+
:desc => "Directory to search for JavaScript files. Will take all *.js " +
|
17
|
+
"files from the given directory (including subdirectories) and use " +
|
18
|
+
"them to generate documentation. This option takes precedence over " +
|
19
|
+
"SOURCE_FILES."
|
20
|
+
|
21
|
+
string :output,
|
22
|
+
:desc => "Directory in which to dump output files",
|
23
|
+
:default => "pdoc"
|
24
|
+
|
25
|
+
string :templates,
|
26
|
+
:desc => "Directory containing template files"
|
27
|
+
|
28
|
+
subcommand :'copy-templates' do
|
29
|
+
synopsis <<-EOS
|
30
|
+
pdoc copy-templates TYPE DESTINATION
|
31
|
+
EOS
|
32
|
+
|
33
|
+
description <<-EOS
|
34
|
+
PDoc includes a set of default templates for each type of output generator.
|
35
|
+
This command lets you extract a set of these templates into a local directory
|
36
|
+
so you can tweak it to suit your needs. Be sure to specify your set of
|
37
|
+
templates next time you run pdoc.
|
38
|
+
EOS
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
begin; options = spec.parse
|
43
|
+
rescue Oyster::HelpRendered; exit
|
44
|
+
end
|
45
|
+
|
46
|
+
if command = options[:'copy-templates']
|
47
|
+
args = command[:unclaimed]
|
48
|
+
PDoc.copy_templates(args[0], File.expand_path(args[1]))
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
files = (d = options[:directory]) ?
|
53
|
+
Dir["#{d}/**/*.js"].map(&File.method(:expand_path)) :
|
54
|
+
options[:unclaimed].dup
|
55
|
+
|
56
|
+
files << {:destination => options[:output], :templates => options[:templates]}
|
57
|
+
PDoc::Runner.new(*files).run
|
58
|
+
|
data/lib/pdoc.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
DIR = File.expand_path(File.dirname(__FILE__))
|
2
|
+
OUTPUT_DIR = File.join(DIR, '..', 'output')
|
3
|
+
TEMPLATES_DIR = File.join(DIR, '..', 'templates')
|
4
|
+
VENDOR_DIR = File.join(DIR, '..', 'vendor')
|
5
|
+
PARSER_DIR = File.join(DIR, 'pdoc', 'parser')
|
6
|
+
|
7
|
+
[DIR, VENDOR_DIR, PARSER_DIR, OUTPUT_DIR, TEMPLATES_DIR].each do |c|
|
8
|
+
$:.unshift(c)
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'rubygems'
|
12
|
+
require 'erb'
|
13
|
+
require 'fileutils'
|
14
|
+
|
15
|
+
require 'pdoc/error'
|
16
|
+
require 'pdoc/runner'
|
17
|
+
require 'pdoc/generators'
|
18
|
+
require 'pdoc/parser'
|
19
|
+
require 'pdoc/models'
|
20
|
+
require 'pdoc/treemaker'
|
21
|
+
|
22
|
+
module PDoc
|
23
|
+
def self.run(options = {})
|
24
|
+
Runner.new(options.dup).run
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.copy_templates(template_type, destination)
|
28
|
+
dir = File.expand_path(destination)
|
29
|
+
raise "File already exists: #{destination}" if File.exist?(dir)
|
30
|
+
FileUtils.cp_r("#{TEMPLATES_DIR}/#{template_type}", dir)
|
31
|
+
end
|
32
|
+
end
|
data/lib/pdoc/error.rb
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'generators', 'abstract_generator'))
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'generators', 'html'))
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'generators', 'pythonesque'))
|
4
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'generators', 'json'))
|
5
|
+
|
6
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module PDoc
|
2
|
+
module Generators
|
3
|
+
class AbstractGenerator
|
4
|
+
attr_reader :options, :root
|
5
|
+
def initialize(root, options = {})
|
6
|
+
@root = root
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
# Creates a new directory with read, write and execute permission.
|
11
|
+
def mkdir(name)
|
12
|
+
Dir.mkdir(name, 0755)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
HTML_DIR = File.expand_path(File.join(File.dirname(__FILE__), "html"))
|
2
|
+
|
3
|
+
require File.join(HTML_DIR, "helpers")
|
4
|
+
require File.join(HTML_DIR, "template")
|
5
|
+
require File.join(HTML_DIR, "page")
|
6
|
+
require File.join(HTML_DIR, "website")
|
7
|
+
require File.join(HTML_DIR, "syntax_highlighter")
|
8
|
+
|
@@ -0,0 +1,256 @@
|
|
1
|
+
module PDoc
|
2
|
+
module Generators
|
3
|
+
module Html
|
4
|
+
module Helpers
|
5
|
+
module BaseHelper
|
6
|
+
def content_tag(tag_name, content, attributes = {})
|
7
|
+
"<#{tag_name}#{attributes_to_html(attributes)}>#{content}</#{tag_name}>"
|
8
|
+
end
|
9
|
+
|
10
|
+
def img_tag(filename, attributes = {})
|
11
|
+
attributes.merge! :src => "#{path_prefix}images/#{filename}"
|
12
|
+
tag(:img, attributes)
|
13
|
+
end
|
14
|
+
|
15
|
+
def tag(tag_name, attributes = {})
|
16
|
+
"<#{tag_name}#{attributes_to_html(attributes)} />"
|
17
|
+
end
|
18
|
+
|
19
|
+
def link_to(name, path, attributes={})
|
20
|
+
content_tag(:a, name, attributes.merge(:href => path))
|
21
|
+
end
|
22
|
+
|
23
|
+
def htmlize(markdown)
|
24
|
+
markdown = Website.syntax_highlighter.parse(markdown)
|
25
|
+
Website.markdown_parser.new(markdown).to_html
|
26
|
+
end
|
27
|
+
|
28
|
+
# Gah, what an ugly hack.
|
29
|
+
def inline_htmlize(markdown)
|
30
|
+
htmlize(markdown).gsub(/^<p>/, '').gsub(/<\/p>$/, '')
|
31
|
+
end
|
32
|
+
|
33
|
+
def javascript_include_tag(*names)
|
34
|
+
names.map do |name|
|
35
|
+
attributes = {
|
36
|
+
:src => "#{path_prefix}javascripts/#{name}.js",
|
37
|
+
:type => "text/javascript",
|
38
|
+
:charset => "utf-8"
|
39
|
+
}
|
40
|
+
content_tag(:script, "", attributes)
|
41
|
+
end.join("\n")
|
42
|
+
end
|
43
|
+
|
44
|
+
def stylesheet_link_tag(*names)
|
45
|
+
names.map do |name|
|
46
|
+
attributes = {
|
47
|
+
:href => "#{path_prefix}stylesheets/#{name}.css",
|
48
|
+
:type => "text/css",
|
49
|
+
:media => "screen, projection",
|
50
|
+
:charset => "utf-8",
|
51
|
+
:rel => "stylesheet"
|
52
|
+
}
|
53
|
+
tag(:link, attributes)
|
54
|
+
end.join("\n")
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def attributes_to_html(attributes)
|
59
|
+
attributes = attributes.sort { |a, b| a.to_s <=> b.to_s }
|
60
|
+
attributes.map do |a|
|
61
|
+
k, v = a
|
62
|
+
k ? " #{k}=\"#{v}\"" : ""
|
63
|
+
end.join
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
module LinkHelper
|
68
|
+
def path_prefix
|
69
|
+
"../" * depth
|
70
|
+
end
|
71
|
+
|
72
|
+
def path_to(obj)
|
73
|
+
path = path_prefix << obj.url << '/'
|
74
|
+
Website.pretty_urls? ? path : "#{path}index.html"
|
75
|
+
end
|
76
|
+
|
77
|
+
def auto_link(obj, options = {})
|
78
|
+
if obj.is_a?(String)
|
79
|
+
original = obj
|
80
|
+
obj = root.find(obj)
|
81
|
+
return original unless obj
|
82
|
+
end
|
83
|
+
name = options.delete(:name) == :short ? obj.name : obj.full_name
|
84
|
+
if obj.type == 'section'
|
85
|
+
title = obj.full_name
|
86
|
+
else
|
87
|
+
title = "#{obj.full_name} (#{obj.type})"
|
88
|
+
end
|
89
|
+
link_to(name, path_to(obj), { :title => title }.merge(options))
|
90
|
+
end
|
91
|
+
|
92
|
+
def auto_link_code(obj, options = {})
|
93
|
+
"<code>#{auto_link(obj, options)}</code>"
|
94
|
+
end
|
95
|
+
|
96
|
+
def auto_link_content(content)
|
97
|
+
return '' if content.nil?
|
98
|
+
content.gsub!(/\[\[([a-zA-Z]+)\s+section\]\]/) do |m|
|
99
|
+
result = auto_link(root.find($1), :name => :long)
|
100
|
+
result
|
101
|
+
end
|
102
|
+
content.gsub(/\[\[([a-zA-Z$\.#]+)(?:\s+([^\]]+))?\]\]/) do |m|
|
103
|
+
if doc_instance = root.find($1)
|
104
|
+
$2 ? link_to($2, path_to(doc_instance)) : auto_link_code(doc_instance, :name => :long)
|
105
|
+
else
|
106
|
+
$1
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def auto_link_types(types, options = {})
|
112
|
+
types = types.split(/\s+\|\s+/) if types.is_a?(String)
|
113
|
+
types.map do |t|
|
114
|
+
if match = /^\[([\w\d\$\.\(\)#]*[\w\d\$\(\)#])...\s*\]$/.match(t) # e.g.: [Element...]
|
115
|
+
"[#{auto_link(match[1], options)}…]"
|
116
|
+
else
|
117
|
+
auto_link(t, options)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def dom_id(obj)
|
123
|
+
"#{obj.id}-#{obj.type.gsub(/\s+/, '_')}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
module CodeHelper
|
128
|
+
def methodize_signature(sig)
|
129
|
+
sig.sub(/\.([\w\d\$]+)\((.*?)(,\s*|\))/) do
|
130
|
+
first_arg = $2.to_s.strip
|
131
|
+
prefix = first_arg[-1, 1] == '[' ? '([' : '('
|
132
|
+
rest = $3 == ')' ? $3 : ''
|
133
|
+
"##{$1}#{prefix}#{rest}"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def methodize_full_name(obj)
|
138
|
+
obj.full_name.sub(/\.([^.]+)$/, '#\1')
|
139
|
+
end
|
140
|
+
|
141
|
+
def method_synopsis(object)
|
142
|
+
result = []
|
143
|
+
object.signatures.each do |signature|
|
144
|
+
if return_value = signature.return_value
|
145
|
+
types = auto_link_types(return_value, :name => :long).join(' | ')
|
146
|
+
result << "#{signature.name} → #{types}"
|
147
|
+
else # Constructors
|
148
|
+
result << signature.name
|
149
|
+
end
|
150
|
+
end
|
151
|
+
result
|
152
|
+
end
|
153
|
+
|
154
|
+
def breadcrumb(obj, options = {})
|
155
|
+
options = {:name => :short}.merge(options)
|
156
|
+
result = []
|
157
|
+
begin
|
158
|
+
result << auto_link(obj, options.dup)
|
159
|
+
obj = obj.parent
|
160
|
+
end until obj.is_a?(Models::Root)
|
161
|
+
result.reverse!
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
module MenuHelper
|
166
|
+
NODES = [
|
167
|
+
:namespaces,
|
168
|
+
:classes,
|
169
|
+
:mixins,
|
170
|
+
:utilities
|
171
|
+
]
|
172
|
+
LEAVES = [
|
173
|
+
:constants,
|
174
|
+
:class_methods,
|
175
|
+
:class_properties,
|
176
|
+
:instance_methods,
|
177
|
+
:instance_properties
|
178
|
+
]
|
179
|
+
|
180
|
+
def menu(obj)
|
181
|
+
if obj.parent
|
182
|
+
html = menu_item(obj, :name => :long)
|
183
|
+
|
184
|
+
html << node_submenu(obj)
|
185
|
+
|
186
|
+
if obj == doc_instance && obj.respond_to?(:constants)
|
187
|
+
html << leaf_submenu(obj)
|
188
|
+
elsif doc_instance && doc_instance.respond_to?(:parent)
|
189
|
+
parent = doc_instance.parent
|
190
|
+
html << leaf_submenu(parent) if parent == obj && obj.respond_to?(:constants)
|
191
|
+
end
|
192
|
+
|
193
|
+
content_tag(:li, html)
|
194
|
+
else #root
|
195
|
+
node_submenu(obj)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def node_submenu(obj)
|
200
|
+
children = []
|
201
|
+
options = {}
|
202
|
+
|
203
|
+
NODES.each do |prop|
|
204
|
+
children.concat(obj.send(prop)) if obj.respond_to?(prop)
|
205
|
+
end
|
206
|
+
|
207
|
+
list_items = children.sort.map { |item| menu(item) }
|
208
|
+
if obj.respond_to?(:sections)
|
209
|
+
obj.sections.each { |section| list_items << menu(section) }
|
210
|
+
options[:class] = "menu-items"
|
211
|
+
options[:id] = "api_menu"
|
212
|
+
elsif obj.type == "section"
|
213
|
+
options[:class] = "menu-section"
|
214
|
+
end
|
215
|
+
list_items.empty? ? '' : content_tag(:ul, list_items.join("\n"), options)
|
216
|
+
end
|
217
|
+
|
218
|
+
def menu_item(obj, options = {})
|
219
|
+
options = options.dup
|
220
|
+
options[:class] = class_names_for(obj, options)
|
221
|
+
content_tag(:div, auto_link(obj, options), :class => 'menu-item')
|
222
|
+
end
|
223
|
+
|
224
|
+
def leaf_submenu(obj)
|
225
|
+
items = []
|
226
|
+
if obj.respond_to?(:constructor) && obj.constructor
|
227
|
+
items << content_tag(:li, menu_item(obj.constructor, :name => :short))
|
228
|
+
end
|
229
|
+
LEAVES.each do |prop|
|
230
|
+
if obj.respond_to?(prop)
|
231
|
+
obj.send(prop).sort!.map do |item|
|
232
|
+
items << content_tag(:li, menu_item(item, :name => :short))
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
content_tag(:ul, items.join("\n"))
|
237
|
+
end
|
238
|
+
|
239
|
+
def class_names_for(obj, options = {})
|
240
|
+
classes = []
|
241
|
+
classes << obj.type.gsub(/\s+/, '-')
|
242
|
+
classes << "deprecated" if obj.deprecated?
|
243
|
+
if doc_instance
|
244
|
+
if obj == doc_instance
|
245
|
+
classes << "current"
|
246
|
+
elsif obj.ancestor_of?(doc_instance)
|
247
|
+
classes << "current-parent"
|
248
|
+
end
|
249
|
+
end
|
250
|
+
classes.join(' ')
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|