Skip to content

Commit

Permalink
resolves asciidoctor#3693 don't break nested dlist with attached bloc…
Browse files Browse the repository at this point in the history
…k if offset from parent list by empty line
  • Loading branch information
mojavelinux committed Nov 5, 2023
1 parent 87e75f3 commit fa799fb
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Improvements::

Bug Fixes::

* Don't break nested dlist with attached block if offset from parent list by empty line (#3693)
* Preserve paragraph breaks in normal table cell in manpage output (#4481)
* Escape spaces in include target (using inline passthrough) when generating link from include directive (#4461)

Expand Down
28 changes: 18 additions & 10 deletions lib/asciidoctor/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ class Parser

AuthorKeys = ::Set['author', 'authorinitials', 'firstname', 'middlename', 'lastname', 'email']

ListContinuation = ::Module.new

ListContinuationPlaceholder = ::String.new.extend ListContinuation

ListContinuationWrapper = (::String.new LIST_CONTINUATION).extend ListContinuation

# Internal: A Hash mapping horizontal alignment abbreviations to alignments
# that can be applied to a table cell (or to all cells in a column)
TableCellHorzAlignments = {
Expand Down Expand Up @@ -1417,17 +1423,18 @@ def self.read_lines_for_list_item reader, list_type, sibling_trait = nil, has_te
# the termination of the list
break if is_sibling_list_item? this_line, list_type, sibling_trait

this_line = ListContinuationWrapper if this_line == LIST_CONTINUATION
prev_line = buffer.empty? ? nil : buffer[-1]

if prev_line == LIST_CONTINUATION
if ListContinuation === prev_line
if continuation == :inactive
continuation = :active
has_text = true
buffer[-1] = '' unless within_nested_list
buffer[-1] = ListContinuationPlaceholder unless within_nested_list
end

# dealing with adjacent list continuations (which is really a syntax error)
if this_line == LIST_CONTINUATION
if ListContinuation === this_line
if continuation != :frozen
continuation = :frozen
buffer << this_line
Expand Down Expand Up @@ -1507,7 +1514,7 @@ def self.read_lines_for_list_item reader, list_type, sibling_trait = nil, has_te

if this_line == LIST_CONTINUATION
detached_continuation = buffer.size
buffer << this_line
buffer << ListContinuationWrapper
elsif has_text # has_text only relevant for dlist, which is more greedy until it has text for an item; has_text is always true for all other lists
# in this block, we have to see whether we stay in the list
# TODO any way to combine this with the check after skipping blank lines?
Expand Down Expand Up @@ -1539,7 +1546,7 @@ def self.read_lines_for_list_item reader, list_type, sibling_trait = nil, has_te
buffer << this_line
has_text = true
end
elsif this_line == LIST_CONTINUATION
elsif ListContinuation === this_line
has_text = true
buffer << this_line
else
Expand All @@ -1560,16 +1567,17 @@ def self.read_lines_for_list_item reader, list_type, sibling_trait = nil, has_te

reader.unshift_line this_line if this_line

buffer[detached_continuation] = '' if detached_continuation
buffer[detached_continuation] = ListContinuationPlaceholder if detached_continuation

until buffer.empty?
# drop optional trailing continuation
if ListContinuation === (last_line = buffer[-1])
buffer.pop
break
# strip trailing blank lines to prevent empty blocks
if (last_line = buffer[-1]).empty?
elsif last_line.empty?
buffer.pop
else
# drop optional trailing continuation
# (a blank line would have served the same purpose in the document)
buffer.pop if last_line == LIST_CONTINUATION
break
end
end
Expand Down
18 changes: 18 additions & 0 deletions test/lists_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3077,6 +3077,24 @@
assert_xpath '//dl//dl/dt[normalize-space(text()) = "label1"]', output, 1
assert_xpath '//dl//dl/dt/following-sibling::dd/p[text() = "detail1"]', output, 1
end

test 'nested dlist with attached block offset by empty line' do
input = <<~'EOS'
category::
term 1:::
+
--
def 1
--
EOS
output = convert_string_to_embedded input
assert_xpath '//dl', output, 2
assert_xpath '//dl//dl', output, 1
assert_xpath '(//dl)[1]/dt[1][normalize-space(text()) = "category"]', output, 1
assert_xpath '(//dl)[1]//dl/dt[1][normalize-space(text()) = "term 1"]', output, 1
assert_xpath '(//dl)[1]//dl/dt[1]/following-sibling::dd//p[starts-with(text(), "def 1")]', output, 1
end
end

context 'Special lists' do
Expand Down

0 comments on commit fa799fb

Please sign in to comment.