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,12 @@
1
+ module Dom
2
+
3
+ class NodeAlreadyExists < Exception; end
4
+
5
+ class RelativePathInNoContext < Exception; end
6
+
7
+ class WrongPath < Exception; end
8
+
9
+ class NoNameInPath < Exception; end
10
+
11
+ class NoPathGiven < Exception; end
12
+ end
@@ -0,0 +1,26 @@
1
+ # ../data.img#1811401:1
2
+ require_relative 'node'
3
+ module Dom
4
+
5
+ # NoDoc is used by {Dom} and {Dom::Node} to preserve the correct hierachy of
6
+ # the tree, while inserting nodes with non existing parents.
7
+ #
8
+ # For example let's add the node 'foo.bar.baz' in our empty Dom. This will
9
+ # result in the following tree:
10
+ #
11
+ # -foo (NoDoc)
12
+ # -bar (NoDoc)
13
+ # -baz
14
+ #
15
+ # If a documented
16
+ class NoDoc
17
+ include Node
18
+
19
+ attr_reader :name
20
+
21
+ def initialize(name)
22
+ @name = name
23
+ super()
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,415 @@
1
+ # ../data.img#1780307:3
2
+ require_relative 'dom'
3
+ require_relative 'exceptions'
4
+
5
+ module Dom
6
+
7
+ # Node can be seen as an **aspect** or feature of another Object. Therefore it can
8
+ # be mixed in to add node-functionality to a class.
9
+ # Such functionality is used by {CodeObject::Base code-objects} and {Document::Document documents}.
10
+ #
11
+ # Instance Variables
12
+ # ------------------
13
+ # The following instance-variables will be set while including Dom::Node into
14
+ # your class:
15
+ #
16
+ # - `@name` (should be already set in your including class)
17
+ # - `@parent`
18
+ # - `@children`
19
+ #
20
+ # @example
21
+ # class MyObject
22
+ # include Dom::Node
23
+ #
24
+ # # The contructor of MyObject should call init_node
25
+ # def initialize(name)
26
+ # super
27
+ # @name = name
28
+ # end
29
+ # end
30
+ #
31
+ # # MyObject can now be used as a node within our Domtree
32
+ # @baz = MyObject.new 'Baz'
33
+ # @baz.add_node(MyObject.new 'foo')
34
+ # @baz.add_node(MyObject.new 'bar')
35
+ #
36
+ # # These Nodes get inserted into Dom, so it looks like
37
+ # Dom.print_tree
38
+ # #=>
39
+ # #-Baz
40
+ # # -foo
41
+ # # -bar
42
+ #
43
+ # @note including Class should implement instance-variable @name
44
+ # @see CodeObject::Base
45
+ # @see Dom
46
+ module Node
47
+
48
+ NS_SEP_STRING = '.'
49
+ NS_SEP = /#{Regexp.escape(NS_SEP_STRING)}/
50
+
51
+ NODENAME = /[0-9a-zA-Z$_]+/
52
+ LEAF = /^#{NS_SEP}(?<name>#{NODENAME})$/
53
+ ABSOLUTE = /^(?<first>#{NODENAME})(?<rest>(#{NS_SEP}#{NODENAME})*)$/
54
+ RELATIVE = /^#{NS_SEP}(?<first>#{NODENAME})(?<rest>(#{NS_SEP}#{NODENAME})*)$/
55
+
56
+
57
+ # @group Initialization
58
+
59
+ # The 'constructor' of {Dom::Node}. It initializes all required
60
+ # instance-variables (see {Dom::Node above}).
61
+ def initialize
62
+ super
63
+ @children, @parent = {}, nil
64
+ @name ||= "" # should be written by including class
65
+ end
66
+
67
+ # @group Traversing
68
+
69
+ # `node.parent` returns the parent {Dom::Node node}, if there is one.
70
+ # If no parent exists `nil` is returned. In this case `node` can be
71
+ # considered either as loose leave or root of the {Dom}.
72
+ #
73
+ # @return [Dom::Node] the parent node, if one exists
74
+ def parent
75
+ @parent
76
+ end
77
+
78
+
79
+ # searches all parents recursivly and returns an array, starting with the
80
+ # highest order parent (excluding the {Dom.root}) and ending with the
81
+ # immediate parent.
82
+ #
83
+ # @example
84
+ # o1 = CodeObject::Base.new :foo
85
+ # o2 = CodeObject::Base.new :bar, o1
86
+ # o3 = CodeObject::Base.new :baz, o2
87
+ #
88
+ # # no parents
89
+ # o1.parents #=> []
90
+ #
91
+ # # all parents
92
+ # o3.parents #=> [#<CodeObject::Base:foo>, #<CodeObject::Base:bar>]
93
+ #
94
+ # @return [Array<Dom::Node>] the associated parents
95
+ def parents
96
+ return [] if @parent.nil? or @parent.parent.nil?
97
+ @parent.parents << @parent
98
+ end
99
+
100
+
101
+ # Returns all immediately associated children of this `node`
102
+ #
103
+ # @return [Hash<Symbol, Dom::Node>]
104
+ def children
105
+ @children
106
+ end
107
+
108
+
109
+ # Get's the child of this node, which is identified by `path`
110
+ #
111
+ # @example childname
112
+ # Dom[:Core] #=> #<CodeObject::Object:Core @parent=__ROOT__ …>
113
+ # Dom['Core'] #=> #<CodeObject::Object:Core @parent=__ROOT__ …>
114
+ #
115
+ # @example path
116
+ # Dom['Core.logger.log'] #=> #<CodeObject::Function:log @parent=logger …>
117
+ #
118
+ # @overload [](childname)
119
+ # @param [String, Symbol] childname
120
+ # @return <Dom::Node>
121
+ #
122
+ # @overload [](path)
123
+ # @param [String] path The path to the desired node
124
+ # @return <Dom::Node>
125
+ def [](path)
126
+ return @children[path] if path.is_a? Symbol
127
+ return @children[path.to_sym] if path.split(NS_SEP_STRING).size == 1
128
+
129
+ path = path.split(NS_SEP_STRING)
130
+ child = @children[path.shift.to_sym]
131
+
132
+ raise WrongPath.new(path) if child.nil?
133
+
134
+ # decend recursive
135
+ child[path.join(NS_SEP_STRING)]
136
+ end
137
+
138
+ # Alias for bracket-access
139
+ # @see #[]
140
+ def find(path)
141
+ self[path]
142
+ end
143
+
144
+
145
+ # Returns if the current node is a leaf or not.
146
+ #
147
+ # @return [Boolean]
148
+ def has_children?
149
+ not (@children.nil? or @children.size == 0)
150
+ end
151
+
152
+ # Finds all siblings of the current node. If there is no parent, it will
153
+ # return `nil`.
154
+ #
155
+ # @return [Array<Dom::Node>, nil]
156
+ def siblings
157
+ return nil if parent.nil?
158
+ @parent.children
159
+ end
160
+
161
+
162
+ # Resolves `nodename` in the current context and tries to find a matching
163
+ # {Dom::Node}. If `nodename` is not the current name and further cannot be found in the list of
164
+ # **children** the parent will be asked for resolution.
165
+ #
166
+ # Given the following example, each query (except `.log`) can be resolved without ambiguity.
167
+ #
168
+ # # -Core
169
+ # # -extend
170
+ # # -extensions
171
+ # # -logger
172
+ # # -log
173
+ # # -properties
174
+ # # -log
175
+ #
176
+ # Dom[:Core][:logger].resolve '.log'
177
+ # #=> #<CodeObject::Function:log @parent=logger @children=[]>
178
+ #
179
+ # Dom[:Core][:logger][:log].resolve '.log'
180
+ # #=> #<CodeObject::Function:log @parent=logger @children=[]>
181
+ #
182
+ # Dom[:Core][:logger][:log].resolve '.logger'
183
+ # #=> #<CodeObject::Object:logger @parent=Core @children=[]>
184
+ #
185
+ # Dom[:Core].resolve '.log'
186
+ # #=> #<CodeObject::Function:log @parent=Core @children=[]>
187
+ #
188
+ # Dom[:Core][:properties].resolve '.log'
189
+ # #=> #<CodeObject::Function:extend @parent=Core @children=[]>
190
+ #
191
+ # Dom[:Core][:logger].resolve 'foo'
192
+ # #=> nil
193
+ #
194
+ # @param [String] nodename
195
+ #
196
+ # @return [Dom::Node, nil]
197
+ def resolve(nodename)
198
+
199
+ return self if nodename == @name
200
+ return nil if @children.nil? and @parent.nil?
201
+
202
+ path = RELATIVE.match(nodename)
203
+
204
+ if path
205
+ first, rest = path.captures
206
+
207
+ # we did find the first part in our list of children
208
+ if not @children.nil? and @children.has_key? first.to_sym
209
+
210
+ # we have to continue our search
211
+ if rest != ""
212
+ @children[first.to_sym].resolve rest
213
+
214
+ # Finish
215
+ else
216
+ @children[first.to_sym]
217
+ end
218
+
219
+ else
220
+ @parent.resolve nodename unless @parent.nil?
221
+ end
222
+
223
+ # It's absolute?
224
+ elsif ABSOLUTE.match nodename
225
+ Dom.root.find nodename
226
+ end
227
+ end
228
+
229
+ # Iterates recursivly over all children of this node and applies `block` to them
230
+ #
231
+ # @param [Block] block
232
+ def each_child(&block)
233
+ @children.values.each do |child|
234
+ yield(child)
235
+ child.each_child(&block)
236
+ end
237
+ end
238
+
239
+
240
+ # @group Manipulation
241
+
242
+ # There are three different cases
243
+ # 1. Last Childnode i.e. ".foo"
244
+ # -> Append node as child
245
+ # 2. absolute path i.e. "Foo"
246
+ # -> delegate path resolution to Dom.root
247
+ # 3. relative path i.e. ".bar.foo"
248
+ # a. if there is a matching child for first element, delegate
249
+ # adding to this node
250
+ # b. create NoDoc node and delegate rest to this NoDoc
251
+ #
252
+ #
253
+ # @overload add_node(path, node)
254
+ # @param [String] path
255
+ # @param [Dom::Node] node
256
+ #
257
+ # @overload add_node(node)
258
+ # @param [Dom::Node] node
259
+ #
260
+ def add_node(*args)
261
+
262
+ # Grabbing right overload
263
+ if args.count == 2
264
+ node = args[1]
265
+ path = args[0]
266
+ elsif args.count == 1
267
+ node = args[0]
268
+
269
+ path = '.'+node.name
270
+ raise NoPathGiven.new("#{node} has no path.") if path.nil?
271
+ else
272
+ raise ArgumentError.new "Wrong number of arguments #{args.count} for 1 or 2"
273
+ end
274
+
275
+ leaf = LEAF.match path
276
+
277
+ if leaf
278
+ # node found, lets insert it
279
+ add_child(leaf[:name], node)
280
+
281
+ else
282
+ matches = RELATIVE.match path
283
+
284
+ if matches
285
+ name = matches[:first].to_s
286
+
287
+ # node not found, what to do?
288
+ add_child(name, NoDoc.new(name)) if self[name].nil?
289
+
290
+ # everything fixed, continue with rest
291
+ self[name].add_node(matches[:rest], node)
292
+
293
+ else
294
+ # has to be an absolute path or something totally strange
295
+ raise WrongPath.new(path) unless ABSOLUTE.match path
296
+
297
+ # begin at top, if absolute
298
+ Dom.add_node '.' + path, node
299
+ end
300
+ end
301
+ end
302
+
303
+ # @group Name- and Path-Handling
304
+
305
+ # Like {#qualified_name} it finds the absolute path.
306
+ # But in contrast to qualified_name it will not include the current node.
307
+ #
308
+ # @example
309
+ # my_node.qualified_name #=> "Core.logger.log"
310
+ # my_node.namespace #=> "Core.logger"
311
+ #
312
+ # @see #qualified_name
313
+ # @return [String]
314
+ def namespace
315
+ parents.map{|p| p.name}.join NS_SEP_STRING
316
+ end
317
+
318
+
319
+ # The **Qualified Name** equals the **Absolute Path** starting from the
320
+ # root-node of the Dom.
321
+ #
322
+ # @example
323
+ # my_node.qualified_name #=> "Core.logger.log"
324
+ #
325
+ # @return [String]
326
+ def qualified_name
327
+ parents.push(self).map{|p| p.name}.join NS_SEP_STRING
328
+ end
329
+
330
+
331
+ # Generates a text-output on console, representing the **subtree-structure**
332
+ # of the current node. The current node is **not** being printed.
333
+ #
334
+ # @example example output
335
+ # -Core
336
+ # -extend
337
+ # -extensions
338
+ # -logger
339
+ # -log
340
+ # -properties
341
+ #
342
+ # @return [nil]
343
+ def print_tree
344
+
345
+ # Because parent = nil and parent = Dom.root are handled the same at #parents
346
+ # we need to make a difference here
347
+ if @parent.nil?
348
+ level = 0
349
+ else
350
+ level = parents.count + 1
351
+ end
352
+
353
+ @children.each do |name, child|
354
+ puts "#{" " * level}-#{name.to_s}#{' (NoDoc)' if child.is_a? NoDoc}"
355
+ child.print_tree
356
+ end
357
+ nil
358
+ end
359
+
360
+ protected
361
+
362
+ def add_child(name, node)
363
+
364
+ name = name.to_sym
365
+
366
+ if self[name].nil?
367
+ self[name] = node
368
+
369
+ # If child is a NoDoc: replace NoDoc with node and move all children from
370
+ # NoDoc to node using node.add_child
371
+ elsif self[name].is_a? NoDoc
372
+ self[name].children.each do |name, childnode|
373
+ node.add_child(name, childnode)
374
+ end
375
+ self[name] = node
376
+
377
+ else
378
+ raise NodeAlreadyExists.new(name)
379
+ end
380
+
381
+ self[name].parent = self
382
+ end
383
+
384
+ # @note unimplemented
385
+ def remove_child(name) end
386
+
387
+ def parent=(node)
388
+ @parent = node
389
+ end
390
+
391
+ # setting a children of this node
392
+ def []=(name, value)
393
+ @children[name.to_sym] = value
394
+ end
395
+
396
+ # path can be absolute like `Foo.bar`, `Foo` or it can be relative like
397
+ # `.foo`, `.foo.bar`.
398
+ # in both cases we need to extract the name from the string and save it
399
+ # as name. After doing this we can use the path to save to dom.
400
+ #
401
+ # @example absolute path
402
+ # Node.extract_name_from("Foo.bar.baz") #=> 'baz'
403
+ # Node.extract_name_from("Foo.bar.baz") #=> 'baz'
404
+ #
405
+ # @param [String] path relative or absolute path of node
406
+ # @return [String] the extracted name
407
+ def extract_name_from(path)
408
+ name = path.split(NS_SEP_STRING).last
409
+ raise NoNameInPath.new(path) if name.nil?
410
+
411
+ return name
412
+ end
413
+
414
+ end
415
+ end