Skip to content

Add PageIndex Flash - #369

Merged
rejojer merged 1 commit into
mainfrom
pageindex-flash
Jul 30, 2026
Merged

Add PageIndex Flash#369
rejojer merged 1 commit into
mainfrom
pageindex-flash

Conversation

@rejojer

@rejojer rejojer commented Jul 30, 2026

Copy link
Copy Markdown
Member

Summary

Add PageIndex Flash, a heuristic TOC extraction engine that builds document structure from PDF layout statistics without an LLM.

The pipeline parses character-level layout via PDFium, clusters text into lines and blocks, then identifies headings from font style and numbering patterns to assemble a nested TOC tree. Optional LLM-based node summaries can be generated on top of the extracted structure.

Test plan

  • page_index_flash(pdf) returns correct tree structure
  • page_index_flash(pdf, summary=False) skips LLM calls

Comment thread pageindex/flash/main.py
)
from .parser_pdfium_parallel import parse_charlevel_meta_parallel
from .phases import assign_reading_order, PageView, process_page
PageView = PageView # re-export for type hints
"""IEEE-754 division, no ZeroDivisionError (``0/0-> NaN, ``x/±0-> ±Inf with the usual sign rules)."""
if other_item != 0.0:
return value / other_item
if value == 0.0 or value != value:
num_val = float(operator_token)
except ValueError:
num_val = 0.0
if num_val != num_val or num_val in (float("inf"), -float("inf")):
value = _parse_int(token_value.decode("latin-1"), 10) if token_value is not None else 0.0
except OverflowError:
value = float("inf") # huge digit run
if value != value or value == float("inf") or value == -float("inf"):
if glyph_prefix == "G": # Gxx
if len(glyph_name) == 3:
parsed_integer = _parse_int(glyph_name[1:], 16)
code = int(parsed_integer) if parsed_integer == parsed_integer else 0 # pi==pi: not NaN
elif glyph_prefix == "g": # g00xx
if len(glyph_name) == 5:
parsed_integer = _parse_int(glyph_name[1:], 16)
code = int(parsed_integer) if parsed_integer == parsed_integer else 0
code_str = glyph_name[1:]
if force_glyphs:
parsed_integer = _parse_int(code_str, 16)
code = int(parsed_integer) if parsed_integer == parsed_integer else 0
# whole encoding as base-16. Non-integer numeric values pass
# through and then fail the integer gate below.
num = _to_number(code_str)
if num != num: # NaN
num = _to_number(code_str)
if num != num: # NaN
parsed_integer = _parse_int(code_str, 16)
if parsed_integer == parsed_integer:
# Empty lines carry an inverted-sentinel bbox. Preserve IEEE division
# edge cases so the later distance comparison simply does not merge.
diff = line_center_y - other_center_y
return float("nan") if diff != diff else float("inf")
@rejojer
rejojer merged commit c9a01fa into main Jul 30, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant