docjs 0.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.
Files changed (109) hide show
  1. data/CONCEPT.md +80 -0
  2. data/DOCUMENTATION.md +41 -0
  3. data/LICENSE.md +19 -0
  4. data/README.md +19 -0
  5. data/RENDERING.md +8 -0
  6. data/bin/docjs +190 -0
  7. data/docjs.gemspec +32 -0
  8. data/lib/boot.rb +34 -0
  9. data/lib/code_object/base.rb +48 -0
  10. data/lib/code_object/converter.rb +48 -0
  11. data/lib/code_object/exceptions.rb +5 -0
  12. data/lib/code_object/function.rb +84 -0
  13. data/lib/code_object/object.rb +18 -0
  14. data/lib/code_object/type.rb +43 -0
  15. data/lib/configs.rb +53 -0
  16. data/lib/document/document.rb +25 -0
  17. data/lib/dom/dom.rb +188 -0
  18. data/lib/dom/exceptions.rb +12 -0
  19. data/lib/dom/no_doc.rb +26 -0
  20. data/lib/dom/node.rb +415 -0
  21. data/lib/helper/helper.rb +120 -0
  22. data/lib/helper/linker.rb +130 -0
  23. data/lib/logger.rb +49 -0
  24. data/lib/parser/comment.rb +69 -0
  25. data/lib/parser/comment_parser.rb +90 -0
  26. data/lib/parser/exceptions.rb +6 -0
  27. data/lib/parser/meta_container.rb +20 -0
  28. data/lib/parser/parser.rb +269 -0
  29. data/lib/processor.rb +123 -0
  30. data/lib/renderer.rb +108 -0
  31. data/lib/tasks/render_task.rb +112 -0
  32. data/lib/thor.rb +27 -0
  33. data/lib/token/container.rb +84 -0
  34. data/lib/token/exceptions.rb +6 -0
  35. data/lib/token/handler.rb +242 -0
  36. data/lib/token/token.rb +46 -0
  37. data/templates/application.rb +14 -0
  38. data/templates/helpers/template.rb +66 -0
  39. data/templates/resources/css/.sass-cache/98c121fba905284c2c8ca6220fe3c590e5c9ec19/application.scssc +0 -0
  40. data/templates/resources/css/application.css +836 -0
  41. data/templates/resources/img/arrow_down.png +0 -0
  42. data/templates/resources/img/arrow_right.png +0 -0
  43. data/templates/resources/img/arrow_up.png +0 -0
  44. data/templates/resources/img/bullet_toggle_minus.png +0 -0
  45. data/templates/resources/img/bullet_toggle_plus.png +0 -0
  46. data/templates/resources/img/constructor.png +0 -0
  47. data/templates/resources/img/function.png +0 -0
  48. data/templates/resources/img/object.png +0 -0
  49. data/templates/resources/img/page.png +0 -0
  50. data/templates/resources/img/prototype.png +0 -0
  51. data/templates/resources/img/tag.png +0 -0
  52. data/templates/resources/js/application.js +318 -0
  53. data/templates/resources/js/jcore.js +129 -0
  54. data/templates/resources/js/jquery.cookie.js +92 -0
  55. data/templates/resources/js/jquery.js +16 -0
  56. data/templates/resources/js/jquery.tooltip.js +77 -0
  57. data/templates/resources/js/jquery.treeview.js +238 -0
  58. data/templates/resources/scss/_footer.scss +10 -0
  59. data/templates/resources/scss/_header.scss +184 -0
  60. data/templates/resources/scss/_helpers.scss +91 -0
  61. data/templates/resources/scss/_print.scss +20 -0
  62. data/templates/resources/scss/_resets.scss +132 -0
  63. data/templates/resources/scss/_tooltip.scss +26 -0
  64. data/templates/resources/scss/application.scss +442 -0
  65. data/templates/tasks/api_index_task.rb +26 -0
  66. data/templates/tasks/docs_task.rb +33 -0
  67. data/templates/tasks/json_data_task.rb +55 -0
  68. data/templates/tasks/typed_task.rb +54 -0
  69. data/templates/tokens/tokens.rb +22 -0
  70. data/templates/types/prototype.rb +20 -0
  71. data/templates/views/api_index.html.erb +21 -0
  72. data/templates/views/doc_page.html.erb +11 -0
  73. data/templates/views/function/_detail.html.erb +8 -0
  74. data/templates/views/function/index.html.erb +53 -0
  75. data/templates/views/index.html.erb +0 -0
  76. data/templates/views/layout/application.html.erb +73 -0
  77. data/templates/views/layout/json.html.erb +3 -0
  78. data/templates/views/object/index.html.erb +63 -0
  79. data/templates/views/tokens/_default.html.erb +11 -0
  80. data/templates/views/tokens/_default_token.html.erb +19 -0
  81. data/templates/views/tokens/_example.html.erb +2 -0
  82. data/templates/views/tokens/_examples.html.erb +1 -0
  83. data/test/code_object/converter.rb +78 -0
  84. data/test/code_object/prototype.rb +70 -0
  85. data/test/configs.rb +65 -0
  86. data/test/docs/README.CONCEPT.md +83 -0
  87. data/test/docs/README.md +14 -0
  88. data/test/dom/dom.absolute_nodes.rb +40 -0
  89. data/test/dom/dom.rb +72 -0
  90. data/test/dom/node.rb +53 -0
  91. data/test/integration/converter.rb +72 -0
  92. data/test/integration/parser_factory.rb +28 -0
  93. data/test/interactive.rb +7 -0
  94. data/test/js-files/absolute.js +11 -0
  95. data/test/js-files/comments_in_strings.js +31 -0
  96. data/test/js-files/core-doc-relative.js +77 -0
  97. data/test/js-files/core-doc.js +145 -0
  98. data/test/js-files/nested.js +34 -0
  99. data/test/js-files/nested_with_strings.js +35 -0
  100. data/test/js-files/prototype.js +33 -0
  101. data/test/js-files/simple.js +17 -0
  102. data/test/js-files/tokens.js +32 -0
  103. data/test/parser/comments_in_strings.rb +51 -0
  104. data/test/parser/intelligent_skip_until.rb +110 -0
  105. data/test/parser/parser.rb +273 -0
  106. data/test/rspec_helper.rb +23 -0
  107. data/test/token/handler.rb +136 -0
  108. data/test/token/tokens.rb +52 -0
  109. metadata +184 -0
