kramdown 1.2.0 → 1.3.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.

Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTERS +5 -1
  3. data/README.md +5 -1
  4. data/Rakefile +5 -3
  5. data/VERSION +1 -1
  6. data/benchmark/generate_data.rb +1 -1
  7. data/doc/default.template +2 -2
  8. data/doc/index.page +3 -4
  9. data/doc/news.feed +1 -1
  10. data/doc/quickref.page +4 -4
  11. data/doc/sidebar.template +7 -8
  12. data/doc/syntax.page +10 -3
  13. data/doc/tests.page +1 -1
  14. data/lib/kramdown/converter.rb +1 -0
  15. data/lib/kramdown/converter/base.rb +57 -9
  16. data/lib/kramdown/converter/kramdown.rb +4 -2
  17. data/lib/kramdown/converter/pdf.rb +638 -0
  18. data/lib/kramdown/document.rb +1 -1
  19. data/lib/kramdown/element.rb +4 -0
  20. data/lib/kramdown/options.rb +44 -8
  21. data/lib/kramdown/parser/base.rb +4 -2
  22. data/lib/kramdown/parser/gfm.rb +25 -18
  23. data/lib/kramdown/parser/html.rb +2 -2
  24. data/lib/kramdown/parser/kramdown.rb +24 -2
  25. data/lib/kramdown/parser/kramdown/abbreviation.rb +3 -2
  26. data/lib/kramdown/parser/kramdown/autolink.rb +2 -1
  27. data/lib/kramdown/parser/kramdown/blockquote.rb +2 -1
  28. data/lib/kramdown/parser/kramdown/codeblock.rb +4 -2
  29. data/lib/kramdown/parser/kramdown/codespan.rb +2 -1
  30. data/lib/kramdown/parser/kramdown/emphasis.rb +2 -1
  31. data/lib/kramdown/parser/kramdown/extensions.rb +5 -4
  32. data/lib/kramdown/parser/kramdown/footnote.rb +6 -4
  33. data/lib/kramdown/parser/kramdown/header.rb +4 -2
  34. data/lib/kramdown/parser/kramdown/horizontal_rule.rb +2 -1
  35. data/lib/kramdown/parser/kramdown/html_entity.rb +4 -2
  36. data/lib/kramdown/parser/kramdown/link.rb +3 -2
  37. data/lib/kramdown/parser/kramdown/list.rb +9 -5
  38. data/lib/kramdown/parser/kramdown/math.rb +5 -3
  39. data/lib/kramdown/parser/kramdown/paragraph.rb +2 -1
  40. data/lib/kramdown/parser/kramdown/table.rb +5 -3
  41. data/lib/kramdown/parser/kramdown/typographic_symbol.rb +10 -5
  42. data/lib/kramdown/utils.rb +1 -0
  43. data/lib/kramdown/utils/string_scanner.rb +52 -0
  44. data/lib/kramdown/version.rb +1 -1
  45. data/man/man1/kramdown.1 +41 -6
  46. data/test/test_files.rb +2 -2
  47. data/test/test_location.rb +158 -0
  48. data/test/test_string_scanner_kramdown.rb +22 -0
  49. data/test/testcases/block/04_header/with_auto_id_stripping.html +1 -0
  50. data/test/testcases/block/04_header/with_auto_id_stripping.options +1 -0
  51. data/test/testcases/block/04_header/with_auto_id_stripping.text +1 -0
  52. data/test/testcases/span/math/normal.html +2 -1
  53. data/test/testcases/span/math/normal.text +2 -1
  54. data/test/testcases_gfm/hard_line_breaks_off.html +2 -0
  55. data/test/testcases_gfm/hard_line_breaks_off.options +1 -0
  56. data/test/testcases_gfm/hard_line_breaks_off.text +2 -0
  57. metadata +27 -3
@@ -20,10 +20,11 @@ module Kramdown
20
20
  def parse_setext_header
21
21
  return false if !after_block_boundary?
22
22
 
