"""Compare the TUI's block list with the web reader's (web_blocks.cjs output). python compare_blocks.py web.json [name-part ...] What must match is the number and tag of the blocks (they make the position anchors shared by all clients). Text differences are reported too: they are cosmetic, but they show where the TUI's HTML parser (lxml) reads a book differently from Chrome's. Exit status 1 when a book's block list differs in length or tags. """ import json import os import sys from pathlib import Path from diora_tui.blocks import load_flat_book def main(ref_file, only): ref = json.load(open(ref_file, encoding="utf-8")) failed = False for file, web in ref.items(): if only and not any(o in file for o in only): continue book = load_flat_book(Path(file)) wb, tb = web["blocks"], book.blocks structure = len(wb) == len(tb) and all(w["tag"] == t.tag for w, t in zip(wb, tb)) texts = [i for i, (w, t) in enumerate(zip(wb, tb)) if w["text"] != t.text] chars = [i for i, (w, t) in enumerate(zip(wb, tb)) if (w["start"], w["len"]) != (t.char_start, t.char_len)] total_ok = web["total"] == book.total_chars failed |= not structure print(f"{'OK ' if structure else 'FAIL'} {os.path.basename(file)[:50]}: web {len(wb)} / tui {len(tb)} blocks, " f"{len(texts)} with other text" + (f" (first: {texts[0]})" if texts else "") + f"; chars {'equal' if not chars and total_ok else f'{len(chars)} blocks differ, total web {web['total']} / tui {book.total_chars}'}") return 1 if failed else 0 if __name__ == "__main__": sys.exit(main(sys.argv[1], sys.argv[2:]))