diff options
| -rw-r--r-- | CHANGELOG.adoc | 2 | ||||
| -rw-r--r-- | lib/asciidoctor/parser.rb | 28 | ||||
| -rw-r--r-- | test/api_test.rb | 125 | ||||
| -rw-r--r-- | test/blocks_test.rb | 2 | ||||
| -rw-r--r-- | test/fixtures/lists.adoc | 96 | ||||
| -rw-r--r-- | test/lists_test.rb | 6 |
6 files changed, 248 insertions, 11 deletions
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 4aa841e9..b9a9ae2d 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -95,6 +95,8 @@ Bug fixes:: Improvements / Refactoring:: + * use cursor marks to track lines more accurately; record cursor at the start of each block, list item, or table cell (PR #2701, PR #2547) (@seikichi) + * populate source_location property on list items when sourcemap option is set on document (PR #2069) (@mogztter) * log a warning message if an unterminated delimited block is detected (#1133, PR #2612) * log a warning when nested section is found inside special section that doesn't support nested sections (#2433, PR #2672) * read files in binary mode to disable automatic endline coercion (then explicitly coerce to UTF-8) (PR #2583, PR #2694) diff --git a/lib/asciidoctor/parser.rb b/lib/asciidoctor/parser.rb index 2295998f..78157615 100644 --- a/lib/asciidoctor/parser.rb +++ b/lib/asciidoctor/parser.rb @@ -1258,13 +1258,22 @@ class Parser # for the parent list Block. def self.next_list_item(reader, list_block, match, sibling_trait = nil) if (list_type = list_block.context) == :dlist + dlist = true + has_text = true unless match[3].nil_or_empty? list_term = ListItem.new(list_block, match[1]) list_item = ListItem.new(list_block, match[3]) - has_text = true unless match[3].nil_or_empty? + if list_block.document.sourcemap + list_term.source_location = reader.cursor + if has_text + list_item.source_location = list_term.source_location + else + sourcemap_assignment_deferred = true + end + end else - # Create list item using first line as the text of the list item - list_item = ListItem.new(list_block, (text = match[2])) has_text = true + list_item = ListItem.new(list_block, (text = match[2])) + list_item.source_location = reader.cursor if list_block.document.sourcemap if list_type == :ulist list_item.marker = (sibling_trait ||= match[1]) if text.start_with?('[') && text.start_with?('[ ] ', '[x] ', '[*] ') @@ -1282,11 +1291,12 @@ class Parser end end - # first skip the line with the marker / term + # first skip the line with the marker / term (it gets put back onto the reader by next_block) reader.shift block_cursor = reader.cursor list_item_reader = Reader.new read_lines_for_list_item(reader, list_type, sibling_trait, has_text), block_cursor if list_item_reader.has_more_lines? + list_item.source_location = block_cursor if sourcemap_assignment_deferred # NOTE peek on the other side of any comment lines comment_lines = list_item_reader.skip_line_comments if (subsequent_line = list_item_reader.peek_line) @@ -1296,7 +1306,7 @@ class Parser else content_adjacent = true # treat lines as paragraph text if continuation does not connect first block (i.e., has_text = nil) - has_text = nil unless list_type == :dlist + has_text = nil unless dlist end else # NOTE we have no use for any trailing comment lines we might have found @@ -1304,19 +1314,17 @@ class Parser content_adjacent = false end - # only relevant for :dlist - options = {:text => !has_text} + attrs, opts = {}, { :text => !has_text } # we can look for blocks until lines are exhausted without worrying about # sections since reader is confined to boundaries of list - while ((block = next_block list_item_reader, list_item, {}, options) && list_item.blocks << block) || - list_item_reader.has_more_lines? + while ((block = next_block list_item_reader, list_item, attrs, opts) && list_item.blocks << block) || list_item_reader.has_more_lines? end list_item.fold_first(continuation_connects_first_block, content_adjacent) end - if list_type == :dlist + if dlist if list_item.text? || list_item.blocks? [list_term, list_item] else diff --git a/test/api_test.rb b/test/api_test.rb index a40d708f..5ec8fa3e 100644 --- a/test/api_test.rb +++ b/test/api_test.rb @@ -283,6 +283,19 @@ content assert_equal 'sample.asciidoc', last_block.file assert_equal 23, last_block.lineno + list_items = last_block.blocks + refute_nil list_items[0].source_location + assert_equal 'sample.asciidoc', list_items[0].file + assert_equal 23, list_items[0].lineno + + refute_nil list_items[1].source_location + assert_equal 'sample.asciidoc', list_items[1].file + assert_equal 24, list_items[1].lineno + + refute_nil list_items[2].source_location + assert_equal 'sample.asciidoc', list_items[2].file + assert_equal 25, list_items[2].lineno + doc = Asciidoctor.load_file fixture_path('master.adoc'), :sourcemap => true, :safe => :safe section_1 = doc.sections[0] @@ -292,6 +305,118 @@ content assert_equal 1, section_1.lineno end + test 'wip should track file and line information on list items if sourcemap option is set' do + doc = Asciidoctor.load_file fixture_path('lists.adoc'), :sourcemap => true + + first_section = doc.blocks[1] + + unordered_basic_list = first_section.blocks[0] + assert_equal 11, unordered_basic_list.lineno + + unordered_basic_list_items = unordered_basic_list.find_by :context => :list_item + assert_equal 11, unordered_basic_list_items[0].lineno + assert_equal 12, unordered_basic_list_items[1].lineno + assert_equal 13, unordered_basic_list_items[2].lineno + + unordered_max_nesting = first_section.blocks[1] + assert_equal 16, unordered_max_nesting.lineno + unordered_max_nesting_items = unordered_max_nesting.find_by :context => :list_item + assert_equal 16, unordered_max_nesting_items[0].lineno + assert_equal 17, unordered_max_nesting_items[1].lineno + assert_equal 18, unordered_max_nesting_items[2].lineno + assert_equal 19, unordered_max_nesting_items[3].lineno + assert_equal 20, unordered_max_nesting_items[4].lineno + assert_equal 21, unordered_max_nesting_items[5].lineno + + checklist = first_section.blocks[2] + assert_equal 24, checklist.lineno + checklist_list_items = checklist.find_by :context => :list_item + assert_equal 24, checklist_list_items[0].lineno + assert_equal 25, checklist_list_items[1].lineno + assert_equal 26, checklist_list_items[2].lineno + assert_equal 27, checklist_list_items[3].lineno + + ordered_basic = first_section.blocks[3] + assert_equal 30, ordered_basic.lineno + ordered_basic_list_items = ordered_basic.find_by :context => :list_item + assert_equal 30, ordered_basic_list_items[0].lineno + assert_equal 31, ordered_basic_list_items[1].lineno + assert_equal 32, ordered_basic_list_items[2].lineno + + ordered_nested = first_section.blocks[4] + assert_equal 35, ordered_nested.lineno + ordered_nested_list_items = ordered_nested.find_by :context => :list_item + assert_equal 35, ordered_nested_list_items[0].lineno + assert_equal 36, ordered_nested_list_items[1].lineno + assert_equal 37, ordered_nested_list_items[2].lineno + assert_equal 38, ordered_nested_list_items[3].lineno + assert_equal 39, ordered_nested_list_items[4].lineno + + ordered_max_nesting = first_section.blocks[5] + assert_equal 42, ordered_max_nesting.lineno + ordered_max_nesting_items = ordered_max_nesting.find_by :context => :list_item + assert_equal 42, ordered_max_nesting_items[0].lineno + assert_equal 43, ordered_max_nesting_items[1].lineno + assert_equal 44, ordered_max_nesting_items[2].lineno + assert_equal 45, ordered_max_nesting_items[3].lineno + assert_equal 46, ordered_max_nesting_items[4].lineno + assert_equal 47, ordered_max_nesting_items[5].lineno + + labeled_singleline = first_section.blocks[6] + assert_equal 50, labeled_singleline.lineno + labeled_singleline_items = labeled_singleline.find_by :context => :list_item + assert_equal 50, labeled_singleline_items[0].lineno + assert_equal 50, labeled_singleline_items[1].lineno + assert_equal 51, labeled_singleline_items[2].lineno + assert_equal 51, labeled_singleline_items[3].lineno + + labeled_multiline = first_section.blocks[7] + assert_equal 54, labeled_multiline.lineno + labeled_multiline_items = labeled_multiline.find_by :context => :list_item + assert_equal 54, labeled_multiline_items[0].lineno + assert_equal 55, labeled_multiline_items[1].lineno + assert_equal 56, labeled_multiline_items[2].lineno + assert_equal 57, labeled_multiline_items[3].lineno + + qanda = first_section.blocks[8] + assert_equal 61, qanda.lineno + qanda_items = qanda.find_by :context => :list_item + assert_equal 61, qanda_items[0].lineno + assert_equal 62, qanda_items[1].lineno + assert_equal 63, qanda_items[2].lineno + assert_equal 63, qanda_items[3].lineno + + mixed = first_section.blocks[9] + assert_equal 66, mixed.lineno + mixed_items = mixed.find_by(:context => :list_item) {|block| block.text? } + assert_equal 66, mixed_items[0].lineno + assert_equal 67, mixed_items[1].lineno + assert_equal 68, mixed_items[2].lineno + assert_equal 69, mixed_items[3].lineno + assert_equal 70, mixed_items[4].lineno + assert_equal 71, mixed_items[5].lineno + assert_equal 72, mixed_items[6].lineno + assert_equal 73, mixed_items[7].lineno + assert_equal 74, mixed_items[8].lineno + assert_equal 75, mixed_items[9].lineno + assert_equal 77, mixed_items[10].lineno + assert_equal 78, mixed_items[11].lineno + assert_equal 79, mixed_items[12].lineno + assert_equal 80, mixed_items[13].lineno + assert_equal 81, mixed_items[14].lineno + assert_equal 82, mixed_items[15].lineno + assert_equal 83, mixed_items[16].lineno + + unordered_complex_list = first_section.blocks[10] + assert_equal 86, unordered_complex_list.lineno + unordered_complex_items = unordered_complex_list.find_by :context => :list_item + assert_equal 86, unordered_complex_items[0].lineno + assert_equal 87, unordered_complex_items[1].lineno + assert_equal 88, unordered_complex_items[2].lineno + assert_equal 92, unordered_complex_items[3].lineno + assert_equal 96, unordered_complex_items[4].lineno + end + test 'should assign correct source location if section occurs on last line of input' do input = <<-EOS = Document Title diff --git a/test/blocks_test.rb b/test/blocks_test.rb index 7ca9fc8c..0703d1d3 100644 --- a/test/blocks_test.rb +++ b/test/blocks_test.rb @@ -218,7 +218,7 @@ supposed to be after sidebar block, except it got swallowed by block comment EOS render_embedded_string input - assert_message @logger, :WARN, '<stdin>: line 8: unterminated comment block', Hash + assert_message @logger, :WARN, '<stdin>: line 5: unterminated comment block', Hash end # WARNING if first line of content is a directive, it will get interpretted before we know it's a comment block diff --git a/test/fixtures/lists.adoc b/test/fixtures/lists.adoc new file mode 100644 index 00000000..324bcd0d --- /dev/null +++ b/test/fixtures/lists.adoc @@ -0,0 +1,96 @@ += Document Title +Doc Writer <thedoc@asciidoctor.org> + +Preamble paragraph. + +NOTE: This is test, only a test. + +== Lists + +.Unordered, basic +* Edgar Allen Poe +* Sheri S. Tepper +* Bill Bryson + +.Unordered, max nesting +* level 1 +** level 2 +*** level 3 +**** level 4 +***** level 5 +* level 1 + +.Checklist +- [*] checked +- [x] also checked +- [ ] not checked +- normal list item + +.Ordered, basic +. Step 1 +. Step 2 +. Step 3 + +.Ordered, nested +. Step 1 +. Step 2 +.. Step 2a +.. Step 2b +. Step 3 + +.Ordered, max nesting +. level 1 +.. level 2 +... level 3 +.... level 4 +..... level 5 +. level 1 + +.Labeled, single-line +first term:: definition of first term +section term:: definition of second term + +.Labeled, multi-line +first term:: +definition of first term +second term:: +definition of second term + +.Q&A +[qanda] +What is Asciidoctor?:: + An implementation of the AsciiDoc processor in Ruby. +What is the answer to the Ultimate Question?:: 42 + +.Mixed +Operating Systems:: + Linux::: + . Fedora + * Desktop + . Ubuntu + * Desktop + * Server + BSD::: + . FreeBSD + . NetBSD + +Cloud Providers:: + PaaS::: + . OpenShift + . CloudBees + IaaS::: + . Amazon EC2 + . Rackspace + +.Unordered, complex +* level 1 +** level 2 +*** level 3 +This is a new line inside an unordered list using {plus} symbol. +We can even force content to start on a separate line... + +Amazing, isn't it? +**** level 4 ++ +The {plus} symbol is on a new line. + +***** level 5 diff --git a/test/lists_test.rb b/test/lists_test.rb index f22770cb..2e0a8559 100644 --- a/test/lists_test.rb +++ b/test/lists_test.rb @@ -4628,5 +4628,11 @@ listing block in list item 1 assert_equal 1, lists[0].lineno assert_equal 2, lists[1].lineno assert_equal 3, lists[2].lineno + + list_items = doc.find_by :context => :list_item + assert_equal 1, list_items[0].lineno + assert_equal 2, list_items[1].lineno + assert_equal 3, list_items[2].lineno + assert_equal 4, list_items[3].lineno end end |