23
+ start_line_number = @src.current_line_number
23
24
  @src.pos += @src.matched_size
24
25
  text, id, level = @src[1], @src[2], @src[3]
25
26
  text.strip!
26
- el = new_block_el(:header, nil, nil, :level => (level == '-' ? 2 : 1), :raw_text => text)
27
+ el = new_block_el(:header, nil, nil, :level => (level == '-' ? 2 : 1), :raw_text => text, :location => start_line_number)
27
28
  add_text(text, el)
28
29
  el.attr['id'] = id if id
29
30
  @tree.children << el
@@ -39,12 +40,13 @@ module Kramdown
39
40
  def parse_atx_header
40
41
  return false if !after_block_boundary?
41
42
 
43
+ start_line_number = @src.current_line_number
42
44
  @src.check(ATX_HEADER_MATCH)
43
45
  level, text, id = @src[1], @src[2].to_s.strip, @src[3]
44
46
  return false if text.empty?
45
47
 
46
48
  @src.pos += @src.matched_size
47
- el = new_block_el(:header, nil, nil, :level => level.length, :raw_text => text)
49
+ el = new_block_el(:header, nil, nil, :level => level.length, :raw_text => text, :location => start_line_number)
48
50
  add_text(text, el)
49
51
  el.attr['id'] = id if id
50
52
  @tree.children << el
@@ -15,8 +15,9 @@ module Kramdown
15
15
 
16
16
  # Parse the horizontal rule at the current location.
17
17
  def parse_horizontal_rule
18
+ start_line_number = @src.current_line_number
18
19
  @src.pos += @src.matched_size
19
- @tree.children << new_block_el(:hr)
20
+ @tree.children << new_block_el(:hr, nil, nil, :location => start_line_number)
20
21
  true
21
22
  end
22
23
  define_parser(:horizontal_rule, HR_START)
@@ -15,12 +15,14 @@ module Kramdown
15
15
 
16
16
  # Parse the HTML entity at the current location.
17
17
  def parse_html_entity
18
+ start_line_number = @src.current_line_number
18
19
  @src.pos += @src.matched_size
19
20
  begin
20
21
  @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity(@src[1] || (@src[2] && @src[2].to_i) || @src[3].hex),
21
- nil, :original => @src.matched)
22
+ nil, :original => @src.matched, :location => start_line_number)
22
23
  rescue ::Kramdown::Error
23
- @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('amp'))
24
+ @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('amp'),
25
+ nil, :location => start_line_number)
24
26
  add_text(@src.matched[1..-1])
25
27
  end
26
28
  end
@@ -22,7 +22,7 @@ module Kramdown
22
22
  def parse_link_definition
23
23
  @src.pos += @src.matched_size
24
24
  link_id, link_url, link_title = normalize_link_id(@src[1]), @src[2] || @src[3], @src[5]
25
- warning("Duplicate link ID '#{link_id}' - overwriting") if @link_defs[link_id]
25
+ warning("Duplicate link ID '#{link_id}' on line #{@src.current_line_number} - overwriting") if @link_defs[link_id]
26
26
  @link_defs[link_id] = [link_url, link_title]
27
27
  @tree.children << Element.new(:eob, :link_def)
28
28
  true
@@ -53,6 +53,7 @@ module Kramdown
53
53
  # Parse the link at the current scanner position. This method is used to parse normal links as
54
54
  # well as image links.
55
55
  def parse_link
56
+ start_line_number = @src.current_line_number
56
57
  result = @src.scan(LINK_START)
57
58
  reset_pos = @src.pos
58
59
 
@@ -63,7 +64,7 @@ module Kramdown
63
64
  add_text(result)
64
65
  return
65
66
  end
66
- el = Element.new(link_type)
67
+ el = Element.new(link_type, nil, nil, :location => start_line_number)
67
68
 
68
69
  count = 1
69
70
  found = parse_spans(el, LINK_BRACKET_STOP_RE) do
@@ -46,8 +46,9 @@ module Kramdown
46
46
 
