summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.adoc1
-rw-r--r--lib/asciidoctor/parser.rb28
-rw-r--r--test/lists_test.rb18
3 files changed, 37 insertions, 10 deletions
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 747371f0..1d98c366 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -74,6 +74,7 @@ Improvements::
Bug Fixes::
* Nested dlist attached using list continuation should not consume detached paragraph (#3535)
+ * 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)
* Style cells in head row as bold in manpage output (#4490)
* Escape spaces in include target (using inline passthrough) when generating link from include directive (#4461)
diff --git a/lib/asciidoctor/parser.rb b/lib/asciidoctor/parser.rb
index 8743b75e..bd1abad1 100644
--- a/lib/asciidoctor/parser.rb
+++ b/lib/asciidoctor/parser.rb
@@ -44,6 +44,12 @@ class Parser
AuthorKeys = ::Set['author', 'authorinitials', 'firstname', 'middlename', 'lastname', 'email']
+ ListContinuationMarker = ::Module.new
+
+ ListContinuationPlaceholder = ::String.new.extend ListContinuationMarker
+
+ ListContinuationString = (::String.new LIST_CONTINUATION).extend ListContinuationMarker
+
# 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 = {
@@ -1417,17 +1423,18 @@ class Parser
# the termination of the list
break if is_sibling_list_item? this_line, list_type, sibling_trait
+ this_line = ListContinuationString if this_line == LIST_CONTINUATION
prev_line = buffer.empty? ? nil : buffer[-1]
- if prev_line == LIST_CONTINUATION
+ if ListContinuationMarker === 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 ListContinuationMarker === this_line
if continuation != :frozen
continuation = :frozen
buffer << this_line
@@ -1507,7 +1514,7 @@ class Parser
if this_line == LIST_CONTINUATION
detached_continuation = buffer.size
- buffer << this_line
+ buffer << ListContinuationString
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?
@@ -1539,7 +1546,7 @@ class Parser
buffer << this_line
has_text = true
end
- elsif this_line == LIST_CONTINUATION
+ elsif ListContinuationMarker === this_line
has_text = true
buffer << this_line
else
@@ -1560,16 +1567,17 @@ class Parser
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 ListContinuationMarker === (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
diff --git a/test/lists_test.rb b/test/lists_test.rb
index e3a1d9da..3dc8b4c6 100644
--- a/test/lists_test.rb
+++ b/test/lists_test.rb
@@ -3092,6 +3092,24 @@ context 'Description lists (:dlist)' do
assert_css '.dlist .paragraph', output, 0
assert_css '.dlist + .paragraph', 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