File size: 3,150 Bytes
3213f50
 
 
 
 
 
 
 
bbbfba8
 
3213f50
 
bbbfba8
 
 
3213f50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bb6107f
3213f50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
"""hyphenation_basic enricher — detects hyphenated words at line boundaries.

If a word ends with '-' at the end of a line, and the next line starts with
a lowercase word, marks both as hyphenated with the combined full_form.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from src.app.domain.models import CanonicalDocument, Hyphenation, TextLine
from src.app.enrichers import BaseEnricher

if TYPE_CHECKING:
    from src.app.policies.document_policy import DocumentPolicy


class HyphenationBasicEnricher(BaseEnricher):
    @property
    def name(self) -> str:
        return "hyphenation_basic"

    def enrich(
        self, doc: CanonicalDocument, policy: DocumentPolicy
    ) -> CanonicalDocument:
        if not policy.allow_hyphenation_detection:
            return doc

        new_pages = []
        changed = False

        for page in doc.pages:
            new_regions = []
            for region in page.text_regions:
                new_lines = list(region.lines)
                modified = self._process_lines(new_lines)
                if modified:
                    changed = True
                new_regions.append(region.model_copy(update={"lines": new_lines}))
            new_pages.append(page.model_copy(update={"text_regions": new_regions}))

        if changed:
            return doc.model_copy(update={"pages": new_pages})
        return doc

    @staticmethod
    def _process_lines(lines: list[TextLine]) -> bool:
        """Process adjacent lines for hyphenation. Mutates the list in place."""
        modified = False

        for i in range(len(lines) - 1):
            line_a = lines[i]
            line_b = lines[i + 1]

            if not line_a.words or not line_b.words:
                continue

            last_word = line_a.words[-1]
            first_word = line_b.words[0]

            # Skip if already hyphenated
            if last_word.hyphenation is not None:
                continue

            # Check: last word ends with '-' and next word starts lowercase
            if not last_word.text.endswith("-"):
                continue
            if not first_word.text or not first_word.text[0].islower():
                continue

            # Build full form
            stem = last_word.text.rstrip("-")
            full_form = stem + first_word.text

            # Update last word of line A
            new_last = last_word.model_copy(update={
                "hyphenation": Hyphenation(
                    is_hyphenated=True, part=1, full_form=full_form
                ),
            })
            new_words_a = list(line_a.words[:-1]) + [new_last]
            lines[i] = line_a.model_copy(update={"words": new_words_a})

            # Update first word of line B
            new_first = first_word.model_copy(update={
                "hyphenation": Hyphenation(
                    is_hyphenated=True, part=2, full_form=full_form
                ),
            })
            new_words_b = [new_first] + list(line_b.words[1:])
            lines[i + 1] = line_b.model_copy(update={"words": new_words_b})

            modified = True

        return modified