kramdown 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of kramdown might be problematic. Click here for more details.
- data/ChangeLog +346 -0
- data/Rakefile +36 -29
- data/VERSION +1 -1
- data/benchmark/testing.sh +1 -1
- data/bin/kramdown +0 -4
- data/doc/index.page +1 -1
- data/doc/links.markdown +4 -0
- data/doc/news.page +2 -1
- data/doc/quickref.page +134 -125
- data/doc/syntax.page +304 -302
- data/lib/kramdown/converter/base.rb +14 -0
- data/lib/kramdown/converter/html.rb +64 -2
- data/lib/kramdown/converter/latex.rb +14 -7
- data/lib/kramdown/document.rb +7 -3
- data/lib/kramdown/options.rb +13 -1
- data/lib/kramdown/parser/kramdown.rb +70 -17
- data/lib/kramdown/parser/kramdown/abbreviation.rb +65 -0
- data/lib/kramdown/parser/kramdown/attribute_list.rb +2 -1
- data/lib/kramdown/parser/kramdown/blank_line.rb +1 -1
- data/lib/kramdown/parser/kramdown/blockquote.rb +1 -1
- data/lib/kramdown/parser/kramdown/codeblock.rb +2 -2
- data/lib/kramdown/parser/kramdown/eob.rb +1 -1
- data/lib/kramdown/parser/kramdown/extension.rb +86 -6
- data/lib/kramdown/parser/kramdown/header.rb +2 -17
- data/lib/kramdown/parser/kramdown/horizontal_rule.rb +1 -1
- data/lib/kramdown/parser/kramdown/list.rb +8 -2
- data/lib/kramdown/parser/kramdown/math.rb +1 -1
- data/lib/kramdown/parser/kramdown/paragraph.rb +1 -1
- data/lib/kramdown/parser/kramdown/smart_quotes.rb +2 -2
- data/lib/kramdown/parser/kramdown/table.rb +1 -1
- data/lib/kramdown/version.rb +1 -1
- data/man/man1/kramdown.1 +77 -63
- data/test/testcases/block/04_header/with_auto_id_prefix.html +3 -0
- data/test/testcases/block/04_header/with_auto_id_prefix.options +2 -0
- data/test/testcases/block/04_header/with_auto_id_prefix.text +3 -0
- data/test/testcases/block/08_list/item_ial.html +9 -0
- data/test/testcases/block/08_list/item_ial.text +5 -0
- data/test/testcases/block/11_ial/auto_id_and_ial.html +1 -1
- data/test/testcases/block/11_ial/auto_id_and_ial.text +1 -1
- data/test/testcases/block/11_ial/simple.html +5 -0
- data/test/testcases/block/11_ial/simple.text +7 -0
- data/test/testcases/block/12_extension/comment.text +5 -5
- data/test/testcases/block/12_extension/ignored.html +0 -2
- data/test/testcases/block/12_extension/ignored.text +3 -6
- data/test/testcases/block/12_extension/nomarkdown.text +4 -4
- data/test/testcases/block/12_extension/options.html +1 -1
- data/test/testcases/block/12_extension/options.text +5 -6
- data/test/testcases/block/12_extension/options2.text +1 -1
- data/test/testcases/block/12_extension/options3.text +1 -1
- data/test/testcases/span/abbreviations/abbrev.html +8 -0
- data/test/testcases/span/abbreviations/abbrev.text +15 -0
- data/test/testcases/span/abbreviations/abbrev_defs.html +2 -0
- data/test/testcases/span/abbreviations/abbrev_defs.text +5 -0
- data/test/testcases/span/extension/comment.html +6 -0
- data/test/testcases/span/extension/comment.text +6 -0
- data/test/testcases/span/extension/ignored.html +1 -0
- data/test/testcases/span/extension/ignored.text +1 -0
- data/test/testcases/span/extension/nomarkdown.html +1 -0
- data/test/testcases/span/extension/nomarkdown.text +1 -0
- data/test/testcases/span/extension/options.html +1 -0
- data/test/testcases/span/extension/options.text +1 -0
- data/test/testcases/span/ial/simple.html +2 -1
- data/test/testcases/span/ial/simple.text +1 -0
- data/test/testcases/span/text_substitutions/typography.html +3 -0
- data/test/testcases/span/text_substitutions/typography.text +3 -0
- metadata +275 -263
@@ -68,6 +68,20 @@ module Kramdown
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
|
72
|
+
# Generate an alpha-numeric ID from the the string +str+.
|
73
|
+
def generate_id(str)
|
74
|
+
gen_id = str.gsub(/[^a-zA-Z0-9 -]/, '').gsub(/^[^a-zA-Z]*/, '').gsub(' ', '-').downcase
|
75
|
+
gen_id = 'section' if gen_id.length == 0
|
76
|
+
@used_ids ||= {}
|
77
|
+
if @used_ids.has_key?(gen_id)
|
78
|
+
gen_id += '-' + (@used_ids[gen_id] += 1).to_s
|
79
|
+
else
|
80
|
+
@used_ids[gen_id] = 0
|
81
|
+
end
|
82
|
+
@doc.options[:auto_id_prefix] + gen_id
|
83
|
+
end
|
84
|
+
|
71
85
|
end
|
72
86
|
|
73
87
|
end
|
@@ -48,6 +48,8 @@ module Kramdown
|
|
48
48
|
super
|
49
49
|
@footnote_counter = @footnote_start = @doc.options[:footnote_nr]
|
50
50
|
@footnotes = []
|
51
|
+
@toc = []
|
52
|
+
@toc_code = nil
|
51
53
|
end
|
52
54
|
|
53
55
|
def convert(el, indent = -INDENTATION, opts = {})
|
@@ -109,6 +111,11 @@ module Kramdown
|
|
109
111
|
end
|
110
112
|
|
111
113
|
def convert_header(el, indent, opts)
|
114
|
+
el = Marshal.load(Marshal.dump(el)) # so that the original is not changed
|
115
|
+
if @doc.options[:auto_ids] && !(el.options[:attr] && el.options[:attr]['id'])
|
116
|
+
(el.options[:attr] ||= {})['id'] = generate_id(el.options[:raw_text])
|
117
|
+
end
|
118
|
+
@toc << [el.options[:level], el.options[:attr]['id'], el.children] if el.options[:attr] && el.options[:attr]['id']
|
112
119
|
"#{' '*indent}<h#{el.options[:level]}#{options_for_element(el)}>#{inner(el, indent, opts)}</h#{el.options[:level]}>\n"
|
113
120
|
end
|
114
121
|
|
@@ -117,7 +124,12 @@ module Kramdown
|
|
117
124
|
end
|
118
125
|
|
119
126
|
def convert_ul(el, indent, opts)
|
120
|
-
|
127
|
+
if !@toc_code && (el.options[:ial][:refs].include?('toc') rescue nil) && (el.type == :ul || el.type == :ol)
|
128
|
+
@toc_code = [el.type, (0..128).to_a.map{|a| rand(36).to_s(36)}.join]
|
129
|
+
@toc_code.last
|
130
|
+
else
|
131
|
+
"#{' '*indent}<#{el.type}#{options_for_element(el)}>\n#{inner(el, indent, opts)}#{' '*indent}</#{el.type}>\n"
|
132
|
+
end
|
121
133
|
end
|
122
134
|
alias :convert_ol :convert_ul
|
123
135
|
alias :convert_dl :convert_ul
|
@@ -269,8 +281,58 @@ module Kramdown
|
|
269
281
|
"<#{type}#{options_for_element(el)}>#{escape_html(el.value, :text)}</#{type}>#{type == 'div' ? "\n" : ''}"
|
270
282
|
end
|
271
283
|
|
284
|
+
def convert_abbreviation(el, indent, opts)
|
285
|
+
title = @doc.parse_infos[:abbrev_defs][el.value]
|
286
|
+
title = nil if title.empty?
|
287
|
+
"<abbr#{title ? " title=\"#{title}\"" : ''}>#{el.value}</abbr>"
|
288
|
+
end
|
289
|
+
|
272
290
|
def convert_root(el, indent, opts)
|
273
|
-
inner(el, indent, opts)
|
291
|
+
result = inner(el, indent, opts)
|
292
|
+
result << footnote_content
|
293
|
+
if @toc_code
|
294
|
+
toc_tree = generate_toc_tree(@toc, @toc_code.first)
|
295
|
+
text = if toc_tree.children.size > 0
|
296
|
+
convert(toc_tree, 0)
|
297
|
+
else
|
298
|
+
''
|
299
|
+
end
|
300
|
+
result.sub!(/#{@toc_code.last}/, text)
|
301
|
+
end
|
302
|
+
result
|
303
|
+
end
|
304
|
+
|
305
|
+
def generate_toc_tree(toc, type)
|
306
|
+
sections = Element.new(type, nil, {:attr => {:id => 'markdown-toc'}})
|
307
|
+
stack = []
|
308
|
+
toc.each do |level, id, children|
|
309
|
+
li = Element.new(:li, nil, {:level => level})
|
310
|
+
a = Element.new(:a, nil, {:attr => {:href => "##{id}"}})
|
311
|
+
a.children += children
|
312
|
+
li.children << a
|
313
|
+
li.children << Element.new(type)
|
314
|
+
|
315
|
+
success = false
|
316
|
+
while !success
|
317
|
+
if stack.empty?
|
318
|
+
sections.children << li
|
319
|
+
stack << li
|
320
|
+
success = true
|
321
|
+
elsif stack.last.options[:level] < li.options[:level]
|
322
|
+
stack.last.children.last.children << li
|
323
|
+
stack << li
|
324
|
+
success = true
|
325
|
+
else
|
326
|
+
item = stack.pop
|
327
|
+
item.children.pop unless item.children.last.children.size > 0
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
while !stack.empty?
|
332
|
+
item = stack.pop
|
333
|
+
item.children.pop unless item.children.last.children.size > 0
|
334
|
+
end
|
335
|
+
sections
|
274
336
|
end
|
275
337
|
|
276
338
|
# Helper method for obfuscating the +text+ by using HTML entities.
|
@@ -103,8 +103,9 @@ module Kramdown
|
|
103
103
|
}
|
104
104
|
def convert_header(el, opts)
|
105
105
|
type = HEADER_TYPES[el.options[:level]]
|
106
|
-
if el.options[:attr] && (id = el.options[:attr]['id'])
|
107
|
-
|
106
|
+
if (el.options[:attr] && (id = el.options[:attr]['id'])) ||
|
107
|
+
(@doc.options[:auto_ids] && (id = generate_id(el.options[:raw_text])))
|
108
|
+
"\\hypertarget{#{id}}{}\\#{type}{#{inner(el, opts)}}\\label{#{id}}\n\n"
|
108
109
|
else
|
109
110
|
"\\#{type}*{#{inner(el, opts)}}\n\n"
|
110
111
|
end
|
@@ -115,12 +116,14 @@ module Kramdown
|
|
115
116
|
end
|
116
117
|
|
117
118
|
def convert_ul(el, opts)
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
119
|
+
if !@doc.conversion_infos[:has_toc] && (el.options[:ial][:refs].include?('toc') rescue nil)
|
120
|
+
@doc.conversion_infos[:has_toc] = true
|
121
|
+
'\tableofcontents'
|
122
|
+
else
|
123
|
+
latex_environment(el.type == :ul ? 'itemize' : 'enumerate', inner(el, opts))
|
124
|
+
end
|
123
125
|
end
|
126
|
+
alias :convert_ol :convert_ul
|
124
127
|
|
125
128
|
def convert_dl(el, opts)
|
126
129
|
latex_environment('description', inner(el, opts))
|
@@ -514,6 +517,10 @@ EOF
|
|
514
517
|
end
|
515
518
|
end
|
516
519
|
|
520
|
+
def convert_abbreviation(el, indent, opts)
|
521
|
+
el.value
|
522
|
+
end
|
523
|
+
|
517
524
|
ESCAPE_MAP = {
|
518
525
|
"^" => "\\^{}",
|
519
526
|
"\\" => "\\textbackslash{}",
|
data/lib/kramdown/document.rb
CHANGED
@@ -91,9 +91,13 @@ module Kramdown
|
|
91
91
|
@warnings = []
|
92
92
|
@parse_infos = {}
|
93
93
|
@conversion_infos = {}
|
94
|
-
|
95
|
-
|
96
|
-
|
94
|
+
parser = (options[:input] || 'kramdown').to_s
|
95
|
+
parser = parser[0..0].upcase + parser[1..-1]
|
96
|
+
if Parser.const_defined?(parser)
|
97
|
+
@tree = Parser.const_get(parser).parse(source, self)
|
98
|
+
else
|
99
|
+
raise Kramdown::Error.new("kramdown has no parser to handle the specified input format: #{options[:input]}")
|
100
|
+
end
|
97
101
|
end
|
98
102
|
|
99
103
|
# Check if a method is invoked that begins with +to_+ and if so, try to instantiate a converter
|
data/lib/kramdown/options.rb
CHANGED
@@ -148,7 +148,19 @@ If this option is `true`, ID values for all headers are automatically
|
|
148
148
|
generated if no ID is explicitly specified.
|
149
149
|
|
150
150
|
Default: true
|
151
|
-
Used by:
|
151
|
+
Used by: HTML/Latex converter
|
152
|
+
EOF
|
153
|
+
|
154
|
+
define(:auto_id_prefix, String, '', <<EOF)
|
155
|
+
Prefix used for automatically generated heaer IDs
|
156
|
+
|
157
|
+
This option can be used to set a prefix for the automatically generated
|
158
|
+
header IDs so that there is no conflict when rendering multiple kramdown
|
159
|
+
documents into one output file separately. The prefix should only
|
160
|
+
contain characters that are valid in an ID!
|
161
|
+
|
162
|
+
Default: ''
|
163
|
+
Used by: HTML/Latex converter
|
152
164
|
EOF
|
153
165
|
|
154
166
|
define(:parse_block_html, Boolean, false, <<EOF)
|
@@ -31,6 +31,44 @@ module Kramdown
|
|
31
31
|
module Parser
|
32
32
|
|
33
33
|
# Used for parsing a document in kramdown format.
|
34
|
+
#
|
35
|
+
# If you want to extend the functionality of the parser, you need to the following:
|
36
|
+
#
|
37
|
+
# * Create a new subclass
|
38
|
+
# * add the needed parser methods
|
39
|
+
# * modify the @block_parsers and @span_parsers variables and add the names of your parser
|
40
|
+
# methods
|
41
|
+
#
|
42
|
+
# Here is a small example for an extended parser class that parses ERB style tags as raw text if
|
43
|
+
# they are used as span level elements (an equivalent block level parser should probably also be
|
44
|
+
# made to handle the block case):
|
45
|
+
#
|
46
|
+
# require 'kramdown/parser/kramdown'
|
47
|
+
#
|
48
|
+
# class Kramdown::Parser::ERBKramdown < Kramdown::Parser::Kramdown
|
49
|
+
#
|
50
|
+
# def initialize(doc)
|
51
|
+
# super(doc)
|
52
|
+
# @span_parsers.unshift(:erb_tags)
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# ERB_TAGS_START = /<%.*?%>/
|
56
|
+
#
|
57
|
+
# def parse_erb_tags
|
58
|
+
# @src.pos += @src.matched_size
|
59
|
+
# @tree.children << Element.new(:raw, @src.matched)
|
60
|
+
# end
|
61
|
+
# define_parser(:erb_tags, ERB_TAGS_START, '<%')
|
62
|
+
#
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# The new parser can be used like this:
|
66
|
+
#
|
67
|
+
# require 'kramdown/document'
|
68
|
+
# # require the file with the above parser class
|
69
|
+
#
|
70
|
+
# Kramdown::Document.new(input_text, :input => 'ERBKramdown').to_html
|
71
|
+
#
|
34
72
|
class Kramdown
|
35
73
|
|
36
74
|
include ::Kramdown
|
@@ -48,10 +86,20 @@ module Kramdown
|
|
48
86
|
@tree = nil
|
49
87
|
@stack = []
|
50
88
|
@text_type = :text
|
89
|
+
@block_ial = nil
|
51
90
|
|
52
91
|
@doc.parse_infos[:ald] = {}
|
53
92
|
@doc.parse_infos[:link_defs] = {}
|
93
|
+
@doc.parse_infos[:abbrev_defs] = {}
|
54
94
|
@doc.parse_infos[:footnotes] = {}
|
95
|
+
|
96
|
+
@block_parsers = [:blank_line, :codeblock, :codeblock_fenced, :blockquote, :table, :atx_header,
|
97
|
+
:setext_header, :horizontal_rule, :list, :definition_list, :link_definition, :block_html,
|
98
|
+
:footnote_definition, :abbrev_definition, :ald, :block_math, :extension_block_depr,
|
99
|
+
:block_extension, :block_ial, :eob_marker, :paragraph]
|
100
|
+
@span_parsers = [:emphasis, :codespan, :autolink, :span_html, :footnote_marker, :link, :smart_quotes, :inline_math,
|
101
|
+
:span_extension, :span_ial, :html_entity, :typographic_syms, :line_break, :escaped_chars]
|
102
|
+
|
55
103
|
end
|
56
104
|
private_class_method(:new, :allocate)
|
57
105
|
|
@@ -67,6 +115,7 @@ module Kramdown
|
|
67
115
|
tree = Element.new(:root)
|
68
116
|
parse_blocks(tree, adapt_source(source))
|
69
117
|
update_tree(tree)
|
118
|
+
replace_abbreviations(tree)
|
70
119
|
@doc.parse_infos[:footnotes].each do |name, data|
|
71
120
|
update_tree(data[:content])
|
72
121
|
end
|
@@ -80,19 +129,13 @@ module Kramdown
|
|
80
129
|
end
|
81
130
|
|
82
131
|
#######
|
83
|
-
|
132
|
+
protected
|
84
133
|
#######
|
85
134
|
|
86
|
-
BLOCK_PARSERS = [:blank_line, :codeblock, :codeblock_fenced, :blockquote, :table, :atx_header,
|
87
|
-
:setext_header, :horizontal_rule, :list, :definition_list, :link_definition, :block_html,
|
88
|
-
:footnote_definition, :ald, :block_ial, :block_math, :extension_block, :eob_marker, :paragraph]
|
89
|
-
SPAN_PARSERS = [:emphasis, :codespan, :autolink, :span_html, :footnote_marker, :link, :smart_quotes, :inline_math,
|
90
|
-
:span_ial, :html_entity, :typographic_syms, :line_break, :escaped_chars]
|
91
|
-
|
92
135
|
# Adapt the object to allow parsing like specified in the options.
|
93
136
|
def configure_parser
|
94
137
|
@parsers = {}
|
95
|
-
(
|
138
|
+
(@block_parsers + @span_parsers).each do |name|
|
96
139
|
if self.class.has_parser?(name)
|
97
140
|
@parsers[name] = self.class.parser(name)
|
98
141
|
else
|
@@ -103,7 +146,7 @@ module Kramdown
|
|
103
146
|
end
|
104
147
|
|
105
148
|
# Create the needed span parser regexps.
|
106
|
-
def span_parser_regexps(parsers =
|
149
|
+
def span_parser_regexps(parsers = @span_parsers)
|
107
150
|
span_start = /#{parsers.map {|name| @parsers[name].span_start}.join('|')}/
|
108
151
|
[span_start, /(?=#{span_start})/]
|
109
152
|
end
|
@@ -115,7 +158,8 @@ module Kramdown
|
|
115
158
|
|
116
159
|
status = catch(:stop_block_parsing) do
|
117
160
|
while !@src.eos?
|
118
|
-
|
161
|
+
block_ial_set = @block_ial
|
162
|
+
@block_parsers.any? do |name|
|
119
163
|
if @src.check(@parsers[name].start_re)
|
120
164
|
send(@parsers[name].method)
|
121
165
|
else
|
@@ -125,6 +169,7 @@ module Kramdown
|
|
125
169
|
warning('Warning: this should not occur - no block parser handled the line')
|
126
170
|
add_text(@src.scan(/.*\n/))
|
127
171
|
end
|
172
|
+
@block_ial = nil if block_ial_set
|
128
173
|
end
|
129
174
|
end
|
130
175
|
|
@@ -157,7 +202,7 @@ module Kramdown
|
|
157
202
|
span_start = @span_start
|
158
203
|
span_start_re = @span_start_re
|
159
204
|
span_start, span_start_re = span_parser_regexps(parsers) if parsers
|
160
|
-
parsers = parsers ||
|
205
|
+
parsers = parsers || @span_parsers
|
161
206
|
|
162
207
|
used_re = (stop_re.nil? ? span_start_re : /(?=#{Regexp.union(stop_re, span_start)})/)
|
163
208
|
stop_re_found = false
|
@@ -211,20 +256,27 @@ module Kramdown
|
|
211
256
|
ial.each {|k,v| attr[k] = v if k.kind_of?(String) && k != 'class' }
|
212
257
|
end
|
213
258
|
|
259
|
+
# Create a new block level element, taking care of applying a preceding block IAL if it exists.
|
260
|
+
def new_block_el(*args)
|
261
|
+
el = Element.new(*args)
|
262
|
+
el.options[:ial] = @block_ial if @block_ial && el.type != :blank && el.type != :eob
|
263
|
+
el
|
264
|
+
end
|
265
|
+
|
214
266
|
# Extract the part of the StringScanner backed string specified by the +range+. This method
|
215
267
|
# also works correctly under Ruby 1.9.
|
216
|
-
def extract_string(range)
|
268
|
+
def extract_string(range, strscan = @src)
|
217
269
|
result = nil
|
218
270
|
if RUBY_VERSION >= '1.9'
|
219
271
|
begin
|
220
|
-
enc =
|
221
|
-
|
222
|
-
result =
|
272
|
+
enc = strscan.string.encoding
|
273
|
+
strscan.string.force_encoding('ASCII-8BIT')
|
274
|
+
result = strscan.string[range].force_encoding(enc)
|
223
275
|
ensure
|
224
|
-
|
276
|
+
strscan.string.force_encoding(enc)
|
225
277
|
end
|
226
278
|
else
|
227
|
-
result =
|
279
|
+
result = strscan.string[range]
|
228
280
|
end
|
229
281
|
result
|
230
282
|
end
|
@@ -285,6 +337,7 @@ module Kramdown
|
|
285
337
|
require 'kramdown/parser/kramdown/emphasis'
|
286
338
|
require 'kramdown/parser/kramdown/smart_quotes'
|
287
339
|
require 'kramdown/parser/kramdown/math'
|
340
|
+
require 'kramdown/parser/kramdown/abbreviation'
|
288
341
|
|
289
342
|
end
|
290
343
|
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2009-2010 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
|
+
module Parser
|
25
|
+
class Kramdown
|
26
|
+
|
27
|
+
ABBREV_DEFINITION_START = /^#{OPT_SPACE}\*\[(.+?)\]:(.*?)\n/
|
28
|
+
|
29
|
+
# Parse the link definition at the current location.
|
30
|
+
def parse_abbrev_definition
|
31
|
+
@src.pos += @src.matched_size
|
32
|
+
abbrev_id, abbrev_text = @src[1], @src[2].strip
|
33
|
+
warning("Duplicate abbreviation ID '#{abbrev_id}' - overwriting") if @doc.parse_infos[:abbrev_defs][abbrev_id]
|
34
|
+
@doc.parse_infos[:abbrev_defs][abbrev_id] = abbrev_text
|
35
|
+
true
|
36
|
+
end
|
37
|
+
define_parser(:abbrev_definition, ABBREV_DEFINITION_START)
|
38
|
+
|
39
|
+
# Replace the abbreviation text with elements.
|
40
|
+
def replace_abbreviations(el, regexps = nil)
|
41
|
+
return if @doc.parse_infos[:abbrev_defs].empty?
|
42
|
+
if !regexps
|
43
|
+
regexps = [Regexp.union(*@doc.parse_infos[:abbrev_defs].keys.map {|k| /#{Regexp.escape(k)}/})]
|
44
|
+
regexps << /(?=(?:\W|^)#{regexps.first}(?!\w))/ # regexp should only match on word boundaries
|
45
|
+
end
|
46
|
+
el.children.map! do |child|
|
47
|
+
if child.type == :text
|
48
|
+
result = []
|
49
|
+
strscan = StringScanner.new(child.value)
|
50
|
+
while temp = strscan.scan_until(regexps.last)
|
51
|
+
temp += strscan.scan(/\W|^/)
|
52
|
+
abbr = strscan.scan(regexps.first)
|
53
|
+
result += [Element.new(:text, temp), Element.new(:abbreviation, abbr)]
|
54
|
+
end
|
55
|
+
result + [Element.new(:text, extract_string(strscan.pos..-1, strscan))]
|
56
|
+
else
|
57
|
+
replace_abbreviations(child, regexps)
|
58
|
+
child
|
59
|
+
end
|
60
|
+
end.flatten!
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -74,6 +74,8 @@ module Kramdown
|
|
74
74
|
@src.pos += @src.matched_size
|
75
75
|
if @tree.children.last && @tree.children.last.type != :blank && @tree.children.last.type != :eob
|
76
76
|
parse_attribute_list(@src[1], @tree.children.last.options[:ial] ||= {})
|
77
|
+
else
|
78
|
+
parse_attribute_list(@src[1], @block_ial = {})
|
77
79
|
end
|
78
80
|
true
|
79
81
|
end
|
@@ -92,7 +94,6 @@ module Kramdown
|
|
92
94
|
update_attr_with_ial(@tree.children.last.options[:attr] ||= {}, attr)
|
93
95
|
else
|
94
96
|
warning("Ignoring span IAL because preceding element is just text")
|
95
|
-
add_text(@src.matched)
|
96
97
|
end
|
97
98
|
end
|
98
99
|
define_parser(:span_ial, IAL_SPAN_START, '\{:')
|