docjs 0.2 → 0.2.1
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.
- data/README.md +14 -0
- data/bin/docjs +85 -46
- data/bin/docjs.rb +85 -46
- data/docjs.gemspec +2 -2
- data/docs/guides/CUSTOMIZE.md +90 -0
- data/lib/boot.rb +12 -2
- data/lib/code_object/base.rb +0 -4
- data/lib/code_object/converter.rb +10 -11
- data/lib/configs.rb +28 -0
- data/lib/document/document.rb +21 -0
- data/lib/dom/dom.rb +0 -9
- data/lib/generator/generator.rb +168 -53
- data/lib/helper/helper.rb +3 -0
- data/lib/parser/comment.rb +1 -1
- data/lib/parser/comment_parser.rb +8 -4
- data/lib/parser/meta_container.rb +5 -1
- data/lib/parser/parser.rb +36 -10
- data/lib/processor.rb +70 -38
- data/lib/renderer.rb +100 -1
- data/lib/thor.rb +2 -0
- data/lib/token/container.rb +9 -5
- data/lib/token/handler.rb +1 -3
- data/lib/token/token.rb +2 -0
- data/templates/generators/api_index_generator.rb +1 -0
- data/templates/generators/api_pages_generator.rb +2 -0
- data/templates/generators/docs_generator.rb +2 -0
- data/templates/generators/json_generator.rb +16 -0
- data/templates/helpers/template.rb +24 -7
- data/templates/resources/css/application.css +18 -3
- data/templates/resources/scss/_header.scss +2 -2
- data/templates/resources/scss/_helpers.scss +3 -2
- data/templates/resources/scss/application.scss +15 -0
- data/test/parser/intelligent_skip_until.rb +10 -0
- data/test/parser/parser.rb +44 -0
- metadata +50 -47
data/lib/boot.rb
CHANGED
@@ -11,9 +11,18 @@ require_relative 'code_object/base'
|
|
11
11
|
require_relative 'dom/dom'
|
12
12
|
require_relative 'processor'
|
13
13
|
|
14
|
+
# `#setup_application` is called during the initialization process of DocJs within {DocJs#docjs}
|
15
|
+
#
|
16
|
+
# 
|
17
|
+
#
|
18
|
+
# It is responsible to configure the two application-wide Singleton Objects {Logger} and {Configs}
|
19
|
+
# and fill {Configs} with the given commandline arguments.
|
20
|
+
#
|
21
|
+
# If the user is using it's own custom templates (see {file:CUSTOMIZE.md}) those templates will be
|
22
|
+
# included before the processing can begin.
|
14
23
|
def setup_application(options = {})
|
15
24
|
|
16
|
-
#
|
25
|
+
# Initialize Logger
|
17
26
|
Logger.setup :logfile => (options[:logfile] && File.expand_path(options[:logfile], Dir.pwd)),
|
18
27
|
:level => (options[:loglevel] || :info).to_sym
|
19
28
|
|
@@ -21,10 +30,11 @@ def setup_application(options = {})
|
|
21
30
|
|
22
31
|
# Process option-values and store them in our Configs-object
|
23
32
|
Configs.set :options => options, # Just store the options for now
|
33
|
+
|
34
|
+
# Set the paths
|
24
35
|
:wdir => Dir.pwd, # The current working directory
|
25
36
|
:output => File.absolute_path(options[:output]),
|
26
37
|
:templates => File.absolute_path(options[:templates]),
|
27
|
-
:includes => (options[:includes] && File.absolute_path(options[:includes])),
|
28
38
|
:files => (options[:files] && options[:files].map {|path| Dir.glob(path) }.flatten),
|
29
39
|
:docs => (options[:docs] && options[:docs].map {|path| Dir.glob(path) }.flatten)
|
30
40
|
|
data/lib/code_object/base.rb
CHANGED
@@ -2,8 +2,6 @@ require_relative 'exceptions'
|
|
2
2
|
|
3
3
|
module CodeObject
|
4
4
|
|
5
|
-
# here the dependencies to {Dom::Node} and {Parser::Comment} should be described
|
6
|
-
#
|
7
5
|
# Converts a comment to a code_object and therefor is included in {Parser::Comment}
|
8
6
|
module Converter
|
9
7
|
|
@@ -11,7 +9,7 @@ module CodeObject
|
|
11
9
|
|
12
10
|
def to_code_object
|
13
11
|
|
14
|
-
# 1. Create a new CodeObject from Type-Token like @function
|
12
|
+
# 1. Create a new CodeObject from Type-Token like @function -> CodeObject::Function
|
15
13
|
@code_object = find_type_for(@tokenlines) or return nil
|
16
14
|
|
17
15
|
# join all documentation-contents and make them one text again
|
@@ -51,16 +49,17 @@ module CodeObject
|
|
51
49
|
|
52
50
|
if types.size > 1
|
53
51
|
raise CodeObject::MultipleTypeDeclarations.new, "Wrong number of TypeDeclarations: #{types}"
|
54
|
-
elsif types.size ==
|
52
|
+
elsif types.size == 1
|
53
|
+
type = types.first
|
54
|
+
|
55
|
+
# Get Class and instantiate it with content
|
56
|
+
klass = available_types[type.token]
|
57
|
+
return klass.new(type.content)
|
58
|
+
|
59
|
+
else
|
55
60
|
# it's not possible to create instance
|
56
61
|
return nil
|
57
|
-
end
|
58
|
-
|
59
|
-
type = types.first
|
60
|
-
|
61
|
-
# Get Class and instantiate it with content
|
62
|
-
klass = available_types[type.token]
|
63
|
-
klass.new(type.content)
|
62
|
+
end
|
64
63
|
end
|
65
64
|
end
|
66
65
|
end
|
data/lib/configs.rb
CHANGED
@@ -1,3 +1,31 @@
|
|
1
|
+
# Systemwide Singleton, which can be used to store global configurations, like paths or some other
|
2
|
+
# settings
|
3
|
+
#
|
4
|
+
# @example Usage
|
5
|
+
# Configs.set :foo, 123
|
6
|
+
# Configs.foo #=> 123
|
7
|
+
#
|
8
|
+
# Configs.set :foo => 456, :bar => "Hello World"
|
9
|
+
# Configs.foo #=> 456
|
10
|
+
# Configs.bar #=> "Hello World"
|
11
|
+
#
|
12
|
+
# Configs.baz #=> nil
|
13
|
+
#
|
14
|
+
# @example List all configs
|
15
|
+
# Configs.attributes #=> { :foo => 456, :bar => "Hello World" }
|
16
|
+
#
|
17
|
+
# @example Real dump of Configs, after setting up DocJs
|
18
|
+
# Configs.attributes #=> [:root, :options, :wdir, :output, :templates, :files, :docs]
|
19
|
+
#
|
20
|
+
# Configs.root #=> #<Pathname:/path/to/application/root>
|
21
|
+
# Configs.options #=> {:files=>["test/js-files/core-doc.js"], :docs=>["test/docs/*.md"],
|
22
|
+
# # :output=>"out", :templates=>#<Pathname:/path/to/templates>,
|
23
|
+
# # :appname=>"Doc.js", :loglevel=>"debug"}
|
24
|
+
# Configs.wdir #=> "/path/to/working/directory"
|
25
|
+
# Configs.output #=> "/path/to/output/directory"
|
26
|
+
# Configs.templates #=> "/path/to/used/template/directory"
|
27
|
+
# Configs.files #=> ["test/js-files/core-doc.js"]
|
28
|
+
# Configs.docs #=> ["test/docs/README.md", "test/docs/README.CONCEPT.md"]
|
1
29
|
module Configs
|
2
30
|
|
3
31
|
def self.set(sym_or_hash, value = nil)
|
data/lib/document/document.rb
CHANGED
@@ -2,6 +2,27 @@ require_relative '../dom/dom'
|
|
2
2
|
|
3
3
|
module Document
|
4
4
|
|
5
|
+
# Document is used to represent Markdown-Files (which should provied further help to your
|
6
|
+
# generated docs)
|
7
|
+
# Each given Markdown-File is converted in a {Document::Document} and then added to {Dom.docs}
|
8
|
+
# Like the {file:USE.md#Namespacing namespacing} in JavaScript-Comments there is a
|
9
|
+
# naming-convention for Markdown-files if you wish to store them in a tree-like structure.
|
10
|
+
#
|
11
|
+
# docs/README.md
|
12
|
+
# docs/README.CONCEPT.md
|
13
|
+
# docs/README.ARCHITECTURE.md
|
14
|
+
#
|
15
|
+
# will result in a tree:
|
16
|
+
#
|
17
|
+
# Dom.docs
|
18
|
+
# |
|
19
|
+
# README
|
20
|
+
# / \
|
21
|
+
# CONCEPT ARCHITECTURE
|
22
|
+
#
|
23
|
+
# @todo it would be much nicer, if a directory is provided in the CLI (like :docs => "/my/docs")
|
24
|
+
# that this tree-structure is reconstructed from the directory-structure. Naming files like
|
25
|
+
# `My.Awesome.File.md` is not that elegant.
|
5
26
|
class Document
|
6
27
|
|
7
28
|
include Dom::Node
|
data/lib/dom/dom.rb
CHANGED
@@ -11,10 +11,6 @@ require_relative 'exceptions'
|
|
11
11
|
# 1. {Dom::NoDoc Not documented nodes} that contain other nodes
|
12
12
|
# 2. {Dom::Node Documented nodes}, that contain other nodes
|
13
13
|
# 3. Leafs of the tree, without children. (Those leafs have to be {Dom::Node documented nodes})
|
14
|
-
#
|
15
|
-
# The architecure of the Dom looks pretty much like this:
|
16
|
-
#
|
17
|
-
# 
|
18
14
|
#
|
19
15
|
# Take the following code-sample:
|
20
16
|
#
|
@@ -82,11 +78,6 @@ require_relative 'exceptions'
|
|
82
78
|
#
|
83
79
|
# Dom.add_node != Dom.root.add_node
|
84
80
|
#
|
85
|
-
# For the example above the full UML-Graph, including the root-node, could look
|
86
|
-
# like:
|
87
|
-
#
|
88
|
-
# 
|
89
|
-
#
|
90
81
|
# @example Adding some Nodes
|
91
82
|
# o1 = CodeObject::Object.new "foo"
|
92
83
|
# o2 = CodeObject::Object.new "poo"
|
data/lib/generator/generator.rb
CHANGED
@@ -4,9 +4,84 @@ require_relative '../helper/helper'
|
|
4
4
|
|
5
5
|
module Generator
|
6
6
|
|
7
|
+
# If you already familiar with Ruby on Rails: Generators are pretty much like Controllers in Rails.
|
8
|
+
# That's like in Rails:
|
9
|
+
#
|
10
|
+
# - They use the existing data-model (The {Dom} in our case)
|
11
|
+
# - They start the rendering process in a view, by calling {Renderer#render render}.
|
12
|
+
# - If you want to make use of data in a view, you can store it in an instance-variable, like `@nodes`
|
13
|
+
# - Helpers are included in the generator, so you can utilize their messages in views
|
14
|
+
#
|
15
|
+
# The major difference between controllers in Rails and generators in DocJs is, that DocJs triggers
|
16
|
+
# all generators one after another and there is no real interaction between the views and the
|
17
|
+
# generator.
|
18
|
+
#
|
19
|
+
# In other words, after collecting all necessary informations about the JavaScript-Files and
|
20
|
+
# Markdown-Documents DocJs uses the Generators to create the final output.
|
21
|
+
#
|
22
|
+
# @example a simple generator
|
23
|
+
# module Generator
|
24
|
+
# class MyTestGenerator < Generator
|
25
|
+
# # For more information about those methods, see section Generator-Specification methods
|
26
|
+
# describe 'does awesome things'
|
27
|
+
# layout 'application'
|
28
|
+
# start_method :go
|
29
|
+
# templates '/views/special_ones'
|
30
|
+
#
|
31
|
+
# protected
|
32
|
+
#
|
33
|
+
# def go
|
34
|
+
# in_context Dom.root do
|
35
|
+
# @elements = []
|
36
|
+
# Dom.root.each_child do |child|
|
37
|
+
# @elements << child unless child.is_a? Dom::NoDoc
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# render 'my_view', :to_file => 'output_file.html'
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# The following image should help you to get a general overview, how the components of DocJs interact:
|
47
|
+
#
|
48
|
+
# 
|
49
|
+
#
|
50
|
+
# One may notice, that {Renderer} and {Generator::Generator} are not that separable, as shown in this
|
51
|
+
# image. In fact the concrete Generator (like {Generator::ApiIndexGenerator}) inherits from
|
52
|
+
# {Generator::Generator}, which in turn inherits from {Renderer}.
|
53
|
+
# So we've got an inheritence-chain like:
|
54
|
+
#
|
55
|
+
# Generator::ApiIndexGenerator < Generator::Generator < Renderer
|
56
|
+
#
|
57
|
+
# Helpers
|
58
|
+
# -------
|
59
|
+
# You can create your own helper functions, bundled in a custom helper-module. They automatically
|
60
|
+
# will be mixed in all Generators, as long as they match the following conditions:
|
61
|
+
#
|
62
|
+
# - Your module has to be a Submodule of Helper
|
63
|
+
# - Your code has to be included somewhere (i.e. `require 'my_helper'` in `application.rb`)
|
64
|
+
#
|
65
|
+
# For example your helper could look like:
|
66
|
+
#
|
67
|
+
# # TEMPLATE_PATH/helpers/my_helper.rb
|
68
|
+
# module Helper::MyHelper
|
69
|
+
# def my_greeter
|
70
|
+
# "Hello Woooorld"
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# # TEMPLATE_PATH/application.rb
|
75
|
+
# require_relative 'helpers/my_helper'
|
76
|
+
#
|
77
|
+
# Then you could use them in your Generator or in your Views
|
78
|
+
#
|
79
|
+
# # TEMPLATE_PATH/views/template.html.erb
|
80
|
+
# <h1><%= my_greeter %></h1>
|
7
81
|
class Generator < Renderer
|
8
82
|
|
9
83
|
def initialize
|
84
|
+
# At this point we pass the configurations to our Parent `Renderer`
|
10
85
|
super(Configs.templates + configs(:templates), configs(:layout))
|
11
86
|
|
12
87
|
# include all Helpers
|
@@ -18,6 +93,90 @@ module Generator
|
|
18
93
|
@_context = Dom.root
|
19
94
|
end
|
20
95
|
|
96
|
+
# @group Generator-Specification methods
|
97
|
+
|
98
|
+
# This description is used in the cli-command `docjs generators` to list all generators and their
|
99
|
+
# descriptions
|
100
|
+
#
|
101
|
+
# @param [String] desc A short description of this generators task
|
102
|
+
def self.describe(desc)
|
103
|
+
self.set_config(:description, desc.to_s)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Specifies which layout should be used to render in (Default is `nil`)
|
107
|
+
#
|
108
|
+
# @param [String] layout_view
|
109
|
+
def self.layout(layout_view)
|
110
|
+
unless layout_view.nil?
|
111
|
+
self.set_config(:layout, 'layout/' + layout_view)
|
112
|
+
else
|
113
|
+
self.set_config(:layout, nil)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Which method should be invoked, if generator is executed (Default is `:index`)
|
118
|
+
#
|
119
|
+
# @param [String, Symbol] method
|
120
|
+
def self.start_method(method)
|
121
|
+
self.set_config(:start_method, method.to_sym)
|
122
|
+
end
|
123
|
+
|
124
|
+
# The path to your views (Default is `/views`)
|
125
|
+
#
|
126
|
+
# You can use this method, to specify a special template path, for example if you want to use
|
127
|
+
# a subdirectory of your views, without always having to provide the full path in all `render`-calls
|
128
|
+
#
|
129
|
+
# @note the layout-path is always relative to your specified path (i.e. `layout 'application'`
|
130
|
+
# and `templates 'my_custom'` will result in a required layout file with a path like
|
131
|
+
# `my_custom/layout/application.html.erb`
|
132
|
+
#
|
133
|
+
# @param [String] path_to_views Relative path from your scaffolded template-directory, but with
|
134
|
+
# a leading `/`, like `/views/classes`
|
135
|
+
def self.templates(path_to_views)
|
136
|
+
self.set_config(:templates, path_to_views)
|
137
|
+
end
|
138
|
+
|
139
|
+
# @note not neccesarily needed, because all Helpers are included by default
|
140
|
+
#
|
141
|
+
# Can be used to include a helper in a Generator
|
142
|
+
def self.use(helper_module)
|
143
|
+
include helper_module
|
144
|
+
end
|
145
|
+
|
146
|
+
# @group Context manipulation- and access-methods
|
147
|
+
|
148
|
+
# Modyfies the Dom-resolution-context {#context} to `new_context`, while in `&block`. After
|
149
|
+
# leaving the block, the context will be switched back.
|
150
|
+
#
|
151
|
+
# @param [Dom::Node] new_context The new context
|
152
|
+
# @yield block The block, in which the context is valid
|
153
|
+
def in_context(new_context, &block)
|
154
|
+
old_context = @_context
|
155
|
+
@_context = new_context
|
156
|
+
yield
|
157
|
+
@_context = old_context
|
158
|
+
end
|
159
|
+
|
160
|
+
# Retreives the current Dom-resolution-context, which can be specified by using {#in_context}
|
161
|
+
#
|
162
|
+
# @return [Dom::Node] the context, to which all relative nodes should be resolved
|
163
|
+
def context
|
164
|
+
@_context
|
165
|
+
end
|
166
|
+
|
167
|
+
# Resolves a nodename in the specified context, by using {Dom::Node#resolve} on it.
|
168
|
+
#
|
169
|
+
# @param [String] nodename
|
170
|
+
# @return [Dom::Node, nil]
|
171
|
+
# @see Dom::Node#resolve
|
172
|
+
def resolve(nodename)
|
173
|
+
@_context.resolve nodename
|
174
|
+
end
|
175
|
+
|
176
|
+
# @group System-Methods
|
177
|
+
|
178
|
+
# Calls always the specified `:start_method` on this Generator. (Default for :start_method is
|
179
|
+
# 'index')
|
21
180
|
def perform
|
22
181
|
|
23
182
|
unless self.respond_to? configs(:start_method)
|
@@ -27,19 +186,17 @@ module Generator
|
|
27
186
|
self.send configs(:start_method)
|
28
187
|
end
|
29
188
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
189
|
+
# Is used by {DocJs#generators} to provide a list of all generators and their descriptions
|
190
|
+
#
|
191
|
+
# @return [String] description, which has been previously entered using `.describe`
|
34
192
|
def self.description
|
35
193
|
configs(:description)
|
36
194
|
end
|
37
195
|
|
38
|
-
#
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
196
|
+
# Returns all Generators, by finding all constants in the Generator-Module and filtering them
|
197
|
+
# for classes with parent {Generator::Generator}.
|
198
|
+
#
|
199
|
+
# @return [Array<Generator>]
|
43
200
|
def self.all
|
44
201
|
# Otherwise we don't get the global Generator-Module
|
45
202
|
gen_module = Object.const_get(:Generator)
|
@@ -50,29 +207,6 @@ module Generator
|
|
50
207
|
|
51
208
|
protected
|
52
209
|
|
53
|
-
# @group Generator-Specification methods
|
54
|
-
|
55
|
-
def self.describe(desc)
|
56
|
-
self.set_config(:description, desc.to_s)
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.layout(layout_view)
|
60
|
-
unless layout_view.nil?
|
61
|
-
self.set_config(:layout, 'layout/' + layout_view)
|
62
|
-
else
|
63
|
-
self.set_config(:layout, nil)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def self.templates(path_to_templates)
|
68
|
-
self.set_config(:templates, path_to_templates)
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.start_method(method)
|
72
|
-
self.set_config(:start_method, method.to_sym)
|
73
|
-
end
|
74
|
-
|
75
|
-
|
76
210
|
# @group helper methods to make usage of class-variables work in **inheriting** classes
|
77
211
|
|
78
212
|
def self.configs(attribute)
|
@@ -82,14 +216,14 @@ module Generator
|
|
82
216
|
defaults = {:templates => '/views',
|
83
217
|
:layout => nil,
|
84
218
|
:description => 'No description given.',
|
85
|
-
:start_method => :
|
219
|
+
:start_method => :index }
|
86
220
|
|
87
221
|
if self.class_variable_defined? key
|
88
222
|
self.class_variable_get(key)
|
89
223
|
else
|
90
224
|
defaults[attribute.to_sym]
|
91
225
|
end
|
92
|
-
end
|
226
|
+
end
|
93
227
|
|
94
228
|
# the instance equivalent to get the class-variable of the **inheriting** class
|
95
229
|
def configs(*args)
|
@@ -102,24 +236,5 @@ module Generator
|
|
102
236
|
self.class_variable_set(key, value)
|
103
237
|
end
|
104
238
|
|
105
|
-
|
106
|
-
# @group context manipulation and access methods
|
107
|
-
|
108
|
-
# maybe we can use this later on, while linking
|
109
|
-
def in_context(new_context, &block)
|
110
|
-
old_context = @_context
|
111
|
-
@_context = new_context
|
112
|
-
yield
|
113
|
-
@_context = old_context
|
114
|
-
end
|
115
|
-
|
116
|
-
def context
|
117
|
-
@_context
|
118
|
-
end
|
119
|
-
|
120
|
-
def resolve(nodename)
|
121
|
-
@_context.resolve nodename
|
122
|
-
end
|
123
|
-
|
124
239
|
end
|
125
240
|
end
|
data/lib/helper/helper.rb
CHANGED
@@ -103,6 +103,9 @@ module Helper
|
|
103
103
|
# @param [Hash] opts
|
104
104
|
# @option opts [Numeric] :firstline (1) The line-numeration will start with that number
|
105
105
|
# @option opts [String] :class ("block") A optional css-class which can be added
|
106
|
+
#
|
107
|
+
# @see http://alexgorbatchev.com/SyntaxHighlighter
|
108
|
+
#
|
106
109
|
# @return [String] the html-code-element
|
107
110
|
def code(source, opts = {})
|
108
111
|
|