47
47
  # Parse the ordered or unordered list at the current location.
48
48
  def parse_list
49
+ start_line_number = @src.current_line_number
49
50
  type, list_start_re = (@src.check(LIST_START_UL) ? [:ul, LIST_START_UL] : [:ol, LIST_START_OL])
50
- list = new_block_el(type)
51
+ list = new_block_el(type, nil, nil, :location => start_line_number)
51
52
 
52
53
  item = nil
53
54
  content_re, lazy_re, indent_re = nil
@@ -55,13 +56,14 @@ module Kramdown
55
56
  nested_list_found = false
56
57
  last_is_blank = false
57
58
  while !@src.eos?
59
+ start_line_number = @src.current_line_number
58
60
  if last_is_blank && @src.check(HR_START)
59
61
  break
60
62
  elsif @src.scan(EOB_MARKER)
61
63
  eob_found = true
62
64
  break
63
65
  elsif @src.scan(list_start_re)
64
- item = Element.new(:li)
66
+ item = Element.new(:li, nil, nil, :location => start_line_number)
65
67
  item.value, indentation, content_re, lazy_re, indent_re = parse_first_list_line(@src[1].length, @src[2])
66
68
  list.children << item
67
69
 
@@ -96,7 +98,7 @@ module Kramdown
96
98
 
97
99
  last = nil
98
100
  list.children.each do |it|
99
- temp = Element.new(:temp)
101
+ temp = Element.new(:temp, nil, nil, :location => it.options[:location])
100
102
  parse_blocks(temp, it.value)
101
103
  it.children = temp.children
102
104
  it.value = nil
@@ -146,8 +148,9 @@ module Kramdown
146
148
  para = @tree.children.pop
147
149
  first_as_para = true
148
150
  end
151
+ deflist.options[:location] = para.options[:location] # take location from preceding para which is the first definition term
149
152
  para.children.first.value.split(/\n/).each do |term|
150
- el = Element.new(:dt)
153
+ el = Element.new(:dt, nil, nil, :location => @src.current_line_number)
151
154
  el.children << Element.new(:raw_text, term)
152
155
  deflist.children << el
153
156
  end
@@ -158,8 +161,9 @@ module Kramdown
158
161
  def_start_re = DEFINITION_LIST_START
159
162
  last_is_blank = false
160
163
  while !@src.eos?
164
+ start_line_number = @src.current_line_number
161
165
  if @src.scan(def_start_re)
162
- item = Element.new(:dd)
166
+ item = Element.new(:dd, nil, nil, :location => start_line_number)
163
167
  item.options[:first_as_para] = first_as_para
164
168
  item.value, indentation, content_re, lazy_re, indent_re = parse_first_list_line(@src[1].length, @src[2])
165
169
  deflist.children << item
@@ -17,6 +17,7 @@ module Kramdown
17
17
 
18
18
  # Parse the math block at the current location.
19
19
  def parse_block_math
20
+ start_line_number = @src.current_line_number
20
21
  if !after_block_boundary?
21
22
  return false
22
23
  elsif @src[1]
@@ -28,7 +29,7 @@ module Kramdown
28
29
  @src.pos += @src.matched_size
29
30
  data = @src[2]
30
31
  if before_block_boundary?
31
- @tree.children << new_block_el(:math, data, nil, :category => :block)
32
+ @tree.children << new_block_el(:math, data, nil, :category => :block, :location => start_line_number)
32
33
  true
33
34
  else
34
35
  @src.pos = orig_pos
@@ -38,12 +39,13 @@ module Kramdown
38
39
  define_parser(:block_math, BLOCK_MATH_START)
39
40
 
40
41
 
41
- INLINE_MATH_START = /\$\$(.*?)\$\$/
42
+ INLINE_MATH_START = /\$\$(.*?)\$\$/m
42
43
 
43
44
  # Parse the inline math at the current location.
44
45
  def parse_inline_math
46
+ start_line_number = @src.current_line_number
45
47
  @src.pos += @src.matched_size
