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.
- data/CONCEPT.md +80 -0
- data/DOCUMENTATION.md +41 -0
- data/LICENSE.md +19 -0
- data/README.md +19 -0
- data/RENDERING.md +8 -0
- data/bin/docjs +190 -0
- data/docjs.gemspec +32 -0
- data/lib/boot.rb +34 -0
- data/lib/code_object/base.rb +48 -0
- data/lib/code_object/converter.rb +48 -0
- data/lib/code_object/exceptions.rb +5 -0
- data/lib/code_object/function.rb +84 -0
- data/lib/code_object/object.rb +18 -0
- data/lib/code_object/type.rb +43 -0
- data/lib/configs.rb +53 -0
- data/lib/document/document.rb +25 -0
- data/lib/dom/dom.rb +188 -0
- data/lib/dom/exceptions.rb +12 -0
- data/lib/dom/no_doc.rb +26 -0
- data/lib/dom/node.rb +415 -0
- data/lib/helper/helper.rb +120 -0
- data/lib/helper/linker.rb +130 -0
- data/lib/logger.rb +49 -0
- data/lib/parser/comment.rb +69 -0
- data/lib/parser/comment_parser.rb +90 -0
- data/lib/parser/exceptions.rb +6 -0
- data/lib/parser/meta_container.rb +20 -0
- data/lib/parser/parser.rb +269 -0
- data/lib/processor.rb +123 -0
- data/lib/renderer.rb +108 -0
- data/lib/tasks/render_task.rb +112 -0
- data/lib/thor.rb +27 -0
- data/lib/token/container.rb +84 -0
- data/lib/token/exceptions.rb +6 -0
- data/lib/token/handler.rb +242 -0
- data/lib/token/token.rb +46 -0
- data/templates/application.rb +14 -0
- data/templates/helpers/template.rb +66 -0
- data/templates/resources/css/.sass-cache/98c121fba905284c2c8ca6220fe3c590e5c9ec19/application.scssc +0 -0
- data/templates/resources/css/application.css +836 -0
- data/templates/resources/img/arrow_down.png +0 -0
- data/templates/resources/img/arrow_right.png +0 -0
- data/templates/resources/img/arrow_up.png +0 -0
- data/templates/resources/img/bullet_toggle_minus.png +0 -0
- data/templates/resources/img/bullet_toggle_plus.png +0 -0
- data/templates/resources/img/constructor.png +0 -0
- data/templates/resources/img/function.png +0 -0
- data/templates/resources/img/object.png +0 -0
- data/templates/resources/img/page.png +0 -0
- data/templates/resources/img/prototype.png +0 -0
- data/templates/resources/img/tag.png +0 -0
- data/templates/resources/js/application.js +318 -0
- data/templates/resources/js/jcore.js +129 -0
- data/templates/resources/js/jquery.cookie.js +92 -0
- data/templates/resources/js/jquery.js +16 -0
- data/templates/resources/js/jquery.tooltip.js +77 -0
- data/templates/resources/js/jquery.treeview.js +238 -0
- data/templates/resources/scss/_footer.scss +10 -0
- data/templates/resources/scss/_header.scss +184 -0
- data/templates/resources/scss/_helpers.scss +91 -0
- data/templates/resources/scss/_print.scss +20 -0
- data/templates/resources/scss/_resets.scss +132 -0
- data/templates/resources/scss/_tooltip.scss +26 -0
- data/templates/resources/scss/application.scss +442 -0
- data/templates/tasks/api_index_task.rb +26 -0
- data/templates/tasks/docs_task.rb +33 -0
- data/templates/tasks/json_data_task.rb +55 -0
- data/templates/tasks/typed_task.rb +54 -0
- data/templates/tokens/tokens.rb +22 -0
- data/templates/types/prototype.rb +20 -0
- data/templates/views/api_index.html.erb +21 -0
- data/templates/views/doc_page.html.erb +11 -0
- data/templates/views/function/_detail.html.erb +8 -0
- data/templates/views/function/index.html.erb +53 -0
- data/templates/views/index.html.erb +0 -0
- data/templates/views/layout/application.html.erb +73 -0
- data/templates/views/layout/json.html.erb +3 -0
- data/templates/views/object/index.html.erb +63 -0
- data/templates/views/tokens/_default.html.erb +11 -0
- data/templates/views/tokens/_default_token.html.erb +19 -0
- data/templates/views/tokens/_example.html.erb +2 -0
- data/templates/views/tokens/_examples.html.erb +1 -0
- data/test/code_object/converter.rb +78 -0
- data/test/code_object/prototype.rb +70 -0
- data/test/configs.rb +65 -0
- data/test/docs/README.CONCEPT.md +83 -0
- data/test/docs/README.md +14 -0
- data/test/dom/dom.absolute_nodes.rb +40 -0
- data/test/dom/dom.rb +72 -0
- data/test/dom/node.rb +53 -0
- data/test/integration/converter.rb +72 -0
- data/test/integration/parser_factory.rb +28 -0
- data/test/interactive.rb +7 -0
- data/test/js-files/absolute.js +11 -0
- data/test/js-files/comments_in_strings.js +31 -0
- data/test/js-files/core-doc-relative.js +77 -0
- data/test/js-files/core-doc.js +145 -0
- data/test/js-files/nested.js +34 -0
- data/test/js-files/nested_with_strings.js +35 -0
- data/test/js-files/prototype.js +33 -0
- data/test/js-files/simple.js +17 -0
- data/test/js-files/tokens.js +32 -0
- data/test/parser/comments_in_strings.rb +51 -0
- data/test/parser/intelligent_skip_until.rb +110 -0
- data/test/parser/parser.rb +273 -0
- data/test/rspec_helper.rb +23 -0
- data/test/token/handler.rb +136 -0
- data/test/token/tokens.rb +52 -0
- metadata +184 -0
@@ -0,0 +1,120 @@
|
|
1
|
+
# ../data.img#1800236:1
|
2
|
+
require 'pathname'
|
3
|
+
require 'rdiscount'
|
4
|
+
|
5
|
+
require_relative 'linker'
|
6
|
+
|
7
|
+
# The Helpers are 'mixed' into your {Tasks::RenderTask} and therefore can be used in all
|
8
|
+
# template-views.
|
9
|
+
# If you are searching for a method and don't know, where it may be implemented i suggest the
|
10
|
+
# following inheritence chain as your search-strategy:
|
11
|
+
#
|
12
|
+
# Helper::IncludedHelpers → Tasks::YourTask → Tasks::RenderTask → Renderer
|
13
|
+
#
|
14
|
+
# Somewhere at that chain you will find your desired function.
|
15
|
+
module Helper
|
16
|
+
|
17
|
+
# The Helper-methods in this module are globally used one and should not depend on the template
|
18
|
+
# you are using. You will find many html-helpers around here.
|
19
|
+
module Helper
|
20
|
+
|
21
|
+
include Linker
|
22
|
+
|
23
|
+
def tag(sym, content = "", attrs = {})
|
24
|
+
|
25
|
+
# @todo FIXME
|
26
|
+
if block_given?
|
27
|
+
_erbout << "<#{sym.to_s} #{attributize(content)}>"
|
28
|
+
content = yield
|
29
|
+
_erbout << "</#{sym.to_s}>"
|
30
|
+
else
|
31
|
+
"<#{sym.to_s} #{attributize(attrs)}>#{content}</#{sym.to_s}>"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def truncate(string, num = 150)
|
36
|
+
if string.length > num
|
37
|
+
string[0..num] + " …"
|
38
|
+
else
|
39
|
+
string
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def style(*args)
|
44
|
+
html = ""
|
45
|
+
args.each do |path|
|
46
|
+
html += tag :link, "", :rel => 'stylesheet', :href => to_relative('css/'+path+'.css')
|
47
|
+
end
|
48
|
+
return html
|
49
|
+
end
|
50
|
+
|
51
|
+
def script(*args)
|
52
|
+
html = ""
|
53
|
+
args.each do |path|
|
54
|
+
html += tag :script, "", :src => to_relative('js/'+path+'.js')
|
55
|
+
end
|
56
|
+
return html
|
57
|
+
end
|
58
|
+
|
59
|
+
def code(source)
|
60
|
+
# find minimal intendation
|
61
|
+
intendation = source.lines.map {|line| line.match(/(^\s+)/) && line.match(/(^\s+)/).captures.first.size || 0 }.min
|
62
|
+
|
63
|
+
# @todo there has to be a better way for that
|
64
|
+
tag :code, source.lines.map { |line| line[intendation .. line.size] }.join(""), :class => 'block'
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_html(markdown_text, *markdown_opts)
|
68
|
+
replace_links RDiscount.new(markdown_text, *markdown_opts).to_html
|
69
|
+
end
|
70
|
+
|
71
|
+
def toc(markdown_text)
|
72
|
+
RDiscount.new(markdown_text, :generate_toc).toc_content
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_relative(path)
|
76
|
+
|
77
|
+
path = Pathname.new(path)
|
78
|
+
base = Pathname.new(@current_path)
|
79
|
+
|
80
|
+
# for example /home/jsdoc/css/style.css
|
81
|
+
# current: /home/jsdoc/output/Foo/Bar.html
|
82
|
+
if not path.absolute?
|
83
|
+
# resolve to Configs.output
|
84
|
+
path = Pathname.new(Configs.output) + path
|
85
|
+
end
|
86
|
+
|
87
|
+
Logger.debug "Relative path '#{path}' from '#{base}'"
|
88
|
+
path.relative_path_from(base).to_s
|
89
|
+
end
|
90
|
+
|
91
|
+
def render_tokens(opts = {})
|
92
|
+
|
93
|
+
code_object = opts[:of] or raise Exception.new("Parameter :of (CodeObject) required")
|
94
|
+
area = opts[:in] or raise Exception.new("Parameter :in (Area) required")
|
95
|
+
|
96
|
+
rendered = ""
|
97
|
+
|
98
|
+
token_groups = code_object.tokens.values.each do |tokens|
|
99
|
+
|
100
|
+
# tokens is an array of Token::Token
|
101
|
+
if not tokens.empty? and tokens.first.area == area
|
102
|
+
|
103
|
+
template = tokens.first.template.to_s
|
104
|
+
|
105
|
+
# overwriting default template with specified option[:template] if existant
|
106
|
+
template = opts[:template].to_s if opts[:template] and template == 'default'
|
107
|
+
|
108
|
+
rendered += render :partial => "tokens/#{template}", :locals => { :tokens => tokens }
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
rendered
|
113
|
+
end
|
114
|
+
|
115
|
+
def attributize(hash)
|
116
|
+
hash.map{|k,v| "#{k}=\"#{v}\""}.join ' '
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Helper
|
2
|
+
|
3
|
+
# This Helper contains all needed functionality to link to an object, on-page-element or some
|
4
|
+
# other urls
|
5
|
+
module Linker
|
6
|
+
|
7
|
+
FILE = /^file\:(\S+)/
|
8
|
+
EXTERNAL = /^((?:http|ftp|https|ssh):\/\/\S+)/
|
9
|
+
MAIL = /^(mailto\:\S+)/
|
10
|
+
HASH = /^#\S*/
|
11
|
+
DOCUMENTATION = /^doc\:([^\s#]+)(#\S+)?/
|
12
|
+
|
13
|
+
# @note link_to - first argument can be
|
14
|
+
# "file:some/path/to_a.file"
|
15
|
+
# "Code.object.path"
|
16
|
+
# ".relative.code_object.path"
|
17
|
+
# "http://external.address.com"
|
18
|
+
# instance_of_code_object
|
19
|
+
#
|
20
|
+
def link_to(target, text = nil, args = {})
|
21
|
+
|
22
|
+
Logger.debug "Trying to link #{target}"
|
23
|
+
|
24
|
+
link = if target.is_a? Document::Document
|
25
|
+
|
26
|
+
text = target.name if text.nil?
|
27
|
+
to_relative path_to target
|
28
|
+
|
29
|
+
elsif target.is_a? CodeObject::Base
|
30
|
+
|
31
|
+
if text.nil? and target.parent == context and context != Dom.root
|
32
|
+
text = ".#{target.name}"
|
33
|
+
text += "()" if target.is_a? CodeObject::Function
|
34
|
+
elsif text.nil?
|
35
|
+
text = target.qualified_name
|
36
|
+
end
|
37
|
+
|
38
|
+
to_relative path_to target
|
39
|
+
|
40
|
+
elsif target.match EXTERNAL or target.match MAIL or target.match HASH
|
41
|
+
target
|
42
|
+
|
43
|
+
elsif target.match FILE
|
44
|
+
to_relative target.match(FILE).captures.first
|
45
|
+
|
46
|
+
elsif target.match DOCUMENTATION
|
47
|
+
Logger.debug target + " matched DOCUMENTATION"
|
48
|
+
|
49
|
+
doc_name, hash = target.match(DOCUMENTATION).captures
|
50
|
+
obj = Dom.docs.find doc_name
|
51
|
+
text ||= obj.name
|
52
|
+
|
53
|
+
# find relative path to our object and reattach hash to path
|
54
|
+
to_relative(path_to obj) + (hash || "") unless obj.nil?
|
55
|
+
|
56
|
+
else
|
57
|
+
# use context dependent resolving functionality as specified in {Tasks::RenderTask}
|
58
|
+
obj = resolve target
|
59
|
+
to_relative path_to obj unless obj.nil?
|
60
|
+
end
|
61
|
+
|
62
|
+
text ||= target
|
63
|
+
|
64
|
+
if link.nil?
|
65
|
+
Logger.warn "Could not resolve link to '#{target}'"
|
66
|
+
return text
|
67
|
+
end
|
68
|
+
|
69
|
+
tag :a, text, :href => link
|
70
|
+
end
|
71
|
+
|
72
|
+
def relative_link(path, text)
|
73
|
+
tag :a, text, :href => to_relative(path)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns the relative path (from dom) to this node
|
77
|
+
# The Node can be either a {CodeObject::Base CodeObject} or a {Document::Document Document}.
|
78
|
+
#
|
79
|
+
# @param [CodeObject::Base, Document::Document] object
|
80
|
+
#
|
81
|
+
# @example
|
82
|
+
# Dom[:Foo][:bar].file_path #=> Foo/bar
|
83
|
+
#
|
84
|
+
def path_to(object, args = {})
|
85
|
+
|
86
|
+
return "" if object.nil?
|
87
|
+
format = args[:format] || :html
|
88
|
+
path = object.parents.push(object).map{|p| p.name}.join('/') + ".#{format.to_s}"
|
89
|
+
|
90
|
+
# object can be either a CodeObject or a Document
|
91
|
+
# maybe source this one out later on in Configs.some_path
|
92
|
+
if object.is_a? CodeObject::Base
|
93
|
+
"api/" + path
|
94
|
+
elsif object.is_a? Document::Document
|
95
|
+
"docs/" + path
|
96
|
+
else
|
97
|
+
Logger.warn "Could not resolve link to '#{object}'"
|
98
|
+
object.to_s
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# (see https://github.com/lsegal/yard/blob/master/lib/yard/templates/helpers/html_helper.rb)
|
103
|
+
def replace_links(text)
|
104
|
+
code_tags = 0
|
105
|
+
text.gsub(/<(\/)?(pre|code|tt)|(\\)?\{(?!\})(\S+?)(?:\s([^\}]*?\S))?\}(?=[\W<]|.+<\/|$)/m) do |str|
|
106
|
+
closed, tag, escape, name, title, match = $1, $2, $3, $4, $5, $&
|
107
|
+
if tag
|
108
|
+
code_tags += (closed ? -1 : 1)
|
109
|
+
next str
|
110
|
+
end
|
111
|
+
next str unless code_tags == 0
|
112
|
+
|
113
|
+
next(match[1..-1]) if escape
|
114
|
+
|
115
|
+
next(match) if name[0,1] == '|'
|
116
|
+
|
117
|
+
link_to(name, title)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def link_on_page(object)
|
122
|
+
if object.is_a? CodeObject::Function
|
123
|
+
link_to "#method-#{object.name}", ".#{object.name}()"
|
124
|
+
else
|
125
|
+
link_to "#object-#{object.name}", ".#{object.name}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
data/lib/logger.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'thor/base'
|
2
|
+
|
3
|
+
# The logger is using colorizing-functionality from Thor's shell
|
4
|
+
module Logger
|
5
|
+
|
6
|
+
LogLevel = Struct.new :numeric, :prefix, :color
|
7
|
+
|
8
|
+
LEVEL = {
|
9
|
+
:debug => LogLevel.new(0, "DEBUG ", :white),
|
10
|
+
:info => LogLevel.new(1, "INFO ", :blue),
|
11
|
+
:warn => LogLevel.new(2, "WARN ", :yellow),
|
12
|
+
:error => LogLevel.new(3, "ERROR ", :red),
|
13
|
+
:system => LogLevel.new(10, "", :black)
|
14
|
+
}
|
15
|
+
|
16
|
+
def self.setup(args = {})
|
17
|
+
|
18
|
+
@@shell = Thor::Base.shell.new
|
19
|
+
@@logfile = args[:file]
|
20
|
+
@@level = LEVEL[args[:level] || :info]
|
21
|
+
|
22
|
+
# write start sequence
|
23
|
+
log LEVEL[:info], ["\n\n== #{Time.now} #{'='*50}"]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.method_missing(name, *args)
|
27
|
+
level = LEVEL[name.to_sym]
|
28
|
+
raise NoMethodError.new(name.to_s) if level.nil?
|
29
|
+
|
30
|
+
log(level, args)
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def self.log(level, msg)
|
36
|
+
return if level.numeric < @@level.numeric
|
37
|
+
|
38
|
+
msg = msg.join "\n"
|
39
|
+
|
40
|
+
unless @@logfile.nil?
|
41
|
+
File.open(@@logfile, "a") do |f|
|
42
|
+
f.write "#{level.prefix} #{msg}\n"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
@@shell.say @@shell.set_color(level.prefix, level.color, true) + msg
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# ../data.img#1781829:1
|
2
|
+
require_relative 'meta_container'
|
3
|
+
require_relative '../code_object/converter'
|
4
|
+
|
5
|
+
module Parser
|
6
|
+
|
7
|
+
# Together with {Parser::Coment} it acts as an **Interface** between {Parser}
|
8
|
+
# and {CodeObject}. Parser::Comment creates instances of Tokenline, which are
|
9
|
+
# then analysed by {Token::Container#process_token}
|
10
|
+
#
|
11
|
+
# @see Parser::Comment
|
12
|
+
# @see Parser::CommentParser
|
13
|
+
Tokenline = Struct.new :token, :content
|
14
|
+
|
15
|
+
# Comment contains all **tokenlines** and **doclines**, which are created by the
|
16
|
+
# {Parser::Parser parser}. The tokenlines are stored as {Tokenline}. Because
|
17
|
+
# of this Comment and Tokenline act as **Interface** for {CodeObject::Base}.
|
18
|
+
#
|
19
|
+
# The tokens will further be processed by {Token::Container}, which
|
20
|
+
# is mixed in to CodeObject::Base).
|
21
|
+
#
|
22
|
+
# @example creating of an comment
|
23
|
+
# c = Parser::Comment.new "the original string of the comment, with all tokens and doclines"
|
24
|
+
# c.add_tokenline :param "[String] first_parameter this is the description for param1"
|
25
|
+
# c.add_docline "Some documentation of the comment"
|
26
|
+
#
|
27
|
+
# @example access of comment-data
|
28
|
+
# c.tokenlines.first.token #=> :param
|
29
|
+
# c.tokenlines.first.content #=> "[String] first_parameter this is the description for param1"
|
30
|
+
# c.doclines #=> ["Some documentation of the comment"]
|
31
|
+
class Comment
|
32
|
+
|
33
|
+
include MetaContainer
|
34
|
+
include CodeObject::Converter
|
35
|
+
|
36
|
+
attr_reader :tokenlines, :doclines, :children
|
37
|
+
|
38
|
+
def initialize(comment_text = "")
|
39
|
+
@original_comment = comment_text
|
40
|
+
|
41
|
+
@tokenlines, @doclines, @children = [], [], []
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param [String, Symbol] tokenname
|
45
|
+
# @param [String] content
|
46
|
+
def add_tokenline(tokenname, content = "")
|
47
|
+
@tokenlines << Tokenline.new(tokenname.to_sym, content)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param [String] docline
|
51
|
+
def add_docline(docline)
|
52
|
+
@doclines << docline
|
53
|
+
end
|
54
|
+
|
55
|
+
# @param [Array<Comment>] comments
|
56
|
+
def add_children(comments)
|
57
|
+
@children += comments
|
58
|
+
end
|
59
|
+
|
60
|
+
def has_tokens?
|
61
|
+
not @tokenlines.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_s
|
65
|
+
"#<Parser::Comment tokenlines=#{@tokenlines.length} doclines=#{@doclines.length}>"
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# ../data.img#1799299:1
|
2
|
+
require_relative 'comment'
|
3
|
+
require_relative 'exceptions'
|
4
|
+
|
5
|
+
module Parser
|
6
|
+
class CommentParser < StringScanner
|
7
|
+
|
8
|
+
def initialize(input)
|
9
|
+
super(input)
|
10
|
+
@comment = Comment.new(input)
|
11
|
+
end
|
12
|
+
|
13
|
+
# All lines, that start with a `@-symbol` will be processed as tokenline
|
14
|
+
# if the next line after a token starts with two spaces, it will be
|
15
|
+
# interpreted as continuation of the preceding token.
|
16
|
+
#
|
17
|
+
# @example multiline token
|
18
|
+
# @multiline_token this is a multi_line token, it won't
|
19
|
+
# stop if i intend the next line with two spaces, like " "
|
20
|
+
#
|
21
|
+
# All other lines are interpreted as doclines
|
22
|
+
#
|
23
|
+
# @return [Parser::Comment] Creates an instance of {Parser::Comment} and
|
24
|
+
# attaches all find doc- and tokenlines to it.
|
25
|
+
def parse
|
26
|
+
# we don't want the linebreak of the comment start in our first docline
|
27
|
+
# i.e. ignore '/**\n'
|
28
|
+
self.skip LINE_END
|
29
|
+
|
30
|
+
while not eos? do
|
31
|
+
parse_comment_line
|
32
|
+
end
|
33
|
+
return @comment
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
# skips leading spaces with asterisk aka {Parser::LINE_START LINE_START}
|
39
|
+
# then checks for {Parser::TOKENLINE_START @-symbol} to parse a token
|
40
|
+
def parse_comment_line
|
41
|
+
self.skip LINE_START
|
42
|
+
|
43
|
+
if self.check TOKENLINE_START
|
44
|
+
tokenline = parse_token
|
45
|
+
matches = tokenline.match(TOKENLINE)
|
46
|
+
|
47
|
+
raise NotValidTokenline.new("Not valid:'#{tokenline}'") if matches.nil?
|
48
|
+
|
49
|
+
name, content = matches.captures
|
50
|
+
@comment.add_tokenline(name, content)
|
51
|
+
else
|
52
|
+
@comment.add_docline parse_doc
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Parses tokens, if the line begins with an @
|
57
|
+
# @token_one some other text etc.
|
58
|
+
#
|
59
|
+
# The parser does the following to detect multiline tokens like:
|
60
|
+
# @token_two some text, and some more
|
61
|
+
# and even some more.
|
62
|
+
#
|
63
|
+
# 1. Scan til the first linebreak (or end of string, if it reaches it first)
|
64
|
+
# 2. Check if next line starts with two spaces, skip them
|
65
|
+
# 3. Parse recursivly til the next line does not start with two spaces
|
66
|
+
#
|
67
|
+
# @see StringScanner.scan_until_ahead to see another example
|
68
|
+
# of the positive lookahead
|
69
|
+
def parse_token
|
70
|
+
|
71
|
+
# scan until the first linebreak, but don't include it in the `content`
|
72
|
+
# content = self.scan_until_or_end(/(?=(#{LINE_END}))/)
|
73
|
+
# so just skip it
|
74
|
+
# self.skip LINE_END
|
75
|
+
content = self.scan_until_or_end LINE_END
|
76
|
+
|
77
|
+
# skip the first two spaces and parse line recursivly
|
78
|
+
unless self.skip(/#{LINE_START}#{NO_BR}{2}/).nil?
|
79
|
+
content + parse_token
|
80
|
+
else
|
81
|
+
content
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def parse_doc
|
86
|
+
self.scan_until_or_end(LINE_END)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|