motion-kramdown 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +84 -0
  3. data/lib/kramdown/compatibility.rb +36 -0
  4. data/lib/kramdown/converter/base.rb +259 -0
  5. data/lib/kramdown/converter/html.rb +461 -0
  6. data/lib/kramdown/converter/kramdown.rb +423 -0
  7. data/lib/kramdown/converter/latex.rb +600 -0
  8. data/lib/kramdown/converter/math_engine/itex2mml.rb +39 -0
  9. data/lib/kramdown/converter/math_engine/mathjax.rb +33 -0
  10. data/lib/kramdown/converter/math_engine/ritex.rb +38 -0
  11. data/lib/kramdown/converter/pdf.rb +624 -0
  12. data/lib/kramdown/converter/remove_html_tags.rb +53 -0
  13. data/lib/kramdown/converter/syntax_highlighter/coderay.rb +78 -0
  14. data/lib/kramdown/converter/syntax_highlighter/rouge.rb +37 -0
  15. data/lib/kramdown/converter/toc.rb +69 -0
  16. data/lib/kramdown/converter.rb +69 -0
  17. data/lib/kramdown/document.rb +144 -0
  18. data/lib/kramdown/element.rb +515 -0
  19. data/lib/kramdown/error.rb +17 -0
  20. data/lib/kramdown/options.rb +584 -0
  21. data/lib/kramdown/parser/base.rb +130 -0
  22. data/lib/kramdown/parser/gfm.rb +55 -0
  23. data/lib/kramdown/parser/html.rb +575 -0
  24. data/lib/kramdown/parser/kramdown/abbreviation.rb +67 -0
  25. data/lib/kramdown/parser/kramdown/autolink.rb +37 -0
  26. data/lib/kramdown/parser/kramdown/blank_line.rb +30 -0
  27. data/lib/kramdown/parser/kramdown/block_boundary.rb +33 -0
  28. data/lib/kramdown/parser/kramdown/blockquote.rb +39 -0
  29. data/lib/kramdown/parser/kramdown/codeblock.rb +56 -0
  30. data/lib/kramdown/parser/kramdown/codespan.rb +44 -0
  31. data/lib/kramdown/parser/kramdown/emphasis.rb +61 -0
  32. data/lib/kramdown/parser/kramdown/eob.rb +26 -0
  33. data/lib/kramdown/parser/kramdown/escaped_chars.rb +25 -0
  34. data/lib/kramdown/parser/kramdown/extensions.rb +201 -0
  35. data/lib/kramdown/parser/kramdown/footnote.rb +56 -0
  36. data/lib/kramdown/parser/kramdown/header.rb +59 -0
  37. data/lib/kramdown/parser/kramdown/horizontal_rule.rb +27 -0
  38. data/lib/kramdown/parser/kramdown/html.rb +160 -0
  39. data/lib/kramdown/parser/kramdown/html_entity.rb +33 -0
  40. data/lib/kramdown/parser/kramdown/line_break.rb +25 -0
  41. data/lib/kramdown/parser/kramdown/link.rb +139 -0
  42. data/lib/kramdown/parser/kramdown/list.rb +256 -0
  43. data/lib/kramdown/parser/kramdown/math.rb +54 -0
  44. data/lib/kramdown/parser/kramdown/paragraph.rb +54 -0
  45. data/lib/kramdown/parser/kramdown/smart_quotes.rb +174 -0
  46. data/lib/kramdown/parser/kramdown/table.rb +171 -0
  47. data/lib/kramdown/parser/kramdown/typographic_symbol.rb +44 -0
  48. data/lib/kramdown/parser/kramdown.rb +359 -0
  49. data/lib/kramdown/parser/markdown.rb +56 -0
  50. data/lib/kramdown/parser.rb +27 -0
  51. data/lib/kramdown/utils/configurable.rb +44 -0
  52. data/lib/kramdown/utils/entities.rb +347 -0
  53. data/lib/kramdown/utils/html.rb +75 -0
  54. data/lib/kramdown/utils/ordered_hash.rb +87 -0
  55. data/lib/kramdown/utils/string_scanner.rb +74 -0
  56. data/lib/kramdown/utils/unidecoder.rb +51 -0
  57. data/lib/kramdown/utils.rb +58 -0
  58. data/lib/kramdown/version.rb +15 -0
  59. data/lib/kramdown.rb +10 -0
  60. data/lib/motion-kramdown.rb +47 -0
  61. data/lib/rubymotion/encodings.rb +37 -0
  62. data/lib/rubymotion/rexml_shim.rb +25 -0
  63. data/lib/rubymotion/set.rb +1349 -0
  64. data/lib/rubymotion/version.rb +6 -0
  65. data/spec/document_tree.rb +48 -0
  66. data/spec/gfm_to_html.rb +95 -0
  67. data/spec/helpers/it_behaves_like.rb +27 -0
  68. data/spec/helpers/option_file.rb +46 -0
  69. data/spec/helpers/spec_options.rb +37 -0
  70. data/spec/helpers/tidy.rb +12 -0
  71. data/spec/html_to_html.rb +40 -0
  72. data/spec/html_to_kramdown_to_html.rb +46 -0
  73. data/spec/kramdown_to_xxx.rb +40 -0
  74. data/spec/test_location.rb +203 -0
  75. data/spec/test_string_scanner_kramdown.rb +19 -0
  76. data/spec/text_to_kramdown_to_html.rb +52 -0
  77. data/spec/text_to_latex.rb +33 -0
  78. metadata +164 -0
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown
11
+ module Parser
12
+ class Kramdown
13
+
14
+ if RUBY_VERSION == '1.8.5'
15
+ ACHARS = '\w\x80-\xFF'
16
+ elsif RUBY_VERSION < '1.9.0'
17
+ ACHARS = '\w'
18
+ else
19
+ ACHARS = '[[:alnum:]]'
20
+ end
21
+ AUTOLINK_START_STR = "<((mailto|https?|ftps?):.+?|[-.#{ACHARS}]+@[-#{ACHARS}]+(?:\.[-#{ACHARS}]+)*\.[a-z]+)>"
22
+ AUTOLINK_START = /#{AUTOLINK_START_STR}/u
23
+
24
+ # Parse the autolink at the current location.
25
+ def parse_autolink
26
+ start_line_number = @src.current_line_number
27
+ @src.pos += @src.matched_size
28
+ href = (@src[2].nil? ? "mailto:#{@src[1]}" : @src[1])
29
+ el = Element.new(:a, nil, {'href' => href}, :location => start_line_number)
30
+ add_text(@src[1].sub(/^mailto:/, ''), el)
31
+ @tree.children << el
32
+ end
33
+ define_parser(:autolink, AUTOLINK_START, '<')
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown
11
+ module Parser
12
+ class Kramdown
13
+
14
+ BLANK_LINE = /(?:^\s*\n)+/m # RM Oniguruma -> ICU
15
+
16
+ # Parse the blank line at the current postition.
17
+ def parse_blank_line
18
+ @src.pos += @src.matched_size
19
+ if @tree.children.last && @tree.children.last.type == :blank
20
+ @tree.children.last.value << @src.matched
21
+ else
22
+ @tree.children << new_block_el(:blank, @src.matched)
23
+ end
24
+ true
25
+ end
26
+ define_parser(:blank_line, BLANK_LINE)
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ # RM require 'kramdown/parser/kramdown/extensions'
11
+ # RM require 'kramdown/parser/kramdown/blank_line'
12
+ # RM require 'kramdown/parser/kramdown/eob'
13
+
14
+ module Kramdown
15
+ module Parser
16
+ class Kramdown
17
+
18
+ BLOCK_BOUNDARY = /#{BLANK_LINE}|#{EOB_MARKER}|#{IAL_BLOCK_START}|\Z/
19
+
20
+ # Return +true+ if we are after a block boundary.
21
+ def after_block_boundary?
22
+ !@tree.children.last || @tree.children.last.type == :blank ||
23
+ (@tree.children.last.type == :eob && @tree.children.last.value.nil?) || @block_ial
24
+ end
25
+
26
+ # Return +true+ if we are before a block boundary.
27
+ def before_block_boundary?
28
+ @src.check(self.class::BLOCK_BOUNDARY)
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,39 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ # RM require 'kramdown/parser/kramdown/blank_line'
11
+ # RM require 'kramdown/parser/kramdown/extensions'
12
+ # RM require 'kramdown/parser/kramdown/eob'
13
+
14
+ module Kramdown
15
+ module Parser
16
+ class Kramdown
17
+
18
+ BLOCKQUOTE_START = /^#{OPT_SPACE}> ?/
19
+
20
+ # Parse the blockquote at the current location.
21
+ def parse_blockquote
22
+ start_line_number = @src.current_line_number
23
+ result = @src.scan(PARAGRAPH_MATCH)
24
+ while !@src.match?(self.class::LAZY_END)
25
+ result << @src.scan(PARAGRAPH_MATCH)
26
+ end
27
+ result.gsub!(BLOCKQUOTE_START, '')
28
+
29
+ el = new_block_el(:blockquote, nil, nil, :location => start_line_number)
30
+ @tree.children << el
31
+ parse_blocks(el, result)
32
+ true
33
+ end
34
+ define_parser(:blockquote, BLOCKQUOTE_START)
35
+
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,56 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ # RM require 'kramdown/parser/kramdown/blank_line'
11
+ # RM require 'kramdown/parser/kramdown/extensions'
12
+ # RM require 'kramdown/parser/kramdown/eob'
13
+ # RM require 'kramdown/parser/kramdown/paragraph'
14
+
15
+ module Kramdown
16
+ module Parser
17
+ class Kramdown
18
+
19
+ CODEBLOCK_START = INDENT
20
+ CODEBLOCK_MATCH = /(?:#{BLANK_LINE}?(?:#{INDENT}[ \t]*\S.*\n)+(?:(?!#{IAL_BLOCK_START}|#{EOB_MARKER}|#{OPT_SPACE_LAZY_END_HTML_STOP}|#{OPT_SPACE_LAZY_END_HTML_START})^[ \t]*\S.*\n)*)*/
21
+ # RM modified CODEBLOCK_MATCH with new combined OPT_SPACE_LAZY_END_HTML_STOP/START to support RM changes
22
+
23
+ # Parse the indented codeblock at the current location.
24
+ def parse_codeblock
25
+ start_line_number = @src.current_line_number
26
+ data = @src.scan(self.class::CODEBLOCK_MATCH)
27
+ data.gsub!(/\n( {0,3}\S)/, ' \\1')
28
+ data.gsub!(INDENT, '')
29
+ @tree.children << new_block_el(:codeblock, data, nil, :location => start_line_number)
30
+ true
31
+ end
32
+ define_parser(:codeblock, CODEBLOCK_START)
33
+
34
+
35
+ FENCED_CODEBLOCK_START = /^~{3,}/
36
+ FENCED_CODEBLOCK_MATCH = /^((~){3,})\s*?(\w+)?\s*?\n(.*?)^\1\2*\s*?\n/m
37
+
38
+ # Parse the fenced codeblock at the current location.
39
+ def parse_codeblock_fenced
40
+ if @src.check(self.class::FENCED_CODEBLOCK_MATCH)
41
+ start_line_number = @src.current_line_number
42
+ @src.pos += @src.matched_size
43
+ el = new_block_el(:codeblock, @src[4], nil, :location => start_line_number)
44
+ lang = @src[3].to_s.strip
45
+ el.attr['class'] = "language-#{lang}" unless lang.empty?
46
+ @tree.children << el
47
+ true
48
+ else
49
+ false
50
+ end
51
+ end
52
+ define_parser(:codeblock_fenced, FENCED_CODEBLOCK_START)
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown
11
+ module Parser
12
+ class Kramdown
13
+
14
+ CODESPAN_DELIMITER = /`+/
15
+
16
+ # Parse the codespan at the current scanner location.
17
+ def parse_codespan
18
+ start_line_number = @src.current_line_number
19
+ result = @src.scan(CODESPAN_DELIMITER)
20
+ simple = (result.length == 1)
21
+ saved_pos = @src.save_pos
22
+
23
+ if simple && @src.pre_match =~ /\s\Z/ && @src.match?(/\s/)
24
+ add_text(result)
25
+ return
26
+ end
27
+
28
+ if text = @src.scan_until(/#{result}/)
29
+ text.sub!(/#{result}\Z/, '')
30
+ if !simple
31
+ text = text[1..-1] if text[0..0] == ' '
32
+ text = text[0..-2] if text[-1..-1] == ' '
33
+ end
34
+ @tree.children << Element.new(:codespan, text, nil, :location => start_line_number)
35
+ else
36
+ @src.revert_pos(saved_pos)
37
+ add_text(result)
38
+ end
39
+ end
40
+ define_parser(:codespan, CODESPAN_DELIMITER, '`')
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,61 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown
11
+ module Parser
12
+ class Kramdown
13
+
14
+ EMPHASIS_START = /(?:\*\*?|__?)/
15
+
16
+ # Parse the emphasis at the current location.
17
+ def parse_emphasis
18
+ start_line_number = @src.current_line_number
19
+ saved_pos = @src.save_pos
20
+
21
+ result = @src.scan(EMPHASIS_START)
22
+ element = (result.length == 2 ? :strong : :em)
23
+ type = result[0..0]
24
+
25
+ if (type == '_' && @src.pre_match =~ /[[:alnum:]]\z/ && @src.check(/[[:alnum:]]/)) || @src.check(/\s/) ||
26
+ @tree.type == element || @stack.any? {|el, _| el.type == element}
27
+ add_text(result)
28
+ return
29
+ end
30
+
31
+ sub_parse = lambda do |delim, elem|
32
+ el = Element.new(elem, nil, nil, :location => start_line_number)
33
+ stop_re = /#{Regexp.escape(delim)}/
34
+ found = parse_spans(el, stop_re) do
35
+ (@src.pre_match[-1, 1] !~ /\s/) &&
36
+ (elem != :em || !@src.match?(/#{Regexp.escape(delim*2)}(?!#{Regexp.escape(delim)})/)) &&
37
+ (type != '_' || !@src.match?(/#{Regexp.escape(delim)}[[:alnum:]]/)) && el.children.size > 0
38
+ end
39
+ [found, el, stop_re]
40
+ end
41
+
42
+ found, el, stop_re = sub_parse.call(result, element)
43
+ if !found && element == :strong && @tree.type != :em
44
+ @src.revert_pos(saved_pos)
45
+ @src.pos += 1
46
+ found, el, stop_re = sub_parse.call(type, :em)
47
+ end
48
+ if found
49
+ @src.scan(stop_re)
50
+ @tree.children << el
51
+ else
52
+ @src.revert_pos(saved_pos)
53
+ @src.pos += result.length
54
+ add_text(result)
55
+ end
56
+ end
57
+ define_parser(:emphasis, EMPHASIS_START, '\*|_')
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,26 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown
11
+ module Parser
12
+ class Kramdown
13
+
14
+ EOB_MARKER = /^\^\s*?\n/m # RM Oniguruma -> ICU
15
+
16
+ # Parse the EOB marker at the current location.
17
+ def parse_eob_marker
18
+ @src.pos += @src.matched_size
19
+ @tree.children << new_block_el(:eob)
20
+ true
21
+ end
22
+ define_parser(:eob_marker, EOB_MARKER)
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown
11
+ module Parser
12
+ class Kramdown
13
+
14
+ ESCAPED_CHARS = /\\([\\.*_+`<>()\[\]{}#!:|"'\$=-])/
15
+
16
+ # Parse the backslash-escaped character at the current location.
17
+ def parse_escaped_chars
18
+ @src.pos += @src.matched_size
19
+ add_text(@src[1])
20
+ end
21
+ define_parser(:escaped_chars, ESCAPED_CHARS, '\\\\')
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,201 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown
11
+ module Parser
12
+ class Kramdown
13
+
14
+ IAL_CLASS_ATTR = 'class'
15
+
16
+ # Parse the string +str+ and extract all attributes and add all found attributes to the hash
17
+ # +opts+.
18
+ def parse_attribute_list(str, opts)
19
+ return if str.strip.empty? || str.strip == ':'
20
+ attrs = str.scan(ALD_TYPE_ANY)
21
+ attrs.each do |key, sep, val, ref, id_and_or_class, _, _|
22
+ if ref
23
+ (opts[:refs] ||= []) << ref
24
+ elsif id_and_or_class
25
+ id_and_or_class.scan(ALD_TYPE_ID_OR_CLASS).each do |id_attr, class_attr|
26
+ if class_attr
27
+ opts[IAL_CLASS_ATTR] = (opts[IAL_CLASS_ATTR] || '') << " #{class_attr}"
28
+ opts[IAL_CLASS_ATTR].lstrip!
29
+ else
30
+ opts['id'] = id_attr
31
+ end
32
+ end
33
+ else
34
+ val.gsub!(/\\(\}|#{sep})/, "\\1")
35
+ opts[key] = val
36
+ end
37
+ end
38
+ warning("No or invalid attributes found in IAL/ALD content: #{str}") if attrs.length == 0
39
+ end
40
+
41
+ # Update the +ial+ with the information from the inline attribute list +opts+.
42
+ def update_ial_with_ial(ial, opts)
43
+ (ial[:refs] ||= []) << opts[:refs]
44
+ opts.each do |k,v|
45
+ if k == IAL_CLASS_ATTR
46
+ ial[k] = (ial[k] || '') << " #{v}"
47
+ ial[k].lstrip!
48
+ elsif k.kind_of?(String)
49
+ ial[k] = v
50
+ end
51
+ end
52
+ end
53
+
54
+ # Parse the generic extension at the current point. The parameter +type+ can either be :block
55
+ # or :span depending whether we parse a block or span extension tag.
56
+ def parse_extension_start_tag(type)
57
+ saved_pos = @src.save_pos
58
+ start_line_number = @src.current_line_number
59
+ @src.pos += @src.matched_size
60
+
61
+ error_block = lambda do |msg|
62
+ warning(msg)
63
+ @src.revert_pos(saved_pos)
64
+ add_text(@src.getch) if type == :span
65
+ false
66
+ end
67
+
68
+ if @src[4] || @src.matched == '{:/}'
69
+ name = (@src[4] ? "for '#{@src[4]}' " : '')
70
+ return error_block.call("Invalid extension stop tag #{name} found on line #{start_line_number} - ignoring it")
71
+ end
72
+
73
+ ext = @src[1]
74
+ opts = {}
75
+ body = nil
76
+ parse_attribute_list(@src[2] || '', opts)
77
+
78
+ if !@src[3]
79
+ stop_re = (type == :block ? /#{EXT_BLOCK_STOP_STR % ext}/ : /#{EXT_STOP_STR % ext}/)
80
+ if result = @src.scan_until(stop_re)
81
+ body = result.sub!(stop_re, '')
82
+ body.chomp! if type == :block
83
+ else
84
+ return error_block.call("No stop tag for extension '#{ext}' found on line #{start_line_number} - ignoring it")
85
+ end
86
+ end
87
+
88
+ if !handle_extension(ext, opts, body, type, start_line_number)
89
+ error_block.call("Invalid extension with name '#{ext}' specified on line #{start_line_number} - ignoring it")
90
+ else
91
+ true
92
+ end
93
+ end
94
+
95
+ def handle_extension(name, opts, body, type, line_no = nil)
96
+ case name
97
+ when 'comment'
98
+ @tree.children << Element.new(:comment, body, nil, :category => type, :location => line_no) if body.kind_of?(String)
99
+ true
100
+ when 'nomarkdown'
101
+ @tree.children << Element.new(:raw, body, nil, :category => type, :location => line_no, :type => opts['type'].to_s.split(/\s+/)) if body.kind_of?(String)
102
+ true
103
+ when 'options'
104
+ opts.select do |k,v|
105
+ k = k.to_sym
106
+ if Kramdown::Options.defined?(k)
107
+ begin
108
+ val = Kramdown::Options.parse(k, v)
109
+ @options[k] = val
110
+ (@root.options[:options] ||= {})[k] = val
111
+ rescue
112
+ end
113
+ false
114
+ else
115
+ true
116
+ end
117
+ end.each do |k,v|
118
+ warning("Unknown kramdown option '#{k}'")
119
+ end
120
+ @tree.children << Element.new(:eob, :extension) if type == :block
121
+ true
122
+ else
123
+ false
124
+ end
125
+ end
126
+
127
+
128
+ ALD_ID_CHARS = /[\w-]/
129
+ ALD_ANY_CHARS = /\\\}|[^\}]/
130
+ ALD_ID_NAME = /\w#{ALD_ID_CHARS}*/
131
+ ALD_TYPE_KEY_VALUE_PAIR = /(#{ALD_ID_NAME})=("|')((?:\\\}|\\\2|[^\}\2])*?)\2/
132
+ ALD_TYPE_CLASS_NAME = /\.(#{ALD_ID_NAME})/
133
+ ALD_TYPE_ID_NAME = /#([A-Za-z][\w:-]*)/
134
+ ALD_TYPE_ID_OR_CLASS = /#{ALD_TYPE_ID_NAME}|#{ALD_TYPE_CLASS_NAME}/
135
+ ALD_TYPE_ID_OR_CLASS_MULTI = /((?:#{ALD_TYPE_ID_NAME}|#{ALD_TYPE_CLASS_NAME})+)/
136
+ ALD_TYPE_REF = /(#{ALD_ID_NAME})/
137
+ ALD_TYPE_ANY = /(?:\A|\s)(?:#{ALD_TYPE_KEY_VALUE_PAIR}|#{ALD_TYPE_REF}|#{ALD_TYPE_ID_OR_CLASS_MULTI})(?=\s|\Z)/
138
+ ALD_START = /^#{OPT_SPACE}\{:(#{ALD_ID_NAME}):(#{ALD_ANY_CHARS}+)\}\s*?\n/
139
+
140
+ EXT_STOP_STR = "\\{:/(%s)?\\}"
141
+ EXT_START_STR = "\\{::(\\w+)(?:\\s(#{ALD_ANY_CHARS}*?)|)(\\/)?\\}"
142
+ EXT_BLOCK_START = /^#{OPT_SPACE}(?:#{EXT_START_STR}|#{EXT_STOP_STR % ALD_ID_NAME})\s*?\n/
143
+ EXT_BLOCK_STOP_STR = "^#{OPT_SPACE}#{EXT_STOP_STR}\s*?\n"
144
+
145
+ IAL_BLOCK = /\{:(?!:|\/)(#{ALD_ANY_CHARS}+)\}\s*?\n/
146
+ IAL_BLOCK_START = /^#{OPT_SPACE}#{IAL_BLOCK}/m # RM Oniguruma -> ICU
147
+
148
+ BLOCK_EXTENSIONS_START = /^#{OPT_SPACE}\{:/
149
+
150
+ # Parse one of the block extensions (ALD, block IAL or generic extension) at the current
151
+ # location.
152
+ def parse_block_extensions
153
+ if @src.scan(ALD_START)
154
+ parse_attribute_list(@src[2], @alds[@src[1]] ||= Utils::OrderedHash.new)
155
+ @tree.children << Element.new(:eob, :ald)
156
+ true
157
+ elsif @src.check(EXT_BLOCK_START)
158
+ parse_extension_start_tag(:block)
159
+ elsif @src.scan(IAL_BLOCK_START)
160
+ if @tree.children.last && @tree.children.last.type != :blank && @tree.children.last.type != :eob
161
+ parse_attribute_list(@src[1], @tree.children.last.options[:ial] ||= Utils::OrderedHash.new)
162
+ @tree.children << Element.new(:eob, :ial) unless @src.check(IAL_BLOCK_START)
163
+ else
164
+ parse_attribute_list(@src[1], @block_ial = Utils::OrderedHash.new)
165
+ end
166
+ true
167
+ else
168
+ false
169
+ end
170
+ end
171
+ define_parser(:block_extensions, BLOCK_EXTENSIONS_START)
172
+
173
+
174
+ EXT_SPAN_START = /#{EXT_START_STR}|#{EXT_STOP_STR % ALD_ID_NAME}/
175
+ IAL_SPAN_START = /\{:(#{ALD_ANY_CHARS}+)\}/
176
+ SPAN_EXTENSIONS_START = /\{:/
177
+
178
+ # Parse the extension span at the current location.
179
+ def parse_span_extensions
180
+ if @src.check(EXT_SPAN_START)
181
+ parse_extension_start_tag(:span)
182
+ elsif @src.check(IAL_SPAN_START)
183
+ if @tree.children.last && @tree.children.last.type != :text
184
+ @src.pos += @src.matched_size
185
+ attr = Utils::OrderedHash.new
186
+ parse_attribute_list(@src[1], attr)
187
+ update_ial_with_ial(@tree.children.last.options[:ial] ||= Utils::OrderedHash.new, attr)
188
+ update_attr_with_ial(@tree.children.last.attr, attr)
189
+ else
190
+ warning("Found span IAL after text - ignoring it")
191
+ add_text(@src.getch)
192
+ end
193
+ else
194
+ add_text(@src.getch)
195
+ end
196
+ end
197
+ define_parser(:span_extensions, SPAN_EXTENSIONS_START, '\{:')
198
+
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,56 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ # RM require 'kramdown/parser/kramdown/extensions'
11
+ # RM require 'kramdown/parser/kramdown/blank_line'
12
+ # RM require 'kramdown/parser/kramdown/codeblock'
13
+
14
+ module Kramdown
15
+ module Parser
16
+ class Kramdown
17
+
18
+ FOOTNOTE_DEFINITION_START = /^#{OPT_SPACE}\[\^(#{ALD_ID_NAME})\]:\s*?(.*?\n#{CODEBLOCK_MATCH})/
19
+
20
+ # Parse the foot note definition at the current location.
21
+ def parse_footnote_definition
22
+ start_line_number = @src.current_line_number
23
+ @src.pos += @src.matched_size
24
+
25
+ el = Element.new(:footnote_def, nil, nil, :location => start_line_number)
26
+ parse_blocks(el, @src[2].gsub(INDENT, ''))
27
+ warning("Duplicate footnote name '#{@src[1]}' on line #{start_line_number} - overwriting") if @footnotes[@src[1]]
28
+ (@footnotes[@src[1]] = {})[:content] = el
29
+ @tree.children << Element.new(:eob, :footnote_def)
30
+ true
31
+ end
32
+ define_parser(:footnote_definition, FOOTNOTE_DEFINITION_START)
33
+
34
+
35
+ FOOTNOTE_MARKER_START = /\[\^(#{ALD_ID_NAME})\]/
36
+
37
+ # Parse the footnote marker at the current location.
38
+ def parse_footnote_marker
39
+ start_line_number = @src.current_line_number
40
+ @src.pos += @src.matched_size
41
+ fn_def = @footnotes[@src[1]]
42
+ if fn_def
43
+ fn_def[:marker] ||= []
44
+ fn_def[:marker].push(Element.new(:footnote, fn_def[:content], nil, :name => @src[1], :location => start_line_number))
45
+ fn_def[:stack] = [@stack.map {|s| s.first}, @tree, fn_def[:marker]].flatten.compact
46
+ @tree.children << fn_def[:marker].last
47
+ else
48
+ warning("Footnote definition for '#{@src[1]}' not found on line #{start_line_number}")
49
+ add_text(@src.matched)
50
+ end
51
+ end
52
+ define_parser(:footnote_marker, FOOTNOTE_MARKER_START, '\[')
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,59 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ # RM require 'kramdown/parser/kramdown/block_boundary'
11
+
12
+ module Kramdown
13
+ module Parser
14
+ class Kramdown
15
+
16
+ HEADER_ID=/(?:[ \t]+\{#([A-Za-z][\w:-]*)\})?/
17
+ SETEXT_HEADER_START = /^(#{OPT_SPACE}[^ \t].*?)#{HEADER_ID}[ \t]*?\n(-|=)+\s*?\n/
18
+
19
+ # Parse the Setext header at the current location.
20
+ def parse_setext_header
21
+ return false if !after_block_boundary?
22
+
23
+ start_line_number = @src.current_line_number
24
+ @src.pos += @src.matched_size
25
+ text, id, level = @src[1], @src[2], @src[3]
26
+ text.strip!
27
+ el = new_block_el(:header, nil, nil, :level => (level == '-' ? 2 : 1), :raw_text => text, :location => start_line_number)
28
+ add_text(text, el)
29
+ el.attr['id'] = id if id
30
+ @tree.children << el
31
+ true
32
+ end
33
+ define_parser(:setext_header, SETEXT_HEADER_START)
34
+
35
+
36
+ ATX_HEADER_START = /^\#{1,6}/
37
+ ATX_HEADER_MATCH = /^(\#{1,6})(.+?(?:\\#)?)\s*?#*#{HEADER_ID}\s*?\n/
38
+
39
+ # Parse the Atx header at the current location.
40
+ def parse_atx_header
41
+ return false if !after_block_boundary?
42
+
43
+ start_line_number = @src.current_line_number
44
+ @src.check(ATX_HEADER_MATCH)
45
+ level, text, id = @src[1], @src[2].to_s.strip, @src[3]
46
+ return false if text.empty?
47
+
48
+ @src.pos += @src.matched_size
49
+ el = new_block_el(:header, nil, nil, :level => level.length, :raw_text => text, :location => start_line_number)
50
+ add_text(text, el)
51
+ el.attr['id'] = id if id
52
+ @tree.children << el
53
+ true
54
+ end
55
+ define_parser(:atx_header, ATX_HEADER_START)
56
+
57
+ end
58
+ end
59
+ end