46
- @tree.children << Element.new(:math, @src[1], nil, :category => :span)
48
+ @tree.children << Element.new(:math, @src[1], nil, :category => :span, :location => start_line_number)
47
49
  end
48
50
  define_parser(:inline_math, INLINE_MATH_START, '\$')
49
51
 
@@ -29,6 +29,7 @@ module Kramdown
29
29
 
30
30
  # Parse the paragraph at the current location.
31
31
  def parse_paragraph
32
+ start_line_number = @src.current_line_number
32
33
  result = @src.scan(PARAGRAPH_MATCH)
33
34
  while !@src.match?(self.class::PARAGRAPH_END)
34
35
  result << @src.scan(PARAGRAPH_MATCH)
@@ -37,7 +38,7 @@ module Kramdown
37
38
  if @tree.children.last && @tree.children.last.type == :p
38
39
  @tree.children.last.children.first.value << "\n" << result
39
40
  else
40
- @tree.children << new_block_el(:p)
41
+ @tree.children << new_block_el(:p, nil, nil, :location => start_line_number)
41
42
  result.lstrip!
42
43
  @tree.children.last.children << Element.new(@text_type, result)
43
44
  end
@@ -26,7 +26,7 @@ module Kramdown
26
26
  return false if !after_block_boundary?
27
27
 
28
28
  orig_pos = @src.pos
29
- table = new_block_el(:table, nil, nil, :alignment => [])
29
+ table = new_block_el(:table, nil, nil, :alignment => [], :location => @src.current_line_number)
30
30
  leading_pipe = (@src.check(TABLE_LINE) =~ /^\s*\|/)
31
31
  @src.scan(TABLE_SEP_LINE)
32
32
 
@@ -66,7 +66,7 @@ module Kramdown
66
66
  if i % 2 == 1
67
67
  (cells.empty? ? cells : cells.last) << str
68
68
  else
69
- reset_env(:src => StringScanner.new(str))
69
+ reset_env(:src => Kramdown::Utils::StringScanner.new(str, @src.current_line_number))
70
70
  root = Element.new(:root)
71
71
  parse_spans(root, nil, [:codespan])
72
72
 
@@ -110,7 +110,9 @@ module Kramdown
110
110
 
111
111
  # Parse all lines of the table with the code span parser
112
112
  env = save_env
113
- reset_env(:src => StringScanner.new(extract_string(orig_pos...(@src.pos-1), @src)))
113
+ l_src = ::Kramdown::Utils::StringScanner.new(extract_string(orig_pos...(@src.pos-1), @src),
114
+ @src.current_line_number)
115
+ reset_env(:src => l_src)
114
116
  root = Element.new(:root)
115
117
  parse_spans(root, nil, [:codespan])
116
118
  restore_env(env)
@@ -20,16 +20,21 @@ module Kramdown
20
20
 
21
21
  # Parse the typographic symbols at the current location.
22
22
  def parse_typographic_syms
23
+ start_line_number = @src.current_line_number
23
24
  @src.pos += @src.matched_size
24
25
  val = TYPOGRAPHIC_SYMS_SUBST[@src.matched]
25
26
  if val.kind_of?(Symbol)
26
- @tree.children << Element.new(:typographic_sym, val)
27
+ @tree.children << Element.new(:typographic_sym, val, nil, :location => start_line_number)
27
28
  elsif @src.matched == '\\<<'
28
- @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('lt'))
29
- @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('lt'))
29
+ @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('lt'),
30
+ nil, :location => start_line_number)
31
+ @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('lt'),
32
+ nil, :location => start_line_number)
30
33
  else
31
- @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('gt'))
32
- @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('gt'))
34
+ @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('gt'),
35
+ nil, :location => start_line_number)
36
+ @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('gt'),
37
+ nil, :location => start_line_number)
33
38
  end
34
39
  end
35
40
  define_parser(:typographic_syms, TYPOGRAPHIC_SYMS_RE, '--|\\.\\.\\.|(?:\\\\| )?(?:<<|>>)')
