rdoc 8.0.0 → 8.1.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.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +1 -3
- data/RI.md +75 -75
- data/exe/rdoc +2 -2
- data/lib/rdoc/code_object/alias.rb +71 -69
- data/lib/rdoc/code_object/any_method.rb +305 -303
- data/lib/rdoc/code_object/attr.rb +150 -148
- data/lib/rdoc/code_object/class_module.rb +798 -792
- data/lib/rdoc/code_object/constant.rb +175 -173
- data/lib/rdoc/code_object/context/section.rb +142 -138
- data/lib/rdoc/code_object/context.rb +926 -958
- data/lib/rdoc/code_object/extend.rb +7 -5
- data/lib/rdoc/code_object/include.rb +7 -5
- data/lib/rdoc/code_object/method_attr.rb +326 -319
- data/lib/rdoc/code_object/mixin.rb +97 -95
- data/lib/rdoc/code_object/normal_class.rb +77 -78
- data/lib/rdoc/code_object/normal_module.rb +61 -59
- data/lib/rdoc/code_object/require.rb +23 -39
- data/lib/rdoc/code_object/single_class.rb +21 -19
- data/lib/rdoc/code_object/top_level.rb +212 -219
- data/lib/rdoc/code_object.rb +305 -303
- data/lib/rdoc/comment.rb +275 -273
- data/lib/rdoc/cross_reference.rb +192 -190
- data/lib/rdoc/encoding.rb +105 -103
- data/lib/rdoc/erb_partial.rb +13 -11
- data/lib/rdoc/erbio.rb +29 -27
- data/lib/rdoc/generator/aliki.rb +161 -153
- data/lib/rdoc/generator/darkfish.rb +645 -635
- data/lib/rdoc/generator/json_index.rb +233 -229
- data/lib/rdoc/generator/markup.rb +164 -146
- data/lib/rdoc/generator/pot/message_extractor.rb +57 -51
- data/lib/rdoc/generator/pot/po.rb +52 -51
- data/lib/rdoc/generator/pot/po_entry.rb +138 -132
- data/lib/rdoc/generator/pot.rb +85 -81
- data/lib/rdoc/generator/ri.rb +23 -19
- data/lib/rdoc/generator/template/aliki/DESIGN.md +6 -4
- data/lib/rdoc/generator/template/aliki/_footer.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_head.rhtml +10 -10
- data/lib/rdoc/generator/template/aliki/_header.rhtml +29 -44
- data/lib/rdoc/generator/template/aliki/_sidebar_search.rhtml +4 -4
- data/lib/rdoc/generator/template/aliki/css/rdoc.css +207 -178
- data/lib/rdoc/generator/template/aliki/js/aliki.js +60 -84
- data/lib/rdoc/generator/template/darkfish/_footer.rhtml +1 -1
- data/lib/rdoc/generator.rb +48 -46
- data/lib/rdoc/i18n/locale.rb +99 -95
- data/lib/rdoc/i18n/text.rb +109 -105
- data/lib/rdoc/i18n.rb +7 -5
- data/lib/rdoc/markdown/byte_runtime.rb +80 -0
- data/lib/rdoc/markdown.kpeg +15 -11
- data/lib/rdoc/markdown.rb +40 -47
- data/lib/rdoc/markup/block_quote.rb +12 -8
- data/lib/rdoc/markup/document.rb +127 -123
- data/lib/rdoc/markup/formatter.rb +219 -215
- data/lib/rdoc/markup/include.rb +33 -29
- data/lib/rdoc/markup/indented_paragraph.rb +37 -33
- data/lib/rdoc/markup/inline_parser.rb +281 -277
- data/lib/rdoc/markup/list.rb +80 -88
- data/lib/rdoc/markup/list_item.rb +73 -85
- data/lib/rdoc/markup/paragraph.rb +23 -19
- data/lib/rdoc/markup/parser.rb +501 -497
- data/lib/rdoc/markup/pre_process.rb +283 -279
- data/lib/rdoc/markup/raw.rb +2 -2
- data/lib/rdoc/markup/rule.rb +16 -12
- data/lib/rdoc/markup/to_ansi.rb +143 -139
- data/lib/rdoc/markup/to_bs.rb +72 -68
- data/lib/rdoc/markup/to_html.rb +594 -565
- data/lib/rdoc/markup/to_html_crossref.rb +234 -230
- data/lib/rdoc/markup/to_html_snippet.rb +232 -227
- data/lib/rdoc/markup/to_joined_paragraph.rb +36 -32
- data/lib/rdoc/markup/to_label.rb +63 -59
- data/lib/rdoc/markup/to_markdown.rb +212 -208
- data/lib/rdoc/markup/to_rdoc.rb +336 -332
- data/lib/rdoc/markup/to_table_of_contents.rb +66 -62
- data/lib/rdoc/markup/to_test.rb +60 -56
- data/lib/rdoc/markup/to_tt_only.rb +84 -80
- data/lib/rdoc/markup/verbatim.rb +62 -58
- data/lib/rdoc/markup.rb +198 -196
- data/lib/rdoc/options.rb +1063 -1061
- data/lib/rdoc/parser/c.rb +1039 -1037
- data/lib/rdoc/parser/changelog.rb +319 -315
- data/lib/rdoc/parser/markdown.rb +17 -13
- data/lib/rdoc/parser/rbs.rb +239 -235
- data/lib/rdoc/parser/rd.rb +17 -13
- data/lib/rdoc/parser/ruby.rb +1245 -1124
- data/lib/rdoc/parser/ruby_colorizer.rb +263 -213
- data/lib/rdoc/parser/simple.rb +31 -27
- data/lib/rdoc/parser/text.rb +12 -8
- data/lib/rdoc/parser.rb +228 -220
- data/lib/rdoc/rbs_helper.rb +1 -1
- data/lib/rdoc/rd/inline.rb +57 -53
- data/lib/rdoc/rd.rb +90 -88
- data/lib/rdoc/rdoc.rb +500 -491
- data/lib/rdoc/ri/driver.rb +1140 -1135
- data/lib/rdoc/ri/formatter.rb +7 -3
- data/lib/rdoc/ri/paths.rb +140 -136
- data/lib/rdoc/ri/servlet.rb +354 -350
- data/lib/rdoc/ri/store.rb +4 -2
- data/lib/rdoc/ri/task.rb +55 -51
- data/lib/rdoc/ri.rb +14 -12
- data/lib/rdoc/rubygems_hook.rb +183 -181
- data/lib/rdoc/server.rb +349 -347
- data/lib/rdoc/stats/normal.rb +46 -42
- data/lib/rdoc/stats/quiet.rb +39 -35
- data/lib/rdoc/stats/verbose.rb +35 -31
- data/lib/rdoc/stats.rb +365 -363
- data/lib/rdoc/store.rb +888 -902
- data/lib/rdoc/task.rb +260 -256
- data/lib/rdoc/text.rb +135 -133
- data/lib/rdoc/token_stream.rb +101 -93
- data/lib/rdoc/tom_doc.rb +203 -201
- data/lib/rdoc/version.rb +1 -1
- metadata +4 -5
- data/lib/rdoc/markdown/literals.kpeg +0 -21
- data/lib/rdoc/markdown/literals.rb +0 -454
data/lib/rdoc/markup/parser.rb
CHANGED
|
@@ -1,585 +1,589 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'strscan'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
# Returns a token stream for +str+, for testing
|
|
69
|
-
|
|
70
|
-
def self.tokenize(str)
|
|
71
|
-
parser = new
|
|
72
|
-
parser.tokenize str
|
|
73
|
-
parser.tokens
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
##
|
|
77
|
-
# Creates a new Parser. See also ::parse
|
|
4
|
+
module RDoc
|
|
5
|
+
class Markup
|
|
6
|
+
##
|
|
7
|
+
# A recursive-descent parser for RDoc markup.
|
|
8
|
+
#
|
|
9
|
+
# The parser tokenizes an input string then parses the tokens into a Document.
|
|
10
|
+
# Documents can be converted into output formats by writing a visitor like
|
|
11
|
+
# RDoc::Markup::ToHTML.
|
|
12
|
+
#
|
|
13
|
+
# The parser only handles the block-level constructs Paragraph, List,
|
|
14
|
+
# ListItem, Heading, Verbatim, BlankLine, Rule and BlockQuote.
|
|
15
|
+
# Inline markup such as <tt>\+blah\+</tt> is handled separately by
|
|
16
|
+
# RDoc::Markup::InlineParser.
|
|
17
|
+
#
|
|
18
|
+
# To see what markup the Parser implements read RDoc. To see how to use
|
|
19
|
+
# RDoc markup to format text in your program read RDoc::Markup.
|
|
20
|
+
|
|
21
|
+
class Parser
|
|
22
|
+
|
|
23
|
+
include Text
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# List token types
|
|
27
|
+
|
|
28
|
+
LIST_TOKENS = [
|
|
29
|
+
:BULLET,
|
|
30
|
+
:LABEL,
|
|
31
|
+
:LALPHA,
|
|
32
|
+
:NOTE,
|
|
33
|
+
:NUMBER,
|
|
34
|
+
:UALPHA,
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# Parser error subclass
|
|
39
|
+
|
|
40
|
+
class Error < RuntimeError; end
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
# Raised when the parser is unable to handle the given markup
|
|
44
|
+
|
|
45
|
+
class ParseError < Error; end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Enables display of debugging information
|
|
49
|
+
|
|
50
|
+
attr_accessor :debug
|
|
51
|
+
|
|
52
|
+
##
|
|
53
|
+
# Token accessor
|
|
54
|
+
|
|
55
|
+
attr_reader :tokens
|
|
56
|
+
|
|
57
|
+
##
|
|
58
|
+
# Parses +str+ into a Document.
|
|
59
|
+
#
|
|
60
|
+
# Use RDoc::Markup#parse instead of this method.
|
|
61
|
+
|
|
62
|
+
def self.parse(str)
|
|
63
|
+
parser = new
|
|
64
|
+
parser.tokenize str
|
|
65
|
+
doc = Markup::Document.new
|
|
66
|
+
parser.parse doc
|
|
67
|
+
end
|
|
78
68
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
@current_token = nil
|
|
82
|
-
@debug = false
|
|
83
|
-
@s = nil
|
|
84
|
-
@tokens = []
|
|
85
|
-
end
|
|
69
|
+
##
|
|
70
|
+
# Returns a token stream for +str+, for testing
|
|
86
71
|
|
|
87
|
-
|
|
88
|
-
|
|
72
|
+
def self.tokenize(str)
|
|
73
|
+
parser = new
|
|
74
|
+
parser.tokenize str
|
|
75
|
+
parser.tokens
|
|
76
|
+
end
|
|
89
77
|
|
|
90
|
-
|
|
91
|
-
|
|
78
|
+
##
|
|
79
|
+
# Creates a new Parser. See also ::parse
|
|
92
80
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
end
|
|
81
|
+
def initialize
|
|
82
|
+
@binary_input = nil
|
|
83
|
+
@current_token = nil
|
|
84
|
+
@debug = false
|
|
85
|
+
@s = nil
|
|
86
|
+
@tokens = []
|
|
87
|
+
end
|
|
101
88
|
|
|
102
|
-
|
|
103
|
-
|
|
89
|
+
##
|
|
90
|
+
# Builds a Heading of +level+
|
|
104
91
|
|
|
105
|
-
|
|
106
|
-
|
|
92
|
+
def build_heading(level)
|
|
93
|
+
type, text, = get
|
|
107
94
|
|
|
108
|
-
|
|
109
|
-
|
|
95
|
+
text = case type
|
|
96
|
+
when :TEXT
|
|
97
|
+
skip :NEWLINE
|
|
98
|
+
text
|
|
99
|
+
else
|
|
100
|
+
unget
|
|
101
|
+
''
|
|
102
|
+
end
|
|
110
103
|
|
|
111
|
-
|
|
112
|
-
|
|
104
|
+
Markup::Heading.new level, text
|
|
105
|
+
end
|
|
113
106
|
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
##
|
|
108
|
+
# Builds a List flush to +margin+
|
|
116
109
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if column < margin || (list.type && list.type != type) then
|
|
120
|
-
unget
|
|
121
|
-
break
|
|
122
|
-
end
|
|
110
|
+
def build_list(margin)
|
|
111
|
+
p :list_start => margin if @debug
|
|
123
112
|
|
|
124
|
-
list
|
|
125
|
-
|
|
113
|
+
list = Markup::List.new
|
|
114
|
+
label = nil
|
|
126
115
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
label = [] unless label
|
|
116
|
+
until @tokens.empty? do
|
|
117
|
+
type, data, column, = get
|
|
130
118
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
peek_type, _, column, = peek_token
|
|
119
|
+
case type
|
|
120
|
+
when *LIST_TOKENS
|
|
121
|
+
if column < margin || (list.type && list.type != type)
|
|
122
|
+
unget
|
|
123
|
+
break
|
|
137
124
|
end
|
|
138
125
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
126
|
+
list.type = type
|
|
127
|
+
peek_type, _, column, = peek_token
|
|
128
|
+
|
|
129
|
+
case type
|
|
130
|
+
when :NOTE, :LABEL
|
|
131
|
+
label = [] unless label
|
|
132
|
+
|
|
133
|
+
if peek_type == :NEWLINE
|
|
134
|
+
# description not on the same line as LABEL/NOTE
|
|
135
|
+
# skip the trailing newline & any blank lines below
|
|
136
|
+
while peek_type == :NEWLINE
|
|
137
|
+
get
|
|
138
|
+
peek_type, _, column, = peek_token
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# we may be:
|
|
142
|
+
# - at end of stream
|
|
143
|
+
# - at a column < margin:
|
|
144
|
+
# [text]
|
|
145
|
+
# blah blah blah
|
|
146
|
+
# - at the same column, but with a different type of list item
|
|
147
|
+
# [text]
|
|
148
|
+
# * blah blah
|
|
149
|
+
# - at the same column, with the same type of list item
|
|
150
|
+
# [one]
|
|
151
|
+
# [two]
|
|
152
|
+
# In all cases, we have an empty description.
|
|
153
|
+
# In the last case only, we continue.
|
|
154
|
+
if peek_type.nil? || column < margin
|
|
155
|
+
empty = true
|
|
156
|
+
elsif column == margin
|
|
157
|
+
case peek_type
|
|
158
|
+
when type
|
|
159
|
+
empty = :continue
|
|
160
|
+
when *LIST_TOKENS
|
|
161
|
+
empty = true
|
|
162
|
+
else
|
|
163
|
+
empty = false
|
|
164
|
+
end
|
|
165
|
+
else
|
|
166
|
+
empty = false
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
if empty
|
|
170
|
+
label << data
|
|
171
|
+
next if empty == :continue
|
|
172
|
+
break
|
|
173
|
+
end
|
|
162
174
|
end
|
|
163
175
|
else
|
|
164
|
-
|
|
176
|
+
data = nil
|
|
165
177
|
end
|
|
166
178
|
|
|
167
|
-
if
|
|
168
|
-
label << data
|
|
169
|
-
|
|
170
|
-
break
|
|
179
|
+
if label
|
|
180
|
+
data = label << data
|
|
181
|
+
label = nil
|
|
171
182
|
end
|
|
183
|
+
|
|
184
|
+
list_item = Markup::ListItem.new data
|
|
185
|
+
parse list_item, column
|
|
186
|
+
list << list_item
|
|
187
|
+
|
|
188
|
+
else
|
|
189
|
+
unget
|
|
190
|
+
break
|
|
172
191
|
end
|
|
173
|
-
else
|
|
174
|
-
data = nil
|
|
175
192
|
end
|
|
176
193
|
|
|
177
|
-
if
|
|
178
|
-
data = label << data
|
|
179
|
-
label = nil
|
|
180
|
-
end
|
|
194
|
+
p :list_end => margin if @debug
|
|
181
195
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
196
|
+
if list.empty?
|
|
197
|
+
return nil unless label
|
|
198
|
+
return nil unless [:LABEL, :NOTE].include? list.type
|
|
185
199
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
end
|
|
190
|
-
end
|
|
200
|
+
list_item = Markup::ListItem.new label, Markup::BlankLine.new
|
|
201
|
+
list << list_item
|
|
202
|
+
end
|
|
191
203
|
|
|
192
|
-
|
|
204
|
+
list
|
|
205
|
+
end
|
|
193
206
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
return nil unless [:LABEL, :NOTE].include? list.type
|
|
207
|
+
##
|
|
208
|
+
# Builds a Paragraph that is flush to +margin+
|
|
197
209
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
end
|
|
210
|
+
def build_paragraph(margin)
|
|
211
|
+
p :paragraph_start => margin if @debug
|
|
201
212
|
|
|
202
|
-
|
|
203
|
-
end
|
|
213
|
+
paragraph = Markup::Paragraph.new
|
|
204
214
|
|
|
205
|
-
|
|
206
|
-
|
|
215
|
+
until @tokens.empty? do
|
|
216
|
+
type, data, column, = get
|
|
207
217
|
|
|
208
|
-
|
|
209
|
-
|
|
218
|
+
if type == :TEXT and column == margin
|
|
219
|
+
paragraph << data
|
|
210
220
|
|
|
211
|
-
|
|
221
|
+
break if peek_token.first == :BREAK
|
|
212
222
|
|
|
213
|
-
|
|
214
|
-
|
|
223
|
+
data << ' ' if skip :NEWLINE and /#{SPACE_SEPARATED_LETTER_CLASS}\z/o.match?(data)
|
|
224
|
+
else
|
|
225
|
+
unget
|
|
226
|
+
break
|
|
227
|
+
end
|
|
228
|
+
end
|
|
215
229
|
|
|
216
|
-
|
|
217
|
-
paragraph << data
|
|
230
|
+
paragraph.parts.last.sub!(/ \z/, '') # cleanup
|
|
218
231
|
|
|
219
|
-
|
|
232
|
+
p :paragraph_end => margin if @debug
|
|
220
233
|
|
|
221
|
-
|
|
222
|
-
else
|
|
223
|
-
unget
|
|
224
|
-
break
|
|
234
|
+
paragraph
|
|
225
235
|
end
|
|
226
|
-
end
|
|
227
236
|
|
|
228
|
-
|
|
237
|
+
##
|
|
238
|
+
# Builds a Verbatim that is indented from +margin+.
|
|
239
|
+
#
|
|
240
|
+
# The verbatim block is shifted left (the least indented lines start in
|
|
241
|
+
# column 0). Each part of the verbatim is one line of text, always
|
|
242
|
+
# terminated by a newline. Blank lines always consist of a single newline
|
|
243
|
+
# character, and there is never a single newline at the end of the verbatim.
|
|
229
244
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
end
|
|
245
|
+
def build_verbatim(margin)
|
|
246
|
+
p :verbatim_begin => margin if @debug
|
|
247
|
+
verbatim = Markup::Verbatim.new
|
|
234
248
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
# The verbatim block is shifted left (the least indented lines start in
|
|
239
|
-
# column 0). Each part of the verbatim is one line of text, always
|
|
240
|
-
# terminated by a newline. Blank lines always consist of a single newline
|
|
241
|
-
# character, and there is never a single newline at the end of the verbatim.
|
|
242
|
-
|
|
243
|
-
def build_verbatim(margin)
|
|
244
|
-
p :verbatim_begin => margin if @debug
|
|
245
|
-
verbatim = RDoc::Markup::Verbatim.new
|
|
249
|
+
min_indent = nil
|
|
250
|
+
generate_leading_spaces = true
|
|
251
|
+
line = ''.dup
|
|
246
252
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
line = ''.dup
|
|
253
|
+
until @tokens.empty? do
|
|
254
|
+
type, data, column, = get
|
|
250
255
|
|
|
251
|
-
|
|
252
|
-
|
|
256
|
+
if type == :NEWLINE
|
|
257
|
+
line << data
|
|
258
|
+
verbatim << line
|
|
259
|
+
line = ''.dup
|
|
260
|
+
generate_leading_spaces = true
|
|
261
|
+
next
|
|
262
|
+
end
|
|
253
263
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
generate_leading_spaces = true
|
|
259
|
-
next
|
|
260
|
-
end
|
|
264
|
+
if column <= margin
|
|
265
|
+
unget
|
|
266
|
+
break
|
|
267
|
+
end
|
|
261
268
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
269
|
+
if generate_leading_spaces
|
|
270
|
+
indent = column - margin
|
|
271
|
+
line << ' ' * indent
|
|
272
|
+
min_indent = indent if min_indent.nil? || indent < min_indent
|
|
273
|
+
generate_leading_spaces = false
|
|
274
|
+
end
|
|
266
275
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
276
|
+
case type
|
|
277
|
+
when :HEADER
|
|
278
|
+
line << '=' * data
|
|
279
|
+
_, _, peek_column, = peek_token
|
|
280
|
+
peek_column ||= column + data
|
|
281
|
+
indent = peek_column - column - data
|
|
282
|
+
line << ' ' * indent
|
|
283
|
+
when :RULE
|
|
284
|
+
width = 2 + data
|
|
285
|
+
line << '-' * width
|
|
286
|
+
_, _, peek_column, = peek_token
|
|
287
|
+
peek_column ||= column + width
|
|
288
|
+
indent = peek_column - column - width
|
|
289
|
+
line << ' ' * indent
|
|
290
|
+
when :BREAK, :TEXT
|
|
291
|
+
line << data
|
|
292
|
+
when :BLOCKQUOTE
|
|
293
|
+
line << '>>>'
|
|
294
|
+
peek_type, _, peek_column = peek_token
|
|
295
|
+
if peek_type != :NEWLINE and peek_column
|
|
296
|
+
line << ' ' * (peek_column - column - 3)
|
|
297
|
+
end
|
|
298
|
+
else # *LIST_TOKENS
|
|
299
|
+
list_marker = case type
|
|
300
|
+
when :BULLET then data
|
|
301
|
+
when :LABEL then "[#{data}]"
|
|
302
|
+
when :NOTE then "#{data}::"
|
|
303
|
+
else # :LALPHA, :NUMBER, :UALPHA
|
|
304
|
+
"#{data}."
|
|
305
|
+
end
|
|
306
|
+
line << list_marker
|
|
307
|
+
peek_type, _, peek_column = peek_token
|
|
308
|
+
unless peek_type == :NEWLINE
|
|
309
|
+
peek_column ||= column + list_marker.length
|
|
310
|
+
indent = peek_column - column - list_marker.length
|
|
311
|
+
line << ' ' * indent
|
|
312
|
+
end
|
|
313
|
+
end
|
|
273
314
|
|
|
274
|
-
case type
|
|
275
|
-
when :HEADER then
|
|
276
|
-
line << '=' * data
|
|
277
|
-
_, _, peek_column, = peek_token
|
|
278
|
-
peek_column ||= column + data
|
|
279
|
-
indent = peek_column - column - data
|
|
280
|
-
line << ' ' * indent
|
|
281
|
-
when :RULE then
|
|
282
|
-
width = 2 + data
|
|
283
|
-
line << '-' * width
|
|
284
|
-
_, _, peek_column, = peek_token
|
|
285
|
-
peek_column ||= column + width
|
|
286
|
-
indent = peek_column - column - width
|
|
287
|
-
line << ' ' * indent
|
|
288
|
-
when :BREAK, :TEXT then
|
|
289
|
-
line << data
|
|
290
|
-
when :BLOCKQUOTE then
|
|
291
|
-
line << '>>>'
|
|
292
|
-
peek_type, _, peek_column = peek_token
|
|
293
|
-
if peek_type != :NEWLINE and peek_column
|
|
294
|
-
line << ' ' * (peek_column - column - 3)
|
|
295
315
|
end
|
|
296
|
-
else # *LIST_TOKENS
|
|
297
|
-
list_marker = case type
|
|
298
|
-
when :BULLET then data
|
|
299
|
-
when :LABEL then "[#{data}]"
|
|
300
|
-
when :NOTE then "#{data}::"
|
|
301
|
-
else # :LALPHA, :NUMBER, :UALPHA
|
|
302
|
-
"#{data}."
|
|
303
|
-
end
|
|
304
|
-
line << list_marker
|
|
305
|
-
peek_type, _, peek_column = peek_token
|
|
306
|
-
unless peek_type == :NEWLINE then
|
|
307
|
-
peek_column ||= column + list_marker.length
|
|
308
|
-
indent = peek_column - column - list_marker.length
|
|
309
|
-
line << ' ' * indent
|
|
310
|
-
end
|
|
311
|
-
end
|
|
312
316
|
|
|
313
|
-
|
|
317
|
+
verbatim << line << "\n" unless line.empty?
|
|
318
|
+
verbatim.parts.each { |p| p.slice!(0, min_indent) unless p == "\n" } if min_indent > 0
|
|
319
|
+
verbatim.normalize
|
|
314
320
|
|
|
315
|
-
|
|
316
|
-
verbatim.parts.each { |p| p.slice!(0, min_indent) unless p == "\n" } if min_indent > 0
|
|
317
|
-
verbatim.normalize
|
|
321
|
+
p :verbatim_end => margin if @debug
|
|
318
322
|
|
|
319
|
-
|
|
323
|
+
verbatim
|
|
324
|
+
end
|
|
320
325
|
|
|
321
|
-
|
|
322
|
-
|
|
326
|
+
##
|
|
327
|
+
# Pulls the next token from the stream.
|
|
323
328
|
|
|
324
|
-
|
|
325
|
-
|
|
329
|
+
def get
|
|
330
|
+
@current_token = @tokens.shift
|
|
331
|
+
p :get => @current_token if @debug
|
|
332
|
+
@current_token
|
|
333
|
+
end
|
|
326
334
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
335
|
+
##
|
|
336
|
+
# Parses the tokens into an array of RDoc::Markup::XXX objects,
|
|
337
|
+
# and appends them to the passed +parent+ RDoc::Markup::YYY object.
|
|
338
|
+
#
|
|
339
|
+
# Exits at the end of the token stream, or when it encounters a token
|
|
340
|
+
# in a column less than +indent+ (unless it is a NEWLINE).
|
|
341
|
+
#
|
|
342
|
+
# Returns +parent+.
|
|
343
|
+
|
|
344
|
+
def parse(parent, indent = 0)
|
|
345
|
+
p :parse_start => indent if @debug
|
|
346
|
+
|
|
347
|
+
until @tokens.empty? do
|
|
348
|
+
type, data, column, = get
|
|
349
|
+
|
|
350
|
+
case type
|
|
351
|
+
when :BREAK
|
|
352
|
+
parent << Markup::BlankLine.new
|
|
353
|
+
skip :NEWLINE, false
|
|
354
|
+
next
|
|
355
|
+
when :NEWLINE
|
|
356
|
+
# trailing newlines are skipped below, so this is a blank line
|
|
357
|
+
parent << Markup::BlankLine.new
|
|
358
|
+
skip :NEWLINE, false
|
|
359
|
+
next
|
|
360
|
+
end
|
|
332
361
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
def parse(parent, indent = 0)
|
|
343
|
-
p :parse_start => indent if @debug
|
|
344
|
-
|
|
345
|
-
until @tokens.empty? do
|
|
346
|
-
type, data, column, = get
|
|
347
|
-
|
|
348
|
-
case type
|
|
349
|
-
when :BREAK then
|
|
350
|
-
parent << RDoc::Markup::BlankLine.new
|
|
351
|
-
skip :NEWLINE, false
|
|
352
|
-
next
|
|
353
|
-
when :NEWLINE then
|
|
354
|
-
# trailing newlines are skipped below, so this is a blank line
|
|
355
|
-
parent << RDoc::Markup::BlankLine.new
|
|
356
|
-
skip :NEWLINE, false
|
|
357
|
-
next
|
|
358
|
-
end
|
|
362
|
+
# indentation change: break or verbatim
|
|
363
|
+
if column < indent
|
|
364
|
+
unget
|
|
365
|
+
break
|
|
366
|
+
elsif column > indent
|
|
367
|
+
unget
|
|
368
|
+
parent << build_verbatim(indent)
|
|
369
|
+
next
|
|
370
|
+
end
|
|
359
371
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
372
|
+
# indentation is the same
|
|
373
|
+
case type
|
|
374
|
+
when :HEADER
|
|
375
|
+
parent << build_heading(data)
|
|
376
|
+
when :RULE
|
|
377
|
+
parent << Markup::Rule.new(data)
|
|
378
|
+
skip :NEWLINE
|
|
379
|
+
when :TEXT
|
|
380
|
+
unget
|
|
381
|
+
parse_text parent, indent
|
|
382
|
+
when :BLOCKQUOTE
|
|
383
|
+
nil while (type, = get; type) and type != :NEWLINE
|
|
384
|
+
_, _, column, = peek_token
|
|
385
|
+
bq = Markup::BlockQuote.new
|
|
386
|
+
p :blockquote_start => [data, column] if @debug
|
|
387
|
+
parse bq, column
|
|
388
|
+
p :blockquote_end => indent if @debug
|
|
389
|
+
parent << bq
|
|
390
|
+
when *LIST_TOKENS
|
|
391
|
+
unget
|
|
392
|
+
parent << build_list(indent)
|
|
393
|
+
else
|
|
394
|
+
type, data, column, line = @current_token
|
|
395
|
+
raise ParseError, "Unhandled token #{type} (#{data.inspect}) at #{line}:#{column}"
|
|
396
|
+
end
|
|
397
|
+
end
|
|
369
398
|
|
|
370
|
-
|
|
371
|
-
case type
|
|
372
|
-
when :HEADER then
|
|
373
|
-
parent << build_heading(data)
|
|
374
|
-
when :RULE then
|
|
375
|
-
parent << RDoc::Markup::Rule.new(data)
|
|
376
|
-
skip :NEWLINE
|
|
377
|
-
when :TEXT then
|
|
378
|
-
unget
|
|
379
|
-
parse_text parent, indent
|
|
380
|
-
when :BLOCKQUOTE then
|
|
381
|
-
nil while (type, = get; type) and type != :NEWLINE
|
|
382
|
-
_, _, column, = peek_token
|
|
383
|
-
bq = RDoc::Markup::BlockQuote.new
|
|
384
|
-
p :blockquote_start => [data, column] if @debug
|
|
385
|
-
parse bq, column
|
|
386
|
-
p :blockquote_end => indent if @debug
|
|
387
|
-
parent << bq
|
|
388
|
-
when *LIST_TOKENS then
|
|
389
|
-
unget
|
|
390
|
-
parent << build_list(indent)
|
|
391
|
-
else
|
|
392
|
-
type, data, column, line = @current_token
|
|
393
|
-
raise ParseError, "Unhandled token #{type} (#{data.inspect}) at #{line}:#{column}"
|
|
394
|
-
end
|
|
395
|
-
end
|
|
399
|
+
p :parse_end => indent if @debug
|
|
396
400
|
|
|
397
|
-
|
|
401
|
+
parent
|
|
398
402
|
|
|
399
|
-
|
|
403
|
+
end
|
|
400
404
|
|
|
401
|
-
|
|
405
|
+
##
|
|
406
|
+
# Small hook that is overridden by RDoc::TomDoc
|
|
402
407
|
|
|
403
|
-
|
|
404
|
-
|
|
408
|
+
def parse_text(parent, indent) # :nodoc:
|
|
409
|
+
parent << build_paragraph(indent)
|
|
410
|
+
end
|
|
405
411
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
end
|
|
412
|
+
##
|
|
413
|
+
# Returns the next token on the stream without modifying the stream
|
|
409
414
|
|
|
410
|
-
|
|
411
|
-
|
|
415
|
+
def peek_token
|
|
416
|
+
token = @tokens.first || []
|
|
417
|
+
p :peek => token if @debug
|
|
418
|
+
token
|
|
419
|
+
end
|
|
412
420
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
p :peek => token if @debug
|
|
416
|
-
token
|
|
417
|
-
end
|
|
421
|
+
##
|
|
422
|
+
# A simple wrapper of StringScanner that is aware of the current column and lineno
|
|
418
423
|
|
|
419
|
-
|
|
420
|
-
|
|
424
|
+
class MyStringScanner
|
|
425
|
+
# :stopdoc:
|
|
421
426
|
|
|
422
|
-
|
|
423
|
-
|
|
427
|
+
def initialize(input)
|
|
428
|
+
@line = @column = 0
|
|
429
|
+
@s = StringScanner.new input
|
|
430
|
+
end
|
|
424
431
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
432
|
+
def scan(re)
|
|
433
|
+
ret = @s.scan(re)
|
|
434
|
+
@column += ret.length if ret
|
|
435
|
+
ret
|
|
436
|
+
end
|
|
429
437
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
end
|
|
438
|
+
def unscan(s)
|
|
439
|
+
@s.pos -= s.bytesize
|
|
440
|
+
@column -= s.length
|
|
441
|
+
end
|
|
435
442
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
end
|
|
443
|
+
def pos
|
|
444
|
+
[@column, @line]
|
|
445
|
+
end
|
|
440
446
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
447
|
+
def newline!
|
|
448
|
+
@column = 0
|
|
449
|
+
@line += 1
|
|
450
|
+
end
|
|
444
451
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
end
|
|
452
|
+
def eos?
|
|
453
|
+
@s.eos?
|
|
454
|
+
end
|
|
449
455
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
456
|
+
def matched
|
|
457
|
+
@s.matched
|
|
458
|
+
end
|
|
453
459
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
460
|
+
def [](i)
|
|
461
|
+
@s[i]
|
|
462
|
+
end
|
|
457
463
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
end
|
|
464
|
+
#:startdoc:
|
|
465
|
+
end
|
|
461
466
|
|
|
462
|
-
|
|
463
|
-
|
|
467
|
+
##
|
|
468
|
+
# Creates the StringScanner
|
|
464
469
|
|
|
465
|
-
|
|
466
|
-
|
|
470
|
+
def setup_scanner(input)
|
|
471
|
+
@s = MyStringScanner.new input
|
|
472
|
+
end
|
|
467
473
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
474
|
+
##
|
|
475
|
+
# Skips the next token if its type is +token_type+.
|
|
476
|
+
#
|
|
477
|
+
# Optionally raises an error if the next token is not of the expected type.
|
|
471
478
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
return unless type # end of stream
|
|
480
|
-
return @current_token if token_type == type
|
|
481
|
-
unget
|
|
482
|
-
raise ParseError, "expected #{token_type} got #{@current_token.inspect}" if error
|
|
483
|
-
end
|
|
479
|
+
def skip(token_type, error = true)
|
|
480
|
+
type, = get
|
|
481
|
+
return unless type # end of stream
|
|
482
|
+
return @current_token if token_type == type
|
|
483
|
+
unget
|
|
484
|
+
raise ParseError, "expected #{token_type} got #{@current_token.inspect}" if error
|
|
485
|
+
end
|
|
484
486
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
487
|
+
##
|
|
488
|
+
# Turns text +input+ into a stream of tokens
|
|
489
|
+
|
|
490
|
+
def tokenize(input)
|
|
491
|
+
setup_scanner input
|
|
492
|
+
|
|
493
|
+
until @s.eos? do
|
|
494
|
+
pos = @s.pos
|
|
495
|
+
|
|
496
|
+
# leading spaces will be reflected by the column of the next token
|
|
497
|
+
# the only thing we loose are trailing spaces at the end of the file
|
|
498
|
+
next if @s.scan(/ +/)
|
|
499
|
+
|
|
500
|
+
# note: after BULLET, LABEL, etc.,
|
|
501
|
+
# indent will be the column of the next non-newline token
|
|
502
|
+
|
|
503
|
+
@tokens << case
|
|
504
|
+
# [CR]LF => :NEWLINE
|
|
505
|
+
when @s.scan(/\r?\n/)
|
|
506
|
+
token = [:NEWLINE, @s.matched, *pos]
|
|
507
|
+
@s.newline!
|
|
508
|
+
token
|
|
509
|
+
# === text => :HEADER then :TEXT
|
|
510
|
+
when @s.scan(/(=+)(\s*)/)
|
|
511
|
+
level = @s[1].length
|
|
512
|
+
header = [:HEADER, level, *pos]
|
|
513
|
+
|
|
514
|
+
if @s[2] =~ /^\r?\n/
|
|
515
|
+
@s.unscan(@s[2])
|
|
516
|
+
header
|
|
517
|
+
else
|
|
518
|
+
pos = @s.pos
|
|
519
|
+
@s.scan(/.*/)
|
|
520
|
+
@tokens << header
|
|
521
|
+
[:TEXT, @s.matched.sub(/\r$/, ''), *pos]
|
|
522
|
+
end
|
|
523
|
+
# --- (at least 3) and nothing else on the line => :RULE
|
|
524
|
+
when @s.scan(/(-{3,}) *\r?$/)
|
|
525
|
+
[:RULE, @s[1].length - 2, *pos]
|
|
526
|
+
# * or - followed by white space and text => :BULLET
|
|
527
|
+
when @s.scan(/([*-]) +(\S)/)
|
|
528
|
+
@s.unscan(@s[2])
|
|
529
|
+
[:BULLET, @s[1], *pos]
|
|
530
|
+
# A. text, a. text, 12. text => :UALPHA, :LALPHA, :NUMBER
|
|
531
|
+
when @s.scan(/([a-z]|\d+)\. +(\S)/i)
|
|
532
|
+
# FIXME if tab(s), the column will be wrong
|
|
533
|
+
# either support tabs everywhere by first expanding them to
|
|
534
|
+
# spaces, or assume that they will have been replaced
|
|
535
|
+
# before (and provide a check for that at least in debug
|
|
536
|
+
# mode)
|
|
537
|
+
list_label = @s[1]
|
|
538
|
+
@s.unscan(@s[2])
|
|
539
|
+
list_type =
|
|
540
|
+
case list_label
|
|
541
|
+
when /[a-z]/ then :LALPHA
|
|
542
|
+
when /[A-Z]/ then :UALPHA
|
|
543
|
+
when /\d/ then :NUMBER
|
|
544
|
+
else
|
|
545
|
+
raise ParseError, "BUG token #{list_label}"
|
|
546
|
+
end
|
|
547
|
+
[list_type, list_label, *pos]
|
|
548
|
+
# [text] followed by spaces or end of line => :LABEL
|
|
549
|
+
when @s.scan(/\[(.*?)\]( +|\r?$)/)
|
|
550
|
+
[:LABEL, @s[1], *pos]
|
|
551
|
+
# text:: followed by spaces or end of line => :NOTE
|
|
552
|
+
when @s.scan(/(.*?)::( +|\r?$)/)
|
|
553
|
+
[:NOTE, @s[1], *pos]
|
|
554
|
+
# >>> followed by end of line => :BLOCKQUOTE
|
|
555
|
+
when @s.scan(/>>> *(\w+)?$/)
|
|
556
|
+
if word = @s[1]
|
|
557
|
+
@s.unscan(word)
|
|
558
|
+
end
|
|
559
|
+
[:BLOCKQUOTE, word, *pos]
|
|
560
|
+
# anything else: :TEXT
|
|
542
561
|
else
|
|
543
|
-
|
|
562
|
+
@s.scan(/(.*?)( )?\r?$/)
|
|
563
|
+
token = [:TEXT, @s[1], *pos]
|
|
564
|
+
|
|
565
|
+
if @s[2]
|
|
566
|
+
@tokens << token
|
|
567
|
+
[:BREAK, @s[2], pos[0] + @s[1].length, pos[1]]
|
|
568
|
+
else
|
|
569
|
+
token
|
|
570
|
+
end
|
|
544
571
|
end
|
|
545
|
-
|
|
546
|
-
# [text] followed by spaces or end of line => :LABEL
|
|
547
|
-
when @s.scan(/\[(.*?)\]( +|\r?$)/) then
|
|
548
|
-
[:LABEL, @s[1], *pos]
|
|
549
|
-
# text:: followed by spaces or end of line => :NOTE
|
|
550
|
-
when @s.scan(/(.*?)::( +|\r?$)/) then
|
|
551
|
-
[:NOTE, @s[1], *pos]
|
|
552
|
-
# >>> followed by end of line => :BLOCKQUOTE
|
|
553
|
-
when @s.scan(/>>> *(\w+)?$/) then
|
|
554
|
-
if word = @s[1]
|
|
555
|
-
@s.unscan(word)
|
|
556
|
-
end
|
|
557
|
-
[:BLOCKQUOTE, word, *pos]
|
|
558
|
-
# anything else: :TEXT
|
|
559
|
-
else
|
|
560
|
-
@s.scan(/(.*?)( )?\r?$/)
|
|
561
|
-
token = [:TEXT, @s[1], *pos]
|
|
562
|
-
|
|
563
|
-
if @s[2] then
|
|
564
|
-
@tokens << token
|
|
565
|
-
[:BREAK, @s[2], pos[0] + @s[1].length, pos[1]]
|
|
566
|
-
else
|
|
567
|
-
token
|
|
568
|
-
end
|
|
569
|
-
end
|
|
570
|
-
end
|
|
572
|
+
end
|
|
571
573
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
+
self
|
|
575
|
+
end
|
|
574
576
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
+
##
|
|
578
|
+
# Returns the current token to the token stream
|
|
577
579
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
580
|
+
def unget
|
|
581
|
+
token = @current_token
|
|
582
|
+
p :unget => token if @debug
|
|
583
|
+
raise Error, 'too many #ungets' if token == @tokens.first
|
|
584
|
+
@tokens.unshift token if token
|
|
585
|
+
end
|
|
584
586
|
|
|
587
|
+
end
|
|
588
|
+
end
|
|
585
589
|
end
|