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.
Files changed (60) hide show
  1. data/AUTHORS +1 -0
  2. data/CONTRIBUTERS +11 -0
  3. data/COPYING +24 -0
  4. data/ChangeLog +6683 -0
  5. data/GPL +674 -0
  6. data/README +43 -0
  7. data/VERSION +1 -0
  8. data/bin/kramdown +78 -0
  9. data/lib/kramdown.rb +23 -0
  10. data/lib/kramdown/compatibility.rb +49 -0
  11. data/lib/kramdown/converter.rb +41 -0
  12. data/lib/kramdown/converter/base.rb +169 -0
  13. data/lib/kramdown/converter/bean_html.rb +71 -0
  14. data/lib/kramdown/converter/html.rb +411 -0
  15. data/lib/kramdown/converter/kramdown.rb +428 -0
  16. data/lib/kramdown/converter/latex.rb +607 -0
  17. data/lib/kramdown/converter/toc.rb +82 -0
  18. data/lib/kramdown/document.rb +119 -0
  19. data/lib/kramdown/element.rb +524 -0
  20. data/lib/kramdown/error.rb +30 -0
  21. data/lib/kramdown/options.rb +373 -0
  22. data/lib/kramdown/parser.rb +39 -0
  23. data/lib/kramdown/parser/base.rb +136 -0
  24. data/lib/kramdown/parser/bean_kramdown.rb +25 -0
  25. data/lib/kramdown/parser/bean_kramdown/info_box.rb +52 -0
  26. data/lib/kramdown/parser/bean_kramdown/oembed.rb +230 -0
  27. data/lib/kramdown/parser/html.rb +570 -0
  28. data/lib/kramdown/parser/kramdown.rb +339 -0
  29. data/lib/kramdown/parser/kramdown/abbreviation.rb +71 -0
  30. data/lib/kramdown/parser/kramdown/autolink.rb +53 -0
  31. data/lib/kramdown/parser/kramdown/blank_line.rb +43 -0
  32. data/lib/kramdown/parser/kramdown/block_boundary.rb +46 -0
  33. data/lib/kramdown/parser/kramdown/blockquote.rb +51 -0
  34. data/lib/kramdown/parser/kramdown/codeblock.rb +63 -0
  35. data/lib/kramdown/parser/kramdown/codespan.rb +56 -0
  36. data/lib/kramdown/parser/kramdown/emphasis.rb +70 -0
  37. data/lib/kramdown/parser/kramdown/eob.rb +39 -0
  38. data/lib/kramdown/parser/kramdown/escaped_chars.rb +38 -0
  39. data/lib/kramdown/parser/kramdown/extensions.rb +204 -0
  40. data/lib/kramdown/parser/kramdown/footnote.rb +74 -0
  41. data/lib/kramdown/parser/kramdown/header.rb +68 -0
  42. data/lib/kramdown/parser/kramdown/horizontal_rule.rb +39 -0
  43. data/lib/kramdown/parser/kramdown/html.rb +169 -0
  44. data/lib/kramdown/parser/kramdown/html_entity.rb +44 -0
  45. data/lib/kramdown/parser/kramdown/image.rb +157 -0
  46. data/lib/kramdown/parser/kramdown/line_break.rb +38 -0
  47. data/lib/kramdown/parser/kramdown/link.rb +154 -0
  48. data/lib/kramdown/parser/kramdown/list.rb +240 -0
  49. data/lib/kramdown/parser/kramdown/math.rb +65 -0
  50. data/lib/kramdown/parser/kramdown/paragraph.rb +63 -0
  51. data/lib/kramdown/parser/kramdown/smart_quotes.rb +214 -0
  52. data/lib/kramdown/parser/kramdown/table.rb +178 -0
  53. data/lib/kramdown/parser/kramdown/typographic_symbol.rb +52 -0
  54. data/lib/kramdown/parser/markdown.rb +69 -0
  55. data/lib/kramdown/utils.rb +42 -0
  56. data/lib/kramdown/utils/entities.rb +348 -0
  57. data/lib/kramdown/utils/html.rb +85 -0
  58. data/lib/kramdown/utils/ordered_hash.rb +100 -0
  59. data/lib/kramdown/version.rb +28 -0
  60. 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