@@ -19,6 +19,7 @@ module Kramdown
19
19
  autoload :Html, 'kramdown/utils/html'
20
20
  autoload :OrderedHash, 'kramdown/utils/ordered_hash'
21
21
  autoload :Unidecoder, 'kramdown/utils/unidecoder'
22
+ autoload :StringScanner, 'kramdown/utils/string_scanner'
22
23
 
23
24
  # Treat +name+ as if it were snake cased (e.g. snake_case) and camelize it (e.g. SnakeCase).
24
25
  def self.camelize(name)
@@ -0,0 +1,52 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'strscan'
4
+
5
+ module Kramdown
6
+ module Utils
7
+
8
+ # This patched StringScanner adds line number information for current scan position and a
9
+ # start_line_number override for nested StringScanners.
10
+ class StringScanner < ::StringScanner
11
+
12
+ # The start line number. Used for nested StringScanners that scan a sub-string of the source
13
+ # document. The kramdown parser uses this, e.g., for span level parsers.
14
+ attr_reader :start_line_number
15
+
16
+ # Takes the start line number as optional second argument.
17
+ #
18
+ # Note: The original second argument is no longer used so this should be safe.
19
+ def initialize(string, start_line_number = 1)
20
+ super(string)
21
+ @start_line_number = start_line_number || 1
22
+ end
23
+
24
+ # To make this unicode (multibyte) aware, we have to use #charpos which was added in Ruby
25
+ # version 2.0.0.
26
+ #
27
+ # This method will work with older versions of Ruby, however it will report incorrect line
28
+ # numbers if the scanned string contains multibyte characters.
29
+ if instance_methods.include?(:charpos)
30
+ def best_pos
31
+ charpos
32
+ end
33
+ else
34
+ def best_pos
35
+ pos
36
+ end
37
+ end
38
+
39
+ # Returns the line number for current charpos.
40
+ #
41
+ # NOTE: Requires that all line endings are normalized to '\n'
42
+ #
43
+ # NOTE: Normally we'd have to add one to the count of newlines to get the correct line number.
44
+ # However we add the one indirectly by using a one-based start_line_number.
45
+ def current_line_number
46
+ string[0..best_pos].count("\n") + start_line_number
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+ end
@@ -10,6 +10,6 @@
10
10
  module Kramdown
11
11
 
12
12
  # The kramdown version.
13
- VERSION = '1.2.0'
13
+ VERSION = '1.3.0'
14
14
 
15
15
  end
@@ -38,6 +38,7 @@ Show the help.
38
38
  .B \-\-template ARG
39
39
 
40
40
  The name of an ERB template file that should be used to wrap the output
41
+ or the ERB template itself.
41
42
 
42
43
  This is used to wrap the output in an environment so that the output can
43
44
  be used as a stand-alone document. For example, an HTML template would
@@ -46,10 +47,13 @@ valid HTML file. If no template is specified, the output will be just
46
47
  the converted text.
47
48
 
48
49
  When resolving the template file, the given template name is used first.
49
- If such a file is not found, the converter extension is appended. If the
50
- file still cannot be found, the templates name is interpreted as a
51
- template name that is provided by kramdown (without the converter
52
- extension).
50
+ If such a file is not found, the converter extension (the same as the
51
+ converter name) is appended. If the file still cannot be found, the
52
+ templates name is interpreted as a template name that is provided by
53
+ kramdown (without the converter extension). If the file is still not
54
+ found, the template name is checked if it starts with 'string://' and if
55
+ it does, this prefix is removed and the rest is used as template
56
+ content.
53
57
 
54
58
  kramdown provides a default template named 'document' for each converter.
55
59
 
@@ -69,10 +73,26 @@ Default: true
69
73
  Used by: HTML/Latex converter
70
74
 
71
75
 