@@ -0,0 +1,112 @@
1
+ require_relative '../renderer'
2
+ require_relative '../dom/dom'
3
+ require_relative '../helper/helper'
4
+
5
+ module Tasks
6
+
7
+ class RenderTask < Renderer
8
+
9
+ include Helper::Helper
10
+
11
+ def initialize
12
+ super(Configs.templates + configs(:templates), configs(:layout))
13
+
14
+ # Set Global Context to Dom's root node
15
+ @_context = Dom.root
16
+ end
17
+
18
+ def perform
19
+
20
+ unless self.respond_to? configs(:start_method)
21
+ raise Exception, "#{self.class} needs to implement specified start-method '#{configs(:start_method)}'"
22
+ end
23
+
24
+ self.send configs(:start_method)
25
+ end
26
+
27
+ def context
28
+ @_context
29
+ end
30
+
31
+ def self.description
32
+ configs(:description)
33
+ end
34
+
35
+ def self.use(helper_module)
36
+ self.include helper_module
37
+ end
38
+
39
+ protected
40
+
41
+ # @group Task-Specification methods
42
+
43
+ def self.describe(desc)
44
+ self.set_config(:description, desc.to_s)
45
+ end
46
+
47
+ def self.layout(layout_view)
48
+ unless layout_view.nil?
49
+ self.set_config(:layout, 'layout/' + layout_view)
50
+ else
51
+ self.set_config(:layout, nil)
52
+ end
53
+ end
54
+
55
+ def self.templates(path_to_templates)
56
+ self.set_config(:templates, path_to_templates)
57
+ end
58
+
59
+ def self.start_method(method)
60
+ self.set_config(:start_method, method.to_sym)
61
+ end
62
+
63
+
64
+ # @group helper methods to make usage of class-variables work in **inheriting** classes
65
+
66
+ def self.configs(attribute)
67
+
68
+ key = "@@_configs_#{attribute.to_s}".to_sym
69
+
70
+ defaults = {:templates => '/views',
71
+ :layout => nil,
72
+ :description => 'No description given.',
73
+ :start_method => :perform_task }
74
+
75
+ if self.class_variable_defined? key
76
+ self.class_variable_get(key)
77
+ else
78
+ defaults[attribute.to_sym]
79
+ end
80
+ end
81
+
82
+ # the instance equivalent to get the class-variable of the **inheriting** class
83
+ def configs(*args)
84
+ self.class.configs(*args)
85
+ end
86
+
87
+ def self.set_config(attribute, value)
88
+ key = "@@_configs_#{attribute.to_s}".to_sym
89
+
90
+ self.class_variable_set(key, value)
91
+ end
92
+
93
+
94
+ # @group context manipulation and access methods
95
+
96
+ # maybe we can use this later on, while linking
97
+ def in_context(new_context, &block)
98
+ old_context = @_context
99
+ @_context = new_context
100
+ yield
101
+ @_context = old_context
102
+ end
103
+
104
+ def context
105
+ @_context
106
+ end
107
+
108
+ def resolve(nodename)
109
+ @_context.resolve nodename
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,27 @@
1
+ class Thor
2
+
3
+ protected
4
+
5
+ # @param [Hash<Hash>] options
6
+ def self.set_options(options)
7
+ options.each {|name, hash| method_option(name, hash) }
8
+ end
9
+
10
+ # Types
11
+ # :boolean - is parsed as --option or --option=true
12
+ # :string - is parsed as --option=VALUE
13
+ # :numeric - is parsed as --option=N
14
+ # :array - is parsed as --option=one two three
15
+ # :hash - is parsed as --option=name:string age:integer
16
+ #
17
+ # @note options declared in a build.yml will override command-line ones
18
+ # @return [Hash] options
19
+ def merge_options(options, filename)
20
+ require 'yaml' # only load yaml if we are reading from file
21
+ configs = YAML.load_file(filename)
22
+ merged = {}
23
+ options.each { |name, value| merged[name.to_sym] = configs[name] || value }
24
+ merged
25
+ end
26
+
27
+ end
@@ -0,0 +1,84 @@
1
+ # ../data.img#1811394:1
2
+ require_relative 'exceptions'
3
+ require_relative 'handler'
4
+
5
+ module Token
6
+
7
+ module Container
8
+
9
+ def initialize
10
+ super
11
+ @tokens = {}
12
+ end
13
+
14
+ # provides access to tokens, through token identifier
15
+ #
16
+ # @example
17
+ # obj.token :public
18
+ # #=> #<struct Token::Handler::Token content=nil>
19
+ #
20
+ # @param [String, Symbol] tokenname the tokenidentifier like :public
21
+ # @return [Token] the token with it's content
22
+ def token(tokenname)
23
+ @tokens[tokenname.to_sym]
24
+ end
25
+
26
+ # @return [Hash<Symbol, Array<Token::Token>>] all tokens of this container
27
+ def tokens
28
+ @tokens
29
+ end
30
+
31
+ # @overload add_token(tokenid, token)
32
+ # @param [Symbol] tokenid
33
+ # @param [Token::Token] token
34
+ #
35
+ # @overload add_token(token)
36
+ # @param [Token::Token] token
37
+ def add_token(tokenid_or_token, token=nil)
38
+
39
+ unless token.nil?
40
+ tokenid = tokenid_or_token
41
+ else
42
+ tokenid = tokenid_or_token.token
43
+ token = tokenid_or_token
44
+ end
45
+
46
+ @tokens[tokenid] ||= []
47
+ @tokens[tokenid] << token
48
+ end
49
+
50
+ # @param [Parser::Tokenline] tokenline consisting of :token and :content
51
+ # then calls matching tokenhandler (if exists) with data in `this`-context
52
+ # @todo only raise error, if config is set to whiny
53
+ def process_token(tokenline)
54
+
55
+ # try to find matching tokenklass for token i.e. Token::Token::ParamToken for :param
56
+ begin
57
+ tokenklass = Token.const_get "#{tokenline.token.capitalize.to_s}Token"
58
+ instance_exec(tokenklass, tokenline.content, &(tokenklass.handler))
59
+ rescue Exception => error
60
+ raise NoTokenHandler.new("No Tokenhandler for: @#{tokenline.token}
61
+ This is no big deal. You can add your custom tokenhandler for @#{tokenline.token} by adding the following line to your included ruby-file:
62
+
63
+ Token::Handler.register :#{tokenline.token} # optionally add a tokenhandler or target-area (See documentation for more infos)
64
+
65
+ After this using '@#{tokenline.token}' in your documentation is no problem...\n\n" + error.message)
66
+ end
67
+ end
68
+
69
+ # Plural version of {#process_token}
70
+ #
71
+ # @param [Array<Parser::Tokenline>] tokenlines
72
+ def process_tokens(tokenlines)
73
+ tokenlines.each {|tokenline| process_token(tokenline) }
74
+ end
75
+
76
+ protected
77
+
78
+ def has_to_be_a(type)
79
+ raise WrongType.new("Not a valid Type: '#{type}'") unless self.is_a? type
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,6 @@
1
+ module Token
2
+
3
+ class NoTokenHandler < Exception; end
4
+ class WrongType < Exception; end
5
+
6
+ end
@@ -0,0 +1,242 @@
1
+ # ../data.img#1799432:1 && #1858562:1
2
+ require_relative 'token'
3
+
4
+ # This module contains all required mixins and modules to register customized
5
+ # tokens, that will be further processed and added to the {CodeObject::Base}.
6
+ #
7
+ # The {CodeObject::Converter converter} starts the {Parser::Tokenline tokenline}-processing, by calling
8
+ # the mixed-in function {Token::Container#process_token}.
9
+ #
10
+ # ![Token UML](../uml/Tokens.svg)
11
+ #
12
+ # The illustration above shows the **two modules** included in {Token}:
13
+ #
14
+ # 1. {Token::Handler}, which can be used to register new token-handlers.
15
+ # 2. {Token::Container}, which is included in {CodeObject::Base} to add
16
+ # individual token-{Token::Container#add_token container} and
17
+ # {Token::Container#process_token -processing} functionality to all CodeObjects.
18
+ #
19
+ module Token
20
+
21
+ # @note This module is **not** built to be used as a mixin! It should be seen as
22
+ # a **global singleton** instead.
23
+ #
24
+ # The {Token::Handler} is meant to be the global store for all Token-handlers.
25
+ # Token-handlers are needed to process incoming {Parser::Tokenline tokenlines}
26
+ # of each comment. The following sample, shows a comment including a token line:
27
+ #
28
+ # /**
29
+ # * @token this is a default tokenline
30
+ # */
31
+ #
32
+ # This Comment will be transformed by the {Parser::CommentParser} into a
33
+ # {Parser::Tokenline tokenline} like the following:
34
+ #
35
+ # puts my_tokenline
36
+ # #=> <struct Parser::Tokenline token="token", content="this is a default tokenline">
37
+ #
38
+ # After creating the right type of {CodeObject::Base CodeObjects} (either a
39
+ # {CodeObject::Object Object} or {CodeObject::Object Function}) the
40
+ # {CodeObject::Converter converter} will trigger the conversion to a 'real'
41
+ # {Token::Handler::Token token} by calling {Token::Container#process_token #process_token}
42
+ # on the CodeObject.
43
+ #
44
+ # code_object.process_token(my_tokenline)
45
+ # code_object.token(:token)
46
+ # #=> [#<struct Token::Handler::Token content="this is a default tokenline">]
47
+ #
48
+ # Tokens are always stored in an array to make multiple usage in one comment
49
+ # possible.
50
+ #
51
+ # @see .register
52
+ module Handler
53
+
54
+ ALL = /./m
55
+ NO_BR = /((?!\n)\s)/
56
+ IDENTIFIER = /(?:[^\s])*/
57
+ TYPELIST = /\[(?<types>#{IDENTIFIER}(?:,#{NO_BR}*#{IDENTIFIER})*)\]/
58
+
59
+ # Token with type and content
60
+ TOKEN_W_TYPE = /#{NO_BR}*#{TYPELIST}#{NO_BR}*(?<content>#{ALL}*)/
61
+
62
+ # Token with type, name and content
63
+ TOKEN_W_TYPE_NAME = /^#{NO_BR}*
64
+ #{TYPELIST}#{NO_BR}*
65
+ (?<name>#{IDENTIFIER})
66
+ #{NO_BR}*
67
+ (?<content>#{ALL}*)
68
+ /x
69
+
70
+ @@defaults = {
71
+ :text_only => ->(tokenklass, content) {
72
+ self.add_token tokenklass.new(:content => content)
73
+ },
74
+
75
+ :typed => ->(tokenklass, content) {
76
+ typestring, content = TOKEN_W_TYPE.match(content).captures
77
+ types = typestring.split /,\s*/
78
+
79
+ self.add_token tokenklass.new(:types => types, :content => content)
80
+ },
81
+
82
+ :typed_with_name => ->(tokenklass, content) {
83
+ typestring, name, content = TOKEN_W_TYPE_NAME.match(content).captures
84
+ types = typestring.split /,\s*/
85
+
86
+ self.add_token tokenklass.new(:name => name, :types => types, :content => content)
87
+ },
88
+
89
+ :named_multiline => ->(tokenklass, content) {
90
+ rows = content.split(/\n/)
91
+
92
+ # use first row as name
93
+ name = rows.shift.strip
94
+ content = rows.join("\n")
95
+
96
+ self.add_token tokenklass.new(:name => name, :content => content)
97
+ },
98
+
99
+ :noop => ->(tokenklass, content) {}
100
+ }
101
+ @@handlers = {}
102
+
103
+ # Attribute-Reader for all registered `@@handlers`
104
+ #
105
+ # @return [Hash<Symbol, Block>]
106
+ def self.handlers
107
+ @@handlers
108
+ end
109
+
110
+ # Registering a new Tokenhandler
111
+ # ==============================
112
+ # It is possible to register your own Tokenhandlers and therefore extend the
113
+ # capabilities of this documentation-program.
114
+ #
115
+ # There are different types of handlers which can be used:
116
+ #
117
+ # 1. Default-handler
118
+ # 2. A handler for Typed-Token
119
+ # 3. A handler for Named-Typed-Tokens
120
+ # 4. Your custom handler (see second overload)
121
+ #
122
+ #
123
+ # @overload self.register(tokenname, type=nil)
124
+ #
125
+ # The first three of the handlers above can be registered with this
126
+ # overload.
127
+ #
128
+ # The Default Handler
129
+ # -------------------
130
+ # The Default Header can be used for tokens like the one in the example above.
131
+ # Trying to add a token like `@token` without adding a handler, you may get
132
+ # an `exception` like:
133
+ #
134
+ # #=> Token::NoTokenHandler: No Tokenhandler for: token
135
+ # # from lib/token/container.rb:41:in process_token
136
+ #
137
+ # So we better register a handler for that token:
138
+ #
139
+ # Token::Handler.register :token
140
+ #
141
+ # As you can see **the second argument can be ommitted** to use a **default
142
+ # handler**. This default handler cannot parse typelists or tokennames, it
143
+ # only saves the content of the token to the struct {Token::Handler::Token Token}.
144
+ #
145
+ # This Default Handler is enough for tokens like `@todo` or `@note`. But for
146
+ # more complex Tokens we need some other handlers.
147
+ #
148
+ # Handler for Typed-Tokens
149
+ # ------------------------
150
+ # Typed tokens look like `@return [Foo, Bar] This is the description` - Additional
151
+ # to their **default content** they specify the possible Types.
152
+ #
153
+ # To register a typed-token, you only need to add a second argument:
154
+ #
155
+ # Token::Handler.register :return, :typed
156
+ #
157
+ # The {Token::Handler::TypedToken typed-token struct}, pretty much looks like
158
+ # the default one.
159
+ #
160
+ # #=> #<struct Token::Handler::TypedToken types=["Foo", "Bar"], content="This is the description\n">
161
+ #
162
+ # Handler for Typed-Named-Tokens
163
+ # ------------------------------
164
+ # They are much like **Typed-Token-Handlers**. They are needed for Tokenlines
165
+ # like `@param [String] my_param This is a param`. They are registered with
166
+ # `:typed_with_name` as the second argument:
167
+ #
168
+ # Token::Handler.register :param, :typed_with_name
169
+ #
170
+ # @param [String, Symbol] tokenname
171
+ # @param [:typed, :typed_with_name, nil] type
172
+ #
173
+ #
174
+ # @overload self.register(tokenname, &handler)
175
+ #
176
+ # Writing your own custom Token-Handler
177
+ # -------------------------------------
178
+ # By adding a block in the Tokenregistration you easily can build your own
179
+ # Tokenhandler:
180
+ #
181
+ # Token::Handler.register(:my_own) do |token_klass, stringcontent|
182
+ # # Do something with token_id and stringcontent
183
+ # # but don't forget to add the token like:
184
+ # self.add_token(token_klass.new(:content => stringcontent)
185
+ # end
186
+ #
187
+ # Because the token processing is done in the **context of the CodeObject** you
188
+ # can easily extend or manipulate the Objects.
189
+ #
190
+ # If you want to assure, that the object you are working on has a specific type
191
+ # (for example a Function) add the following line to your handler:
192
+ #
193
+ # has_to_be_a CodeObject::Function
194
+ #
195
+ # @param [String, Symbol] tokenname
196
+ # @yield [tokenklass, stringcontent] Your custom tokenhandler
197
+ #
198
+ def self.register(tokenname, options = {}, &handler)
199
+
200
+ tokenname = tokenname.to_sym
201
+
202
+ # search matching handler
203
+ if block_given?
204
+ # handler is already defined
205
+ elsif options[:handler] and @@defaults.include?(options[:handler])
206
+ handler = @@defaults[options[:handler]]
207
+ elsif options[:handler]
208
+ raise Exception, "#{type} has no registered Tokenhandler"
209
+ else
210
+ handler = @@defaults[:text_only]
211
+ end
212
+
213
+ # Dynamically create Class named TokennameToken
214
+ klass = Token.const_set "#{tokenname.to_s.capitalize}Token", Class.new(Token)
215
+
216
+ klass.process_options options.merge({
217
+
218
+ :token => tokenname,
219
+ :handler => handler
220
+
221
+ });
222
+
223
+ @@handlers[tokenname] = klass
224
+ end
225
+
226
+ # Remove a registered handler from the list
227
+ #
228
+ # @example
229
+ # Token::Handler.register :foo
230
+ # Token::Handler.unregister :foo
231
+ #
232
+ # @param [String, Symbol] tokenname
233
+ def self.unregister(tokenname)
234
+ @@handlers.delete(tokenname.to_sym)
235
+ end
236
+
237
+ def self.add_default_handler(name, &block)
238
+ @@defaults[name] = block;
239
+ end
240
+
241
+ end
242
+ end