- Introduced common.js for shared functions including API calls, error reporting, and UI helpers. - Implemented feedback.js for the feedback reporting page, including form handling and displaying feedback status. - Added layout.js for managing galaxy and section layouts in the visualization. - Created login.js for user authentication with session management. - Developed search.js for term searching based on user input and synonyms. - Implemented signup.js for user registration with validation and immediate login.
83 lines
2.4 KiB
Python
83 lines
2.4 KiB
Python
"""PDF 텍스트 줄 단위 추출 도우미."""
|
||
import re
|
||
import unicodedata
|
||
from dataclasses import dataclass
|
||
|
||
import pymupdf
|
||
|
||
|
||
@dataclass
|
||
class Line:
|
||
page: int
|
||
x: float
|
||
y: float
|
||
x1: float
|
||
size: float
|
||
font: str
|
||
text: str
|
||
|
||
|
||
def clean(s: str) -> str:
|
||
s = unicodedata.normalize("NFC", s)
|
||
s = "".join(c for c in s if c in "\n\t" or unicodedata.category(c)[0] != "C")
|
||
s = s.replace(" ", " ").replace(" ", " ").replace(" ", " ")
|
||
s = s.replace("ᝍ", "-").replace("․", "·")
|
||
return re.sub(r"\s+", " ", s).strip()
|
||
|
||
|
||
def page_lines(doc: pymupdf.Document, i: int) -> list[Line]:
|
||
out = []
|
||
for b in doc[i].get_text("dict")["blocks"]:
|
||
for l in b.get("lines", []):
|
||
spans = l["spans"]
|
||
if not spans:
|
||
continue
|
||
text = clean("".join(s["text"] for s in spans))
|
||
if not text:
|
||
continue
|
||
x0, y0, x1, _ = l["bbox"]
|
||
out.append(Line(i, x0, y0, x1, spans[0]["size"], spans[0]["font"], text))
|
||
return out
|
||
|
||
|
||
def print_label(doc: pymupdf.Document, i: int) -> str:
|
||
return doc[i].get_label() or str(i + 1)
|
||
|
||
|
||
def label_to_index(doc: pymupdf.Document) -> dict[str, int]:
|
||
"""인쇄 페이지 번호(라벨) → PDF 파일상 0-based 페이지. 아라비아 숫자 라벨만."""
|
||
m = {}
|
||
for i in range(len(doc)):
|
||
lab = doc[i].get_label() or str(i + 1)
|
||
if lab.isdigit() and lab not in m:
|
||
m[lab] = i
|
||
return m
|
||
|
||
|
||
def body_text(doc: pymupdf.Document, i: int) -> str:
|
||
"""머리말·꼬리말을 뺀 본문 텍스트. 줄바꿈으로 끊긴 단어를 이어 붙임."""
|
||
h = doc[i].rect.height
|
||
parts = []
|
||
for b in doc[i].get_text("dict")["blocks"]:
|
||
buf = ""
|
||
for l in b.get("lines", []):
|
||
y = l["bbox"][1]
|
||
if y < 50 or y > h - 45:
|
||
continue
|
||
raw = unicodedata.normalize("NFC", "".join(s["text"] for s in l["spans"]))
|
||
if not raw.strip():
|
||
continue
|
||
if buf and not buf.endswith(" ") and not raw.startswith(" "):
|
||
# 한글끼리 줄이 바뀌면 단어 중간에서 끊긴 것으로 보고 붙인다
|
||
if not (_is_hangul(buf[-1]) and _is_hangul(raw[0])):
|
||
buf += " "
|
||
buf += raw
|
||
t = clean(buf)
|
||
if t:
|
||
parts.append(t)
|
||
return "\n".join(parts)
|
||
|
||
|
||
def _is_hangul(c: str) -> bool:
|
||
return "가" <= c <= "힣"
|