76
+ .TP
77
+ .B \-\-[no\-]auto-id-stripping
78
+
79
+ Strip all formatting from header text for automatic ID generation
80
+
81
+ If this option is `true`, only the text elements of a header are used
82
+ for generating the ID later (in contrast to just using the raw header
83
+ text line).
84
+
85
+ This option will be removed in version 2.0 because this will be the
86
+ default then.
87
+
88
+ Default: false
89
+ Used by: kramdown parser
90
+
91
+
72
92
  .TP
73
93
  .B \-\-auto-id-prefix ARG
74
94
 
75
- Prefix used for automatically generated heaer IDs
95
+ Prefix used for automatically generated header IDs
76
96
 
77
97
  This option can be used to set a prefix for the automatically generated
78
98
  header IDs so that there is no conflict when rendering multiple kramdown
@@ -227,6 +247,9 @@ Used by: HTML converter
227
247
 
228
248
  Defines how often a line number should be made bold
229
249
 
250
+ Can either be an integer or false (to turn off bold line numbers
251
+ completely).
252
+
230
253
  Default: 10
231
254
  Used by: HTML converter
232
255
 
@@ -357,10 +380,22 @@ Default: 0
357
380
  Used by: HTML converter, Kramdown converter, Latex converter
358
381
 
359
382
 
383
+ .TP
384
+ .B \-\-[no\-]hard-wrap
385
+
386
+ Interprets line breaks literally
387
+
388
+ Insert HTML `<br />` tags inside paragraphs where the original Markdown
389
+ document had newlines (by default, Markdown ignores these newlines).
390
+
391
+ Default: true
392
+ Used by: GFM parser
393
+
394
+
360
395
  .SH EXIT STATUS
361
396
  The exit status is 0 if no error happened. Otherwise it is 1.
362
397
  .SH SEE ALSO
363
- The kramdown website, http://kramdown.rubyforge.org/ for more information, especially on the supported
398
+ The kramdown website, http://kramdown.gettalong.org/ for more information, especially on the supported
364
399
  input syntax.
365
400
  .SH AUTHOR
366
401
  kramdown was written by Thomas Leitner <t_leitner@gmx.at>.
@@ -7,14 +7,14 @@
7
7
  #++
8
8
  #
9
9
 
10
- require 'test/unit'
10
+ require 'minitest/autorun'
11
11
  require 'kramdown'
12
12
  require 'yaml'
13
13
  require 'tmpdir'
14
14
 
15
15
  Encoding.default_external = 'utf-8' if RUBY_VERSION >= '1.9'
16
16
 
17
- class TestFiles < Test::Unit::TestCase
17
+ class TestFiles < Minitest::Test
18
18
 
19
19
  EXCLUDE_KD_FILES = [('test/testcases/block/04_header/with_auto_ids.text' if RUBY_VERSION <= '1.8.6'), # bc of dep stringex not working
20
20
  ].compact
