kramdown 2.0.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CONTRIBUTERS +13 -3
- data/README.md +8 -2
- data/VERSION +1 -1
- data/bin/kramdown +48 -19
- data/lib/kramdown/converter/base.rb +2 -1
- data/lib/kramdown/converter/html.rb +36 -29
- data/lib/kramdown/converter/kramdown.rb +12 -7
- data/lib/kramdown/converter/latex.rb +2 -2
- data/lib/kramdown/converter/math_engine/mathjax.rb +7 -33
- data/lib/kramdown/converter/syntax_highlighter.rb +1 -1
- data/lib/kramdown/converter/syntax_highlighter/rouge.rb +20 -10
- data/lib/kramdown/element.rb +24 -0
- data/lib/kramdown/options.rb +53 -12
- data/lib/kramdown/parser/base.rb +3 -1
- data/lib/kramdown/parser/html.rb +8 -8
- data/lib/kramdown/parser/kramdown.rb +8 -1
- data/lib/kramdown/parser/kramdown/abbreviation.rb +1 -1
- data/lib/kramdown/parser/kramdown/autolink.rb +2 -2
- data/lib/kramdown/parser/kramdown/blank_line.rb +2 -2
- data/lib/kramdown/parser/kramdown/block_boundary.rb +3 -2
- data/lib/kramdown/parser/kramdown/codespan.rb +13 -3
- data/lib/kramdown/parser/kramdown/emphasis.rb +1 -1
- data/lib/kramdown/parser/kramdown/extensions.rb +13 -7
- data/lib/kramdown/parser/kramdown/header.rb +3 -2
- data/lib/kramdown/parser/kramdown/html.rb +4 -10
- data/lib/kramdown/parser/kramdown/link.rb +3 -2
- data/lib/kramdown/parser/kramdown/list.rb +64 -33
- data/lib/kramdown/parser/kramdown/math.rb +1 -1
- data/lib/kramdown/parser/kramdown/paragraph.rb +3 -3
- data/lib/kramdown/parser/kramdown/table.rb +3 -3
- data/lib/kramdown/utils/html.rb +9 -0
- data/lib/kramdown/version.rb +1 -1
- data/man/man1/kramdown.1 +22 -1
- data/test/test_files.rb +27 -18
- data/test/test_location.rb +2 -2
- data/test/test_string_scanner_kramdown.rb +1 -1
- data/test/testcases/block/03_paragraph/standalone_image.html +5 -0
- data/test/testcases/block/03_paragraph/standalone_image.text +3 -0
- data/test/testcases/block/04_header/atx_header.html +6 -0
- data/test/testcases/block/04_header/atx_header.text +6 -0
- data/test/testcases/block/06_codeblock/guess_lang_css_class.html +15 -0
- data/test/testcases/block/06_codeblock/guess_lang_css_class.options +2 -0
- data/test/testcases/block/06_codeblock/guess_lang_css_class.text +13 -0
- data/test/testcases/block/06_codeblock/rouge/multiple.html +1 -1
- data/test/testcases/block/06_codeblock/rouge/simple.html +1 -1
- data/test/testcases/block/09_html/processing_instruction.html +5 -6
- data/test/testcases/block/09_html/standalone_image_in_div.htmlinput +7 -0
- data/test/testcases/block/09_html/standalone_image_in_div.text +8 -0
- data/test/testcases/block/09_html/table.kramdown +8 -0
- data/test/testcases/block/09_html/table.text +7 -0
- data/test/testcases/block/12_extension/options.html +4 -4
- data/test/testcases/block/12_extension/options.text +2 -0
- data/test/testcases/block/12_extension/options2.html +4 -4
- data/test/testcases/block/14_table/table_with_footnote.html +4 -4
- data/test/testcases/block/15_math/gh_128.html +1 -2
- data/test/testcases/block/15_math/normal.html +16 -15
- data/test/testcases/block/16_toc/toc_with_footnotes.html +4 -4
- data/test/testcases/cjk-line-break.html +4 -0
- data/test/testcases/cjk-line-break.options +1 -0
- data/test/testcases/cjk-line-break.text +12 -0
- data/test/testcases/span/02_emphasis/normal.html +4 -0
- data/test/testcases/span/02_emphasis/normal.text +4 -0
- data/test/testcases/span/03_codespan/normal-css-class.html +1 -0
- data/test/testcases/span/03_codespan/normal-css-class.options +2 -0
- data/test/testcases/span/03_codespan/normal-css-class.text +1 -0
- data/test/testcases/span/03_codespan/normal.html +4 -0
- data/test/testcases/span/03_codespan/normal.text +4 -0
- data/test/testcases/span/04_footnote/backlink_inline.html +21 -21
- data/test/testcases/span/04_footnote/backlink_text.html +4 -4
- data/test/testcases/span/04_footnote/footnote_nr.html +6 -6
- data/test/testcases/span/04_footnote/footnote_prefix.html +6 -6
- data/test/testcases/span/04_footnote/inside_footnote.html +9 -9
- data/test/testcases/span/04_footnote/markers.html +16 -16
- data/test/testcases/span/04_footnote/placement.html +4 -4
- data/test/testcases/span/04_footnote/regexp_problem.html +4 -4
- data/test/testcases/span/04_footnote/without_backlink.html +3 -3
- data/test/testcases/span/05_html/normal.html +1 -1
- data/test/testcases/span/abbreviations/abbrev_in_html.html +9 -0
- data/test/testcases/span/abbreviations/abbrev_in_html.text +10 -0
- data/test/testcases/span/abbreviations/in_footnote.html +4 -4
- data/test/testcases/span/math/normal.html +4 -4
- data/test/testcases/span/text_substitutions/entities.html +1 -1
- data/test/testcases/span/text_substitutions/entities.text +1 -1
- metadata +40 -15
- data/test/testcases/block/15_math/mathjax_preview.html +0 -4
- data/test/testcases/block/15_math/mathjax_preview.options +0 -2
- data/test/testcases/block/15_math/mathjax_preview.text +0 -5
- data/test/testcases/block/15_math/mathjax_preview_as_code.html +0 -4
- data/test/testcases/block/15_math/mathjax_preview_as_code.options +0 -3
- data/test/testcases/block/15_math/mathjax_preview_as_code.text +0 -5
- data/test/testcases/block/15_math/mathjax_preview_simple.html +0 -4
- data/test/testcases/block/15_math/mathjax_preview_simple.options +0 -2
- data/test/testcases/block/15_math/mathjax_preview_simple.text +0 -5
|
@@ -42,7 +42,7 @@ module Kramdown
|
|
|
42
42
|
#
|
|
43
43
|
# == Special Implementation Details
|
|
44
44
|
#
|
|
45
|
-
# HTML converter:: If the syntax highlighter is used with
|
|
45
|
+
# HTML converter:: If the syntax highlighter is used with an HTML converter, it should return
|
|
46
46
|
# :block type text correctly wrapped (i.e. normally inside a pre-tag, but may
|
|
47
47
|
# also be a table-tag or just a div-tag) but :span type text *without* a
|
|
48
48
|
# code-tag!
|
|
@@ -25,8 +25,10 @@ module Kramdown::Converter::SyntaxHighlighter
|
|
|
25
25
|
opts = options(converter, type)
|
|
26
26
|
call_opts[:default_lang] = opts[:default_lang]
|
|
27
27
|
return nil unless lang || opts[:default_lang] || opts[:guess_lang]
|
|
28
|
+
|
|
28
29
|
lexer = ::Rouge::Lexer.find_fancy(lang || opts[:default_lang], text)
|
|
29
|
-
return nil if opts[:disable] || !lexer || lexer.tag == "plaintext"
|
|
30
|
+
return nil if opts[:disable] || !lexer || (lexer.tag == "plaintext" && !opts[:guess_lang])
|
|
31
|
+
|
|
30
32
|
opts[:css_class] ||= 'highlight' # For backward compatibility when using Rouge 2.0
|
|
31
33
|
formatter = formatter_class(opts).new(opts)
|
|
32
34
|
formatter.format(lexer.lex(text))
|
|
@@ -43,24 +45,32 @@ module Kramdown::Converter::SyntaxHighlighter
|
|
|
43
45
|
cache = converter.data[:syntax_highlighter_rouge] = {}
|
|
44
46
|
|
|
45
47
|
opts = converter.options[:syntax_highlighter_opts].dup
|
|
46
|
-
span_opts = (opts.delete(:span) || {}).dup
|
|
47
|
-
block_opts = (opts.delete(:block) || {}).dup
|
|
48
|
-
[span_opts, block_opts].each do |hash|
|
|
49
|
-
hash.keys.each do |k|
|
|
50
|
-
hash[k.kind_of?(String) ? Kramdown::Options.str_to_sym(k) : k] = hash.delete(k)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
48
|
|
|
54
|
-
|
|
49
|
+
span_opts = opts.delete(:span)&.dup || {}
|
|
50
|
+
block_opts = opts.delete(:block)&.dup || {}
|
|
51
|
+
normalize_keys(span_opts)
|
|
52
|
+
normalize_keys(block_opts)
|
|
53
|
+
|
|
54
|
+
cache[:span] = opts.merge(span_opts)
|
|
55
|
+
cache[:span][:wrap] = false
|
|
56
|
+
|
|
55
57
|
cache[:block] = opts.merge(block_opts)
|
|
56
58
|
end
|
|
57
59
|
|
|
60
|
+
def self.normalize_keys(hash)
|
|
61
|
+
return if hash.empty?
|
|
62
|
+
|
|
63
|
+
hash.keys.each do |k|
|
|
64
|
+
hash[k.kind_of?(String) ? Kramdown::Options.str_to_sym(k) : k] = hash.delete(k)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
58
68
|
def self.formatter_class(opts = {})
|
|
59
69
|
case formatter = opts[:formatter]
|
|
60
70
|
when Class
|
|
61
71
|
formatter
|
|
62
72
|
when /\A[[:upper:]][[:alnum:]_]*\z/
|
|
63
|
-
::Rouge::Formatters.const_get(formatter)
|
|
73
|
+
::Rouge::Formatters.const_get(formatter, false)
|
|
64
74
|
else
|
|
65
75
|
# Available in Rouge 2.0 or later
|
|
66
76
|
::Rouge::Formatters::HTMLLegacy
|
data/lib/kramdown/element.rb
CHANGED
|
@@ -14,6 +14,14 @@ module Kramdown
|
|
|
14
14
|
# kramdown only uses this one class for representing all available elements in an element tree
|
|
15
15
|
# (paragraphs, headers, emphasis, ...). The type of element can be set via the #type accessor.
|
|
16
16
|
#
|
|
17
|
+
# The root of a kramdown element tree has to be an element of type :root. It needs to have certain
|
|
18
|
+
# option keys set so that conversions work correctly. If only a part of a tree should be
|
|
19
|
+
# converted, duplicate the root node and assign the #children appropriately, e.g:
|
|
20
|
+
#
|
|
21
|
+
# root = doc.root
|
|
22
|
+
# new_root = root.dup
|
|
23
|
+
# new_root.children = [root.children[0]] # assign new array with elements to convert
|
|
24
|
+
#
|
|
17
25
|
# Following is a description of all supported element types.
|
|
18
26
|
#
|
|
19
27
|
# Note that the option :location may contain the start line number of an element in the source
|
|
@@ -522,6 +530,22 @@ module Kramdown
|
|
|
522
530
|
CATEGORY[el.type] || el.options[:category]
|
|
523
531
|
end
|
|
524
532
|
|
|
533
|
+
# syntactic sugar to simplify calls such as +Kramdown::Element.category(el) == :block+ with
|
|
534
|
+
# +el.block?+.
|
|
535
|
+
#
|
|
536
|
+
# Returns boolean true or false.
|
|
537
|
+
def block?
|
|
538
|
+
(CATEGORY[type] || options[:category]) == :block
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
# syntactic sugar to simplify calls such as +Kramdown::Element.category(el) == :span+ with
|
|
542
|
+
# +el.span?+.
|
|
543
|
+
#
|
|
544
|
+
# Returns boolean true or false.
|
|
545
|
+
def span?
|
|
546
|
+
(CATEGORY[type] || options[:category]) == :span
|
|
547
|
+
end
|
|
548
|
+
|
|
525
549
|
end
|
|
526
550
|
|
|
527
551
|
end
|
data/lib/kramdown/options.rb
CHANGED
|
@@ -39,6 +39,7 @@ module Kramdown
|
|
|
39
39
|
ALLOWED_TYPES = [String, Integer, Float, Symbol, Boolean, Object]
|
|
40
40
|
|
|
41
41
|
@options = {}
|
|
42
|
+
@cached_defaults = nil
|
|
42
43
|
|
|
43
44
|
# Define a new option called +name+ (a Symbol) with the given +type+ (String, Integer, Float,
|
|
44
45
|
# Symbol, Boolean, Object), default value +default+ and the description +desc+. If a block is
|
|
@@ -54,6 +55,7 @@ module Kramdown
|
|
|
54
55
|
raise ArgumentError, "Invalid type for default value" if !(type === default) && !default.nil?
|
|
55
56
|
raise ArgumentError, "Missing validator block" if type == Object && block.nil?
|
|
56
57
|
@options[name] = Definition.new(name, type, default, desc, block)
|
|
58
|
+
@cached_defaults = nil
|
|
57
59
|
end
|
|
58
60
|
|
|
59
61
|
# Return all option definitions.
|
|
@@ -68,15 +70,17 @@ module Kramdown
|
|
|
68
70
|
|
|
69
71
|
# Return a Hash with the default values for all options.
|
|
70
72
|
def self.defaults
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
@cached_defaults ||= begin
|
|
74
|
+
temp = {}
|
|
75
|
+
@options.each {|_n, o| temp[o.name] = o.default }
|
|
76
|
+
temp.freeze
|
|
77
|
+
end
|
|
74
78
|
end
|
|
75
79
|
|
|
76
80
|
# Merge the #defaults Hash with the *parsed* options from the given Hash, i.e. only valid option
|
|
77
81
|
# names are considered and their value is run through the #parse method.
|
|
78
82
|
def self.merge(hash)
|
|
79
|
-
temp = defaults
|
|
83
|
+
temp = defaults.dup
|
|
80
84
|
hash.each do |k, v|
|
|
81
85
|
k = k.to_sym
|
|
82
86
|
temp[k] = @options.key?(k) ? parse(k, v) : v
|
|
@@ -328,7 +332,11 @@ module Kramdown
|
|
|
328
332
|
Used by: HTML converter, kramdown converter
|
|
329
333
|
EOF
|
|
330
334
|
|
|
331
|
-
|
|
335
|
+
TOC_LEVELS_RANGE = (1..6).freeze
|
|
336
|
+
TOC_LEVELS_ARRAY = TOC_LEVELS_RANGE.to_a.freeze
|
|
337
|
+
private_constant :TOC_LEVELS_RANGE, :TOC_LEVELS_ARRAY
|
|
338
|
+
|
|
339
|
+
define(:toc_levels, Object, TOC_LEVELS_ARRAY, <<~EOF) do |val|
|
|
332
340
|
Defines the levels that are used for the table of contents
|
|
333
341
|
|
|
334
342
|
The individual levels can be specified by separating them with commas
|
|
@@ -347,12 +355,20 @@ module Kramdown
|
|
|
347
355
|
else
|
|
348
356
|
raise Kramdown::Error, "Invalid syntax for option toc_levels"
|
|
349
357
|
end
|
|
350
|
-
when Array
|
|
351
|
-
|
|
358
|
+
when Array
|
|
359
|
+
unless val.eql?(TOC_LEVELS_ARRAY)
|
|
360
|
+
val = val.map(&:to_i).uniq
|
|
361
|
+
end
|
|
362
|
+
when Range
|
|
363
|
+
if val.eql?(TOC_LEVELS_RANGE)
|
|
364
|
+
val = TOC_LEVELS_ARRAY
|
|
365
|
+
else
|
|
366
|
+
val = val.map(&:to_i).uniq
|
|
367
|
+
end
|
|
352
368
|
else
|
|
353
369
|
raise Kramdown::Error, "Invalid type #{val.class} for option toc_levels"
|
|
354
370
|
end
|
|
355
|
-
if val.any? {|i| !
|
|
371
|
+
if val.any? {|i| !TOC_LEVELS_RANGE.cover?(i) }
|
|
356
372
|
raise Kramdown::Error, "Level numbers for option toc_levels have to be integers from 1 to 6"
|
|
357
373
|
end
|
|
358
374
|
val
|
|
@@ -377,7 +393,11 @@ module Kramdown
|
|
|
377
393
|
simple_array_validator(val, :latex_headers, 6)
|
|
378
394
|
end
|
|
379
395
|
|
|
380
|
-
|
|
396
|
+
SMART_QUOTES_ENTITIES = %w[lsquo rsquo ldquo rdquo].freeze
|
|
397
|
+
SMART_QUOTES_STR = SMART_QUOTES_ENTITIES.join(',').freeze
|
|
398
|
+
private_constant :SMART_QUOTES_ENTITIES, :SMART_QUOTES_STR
|
|
399
|
+
|
|
400
|
+
define(:smart_quotes, Object, SMART_QUOTES_ENTITIES, <<~EOF) do |val|
|
|
381
401
|
Defines the HTML entity names or code points for smart quote output
|
|
382
402
|
|
|
383
403
|
The entities identified by entity name or code point that should be
|
|
@@ -388,9 +408,13 @@ module Kramdown
|
|
|
388
408
|
Default: lsquo,rsquo,ldquo,rdquo
|
|
389
409
|
Used by: HTML/Latex converter
|
|
390
410
|
EOF
|
|
391
|
-
val
|
|
392
|
-
|
|
393
|
-
|
|
411
|
+
if val == SMART_QUOTES_STR || val == SMART_QUOTES_ENTITIES
|
|
412
|
+
SMART_QUOTES_ENTITIES
|
|
413
|
+
else
|
|
414
|
+
val = simple_array_validator(val, :smart_quotes, 4)
|
|
415
|
+
val.map! {|v| Integer(v) rescue v }
|
|
416
|
+
val
|
|
417
|
+
end
|
|
394
418
|
end
|
|
395
419
|
|
|
396
420
|
define(:typographic_symbols, Object, {}, <<~EOF) do |val|
|
|
@@ -562,6 +586,23 @@ module Kramdown
|
|
|
562
586
|
Used by: HTML
|
|
563
587
|
EOF
|
|
564
588
|
|
|
589
|
+
define(:remove_line_breaks_for_cjk, Boolean, false, <<~EOF)
|
|
590
|
+
Specifies whether line breaks should be removed between CJK characters
|
|
591
|
+
|
|
592
|
+
Default: false
|
|
593
|
+
Used by: HTML converter
|
|
594
|
+
EOF
|
|
595
|
+
|
|
596
|
+
define(:forbidden_inline_options, Object, %w[template], <<~EOF) do |val|
|
|
597
|
+
Defines the options that may not be set using the {::options} extension
|
|
598
|
+
|
|
599
|
+
Default: template
|
|
600
|
+
Used by: HTML converter
|
|
601
|
+
EOF
|
|
602
|
+
val.map! {|item| item.kind_of?(String) ? str_to_sym(item) : item }
|
|
603
|
+
simple_array_validator(val, :forbidden_inline_options)
|
|
604
|
+
end
|
|
605
|
+
|
|
565
606
|
end
|
|
566
607
|
|
|
567
608
|
end
|
data/lib/kramdown/parser/base.rb
CHANGED
|
@@ -93,7 +93,9 @@ module Kramdown
|
|
|
93
93
|
raise "The source text contains invalid characters for the used encoding #{source.encoding}"
|
|
94
94
|
end
|
|
95
95
|
source = source.encode('UTF-8')
|
|
96
|
-
source.gsub(/\r\n?/, "\n")
|
|
96
|
+
source.gsub!(/\r\n?/, "\n")
|
|
97
|
+
source.chomp!
|
|
98
|
+
source << "\n"
|
|
97
99
|
end
|
|
98
100
|
|
|
99
101
|
# This helper method adds the given +text+ either to the last element in the +tree+ if it is a
|
data/lib/kramdown/parser/html.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Kramdown
|
|
|
16
16
|
|
|
17
17
|
module Parser
|
|
18
18
|
|
|
19
|
-
# Used for parsing
|
|
19
|
+
# Used for parsing an HTML document.
|
|
20
20
|
#
|
|
21
21
|
# The parsing code is in the Parser module that can also be used by other parsers.
|
|
22
22
|
class Html < Base
|
|
@@ -286,7 +286,7 @@ module Kramdown
|
|
|
286
286
|
src = Kramdown::Utils::StringScanner.new(raw)
|
|
287
287
|
result = []
|
|
288
288
|
until src.eos?
|
|
289
|
-
if (tmp = src.scan_until(/(?=#{HTML_ENTITY_RE})/))
|
|
289
|
+
if (tmp = src.scan_until(/(?=#{HTML_ENTITY_RE})/o))
|
|
290
290
|
result << Element.new(:text, tmp)
|
|
291
291
|
src.scan(HTML_ENTITY_RE)
|
|
292
292
|
val = src[1] || (src[2]&.to_i) || src[3].hex
|
|
@@ -324,7 +324,7 @@ module Kramdown
|
|
|
324
324
|
tmp = []
|
|
325
325
|
last_is_p = false
|
|
326
326
|
el.children.each do |c|
|
|
327
|
-
if
|
|
327
|
+
if !c.block? || c.type == :text
|
|
328
328
|
unless last_is_p
|
|
329
329
|
tmp << Element.new(:p, nil, nil, transparent: true)
|
|
330
330
|
last_is_p = true
|
|
@@ -354,8 +354,8 @@ module Kramdown
|
|
|
354
354
|
el.children = el.children.reject do |c|
|
|
355
355
|
i += 1
|
|
356
356
|
c.type == :text && c.value.strip.empty? &&
|
|
357
|
-
(i == 0 || i == el.children.length - 1 || (
|
|
358
|
-
|
|
357
|
+
(i == 0 || i == el.children.length - 1 || ((el.children[i - 1]).block? &&
|
|
358
|
+
(el.children[i + 1]).block?))
|
|
359
359
|
end
|
|
360
360
|
end
|
|
361
361
|
|
|
@@ -581,11 +581,11 @@ module Kramdown
|
|
|
581
581
|
@src = Kramdown::Utils::StringScanner.new(adapt_source(source))
|
|
582
582
|
|
|
583
583
|
while true
|
|
584
|
-
if (result = @src.scan(/\s*#{HTML_INSTRUCTION_RE}/))
|
|
584
|
+
if (result = @src.scan(/\s*#{HTML_INSTRUCTION_RE}/o))
|
|
585
585
|
@tree.children << Element.new(:xml_pi, result.strip, nil, category: :block)
|
|
586
|
-
elsif (result = @src.scan(/\s*#{HTML_DOCTYPE_RE}/))
|
|
586
|
+
elsif (result = @src.scan(/\s*#{HTML_DOCTYPE_RE}/o))
|
|
587
587
|
# ignore the doctype
|
|
588
|
-
elsif (result = @src.scan(/\s*#{HTML_COMMENT_RE}/))
|
|
588
|
+
elsif (result = @src.scan(/\s*#{HTML_COMMENT_RE}/o))
|
|
589
589
|
@tree.children << Element.new(:xml_comment, result.strip, nil, category: :block)
|
|
590
590
|
else
|
|
591
591
|
break
|
|
@@ -79,6 +79,8 @@ module Kramdown
|
|
|
79
79
|
@span_parsers = [:emphasis, :codespan, :autolink, :span_html, :footnote_marker, :link,
|
|
80
80
|
:smart_quotes, :inline_math, :span_extensions, :html_entity,
|
|
81
81
|
:typographic_syms, :line_break, :escaped_chars]
|
|
82
|
+
|
|
83
|
+
@span_pattern_cache ||= Hash.new { |h, k| h[k] = {} }
|
|
82
84
|
end
|
|
83
85
|
private_class_method(:new, :allocate)
|
|
84
86
|
|
|
@@ -195,6 +197,11 @@ module Kramdown
|
|
|
195
197
|
end.flatten!
|
|
196
198
|
end
|
|
197
199
|
|
|
200
|
+
def span_pattern_cache(stop_re, span_start)
|
|
201
|
+
@span_pattern_cache[stop_re][span_start] ||= /(?=#{Regexp.union(stop_re, span_start)})/
|
|
202
|
+
end
|
|
203
|
+
private :span_pattern_cache
|
|
204
|
+
|
|
198
205
|
# Parse all span-level elements in the source string of @src into +el+.
|
|
199
206
|
#
|
|
200
207
|
# If the parameter +stop_re+ (a regexp) is used, parsing is immediately stopped if the regexp
|
|
@@ -213,7 +220,7 @@ module Kramdown
|
|
|
213
220
|
span_start, span_start_re = span_parser_regexps(parsers) if parsers
|
|
214
221
|
parsers ||= @span_parsers
|
|
215
222
|
|
|
216
|
-
used_re = (stop_re.nil? ? span_start_re :
|
|
223
|
+
used_re = (stop_re.nil? ? span_start_re : span_pattern_cache(stop_re, span_start))
|
|
217
224
|
stop_re_found = false
|
|
218
225
|
while !@src.eos? && !stop_re_found
|
|
219
226
|
if (result = @src.scan_until(used_re))
|
|
@@ -46,7 +46,7 @@ module Kramdown
|
|
|
46
46
|
regexps << /(?=(?:\W|^)#{regexps.first}(?!\w))/ # regexp should only match on word boundaries
|
|
47
47
|
end
|
|
48
48
|
el.children.map! do |child|
|
|
49
|
-
if child.type == :text
|
|
49
|
+
if child.type == :text && el.options[:content_model] != :raw
|
|
50
50
|
if child.value =~ regexps.first
|
|
51
51
|
result = []
|
|
52
52
|
strscan = Kramdown::Utils::StringScanner.new(child.value, child.options[:location])
|
|
@@ -11,8 +11,8 @@ module Kramdown
|
|
|
11
11
|
module Parser
|
|
12
12
|
class Kramdown
|
|
13
13
|
|
|
14
|
-
ACHARS = '[[:alnum:]]_'
|
|
15
|
-
AUTOLINK_START_STR = "<((mailto|https?|ftps?):.+?|[
|
|
14
|
+
ACHARS = '[[:alnum:]]-_.'
|
|
15
|
+
AUTOLINK_START_STR = "<((mailto|https?|ftps?):.+?|[#{ACHARS}]+?@[#{ACHARS}]+?)>"
|
|
16
16
|
AUTOLINK_START = /#{AUTOLINK_START_STR}/u
|
|
17
17
|
|
|
18
18
|
# Parse the autolink at the current location.
|
|
@@ -16,8 +16,8 @@ module Kramdown
|
|
|
16
16
|
# Parse the blank line at the current postition.
|
|
17
17
|
def parse_blank_line
|
|
18
18
|
@src.pos += @src.matched_size
|
|
19
|
-
if @tree.children.last &&
|
|
20
|
-
|
|
19
|
+
if (last_child = @tree.children.last) && last_child.type == :blank
|
|
20
|
+
last_child.value << @src.matched
|
|
21
21
|
else
|
|
22
22
|
@tree.children << new_block_el(:blank, @src.matched)
|
|
23
23
|
end
|
|
@@ -19,8 +19,9 @@ module Kramdown
|
|
|
19
19
|
|
|
20
20
|
# Return +true+ if we are after a block boundary.
|
|
21
21
|
def after_block_boundary?
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
last_child = @tree.children.last
|
|
23
|
+
!last_child || last_child.type == :blank ||
|
|
24
|
+
(last_child.type == :eob && last_child.value.nil?) || @block_ial
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
# Return +true+ if we are before a block boundary.
|
|
@@ -20,13 +20,23 @@ module Kramdown
|
|
|
20
20
|
simple = (result.length == 1)
|
|
21
21
|
saved_pos = @src.save_pos
|
|
22
22
|
|
|
23
|
-
if simple && @src.pre_match =~ /\s\Z/ && @src.match?(/\s/)
|
|
23
|
+
if simple && @src.pre_match =~ /\s\Z|\A\Z/ && @src.match?(/\s/)
|
|
24
24
|
add_text(result)
|
|
25
25
|
return
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
# assign static regex to avoid allocating the same on every instance
|
|
29
|
+
# where +result+ equals a single-backtick. Interpolate otherwise.
|
|
30
|
+
if result == '`'
|
|
31
|
+
scan_pattern = /`/
|
|
32
|
+
str_sub_pattern = /`\Z/
|
|
33
|
+
else
|
|
34
|
+
scan_pattern = /#{result}/
|
|
35
|
+
str_sub_pattern = /#{result}\Z/
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
if (text = @src.scan_until(scan_pattern))
|
|
39
|
+
text.sub!(str_sub_pattern, '')
|
|
30
40
|
unless simple
|
|
31
41
|
text = text[1..-1] if text[0..0] == ' '
|
|
32
42
|
text = text[0..-2] if text[-1..-1] == ' '
|
|
@@ -22,7 +22,7 @@ module Kramdown
|
|
|
22
22
|
element = (result.length == 2 ? :strong : :em)
|
|
23
23
|
type = result[0..0]
|
|
24
24
|
|
|
25
|
-
if (type == '_' && @src.pre_match =~ /[[:alpha:]
|
|
25
|
+
if (type == '_' && @src.pre_match =~ /[[:alpha:]]-?[[:alpha:]]*\z/) || @src.check(/\s/) ||
|
|
26
26
|
@tree.type == element || @stack.any? {|el, _| el.type == element }
|
|
27
27
|
add_text(result)
|
|
28
28
|
return
|
|
@@ -110,6 +110,12 @@ module Kramdown
|
|
|
110
110
|
opts.select do |k, v|
|
|
111
111
|
k = k.to_sym
|
|
112
112
|
if Kramdown::Options.defined?(k)
|
|
113
|
+
if @options[:forbidden_inline_options].include?(k) ||
|
|
114
|
+
k == :forbidden_inline_options
|
|
115
|
+
warning("Option #{k} may not be set inline")
|
|
116
|
+
next false
|
|
117
|
+
end
|
|
118
|
+
|
|
113
119
|
begin
|
|
114
120
|
val = Kramdown::Options.parse(k, v)
|
|
115
121
|
@options[k] = val
|
|
@@ -163,10 +169,10 @@ module Kramdown
|
|
|
163
169
|
elsif @src.check(EXT_BLOCK_START)
|
|
164
170
|
parse_extension_start_tag(:block)
|
|
165
171
|
elsif @src.scan(IAL_BLOCK_START)
|
|
166
|
-
if @tree.children.last &&
|
|
167
|
-
(
|
|
168
|
-
[:link_def, :abbrev_def, :footnote_def].include?(
|
|
169
|
-
parse_attribute_list(@src[1],
|
|
172
|
+
if (last_child = @tree.children.last) && last_child.type != :blank &&
|
|
173
|
+
(last_child.type != :eob ||
|
|
174
|
+
[:link_def, :abbrev_def, :footnote_def].include?(last_child.value))
|
|
175
|
+
parse_attribute_list(@src[1], last_child.options[:ial] ||= {})
|
|
170
176
|
@tree.children << new_block_el(:eob, :ial) unless @src.check(IAL_BLOCK_START)
|
|
171
177
|
else
|
|
172
178
|
parse_attribute_list(@src[1], @block_ial ||= {})
|
|
@@ -187,12 +193,12 @@ module Kramdown
|
|
|
187
193
|
if @src.check(EXT_SPAN_START)
|
|
188
194
|
parse_extension_start_tag(:span)
|
|
189
195
|
elsif @src.check(IAL_SPAN_START)
|
|
190
|
-
if @tree.children.last &&
|
|
196
|
+
if (last_child = @tree.children.last) && last_child.type != :text
|
|
191
197
|
@src.pos += @src.matched_size
|
|
192
198
|
attr = {}
|
|
193
199
|
parse_attribute_list(@src[1], attr)
|
|
194
|
-
update_ial_with_ial(
|
|
195
|
-
update_attr_with_ial(
|
|
200
|
+
update_ial_with_ial(last_child.options[:ial] ||= {}, attr)
|
|
201
|
+
update_attr_with_ial(last_child.attr, attr)
|
|
196
202
|
else
|
|
197
203
|
warning("Found span IAL after text - ignoring it")
|
|
198
204
|
add_text(@src.getch)
|