bean-kramdown 0.13.5
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/AUTHORS +1 -0
- data/CONTRIBUTERS +11 -0
- data/COPYING +24 -0
- data/ChangeLog +6683 -0
- data/GPL +674 -0
- data/README +43 -0
- data/VERSION +1 -0
- data/bin/kramdown +78 -0
- data/lib/kramdown.rb +23 -0
- data/lib/kramdown/compatibility.rb +49 -0
- data/lib/kramdown/converter.rb +41 -0
- data/lib/kramdown/converter/base.rb +169 -0
- data/lib/kramdown/converter/bean_html.rb +71 -0
- data/lib/kramdown/converter/html.rb +411 -0
- data/lib/kramdown/converter/kramdown.rb +428 -0
- data/lib/kramdown/converter/latex.rb +607 -0
- data/lib/kramdown/converter/toc.rb +82 -0
- data/lib/kramdown/document.rb +119 -0
- data/lib/kramdown/element.rb +524 -0
- data/lib/kramdown/error.rb +30 -0
- data/lib/kramdown/options.rb +373 -0
- data/lib/kramdown/parser.rb +39 -0
- data/lib/kramdown/parser/base.rb +136 -0
- data/lib/kramdown/parser/bean_kramdown.rb +25 -0
- data/lib/kramdown/parser/bean_kramdown/info_box.rb +52 -0
- data/lib/kramdown/parser/bean_kramdown/oembed.rb +230 -0
- data/lib/kramdown/parser/html.rb +570 -0
- data/lib/kramdown/parser/kramdown.rb +339 -0
- data/lib/kramdown/parser/kramdown/abbreviation.rb +71 -0
- data/lib/kramdown/parser/kramdown/autolink.rb +53 -0
- data/lib/kramdown/parser/kramdown/blank_line.rb +43 -0
- data/lib/kramdown/parser/kramdown/block_boundary.rb +46 -0
- data/lib/kramdown/parser/kramdown/blockquote.rb +51 -0
- data/lib/kramdown/parser/kramdown/codeblock.rb +63 -0
- data/lib/kramdown/parser/kramdown/codespan.rb +56 -0
- data/lib/kramdown/parser/kramdown/emphasis.rb +70 -0
- data/lib/kramdown/parser/kramdown/eob.rb +39 -0
- data/lib/kramdown/parser/kramdown/escaped_chars.rb +38 -0
- data/lib/kramdown/parser/kramdown/extensions.rb +204 -0
- data/lib/kramdown/parser/kramdown/footnote.rb +74 -0
- data/lib/kramdown/parser/kramdown/header.rb +68 -0
- data/lib/kramdown/parser/kramdown/horizontal_rule.rb +39 -0
- data/lib/kramdown/parser/kramdown/html.rb +169 -0
- data/lib/kramdown/parser/kramdown/html_entity.rb +44 -0
- data/lib/kramdown/parser/kramdown/image.rb +157 -0
- data/lib/kramdown/parser/kramdown/line_break.rb +38 -0
- data/lib/kramdown/parser/kramdown/link.rb +154 -0
- data/lib/kramdown/parser/kramdown/list.rb +240 -0
- data/lib/kramdown/parser/kramdown/math.rb +65 -0
- data/lib/kramdown/parser/kramdown/paragraph.rb +63 -0
- data/lib/kramdown/parser/kramdown/smart_quotes.rb +214 -0
- data/lib/kramdown/parser/kramdown/table.rb +178 -0
- data/lib/kramdown/parser/kramdown/typographic_symbol.rb +52 -0
- data/lib/kramdown/parser/markdown.rb +69 -0
- data/lib/kramdown/utils.rb +42 -0
- data/lib/kramdown/utils/entities.rb +348 -0
- data/lib/kramdown/utils/html.rb +85 -0
- data/lib/kramdown/utils/ordered_hash.rb +100 -0
- data/lib/kramdown/version.rb +28 -0
- metadata +140 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2009-2012 Thomas Leitner <t_leitner@gmx.at>
|
5
|
+
#
|
6
|
+
# This file is part of kramdown.
|
7
|
+
#
|
8
|
+
# kramdown is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
module Kramdown
|
24
|
+
|
25
|
+
# This error is raised when an error condition is encountered.
|
26
|
+
#
|
27
|
+
# *Note* that this error is only raised by the support framework for the parsers and converters.
|
28
|
+
class Error < RuntimeError; end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,373 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2009-2012 Thomas Leitner <t_leitner@gmx.at>
|
5
|
+
#
|
6
|
+
# This file is part of kramdown.
|
7
|
+
#
|
8
|
+
# kramdown is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
module Kramdown
|
24
|
+
|
25
|
+
# This module defines all options that are used by parsers and/or converters as well as providing
|
26
|
+
# methods to deal with the options.
|
27
|
+
module Options
|
28
|
+
|
29
|
+
# Helper class introducing a boolean type for specifying boolean values (+true+ and +false+) as
|
30
|
+
# option types.
|
31
|
+
class Boolean
|
32
|
+
|
33
|
+
# Return +true+ if +other+ is either +true+ or +false+
|
34
|
+
def self.===(other)
|
35
|
+
FalseClass === other || TrueClass === other
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
# ----------------------------
|
41
|
+
# :section: Option definitions
|
42
|
+
#
|
43
|
+
# This sections describes the methods that can be used on the Options module.
|
44
|
+
# ----------------------------
|
45
|
+
|
46
|
+
# Struct class for storing the definition of an option.
|
47
|
+
Definition = Struct.new(:name, :type, :default, :desc, :validator)
|
48
|
+
|
49
|
+
# Allowed option types.
|
50
|
+
ALLOWED_TYPES = [String, Integer, Float, Symbol, Boolean, Object]
|
51
|
+
|
52
|
+
@options = {}
|
53
|
+
|
54
|
+
# Define a new option called +name+ (a Symbol) with the given +type+ (String, Integer, Float,
|
55
|
+
# Symbol, Boolean, Object), default value +default+ and the description +desc+. If a block is
|
56
|
+
# specified, it should validate the value and either raise an error or return a valid value.
|
57
|
+
#
|
58
|
+
# The type 'Object' should only be used for complex types for which none of the other types
|
59
|
+
# suffices. A block needs to be specified when using type 'Object' and it has to cope with
|
60
|
+
# a value given as string and as the opaque type.
|
61
|
+
def self.define(name, type, default, desc, &block)
|
62
|
+
raise ArgumentError, "Option name #{name} is already used" if @options.has_key?(name)
|
63
|
+
raise ArgumentError, "Invalid option type #{type} specified" if !ALLOWED_TYPES.include?(type)
|
64
|
+
raise ArgumentError, "Invalid type for default value" if !(type === default) && !default.nil?
|
65
|
+
raise ArgumentError, "Missing validator block" if type == Object && block.nil?
|
66
|
+
@options[name] = Definition.new(name, type, default, desc, block)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Return all option definitions.
|
70
|
+
def self.definitions
|
71
|
+
@options
|
72
|
+
end
|
73
|
+
|
74
|
+
# Return +true+ if an option called +name+ is defined.
|
75
|
+
def self.defined?(name)
|
76
|
+
@options.has_key?(name)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Return a Hash with the default values for all options.
|
80
|
+
def self.defaults
|
81
|
+
temp = {}
|
82
|
+
@options.each {|n, o| temp[o.name] = o.default}
|
83
|
+
temp
|
84
|
+
end
|
85
|
+
|
86
|
+
# Merge the #defaults Hash with the *parsed* options from the given Hash, i.e. only valid option
|
87
|
+
# names are considered and their value is run through the #parse method.
|
88
|
+
def self.merge(hash)
|
89
|
+
temp = defaults
|
90
|
+
hash.each do |k,v|
|
91
|
+
next unless @options.has_key?(k)
|
92
|
+
temp[k] = parse(k, v)
|
93
|
+
end
|
94
|
+
temp
|
95
|
+
end
|
96
|
+
|
97
|
+
# Parse the given value +data+ as if it was a value for the option +name+ and return the parsed
|
98
|
+
# value with the correct type.
|
99
|
+
#
|
100
|
+
# If +data+ already has the correct type, it is just returned. Otherwise it is converted to a
|
101
|
+
# String and then to the correct type.
|
102
|
+
def self.parse(name, data)
|
103
|
+
raise ArgumentError, "No option named #{name} defined" if !@options.has_key?(name)
|
104
|
+
if !(@options[name].type === data)
|
105
|
+
data = data.to_s
|
106
|
+
data = if @options[name].type == String
|
107
|
+
data
|
108
|
+
elsif @options[name].type == Integer
|
109
|
+
Integer(data) rescue raise Kramdown::Error, "Invalid integer value for option '#{name}': '#{data}'"
|
110
|
+
elsif @options[name].type == Float
|
111
|
+
Float(data) rescue raise Kramdown::Error, "Invalid float value for option '#{name}': '#{data}'"
|
112
|
+
elsif @options[name].type == Symbol
|
113
|
+
(data.strip.empty? ? nil : data.to_sym)
|
114
|
+
elsif @options[name].type == Boolean
|
115
|
+
data.downcase.strip != 'false' && !data.empty?
|
116
|
+
end
|
117
|
+
end
|
118
|
+
data = @options[name].validator[data] if @options[name].validator
|
119
|
+
data
|
120
|
+
end
|
121
|
+
|
122
|
+
# ----------------------------
|
123
|
+
# :section: Option Validators
|
124
|
+
#
|
125
|
+
# This sections contains all pre-defined option validators.
|
126
|
+
# ----------------------------
|
127
|
+
|
128
|
+
# Ensures that the option value +val+ for the option called +name+ is a valid array. The
|
129
|
+
# parameter +val+ can be
|
130
|
+
#
|
131
|
+
# - a comma separated string which is split into an array of values
|
132
|
+
# - or an array.
|
133
|
+
#
|
134
|
+
# Additionally, the array is checked for the correct size.
|
135
|
+
def self.simple_array_validator(val, name, size)
|
136
|
+
if String === val
|
137
|
+
val = val.split(/,/)
|
138
|
+
elsif !(Array === val)
|
139
|
+
raise Kramdown::Error, "Invalid type #{val.class} for option #{name}"
|
140
|
+
end
|
141
|
+
if val.size != size
|
142
|
+
raise Kramdown::Error, "Option #{name} needs exactly #{size} values"
|
143
|
+
end
|
144
|
+
val
|
145
|
+
end
|
146
|
+
|
147
|
+
# ----------------------------
|
148
|
+
# :section: Option Definitions
|
149
|
+
#
|
150
|
+
# This sections contains all option definitions that are used by the included
|
151
|
+
# parsers/converters.
|
152
|
+
# ----------------------------
|
153
|
+
|
154
|
+
define(:template, String, '', <<EOF)
|
155
|
+
The name of an ERB template file that should be used to wrap the output
|
156
|
+
|
157
|
+
This is used to wrap the output in an environment so that the output can
|
158
|
+
be used as a stand-alone document. For example, an HTML template would
|
159
|
+
provide the needed header and body tags so that the whole output is a
|
160
|
+
valid HTML file. If no template is specified, the output will be just
|
161
|
+
the converted text.
|
162
|
+
|
163
|
+
When resolving the template file, the given template name is used first.
|
164
|
+
If such a file is not found, the converter extension is appended. If the
|
165
|
+
file still cannot be found, the templates name is interpreted as a
|
166
|
+
template name that is provided by kramdown (without the converter
|
167
|
+
extension).
|
168
|
+
|
169
|
+
kramdown provides a default template named 'document' for each converter.
|
170
|
+
|
171
|
+
Default: ''
|
172
|
+
Used by: all converters
|
173
|
+
EOF
|
174
|
+
|
175
|
+
define(:auto_ids, Boolean, true, <<EOF)
|
176
|
+
Use automatic header ID generation
|
177
|
+
|
178
|
+
If this option is `true`, ID values for all headers are automatically
|
179
|
+
generated if no ID is explicitly specified.
|
180
|
+
|
181
|
+
Default: true
|
182
|
+
Used by: HTML/Latex converter
|
183
|
+
EOF
|
184
|
+
|
185
|
+
define(:auto_id_prefix, String, '', <<EOF)
|
186
|
+
Prefix used for automatically generated heaer IDs
|
187
|
+
|
188
|
+
This option can be used to set a prefix for the automatically generated
|
189
|
+
header IDs so that there is no conflict when rendering multiple kramdown
|
190
|
+
documents into one output file separately. The prefix should only
|
191
|
+
contain characters that are valid in an ID!
|
192
|
+
|
193
|
+
Default: ''
|
194
|
+
Used by: HTML/Latex converter
|
195
|
+
EOF
|
196
|
+
|
197
|
+
define(:parse_block_html, Boolean, false, <<EOF)
|
198
|
+
Process kramdown syntax in block HTML tags
|
199
|
+
|
200
|
+
If this option is `true`, the kramdown parser processes the content of
|
201
|
+
block HTML tags as text containing block-level elements. Since this is
|
202
|
+
not wanted normally, the default is `false`. It is normally better to
|
203
|
+
selectively enable kramdown processing via the markdown attribute.
|
204
|
+
|
205
|
+
Default: false
|
206
|
+
Used by: kramdown parser
|
207
|
+
EOF
|
208
|
+
|
209
|
+
define(:parse_span_html, Boolean, true, <<EOF)
|
210
|
+
Process kramdown syntax in span HTML tags
|
211
|
+
|
212
|
+
If this option is `true`, the kramdown parser processes the content of
|
213
|
+
span HTML tags as text containing span-level elements.
|
214
|
+
|
215
|
+
Default: true
|
216
|
+
Used by: kramdown parser
|
217
|
+
EOF
|
218
|
+
|
219
|
+
define(:html_to_native, Boolean, false, <<EOF)
|
220
|
+
Convert HTML elements to native elements
|
221
|
+
|
222
|
+
If this option is `true`, the parser converts HTML elements to native
|
223
|
+
elements. For example, when parsing `<em>hallo</em>` the emphasis tag
|
224
|
+
would normally be converted to an `:html` element with tag type `:em`.
|
225
|
+
If `html_to_native` is `true`, then the emphasis would be converted to a
|
226
|
+
native `:em` element.
|
227
|
+
|
228
|
+
This is useful for converters that cannot deal with HTML elements.
|
229
|
+
|
230
|
+
Default: false
|
231
|
+
Used by: kramdown parser
|
232
|
+
EOF
|
233
|
+
|
234
|
+
define(:footnote_nr, Integer, 1, <<EOF)
|
235
|
+
The number of the first footnote
|
236
|
+
|
237
|
+
This option can be used to specify the number that is used for the first
|
238
|
+
footnote.
|
239
|
+
|
240
|
+
Default: 1
|
241
|
+
Used by: HTML converter
|
242
|
+
EOF
|
243
|
+
|
244
|
+
define(:coderay_wrap, Symbol, :div, <<EOF)
|
245
|
+
Defines how the highlighted code should be wrapped
|
246
|
+
|
247
|
+
The possible values are :span, :div or nil.
|
248
|
+
|
249
|
+
Default: :div
|
250
|
+
Used by: HTML converter
|
251
|
+
EOF
|
252
|
+
|
253
|
+
define(:coderay_line_numbers, Symbol, :inline, <<EOF)
|
254
|
+
Defines how and if line numbers should be shown
|
255
|
+
|
256
|
+
The possible values are :table, :inline, :list or nil. If this option is
|
257
|
+
nil, no line numbers are shown.
|
258
|
+
|
259
|
+
Default: :inline
|
260
|
+
Used by: HTML converter
|
261
|
+
EOF
|
262
|
+
|
263
|
+
define(:coderay_line_number_start, Integer, 1, <<EOF)
|
264
|
+
The start value for the line numbers
|
265
|
+
|
266
|
+
Default: 1
|
267
|
+
Used by: HTML converter
|
268
|
+
EOF
|
269
|
+
|
270
|
+
define(:coderay_tab_width, Integer, 8, <<EOF)
|
271
|
+
The tab width used in highlighted code
|
272
|
+
|
273
|
+
Used by: HTML converter
|
274
|
+
EOF
|
275
|
+
|
276
|
+
define(:coderay_bold_every, Integer, 10, <<EOF)
|
277
|
+
Defines how often a line number should be made bold
|
278
|
+
|
279
|
+
Default: 10
|
280
|
+
Used by: HTML converter
|
281
|
+
EOF
|
282
|
+
|
283
|
+
define(:coderay_css, Symbol, :style, <<EOF)
|
284
|
+
Defines how the highlighted code gets styled
|
285
|
+
|
286
|
+
Possible values are :class (CSS classes are applied to the code
|
287
|
+
elements, one must supply the needed CSS file) or :style (default CSS
|
288
|
+
styles are directly applied to the code elements).
|
289
|
+
|
290
|
+
Default: style
|
291
|
+
Used by: HTML converter
|
292
|
+
EOF
|
293
|
+
|
294
|
+
define(:entity_output, Symbol, :as_char, <<EOF)
|
295
|
+
Defines how entities are output
|
296
|
+
|
297
|
+
The possible values are :as_input (entities are output in the same
|
298
|
+
form as found in the input), :numeric (entities are output in numeric
|
299
|
+
form), :symbolic (entities are output in symbolic form if possible) or
|
300
|
+
:as_char (entities are output as characters if possible, only available
|
301
|
+
on Ruby 1.9).
|
302
|
+
|
303
|
+
Default: :as_char
|
304
|
+
Used by: HTML converter, kramdown converter
|
305
|
+
EOF
|
306
|
+
|
307
|
+
define(:toc_levels, Object, (1..6).to_a, <<EOF) do |val|
|
308
|
+
Defines the levels that are used for the table of contents
|
309
|
+
|
310
|
+
The individual levels can be specified by separating them with commas
|
311
|
+
(e.g. 1,2,3) or by using the range syntax (e.g. 1..3). Only the
|
312
|
+
specified levels are used for the table of contents.
|
313
|
+
|
314
|
+
Default: 1..6
|
315
|
+
Used by: HTML/Latex converter
|
316
|
+
EOF
|
317
|
+
if String === val
|
318
|
+
if val =~ /^(\d)\.\.(\d)$/
|
319
|
+
val = Range.new($1.to_i, $2.to_i).to_a
|
320
|
+
elsif val =~ /^\d(?:,\d)*$/
|
321
|
+
val = val.split(/,/).map {|s| s.to_i}.uniq
|
322
|
+
else
|
323
|
+
raise Kramdown::Error, "Invalid syntax for option toc_levels"
|
324
|
+
end
|
325
|
+
elsif Array === val
|
326
|
+
val = val.map {|s| s.to_i}.uniq
|
327
|
+
else
|
328
|
+
raise Kramdown::Error, "Invalid type #{val.class} for option toc_levels"
|
329
|
+
end
|
330
|
+
if val.any? {|i| !(1..6).include?(i)}
|
331
|
+
raise Kramdown::Error, "Level numbers for option toc_levels have to be integers from 1 to 6"
|
332
|
+
end
|
333
|
+
val
|
334
|
+
end
|
335
|
+
|
336
|
+
define(:line_width, Integer, 72, <<EOF)
|
337
|
+
Defines the line width to be used when outputting a document
|
338
|
+
|
339
|
+
Default: 72
|
340
|
+
Used by: kramdown converter
|
341
|
+
EOF
|
342
|
+
|
343
|
+
define(:latex_headers, Object, %w{section subsection subsubsection paragraph subparagraph subparagraph}, <<EOF) do |val|
|
344
|
+
Defines the LaTeX commands for different header levels
|
345
|
+
|
346
|
+
The commands for the header levels one to six can be specified by
|
347
|
+
separating them with commas.
|
348
|
+
|
349
|
+
Default: section,subsection,subsubsection,paragraph,subparagraph,subsubparagraph
|
350
|
+
Used by: Latex converter
|
351
|
+
EOF
|
352
|
+
simple_array_validator(val, :latex_headers, 6)
|
353
|
+
end
|
354
|
+
|
355
|
+
define(:smart_quotes, Object, %w{lsquo rsquo ldquo rdquo}, <<EOF) do |val|
|
356
|
+
Defines the HTML entity names or code points for smart quote output
|
357
|
+
|
358
|
+
The entities identified by entity name or code point that should be
|
359
|
+
used for, in order, a left single quote, a right single quote, a left
|
360
|
+
double and a right double quote are specified by separating them with
|
361
|
+
commas.
|
362
|
+
|
363
|
+
Default: lsquo,rsquo,ldquo,rdquo
|
364
|
+
Used by: HTML/Latex converter
|
365
|
+
EOF
|
366
|
+
val = simple_array_validator(val, :smart_quotes, 4)
|
367
|
+
val.map! {|v| Integer(v) rescue v}
|
368
|
+
val
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
372
|
+
|
373
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2009-2012 Thomas Leitner <t_leitner@gmx.at>
|
5
|
+
#
|
6
|
+
# This file is part of kramdown.
|
7
|
+
#
|
8
|
+
# kramdown is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
module Kramdown
|
24
|
+
|
25
|
+
# This module contains all available parsers. A parser takes an input string and converts the
|
26
|
+
# string to an element tree.
|
27
|
+
#
|
28
|
+
# New parsers should be derived from the Base class which provides common functionality - see its
|
29
|
+
# API documentation for how to create a custom converter class.
|
30
|
+
module Parser
|
31
|
+
|
32
|
+
autoload :Base, 'kramdown/parser/base'
|
33
|
+
autoload :Kramdown, 'kramdown/parser/kramdown'
|
34
|
+
autoload :Html, 'kramdown/parser/html'
|
35
|
+
autoload :Markdown, 'kramdown/parser/markdown'
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2009-2012 Thomas Leitner <t_leitner@gmx.at>
|
5
|
+
#
|
6
|
+
# This file is part of kramdown.
|
7
|
+
#
|
8
|
+
# kramdown is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
module Kramdown
|
24
|
+
|
25
|
+
module Parser
|
26
|
+
|
27
|
+
# == \Base class for parsers
|
28
|
+
#
|
29
|
+
# This class serves as base class for parsers. It provides common methods that can/should be
|
30
|
+
# used by all parsers, especially by those using StringScanner for parsing.
|
31
|
+
#
|
32
|
+
# A parser object is used as a throw-away object, i.e. it is only used for storing the needed
|
33
|
+
# state information during parsing. Therefore one can't instantiate a parser object directly but
|
34
|
+
# only use the Base::parse method.
|
35
|
+
#
|
36
|
+
# == Implementing a parser
|
37
|
+
#
|
38
|
+
# Implementing a new parser is rather easy: just derive a new class from this class and put it
|
39
|
+
# in the Kramdown::Parser module -- the latter is needed so that the auto-detection of the new
|
40
|
+
# parser works correctly. Then you need to implement the +#parse+ method which has to contain
|
41
|
+
# the parsing code.
|
42
|
+
#
|
43
|
+
# Have a look at the Base::parse, Base::new and Base#parse methods for additional information!
|
44
|
+
class Base
|
45
|
+
|
46
|
+
# The hash with the parsing options.
|
47
|
+
attr_reader :options
|
48
|
+
|
49
|
+
# The array with the parser warnings.
|
50
|
+
attr_reader :warnings
|
51
|
+
|
52
|
+
# The original source string.
|
53
|
+
attr_reader :source
|
54
|
+
|
55
|
+
# The root element of element tree that is created from the source string.
|
56
|
+
attr_reader :root
|
57
|
+
|
58
|
+
# Initialize the parser object with the +source+ string and the parsing +options+.
|
59
|
+
#
|
60
|
+
# The @root element, the @warnings array and @text_type (specifies the default type for newly
|
61
|
+
# created text nodes) are automatically initialized.
|
62
|
+
def initialize(source, options)
|
63
|
+
@source = source
|
64
|
+
@options = Kramdown::Options.merge(options)
|
65
|
+
@root = Element.new(:root, nil, nil, :encoding => (RUBY_VERSION >= '1.9' ? source.encoding : nil))
|
66
|
+
@warnings = []
|
67
|
+
@text_type = :text
|
68
|
+
end
|
69
|
+
private_class_method(:new, :allocate)
|
70
|
+
|
71
|
+
# Parse the +source+ string into an element tree, possibly using the parsing +options+, and
|
72
|
+
# return the root element of the element tree and an array with warning messages.
|
73
|
+
#
|
74
|
+
# Initializes a new instance of the calling class and then calls the +#parse+ method that must
|
75
|
+
# be implemented by each subclass.
|
76
|
+
def self.parse(source, options = {})
|
77
|
+
parser = new(source, options)
|
78
|
+
parser.parse
|
79
|
+
[parser.root, parser.warnings]
|
80
|
+
end
|
81
|
+
|
82
|
+
# Parse the source string into an element tree.
|
83
|
+
#
|
84
|
+
# The parsing code should parse the source provided in @source and build an element tree the
|
85
|
+
# root of which should be @root.
|
86
|
+
#
|
87
|
+
# This is the only method that has to be implemented by sub-classes!
|
88
|
+
def parse
|
89
|
+
raise NotImplementedError
|
90
|
+
end
|
91
|
+
|
92
|
+
# Add the given warning +text+ to the warning array.
|
93
|
+
def warning(text)
|
94
|
+
@warnings << text
|
95
|
+
#TODO: add position information
|
96
|
+
end
|
97
|
+
|
98
|
+
# Modify the string +source+ to be usable by the parser (unifies line ending characters to
|
99
|
+
# +\n+ and makes sure +source+ ends with a new line character).
|
100
|
+
def adapt_source(source)
|
101
|
+
source.gsub(/\r\n?/, "\n").chomp + "\n"
|
102
|
+
end
|
103
|
+
|
104
|
+
# This helper method adds the given +text+ either to the last element in the +tree+ if it is a
|
105
|
+
# +type+ element or creates a new text element with the given +type+.
|
106
|
+
def add_text(text, tree = @tree, type = @text_type)
|
107
|
+
if tree.children.last && tree.children.last.type == type
|
108
|
+
tree.children.last.value << text
|
109
|
+
elsif !text.empty?
|
110
|
+
tree.children << Element.new(type, text)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Extract the part of the StringScanner +strscan+ backed string specified by the +range+. This
|
115
|
+
# method works correctly under Ruby 1.8 and Ruby 1.9.
|
116
|
+
def extract_string(range, strscan)
|
117
|
+
result = nil
|
118
|
+
if RUBY_VERSION >= '1.9'
|
119
|
+
begin
|
120
|
+
enc = strscan.string.encoding
|
121
|
+
strscan.string.force_encoding('ASCII-8BIT')
|
122
|
+
result = strscan.string[range].force_encoding(enc)
|
123
|
+
ensure
|
124
|
+
strscan.string.force_encoding(enc)
|
125
|
+
end
|
126
|
+
else
|
127
|
+
result = strscan.string[range]
|
128
|
+
end
|
129
|
+
result
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|