@@ -0,0 +1,158 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'minitest/autorun'
4
+ require 'kramdown'
5
+
6
+ Encoding.default_external = 'utf-8' if RUBY_VERSION >= '1.9'
7
+
8
+ describe 'location' do
9
+
10
+ # checks that +element+'s :location option corresponds to the location stored
11
+ # in the element.attr['class']
12
+ def check_element_for_location(element)
13
+ if (match = /^line-(\d+)/.match(element.attr['class'] || ''))
14
+ expected_line = match[1].to_i
15
+ element.options[:location].must_equal(expected_line)
16
+ end
17
+ element.children.each do |child|
18
+ check_element_for_location(child)
19
+ end
20
+ end
21
+
22
+ # Test cases consist of a kramdown string that uses IALs to specify the expected
23
+ # line numbers for a given element.
24
+ test_cases = {
25
+ 'autolink' => %(testing autolinks\n\n<http://kramdown.org>{:.line-3}),
26
+ 'blockquote' => %(
27
+ > block quote1
28
+ >
29
+ > * {:.line-3} list item in block quote
30
+ > * {:.line-4} list item in block quote
31
+ > {:.line-3}
32
+ {:.line-1}
33
+
34
+ > block quote2
35
+ {:.line-8}
36
+ ),
37
+ 'codeblock' => %(\na para\n\n~~~~\ntest code 1\n~~~~\n{:.line-3}\n\n test code 2\n{:.line-8}\n),
38
+ 'codespan' => %(a para\n\nanother para `<code>`{:.line-3} with code\n),
39
+ 'emphasis' => %(
40
+ para *span*{:.line-1}
41
+ {:.line-1}
42
+
43
+ ## header *span*{:.line-4}
44
+ {:.line-4}
45
+
46
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
47
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
48
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
49
+ consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
50
+ cillum *short span on single line*{:.line-11}
51
+ dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
52
+ *long span over multiple lines - proident, sunt in culpa qui officia deserunt
53
+ mollit anim id est laborum.*{:.line-13}
54
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
55
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
56
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
57
+ `code span`{:.line-18}
58
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
59
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
60
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
61
+ {:.line-7}
62
+ ),
63
+ 'header' => %(
64
+ # header1
65
+ {:.line-1}
66
+
67
+ ## header2
68
+ {:.line-4}
69
+
70
+ ## header3
71
+ {:.line-7}
72
+
73
+ header4
74
+ =======
75
+ {:.line-10}
76
+
77
+ header5
78
+ -------
79
+ {:.line-14}
80
+ ),
81
+ 'horizontal_rule' => %(\na para\n\n----\n{:.line-3}\n),
82
+ 'html_entity' => "a para\n\nanother para with &amp;{:.line-3} html entity.\n",
83
+ 'link' => %(
84
+ a para
85
+
86
+ This is [a link](http://rubyforge.org){:.line-3} to a page.
87
+
88
+ Here comes a ![smiley](../images/smiley.png){:.line-5}
89
+ ),
90
+ 'list' => %(
91
+ * {:.line-1} list item
92
+ * {:.line-2} list item
93
+ * {:.line-3} list item
94
+ {:.line-1}
95
+
96
+ {:.line-7}
97
+ 1. {:.line-7} list item
98
+ 2. {:.line-8} list item
99
+ 3. {:.line-9} list item
100
+
101
+ {:.line-12}
102
+ definition term 1
103
+ : {:.line-13} definition definition 1
104
+ definition term 2
105
+ : {:.line-15} definition definition 2
106
+ ),
107
+ 'math_block' => %(\na para\n\n$$5+5$$\n{:.line-3}\n),
108
+ 'math_inline' => %(\na para\n\nanother para with inline math $$5+5$${:.line-3}\n),
109
+ 'paragraph' => %(
110
+ para1
111
+ {:.line-1}
112
+
113
+ para2
114
+ {:.line-4}
115
+
116
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
117
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
118
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
119
+ consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
120
+ {:.line-7}
121
+
122
+ {:.line-14}
123
+ para with leading IAL
124
+ ),
125
+ 'table' => %(
126
+ a para
127
+
128
+ |first|second|third|
129
+ |-----|------|-----|
130
+ |a |b |c |
131
+ {:.line-3}
132
+ ),
133
+ 'typographic_symbol' => %(
134
+ a para
135
+
136
+ another para ---{:.line-3}
137
+
138
+ another para ...{:.line-5}
139
+ )
140
+ }
141
+ test_cases.each do |name, test_string|
142
+ it "Handles #{ name }" do
143
+ doc = Kramdown::Document.new(test_string.gsub(/^ /, '').strip)
144
+ check_element_for_location(doc.root)
145
+ end
146
+ end
147
+
148
+ it 'adds location info to duplicate abbreviation definition warnings' do
149
+ test_string = %(This snippet contains a duplicate abbreviation definition
150
+
151
+ *[duplicate]: The first definition
152
+ *[duplicate]: The second definition
153
+ )
154
+ doc = Kramdown::Document.new(test_string.strip)
155
+ doc.warnings.must_equal ["Duplicate abbreviation ID 'duplicate' on line 4 - overwriting"]
156
+ end
157
+
158
+ end