pdoc 0.2.0

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.
Files changed (122) hide show
  1. data/README.markdown +34 -0
  2. data/Rakefile +46 -0
  3. data/bin/pdoc +58 -0
  4. data/lib/pdoc.rb +32 -0
  5. data/lib/pdoc/error.rb +4 -0
  6. data/lib/pdoc/generators.rb +6 -0
  7. data/lib/pdoc/generators/abstract_generator.rb +16 -0
  8. data/lib/pdoc/generators/html.rb +8 -0
  9. data/lib/pdoc/generators/html/helpers.rb +256 -0
  10. data/lib/pdoc/generators/html/page.rb +71 -0
  11. data/lib/pdoc/generators/html/syntax_highlighter.rb +41 -0
  12. data/lib/pdoc/generators/html/template.rb +37 -0
  13. data/lib/pdoc/generators/html/website.rb +194 -0
  14. data/lib/pdoc/generators/json.rb +15 -0
  15. data/lib/pdoc/generators/pythonesque.rb +105 -0
  16. data/lib/pdoc/models.rb +47 -0
  17. data/lib/pdoc/models/argument.rb +37 -0
  18. data/lib/pdoc/models/base.rb +107 -0
  19. data/lib/pdoc/models/callable.rb +19 -0
  20. data/lib/pdoc/models/class.rb +28 -0
  21. data/lib/pdoc/models/class_method.rb +18 -0
  22. data/lib/pdoc/models/class_property.rb +9 -0
  23. data/lib/pdoc/models/constant.rb +9 -0
  24. data/lib/pdoc/models/constructor.rb +14 -0
  25. data/lib/pdoc/models/container.rb +114 -0
  26. data/lib/pdoc/models/entity.rb +54 -0
  27. data/lib/pdoc/models/instance_method.rb +18 -0
  28. data/lib/pdoc/models/instance_property.rb +9 -0
  29. data/lib/pdoc/models/mixin.rb +10 -0
  30. data/lib/pdoc/models/namespace.rb +10 -0
  31. data/lib/pdoc/models/root.rb +27 -0
  32. data/lib/pdoc/models/section.rb +19 -0
  33. data/lib/pdoc/models/signature.rb +27 -0
  34. data/lib/pdoc/models/utility.rb +11 -0
  35. data/lib/pdoc/parser.rb +109 -0
  36. data/lib/pdoc/parser/argument_description_nodes.rb +21 -0
  37. data/lib/pdoc/parser/basic_nodes.rb +31 -0
  38. data/lib/pdoc/parser/description_nodes.rb +42 -0
  39. data/lib/pdoc/parser/documentation_nodes.rb +483 -0
  40. data/lib/pdoc/parser/ebnf_arguments_nodes.rb +58 -0
  41. data/lib/pdoc/parser/ebnf_expression_nodes.rb +227 -0
  42. data/lib/pdoc/parser/fragment.rb +55 -0
  43. data/lib/pdoc/parser/section_content_nodes.rb +19 -0
  44. data/lib/pdoc/parser/tags_nodes.rb +14 -0
  45. data/lib/pdoc/parser/treetop_files/argument_description.treetop +31 -0
  46. data/lib/pdoc/parser/treetop_files/basic.treetop +41 -0
  47. data/lib/pdoc/parser/treetop_files/description.treetop +7 -0
  48. data/lib/pdoc/parser/treetop_files/documentation.treetop +75 -0
  49. data/lib/pdoc/parser/treetop_files/ebnf_arguments.treetop +33 -0
  50. data/lib/pdoc/parser/treetop_files/ebnf_expression.treetop +70 -0
  51. data/lib/pdoc/parser/treetop_files/ebnf_javascript.treetop +54 -0
  52. data/lib/pdoc/parser/treetop_files/events.treetop +17 -0
  53. data/lib/pdoc/parser/treetop_files/section_content.treetop +8 -0
  54. data/lib/pdoc/parser/treetop_files/tags.treetop +31 -0
  55. data/lib/pdoc/runner.rb +110 -0
  56. data/lib/pdoc/treemaker.rb +94 -0
  57. data/pdoc.gemspec +31 -0
  58. data/templates/html/assets/images/pdoc/alias.png +0 -0
  59. data/templates/html/assets/images/pdoc/class.png +0 -0
  60. data/templates/html/assets/images/pdoc/class_deprecated.png +0 -0
  61. data/templates/html/assets/images/pdoc/class_method.png +0 -0
  62. data/templates/html/assets/images/pdoc/class_property.png +0 -0
  63. data/templates/html/assets/images/pdoc/constant.png +0 -0
  64. data/templates/html/assets/images/pdoc/constructor.png +0 -0
  65. data/templates/html/assets/images/pdoc/deprecated.png +0 -0
  66. data/templates/html/assets/images/pdoc/description.png +0 -0
  67. data/templates/html/assets/images/pdoc/information.png +0 -0
  68. data/templates/html/assets/images/pdoc/instance_method.png +0 -0
  69. data/templates/html/assets/images/pdoc/instance_property.png +0 -0
  70. data/templates/html/assets/images/pdoc/method.png +0 -0
  71. data/templates/html/assets/images/pdoc/method_deprecated.png +0 -0
  72. data/templates/html/assets/images/pdoc/mixin.png +0 -0
  73. data/templates/html/assets/images/pdoc/namespace.png +0 -0
  74. data/templates/html/assets/images/pdoc/property.png +0 -0
  75. data/templates/html/assets/images/pdoc/related_to.png +0 -0
  76. data/templates/html/assets/images/pdoc/search-background.png +0 -0
  77. data/templates/html/assets/images/pdoc/section-background.png +0 -0
  78. data/templates/html/assets/images/pdoc/section.png +0 -0
  79. data/templates/html/assets/images/pdoc/selected-section-background.png +0 -0
  80. data/templates/html/assets/images/pdoc/subclass.png +0 -0
  81. data/templates/html/assets/images/pdoc/superclass.png +0 -0
  82. data/templates/html/assets/images/pdoc/utility.png +0 -0
  83. data/templates/html/assets/javascripts/pdoc/application.js +478 -0
  84. data/templates/html/assets/javascripts/pdoc/prototype.js +4874 -0
  85. data/templates/html/assets/javascripts/pdoc/tabs.js +506 -0
  86. data/templates/html/assets/stylesheets/pdoc/api.css +677 -0
  87. data/templates/html/assets/stylesheets/pdoc/pygments.css +62 -0
  88. data/templates/html/helpers.rb +35 -0
  89. data/templates/html/index.erb +18 -0
  90. data/templates/html/item_index.js.erb +6 -0
  91. data/templates/html/layout.erb +67 -0
  92. data/templates/html/leaf.erb +22 -0
  93. data/templates/html/node.erb +30 -0
  94. data/templates/html/partials/class_relationships.erb +19 -0
  95. data/templates/html/partials/classes.erb +7 -0
  96. data/templates/html/partials/constructor.erb +5 -0
  97. data/templates/html/partials/description.erb +5 -0
  98. data/templates/html/partials/link_list.erb +1 -0
  99. data/templates/html/partials/method_signatures.erb +14 -0
  100. data/templates/html/partials/methodized_note.erb +9 -0
  101. data/templates/html/partials/mixins.erb +7 -0
  102. data/templates/html/partials/namespaces.erb +7 -0
  103. data/templates/html/partials/related_utilities.erb +5 -0
  104. data/templates/html/partials/relationships.erb +11 -0
  105. data/templates/html/partials/short_description_list.erb +7 -0
  106. data/templates/html/partials/title.erb +22 -0
  107. data/templates/html/section.erb +18 -0
  108. data/test/unit/parser/argument_description_test.rb +40 -0
  109. data/test/unit/parser/basic_test.rb +55 -0
  110. data/test/unit/parser/description_test.rb +34 -0
  111. data/test/unit/parser/documentation_test.rb +520 -0
  112. data/test/unit/parser/ebnf_arguments_test.rb +81 -0
  113. data/test/unit/parser/ebnf_expression_test.rb +382 -0
  114. data/test/unit/parser/ebnf_javascript_test.rb +37 -0
  115. data/test/unit/parser/events_test.rb +27 -0
  116. data/test/unit/parser/section_content_test.rb +44 -0
  117. data/test/unit/parser/tags_test.rb +39 -0
  118. data/test/unit/parser/test_fragment.rb +80 -0
  119. data/test/unit/parser_test_helper.rb +62 -0
  120. data/test/unit/runner/basic_test.rb +14 -0
  121. data/test/unit/templates/html_helpers_test.rb +25 -0
  122. metadata +222 -0
