Paragraph & List Grouping of OCR Lines
text_regions.find_text_lines merges glyphs into lines, but nothing groups those lines
into paragraphs or detects lists — ocr/structure stops at flat rows. text_blocks adds
that: group_paragraphs splits lines into paragraphs wherever the vertical gap exceeds a
multiple of the median line height (the standard whitespace-grouping heuristic), and
detect_lists recognises bulleted / numbered items by their leading marker and left indent.
Pure-stdlib over plain line dicts (text + bbox); fully unit-testable with no image and no OCR
engine. Reuses table_grid_fill’s box-bounds reader. Imports no PySide6.
Headless API
from je_auto_control import group_paragraphs, detect_lists
for para in group_paragraphs(ocr_lines, line_gap_factor=1.6):
print(para["n_lines"], para["text"])
for item in detect_lists(ocr_lines):
print(item["marker"], item["indent"], item["text"])
group_paragraphs returns paragraph dicts (left / top / right / bottom /
text / n_lines) — a new paragraph begins when the gap from the previous line’s bottom
exceeds line_gap_factor times the median line height. detect_lists returns the lines
whose text starts with a bullet (• / - / *) or an ordinal (1. / 2) /
a.), each as {text, marker, indent, box} (indent is the left x, for nesting).
Executor commands
AC_group_paragraphs (lines / line_gap_factor → {count, paragraphs}) and
AC_detect_lists (lines → {count, items}). They are exposed as the MCP tools
ac_group_paragraphs / ac_detect_lists (read-only) and as the Script Builder commands
Group Paragraphs / Detect Lists under OCR.