motion-kramdown 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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