@@ -0,0 +1,7 @@
1
+ grammar Description
2
+ include Basic
3
+
4
+ rule text
5
+ (blank_line / text_line)* <Text>
6
+ end
7
+ end
@@ -0,0 +1,75 @@
1
+ grammar Documentation
2
+ include Tags
3
+ include Events
4
+ include ArgumentDescription
5
+ include Description
6
+ include SectionContent
7
+ include EbnfExpression
8
+
9
+ rule documentation
10
+ ((!comment_start .)* doc_instance)+ (!comment_start .)* <Doc> / (!comment_start .)* {
11
+ def each
12
+ end
13
+ }
14
+ end
15
+
16
+ rule doc_instance
17
+ section_doc / klass_method_doc / instance_method_doc / klass_property_doc / instance_property_doc / utility_doc / constructor_doc / klass_doc / mixin_doc / constant_doc / namespace_doc
18
+ end
19
+
20
+ rule section_doc
21
+ start section comment_end <Section>
22
+ end
23
+
24
+ rule constructor_doc
25
+ start ebnf:(line constructor)+ argument_descriptions events text comment_end <Constructor>
26
+ end
27
+
28
+ rule mixin_doc
29
+ start line ebnf:mixin text comment_end <Mixin>
30
+ end
31
+
32
+ rule klass_doc
33
+ start line space* ebnf:klass text comment_end <Klass>
34
+ end
35
+
36
+ rule klass_method_doc
37
+ start ebnf:(line klass_method)+ argument_descriptions events text comment_end <KlassMethod>
38
+ end
39
+
40
+ rule instance_method_doc
41
+ start ebnf:(line instance_method)+ argument_descriptions events text comment_end <InstanceMethod>
42
+ end
43
+
44
+ rule klass_property_doc
45
+ start line ebnf:klass_property text comment_end <KlassProperty>
46
+ end
47
+
48
+ rule instance_property_doc
49
+ start line ebnf:instance_property text comment_end <InstanceProperty>
50
+ end
51
+
52
+ rule constant_doc
53
+ start line ebnf:constant text comment_end <Constant>
54
+ end
55
+
56
+ rule utility_doc
57
+ start ebnf:(line utility)+ argument_descriptions events text comment_end <Utility>
58
+ end
59
+
60
+ rule namespace_doc
61
+ start line space* ebnf:namespace text comment_end <Namespace>
62
+ end
63
+
64
+ rule start
65
+ comment_start space* (tags)?
66
+ end
67
+
68
+ rule argument_descriptions
69
+ (argument_description+ blank_line)?
70
+ end
71
+
72
+ rule events
73
+ (super)?
74
+ end
75
+ end
@@ -0,0 +1,33 @@
1
+ grammar EbnfArguments
2
+ include EbnfJavascript
3
+
4
+ rule arguments
5
+ first_argument:argument rest:(argument_separator argument)* <Arguments>
6
+ /
7
+ space* {
8
+ def to_a
9
+ []
10
+ end
11
+ }
12
+ end
13
+
14
+ rule argument
15
+ optional_argument / required_argument
16
+ end
17
+
18
+ rule argument_separator
19
+ space* (&'[' / ',')
20
+ end
21
+
22
+ rule optional_argument
23
+ "[" space* ","? required_argument default:(default_value?) nested:(optional_argument*) "]" <OptionalArgument>
24
+ end
25
+
26
+ rule default_value
27
+ space* "=" space* value:[^\[\]]+
28
+ end
29
+
30
+ rule required_argument
31
+ space* (js_variable / js_object) '...'? space* <Argument>
32
+ end
33
+ end
@@ -0,0 +1,70 @@
1
+ grammar EbnfExpression
2
+ include EbnfArguments
3
+ rule ebnf
4
+ klass_method / instance_method / klass_property / instance_property / utility / constructor / mixin / klass / constant / namespace
5
+ end
6
+
7
+ rule mixin
8
+ space* 'mixin' space+ js_namespace (includes)? <Mixin>
9
+ end
10
+
11
+ rule klass
12
+ space* 'class' space+ js_namespace extends:(space+ '<' space+ js_namespace)? (includes)? <Klass>
13
+ end
14
+
15
+ rule includes
16
+ line space* 'includes' space+ js_namespace more:(',' space+ js_namespace)*
17
+ end
18
+
19
+ rule constructor
20
+ space* 'new' (space)+ js_namespace args <Constructor>
21
+ end
22
+
23
+ rule instance_accessor
24
+ js_namespace '#' js_variable
25
+ end
26
+
27
+ rule instance_signature
28
+ instance_accessor args
29
+ end
30
+
31
+ rule klass_method
32
+ space* js_namespace args return_value <KlassMethod>
33
+ end
34
+
35
+ rule instance_method
36
+ space* instance_signature return_value <InstanceMethod>
37
+ end
38
+
39
+ rule klass_property
40
+ space* js_namespace return_value <KlassProperty>
41
+ end
42
+
43
+ rule instance_property
44
+ space* instance_accessor return_value <InstanceProperty>
45
+ end
46
+
47
+ rule constant
48
+ space* js_namespace space* "=" space* value:(char)+ space* <Constant>
49
+ end
50
+
51
+ rule utility
52
+ space* utility_name:('$' [$a-zA-Z]*) args return_value <Utility>
53
+ end
54
+
55
+ rule args
56
+ '(' space* methodize:'@'? arguments space* ')' {
57
+ def text_value
58
+ super.to_s.sub('( )', '()')
59
+ end
60
+ }
61
+ end
62
+
63
+ rule namespace
64
+ js_namespace (includes)? <Namespace>
65
+ end
66
+
67
+ rule return_value
68
+ space* '->' space* value:(char)+
69
+ end
70
+ end
@@ -0,0 +1,54 @@
1
+ grammar EbnfJavascript
2
+ include Basic
3
+ rule primitive
4
+ js_all_caps_constant / js_namespace / js_constant / js_variable / js_object
5
+ end
6
+
7
+ rule js_object
8
+ '{' [^}]* '}'
9
+ end
10
+
11
+ rule js_constant
12
+ [A-Z] [a-zA-Z_0-9$]* {
13
+ def value
14
+ text_value
15
+ end
16
+ }
17
+ end
18
+
19
+ rule js_all_caps_constant
20
+ [A-Z] [A-Z_]+ {
21
+ def value
22
+ text_value
23
+ end
24
+ }
25
+ end
26
+
27
+ rule js_variable
28
+ [_a-zA-Z] [_a-zA-Z0-9]* {
29
+ def value
30
+ text_value
31
+ end
32
+ }
33
+ end
34
+
35
+ rule js_namespace
36
+ (js_constant / js_all_caps_constant / js_variable) ('.' (js_constant / js_all_caps_constant / js_variable))* {
37
+ def namespace
38
+ to_a.slice(0..-2).join(".")
39
+ end
40
+
41
+ def name
42
+ to_a.pop
43
+ end
44
+
45
+ def to_a
46
+ text_value.split('.')
47
+ end
48
+
49
+ def full_name
50
+ text_value
51
+ end
52
+ }
53
+ end
54
+ end
@@ -0,0 +1,17 @@
1
+ grammar Events
2
+ include Basic
3
+
4
+ rule events
5
+ line space* 'fires' space+ event more:(',' space* event)* {
6
+ def to_a
7
+ [event.text_value].concat(more.elements.map{ |e| e.event.text_value })
8
+ end
9
+ }
10
+ end
11
+
12
+ rule event
13
+ [a-zA-Z]+ (':' [a-zA-Z]+)*
14
+ end
15
+ end
16
+
17
+
@@ -0,0 +1,8 @@
1
+ grammar SectionContent
2
+ include Basic
3
+ include Description
4
+
5
+ rule section
6
+ line space* '==' space* title:[a-zA-Z0-9\s]+ space* '==' space* text <Section>
7
+ end
8
+ end
@@ -0,0 +1,31 @@
1
+ grammar Tags
2
+ include Basic
3
+
4
+ rule tags
5
+ tag more:(', ' tag)* <Tags>
6
+ end
7
+
8
+ rule tag
9
+ tag_name opt:(": " tag_value)? {
10
+ def name
11
+ tag_name.text_value
12
+ end
13
+
14
+ def value
15
+ if opt.respond_to?("tag_value")
16
+ opt.tag_value.text_value
17
+ else
18
+ nil
19
+ end
20
+ end
21
+ }
22
+ end
23
+
24
+ rule tag_value
25
+ (![\n:,] .)+
26
+ end
27
+
28
+ rule tag_name
29
+ (![\n:,] .)+
30
+ end
31
+ end
@@ -0,0 +1,110 @@
1
+ module PDoc
2
+ require 'yaml'
3
+
4
+ class Runner
5
+ def initialize(*source_files)
6
+ options = source_files.last.is_a?(Hash) ? source_files.pop : {}
7
+ @source_files = source_files.empty? ? options[:source_files] : source_files
8
+ @output_directory = File.expand_path(options.delete(:destination) || OUTPUT_DIR)
9
+ @generator = options.delete(:generator) || Generators::Html::Website
10
+ @parser = Parser
11
+ @serializer = Serializer
12
+ @bust_cache = options.delete(:bust_cache) || false
13
+ Models.src_code_href = options.delete(:src_code_href)
14
+ Models.doc_href = options.delete(:doc_href)
15
+ @generator_options = options
16
+ end
17
+
18
+ def serialize(files)
19
+ files.each do |path|
20
+ File.open(pdoc_file(path), "w+") do |f|
21
+ f << serialize_file(path)
22
+ end
23
+ end
24
+ end
25
+
26
+ def deserialize(files)
27
+ results = []
28
+ files.each do |file|
29
+ file = pdoc_file(file)
30
+ File.open(file) do |y|
31
+ YAML.load_documents(y) { |doc| results << doc }
32
+ end
33
+ end
34
+ results
35
+ end
36
+
37
+ def new_files
38
+ @source_files.select do |path|
39
+ pdoc = pdoc_file(path)
40
+ !File.exist?(pdoc) || File.mtime(path) > File.mtime(pdoc)
41
+ end
42
+ end
43
+
44
+ def run
45
+ opts = @generator_options
46
+ puts
47
+ puts " Markdown parser: #{opts[:markdown_parser]}" if opts[:markdown_parser]
48
+ puts " Syntax highlighter: #{opts[:syntax_highlighter]}" if opts[:syntax_highlighter]
49
+ puts " Pretty urls: #{opts[:pretty_urls]}" if opts[:pretty_urls]
50
+ puts " Index page: #{opts[:index_page]}" if opts[:index_page]
51
+ puts " Output directory: #{@output_directory}\n\n"
52
+
53
+ files = @bust_cache ? @source_files : new_files
54
+ if files.empty?
55
+ puts " Restoring serialized documentation from cache.\n\n"
56
+ else
57
+ puts " Parsing JS files for PDoc comments:"
58
+ start_time = Time.new
59
+ serialize(files)
60
+ puts " Finished parsing files in #{Time.new - start_time} seconds.\n\n"
61
+ end
62
+
63
+
64
+ start_time = Time.new
65
+ data = deserialize(@source_files)
66
+ root = Treemaker.new(data).root
67
+ puts " Building documentation tree. Finished in #{Time.new - start_time} seconds.\n\n"
68
+
69
+ start_time = Time.new
70
+ puts " Generating documentation:"
71
+ @generator.new(root, @generator_options).render(@output_directory)
72
+ puts "\n Finished generating documentation in #{Time.new - start_time} seconds.\n\n"
73
+ end
74
+
75
+ private
76
+ def serialize_file(path)
77
+ serializer = @serializer.new
78
+ serializer.path = path
79
+ puts " Parsing #{path}..."
80
+ File.open(path) do |file|
81
+ @parser.new(file.read).parse.each do |fragment|
82
+ fragment.serialize(serializer)
83
+ end
84
+ end
85
+ serializer
86
+ end
87
+
88
+ def pdoc_file(path)
89
+ name = '.' << File.basename(path, '.js') << '.pdoc.yaml'
90
+ File.expand_path(File.join(File.dirname(path), name))
91
+ end
92
+ end
93
+
94
+ class Serializer
95
+ attr_accessor :path
96
+ def initialize
97
+ @doc_fragments = []
98
+ end
99
+
100
+ def <<(fragment)
101
+ fragment = "---\n#{fragment}"
102
+ fragment << "\nfile: #{path}"
103
+ @doc_fragments << fragment
104
+ end
105
+
106
+ def to_s
107
+ @doc_fragments.join("\n\n")
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,94 @@
1
+ module PDoc
2
+ class Treemaker
3
+ include Models
4
+
5
+ def initialize(doc_fragments = [])
6
+ methodized = []
7
+ doc_fragments.each do |attributes|
8
+ if attributes['methodized']
9
+ dups = attributes.dup
10
+ dups['id'] = methodize_id(dups['id'])
11
+ dups['type'] = 'instance method'
12
+ if dups['signatures']
13
+ dups['signatures'] = dups['signatures'].map do |s|
14
+ {
15
+ 'signature' => methodize_signature(s['signature']),
16
+ 'return_value' => s['return_value']
17
+ }
18
+ end
19
+ end
20
+ if dups['alias_of']
21
+ dups['alias_of'] = methodize_id(dups['alias_of'])
22
+ end
23
+ methodized << dups
24
+ i = instantiate_from(dups)
25
+ c = instantiate_from(attributes)
26
+ i.functionalized_self = c
27
+ c.methodized_self = i
28
+ else
29
+ instantiate_from(attributes)
30
+ end
31
+ end
32
+
33
+ doc_fragments.concat(methodized).each do |attributes|
34
+ if parent_id = attributes['parent_id']
35
+ parent = root.find(parent_id)
36
+ raise "Undocumented object: #{parent_id}." unless parent
37
+ else
38
+ parent = root
39
+ end
40
+ object = root.find(attributes['id'])
41
+ object.parent = parent
42
+ object.attach_to_parent(parent)
43
+
44
+ if superclass_id = attributes['superclass_id']
45
+ superclass = root.find(superclass_id)
46
+ raise "Undocumented object: #{superclass_id}." unless superclass
47
+ object.superclass = superclass
48
+ superclass.subclasses << object
49
+ end
50
+
51
+ if included = attributes['included']
52
+ included.each do |id|
53
+ mixin = root.find(id)
54
+ raise "Undocumented object: #{id}." unless mixin
55
+ object.included_mixins << mixin
56
+ end
57
+ end
58
+
59
+ if alias_of_id = attributes['alias_of']
60
+ alias_of = root.find(alias_of_id)
61
+ raise "Undocumented object: #{alias_of_id}." unless alias_of
62
+ object.alias = alias_of
63
+ alias_of.aliases << object
64
+ end
65
+ end
66
+ end
67
+
68
+ def instantiate_from(attributes)
69
+ arguments = attributes.delete('arguments')
70
+ signatures = attributes.delete('signatures')
71
+ object = Base.instantiate(attributes)
72
+ arguments.each { |a| Argument.new(a).attach_to_parent(object) } if arguments
73
+ signatures.each { |s| Signature.new(s).attach_to_parent(object) } if signatures
74
+ object.register_on(root.registry)
75
+ end
76
+
77
+ def methodize_signature(sig)
78
+ sig.sub(/\.([\w\d\$]+)\((.*?)(,\s*|\))/) do
79
+ first_arg = $2.to_s.strip
80
+ prefix = first_arg[-1, 1] == '[' ? '([' : '('
81
+ rest = $3 == ')' ? $3 : ''
82
+ "##{$1}#{prefix}#{rest}"
83
+ end
84
+ end
85
+
86
+ def methodize_id(id)
87
+ id.sub(/\.([^\.]+)$/) { "##{$1}" }
88
+ end
89
+
90
+ def root
91
+ @root ||= Root.new
92
+ end
93
+ end
94
+ end