fix(slack): guard blank-line list continuation on next-item lookahead
Refine the blank-line handling so a blank line only continues a list run when the next non-blank line is another list item. This keeps a list -> paragraph -> list sequence as three separate blocks and matches the contiguous-list layout for mixed/nested lists (one rich_text block, split into sub-lists by (indent, ordered)), rather than emitting a separate block per item. Adds regression tests for the mixed blank-separated layout and the list->paragraph->list boundary.
This commit is contained in:
parent
d3c8a155cb
commit
033d7bf259
2 changed files with 41 additions and 4 deletions
|
|
@ -451,10 +451,22 @@ def render_blocks(
|
|||
indent, ordered, txt = items[-1]
|
||||
items[-1] = (indent, ordered, txt + " " + lines[i].strip())
|
||||
i += 1
|
||||
elif not lines[i].strip():
|
||||
# blank line — soft separator within a list run;
|
||||
# skip so that ordered items stay in one rich_text_list.
|
||||
i += 1
|
||||
elif not lines[i].strip() and items:
|
||||
# Blank line inside a list run. LLM-authored ordered
|
||||
# lists commonly separate items with a blank line; if
|
||||
# the next non-blank line is another list item, treat
|
||||
# the blank(s) as a soft separator and keep the run
|
||||
# going so the items stay in one rich_text_list (Slack
|
||||
# numbers each list independently, so splitting would
|
||||
# restart every item at "1."). Otherwise the blank
|
||||
# ends the list.
|
||||
j = i + 1
|
||||
while j < n and not lines[j].strip():
|
||||
j += 1
|
||||
if j < n and (_BULLET_RE.match(lines[j]) or _ORDERED_RE.match(lines[j])):
|
||||
i = j
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
blocks.append(_list_block(items))
|
||||
|
|
|
|||
|
|
@ -106,6 +106,31 @@ class TestInlineFormatting:
|
|||
items = lists[0]["elements"]
|
||||
assert len(items) == 3
|
||||
|
||||
def test_blank_separated_mixed_list_matches_contiguous_layout(self):
|
||||
"""A blank line between different list kinds must render like the
|
||||
contiguous form: one rich_text block whose sub-lists split only on
|
||||
(indent, ordered) changes — not a separate block per item.
|
||||
"""
|
||||
rich = [b for b in render_blocks("1. a\n\n- b") if b["type"] == "rich_text"]
|
||||
# Single rich_text block (matches contiguous "1. a\n- b"), two sub-lists
|
||||
assert len(rich) == 1
|
||||
styles = [e["style"] for e in rich[0]["elements"] if e["type"] == "rich_text_list"]
|
||||
assert styles == ["ordered", "bullet"]
|
||||
|
||||
def test_blank_line_before_paragraph_ends_the_list(self):
|
||||
"""A blank line followed by non-list content must still end the run,
|
||||
so a list → paragraph → list sequence stays three separate blocks.
|
||||
"""
|
||||
blocks = render_blocks("1. a\n\nsome paragraph text\n\n1. b")
|
||||
lists = [
|
||||
e
|
||||
for b in blocks
|
||||
for e in b.get("elements", [])
|
||||
if e.get("type") == "rich_text_list"
|
||||
]
|
||||
# Two independent single-item lists, not one merged three-item list
|
||||
assert [len(e["elements"]) for e in lists] == [1, 1]
|
||||
|
||||
|
||||
class TestTables:
|
||||
def test_pipe_table_renders_native_table_block(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue