From 15ff7061b08aaa946525964f3c559df4da19824f Mon Sep 17 00:00:00 2001 From: main Date: Sat, 23 May 2026 19:37:10 -0400 Subject: Scrub parked WIP skills from main --- noo-harvest/scripts/normalize_legacy_pdf_text.py | 147 ----------------------- 1 file changed, 147 deletions(-) delete mode 100644 noo-harvest/scripts/normalize_legacy_pdf_text.py (limited to 'noo-harvest/scripts/normalize_legacy_pdf_text.py') diff --git a/noo-harvest/scripts/normalize_legacy_pdf_text.py b/noo-harvest/scripts/normalize_legacy_pdf_text.py deleted file mode 100644 index 12d2b4b..0000000 --- a/noo-harvest/scripts/normalize_legacy_pdf_text.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env -S uv run --script -# /// script -# requires-python = "==3.13.*" -# dependencies = [] -# /// - -from __future__ import annotations - -import argparse -import json -import re -import sys -from pathlib import Path -from typing import Any - - -TEXT_KEYS = {"text", "orig"} - -ACUTE_MAP = str.maketrans( - { - "a": "á", - "e": "é", - "i": "í", - "o": "ó", - "u": "ú", - "y": "ý", - "A": "Á", - "E": "É", - "I": "Í", - "O": "Ó", - "U": "Ú", - "Y": "Ý", - } -) - -TILDE_MAP = str.maketrans( - { - "a": "ã", - "o": "õ", - "n": "ñ", - "A": "Ã", - "O": "Õ", - "N": "Ñ", - } -) - -SIMPLE_REPLACEMENTS = { - "\x03": "*", - "\x07": "", - "\x0f": "", - "\x10": "i", - "\x12": "⊆", - "\x14": "κ", - "\x15": "≥", - "\x19": "ß", - "\x1b": "σ", - "\x1c": "ø", - "\x1d": "", - "\x1e": "≺", - "\x7f": "", -} - - -def normalize_legacy_pdf_text(text: str) -> str: - # Legacy TeX/PostScript accent markers. - text = text.replace("\x13\x10", "í") - text = re.sub("\x13([AEIOUYaeiouy])", lambda m: m.group(1).translate(ACUTE_MAP), text) - text = re.sub("\x18([cC])", lambda m: "ç" if m.group(1) == "c" else "Ç", text) - text = text.replace("\x18", "~") - text = re.sub("\x16([A-Za-z])", lambda m: m.group(1) + "\u0304", text) - - # Ligatures and overloaded glyph slots. The \x0c slot is context-sensitive: - # inside a word it is usually the "fi" ligature; otherwise it is usually β. - text = re.sub("\x0e(?=[A-Za-z])", "ffi", text) - text = re.sub("\x0b(?=[A-Za-z])", "ff", text) - text = re.sub("\x0c(?=[A-Za-z])", "fi", text) - text = text.replace("\x0c", "β") - - for src, dst in SIMPLE_REPLACEMENTS.items(): - text = text.replace(src, dst) - - # TeX-ish accent remnants that lost their backslash. - text = re.sub(r"~([aAoOnN])", lambda m: m.group(1).translate(TILDE_MAP), text) - - # Small cleanup passes that are common in this extraction family. - text = text.replace("sub ject classifications", "subject classifications") - text = text.replace("subject classifications", "subject classifications") - text = re.sub(r"(?m)^y(?=[A-Z])", "†", text) - text = re.sub(r"\*{3,}", "**", text) - text = re.sub(r"[ \t]+", " ", text) - text = re.sub(r"\n{3,}", "\n\n", text) - - return text - - -def normalize_docling_json(node: Any) -> Any: - if isinstance(node, dict): - out: dict[str, Any] = {} - for key, value in node.items(): - if isinstance(value, str) and key in TEXT_KEYS: - out[key] = normalize_legacy_pdf_text(value) - else: - out[key] = normalize_docling_json(value) - return out - if isinstance(node, list): - return [normalize_docling_json(item) for item in node] - return node - - -def parse_args() -> argparse.Namespace: - parser = argparse.ArgumentParser( - description=( - "Normalize legacy TeX/PostScript glyph corruption in extracted PDF text. " - "Accepts Markdown/plaintext directly, or a Docling JSON document." - ) - ) - parser.add_argument("input", type=Path, help="Input file") - parser.add_argument("-o", "--output", type=Path, help="Output file; default is stdout") - parser.add_argument( - "--docling-json", - action="store_true", - help="Treat the input as a DoclingDocument JSON file and normalize text-bearing fields", - ) - return parser.parse_args() - - -def main() -> int: - args = parse_args() - raw = args.input.read_text(errors="replace") - - if args.docling_json: - data = json.loads(raw) - normalized = json.dumps(normalize_docling_json(data), ensure_ascii=False, indent=2) - else: - normalized = normalize_legacy_pdf_text(raw) - - if args.output is None: - sys.stdout.write(normalized) - else: - args.output.parent.mkdir(parents=True, exist_ok=True) - args.output.write_text(normalized) - - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) -- cgit v1.2.3