diff --git a/README.md b/README.md index 27bc2c3..12b33bd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ | in progress // в процессе разработки | |--------------------------------------| -| --1 | +| ---2 | # Типограф для Web diff --git a/etpgrf/comutil.py b/etpgrf/comutil.py index 6ef4967..0b1baae 100644 --- a/etpgrf/comutil.py +++ b/etpgrf/comutil.py @@ -1,7 +1,34 @@ -from etpgrf.config import DEFAULT_LANGS, SUPPORTED_LANGS +# Общие функции для типографа etpgrf +from etpgrf.config import MODE_UNICODE, MODE_MNEMONIC, MODE_MIXED, DEFAULT_MODE, DEFAULT_LANGS, SUPPORTED_LANGS import os import regex -# Общие функции для типографа etpgrf + + +def parce_and_validate_mode( + mode_input: str | None = None, +) -> str: + """ + Обрабатывает и валидирует входной параметр mode. + Если mode_input не предоставлен (None), используется режим по умолчанию. + + :param mode_input: Режим обработки текста. Может быть 'unicode', 'mnemonic' или 'mixed'. + :return: Валидированный режим в нижнем регистре. + :raises TypeError: Если mode_input имеет неожиданный тип. + :raises ValueError: Если mode_input пуст после обработки или содержит неподдерживаемый режим. + """ + if mode_input is None: + # Если mode_input не предоставлен явно, используем режим по умолчанию + _mode_input = DEFAULT_MODE + else: + _mode_input = str(mode_input).lower() + + if _mode_input not in {MODE_UNICODE, MODE_MNEMONIC, MODE_MIXED}: + raise ValueError( + f"etpgrf: режим '{_mode_input}' не поддерживается. Поддерживаемые режимы: {MODE_UNICODE}, {MODE_MNEMONIC}, {MODE_MIXED}" + ) + + return _mode_input + def parse_and_validate_langs( langs_input: str | list[str] | tuple[str, ...] | frozenset[str] | None = None, diff --git a/etpgrf/hyphenation.py b/etpgrf/hyphenation.py index df85452..3118b2f 100755 --- a/etpgrf/hyphenation.py +++ b/etpgrf/hyphenation.py @@ -1,7 +1,6 @@ -from os.path import exists - import regex -from etpgrf.comutil import parse_and_validate_langs +from etpgrf.config import DEFAULT_MODE, DEFAULT_LANGS, SHY_ENTITIES, MODE_UNICODE +from etpgrf.comutil import parce_and_validate_mode, parse_and_validate_langs _RU_VOWELS_UPPER = frozenset(['А', 'О', 'И', 'Е', 'Ё', 'Э', 'Ы', 'У', 'Ю', 'Я']) _RU_CONSONANTS_UPPER = frozenset(['Б', 'В', 'Г', 'Д', 'Ж', 'З', 'К', 'Л', 'М', 'Н', 'П', 'Р', 'С', 'Т', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ']) @@ -16,10 +15,12 @@ class Hyphenator: """Правила расстановки переносов для разных языков. """ def __init__(self, - langs: frozenset[str], # Языки, которые обрабатываем в переносе слов + langs: frozenset[str] = DEFAULT_LANGS, # Языки, которые обрабатываем в переносе слов + mode: str = DEFAULT_MODE, # Режим обработки текста max_unhyphenated_len: int = 14, # Максимальная длина непереносимой группы min_chars_per_part: int = 3): # Минимальная длина после переноса (хвост, который разрешено переносить) self.langs: frozenset[str] = parse_and_validate_langs(langs) + self.mode: str = parce_and_validate_mode(mode) self.max_unhyphenated_len = max_unhyphenated_len self.min_chars_per_part = min_chars_per_part @@ -28,10 +29,10 @@ class Hyphenator: self._consonants: frozenset = frozenset() self._j_sound_upper: frozenset = frozenset() self._signs_upper: frozenset = frozenset() - - self._load_language_resources_for_hyphenation() # Загружает наборы символов на основе self.langs - - self._split_memo: dict[str, str] = {} # Кеш для этого экземпляра + # Загружает наборы символов на основе self.langs + self._load_language_resources_for_hyphenation() + # Определяем символ переноса в зависимости от режима + self._split_code: str = SHY_ENTITIES['SHY'][0] if self.mode == MODE_UNICODE else SHY_ENTITIES['SHY'][1] def _load_language_resources_for_hyphenation(self): @@ -118,8 +119,8 @@ class Hyphenator: left_part = word_to_split[:hyphen_idx] right_part = word_to_split[hyphen_idx:] - # Рекурсивно делим левую и правую части - return split_word(left_part) + "-­" + split_word(right_part) + # Рекурсивно делим левую и правую части и соединяем их через символ переноса + return split_word(left_part) + self._split_code + split_word(right_part) # Основная логика if len(word) <= self.max_unhyphenated_len or not any(self._is_vow(c) for c in word): diff --git a/etpgrf/typograph.py b/etpgrf/typograph.py index ffc0730..bf5233b 100644 --- a/etpgrf/typograph.py +++ b/etpgrf/typograph.py @@ -1,13 +1,13 @@ -from etpgrf.config import UTF, MNEMO_CODE -from etpgrf.comutil import parse_and_validate_langs +from etpgrf.config import DEFAULT_MODE, DEFAULT_LANGS +from etpgrf.comutil import parce_and_validate_mode, parse_and_validate_langs from etpgrf.hyphenation import Hyphenator # --- Основной класс Typographer --- class Typographer: def __init__(self, - langs: str | list[str] | tuple[str, ...] | frozenset[str] = 'ru', - code_out: str = 'mnemo', + langs: str | list[str] | tuple[str, ...] | frozenset[str] = DEFAULT_LANGS, + mode: str = DEFAULT_MODE, hyphenation_rule: Hyphenator | None = None, # Перенос слов и параметры расстановки переносов # glue_prepositions_rule: GluePrepositionsRule | None = None, # Для других правил # ... другие модули правил ... @@ -16,16 +16,12 @@ class Typographer: # --- Обработка и валидация параметра langs --- self.langs: frozenset[str] = parse_and_validate_langs(langs) - # --- Обработка и валидация параметра code_out --- - if code_out not in MNEMO_CODE | UTF: - raise ValueError(f"etpgrf: code_out '{code_out}' is not supported. Supported codes: {MNEMO_CODE | UTF}") + # --- Обработка и валидация параметра mode --- + self.mode: str = parce_and_validate_mode(mode) # Сохраняем переданные модули правил self.hyphenation_rule = hyphenation_rule - # TODO: вынести все соответствия UTF ⇄ MNEMO_CODE в отдельный класс - # self.hyphen_char = "­" if code_out in UTF else "­" # Мягкий перенос по умолчанию - # Конвейер для обработки текста def process(self, text: str) -> str: processed_text = text @@ -43,5 +39,5 @@ class Typographer: return processed_text # def _get_nbsp(self): # Пример получения неразрывного пробела - # return "\u00A0" if self.code_out in UTF else " " + # return "\u00A0" if self.mode in UTF else " " diff --git a/main.py b/main.py index c8e57db..159aae2 100644 --- a/main.py +++ b/main.py @@ -8,7 +8,7 @@ if __name__ == '__main__': # Определяем пользовательские правила переносов hyphen_settings = etpgrf.Hyphenator(langs=frozenset(['ru']), max_unhyphenated_len=8) # Определяем пользовательские правила типографа - typo = etpgrf.Typographer(langs='ru', code_out='utf-8', hyphenation_rule=hyphen_settings) + typo = etpgrf.Typographer(langs='ru', mode='mnemonic', hyphenation_rule=hyphen_settings) result = hyphen_settings.hyp_in_text("Бармалейщина") print(result, "\n\n")