diff --git a/epub2md/html_converter.py b/epub2md/html_converter.py index 3e619cf..fb8f6ff 100644 --- a/epub2md/html_converter.py +++ b/epub2md/html_converter.py @@ -221,6 +221,8 @@ def _box_type(hint: str) -> str: return "important" if re.search(r"tipp|\btip|hint", h): return "tip" + if re.search(r"hinweis|\bnote|notiz|anmerkung|\binfo", h): + return "note" return "" diff --git a/epub2md/normalize.py b/epub2md/normalize.py index 8f9dc66..78db4e1 100644 --- a/epub2md/normalize.py +++ b/epub2md/normalize.py @@ -3,6 +3,7 @@ from __future__ import annotations import re +from collections.abc import Callable from dataclasses import dataclass, field from typing import Any @@ -80,7 +81,8 @@ def book_uses_title_tables(docs: list[Doc]) -> bool: return False -def normalize_doc(doc: Doc, diag: Diagnostics, title_tables: bool) -> None: +def normalize_doc(doc: Doc, diag: Diagnostics, title_tables: bool, + hidden: Callable[[Any], bool] | None = None) -> None: body = doc.body for el in list(iter_elements(body)): if not _attached(el, body): @@ -107,19 +109,19 @@ def normalize_doc(doc: Doc, diag: Diagnostics, title_tables: bool) -> None: doc.toc_ids.update(e.get("id") for e in iter_elements(el) if e.get("id")) remove_keep_tail(el) diag.info("html-toc-removed", "HTML-Inhaltsverzeichnis entfernt (ersetzt durch README.md).", doc.path) - separated = _separate_field_spans(body) + separated = _separate_field_spans(body, hidden or (lambda el: False)) if separated: diag.info("inline-separator-added", f"{separated} Leerzeichen zwischen aneinanderstoßenden Feld-Spans eingefügt.", doc.path) -def _separate_field_spans(body: Any) -> int: +def _separate_field_spans(body: Any, hidden: Callable[[Any], bool]) -> int: """Insert a space between adjacent class-styled "fields" that touch without whitespace. Publishers sometimes lay out metadata as sibling spans (author | title | series) separated only by CSS. Narrow rule to keep drop caps ("D|as") and split words ("Haupt|bahnhof") intact: both spans carry different classes, no text between them, both have >= 2 characters and the right one starts - with an uppercase letter or digit. + with an uppercase letter or digit. Spans hidden by the book's CSS (display:none) get no separator. """ count = 0 for parent in iter_elements(body): @@ -132,7 +134,7 @@ def _separate_field_spans(body: Any) -> int: lt, rt = text_content(left), text_content(right) if len(lt.strip()) < 2 or len(rt.strip()) < 2 or lt[-1].isspace() or rt[0].isspace(): continue - if rt[0].isupper() or rt[0].isdigit(): + if (rt[0].isupper() or rt[0].isdigit()) and not hidden(left) and not hidden(right): left.tail = " " count += 1 return count diff --git a/epub2md/pipeline.py b/epub2md/pipeline.py index c9021b4..bc10e24 100644 --- a/epub2md/pipeline.py +++ b/epub2md/pipeline.py @@ -8,6 +8,7 @@ import re import shutil import sys import tempfile +from collections.abc import Callable from dataclasses import asdict, dataclass, field from datetime import datetime, timezone from pathlib import Path @@ -16,7 +17,7 @@ from typing import Any from . import TOOL_NAME, __version__ from .chapters import ChapterBuilder from .diagnostics import Diagnostics -from .css import StyleSheet, base_style +from .css import StyleSheet, base_style, emphasis from .epub_reader import EpubReader, decode_markup, parse_xml from .errors import ContainerError, InputError, StructureError from .footnotes import collect_notes @@ -140,7 +141,8 @@ def _convert(reader: EpubReader, input_path: Path, output_dir: Path, opts: Optio diag.step(f"EPUB {package.version}: {package.metadata.title!r}, {len(package.spine)} Spine-Dokumente") docs = _load_docs(reader, package, diag) stylesheet = _load_stylesheet(reader, package, docs, diag) # before normalization drops