From 39ef02884ef3779e4414221f0c23f5a9772b1e9b Mon Sep 17 00:00:00 2001 From: erjemin Date: Fri, 22 Aug 2025 15:37:02 +0300 Subject: [PATCH] =?UTF-8?q?mod:=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D1=81=D0=B8=D0=BC=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- etpgrf/config.py | 101 +++++++++++++++++++++++++++----------- etpgrf/hyphenation.py | 6 +-- etpgrf/quotes.py | 9 ++-- etpgrf/unbreakables.py | 6 +-- tests/test_hyphenation.py | 70 +++++++++++++------------- 5 files changed, 119 insertions(+), 73 deletions(-) diff --git a/etpgrf/config.py b/etpgrf/config.py index 5d3eac9..7b39526 100644 --- a/etpgrf/config.py +++ b/etpgrf/config.py @@ -35,16 +35,61 @@ EN_ALPHABET_LOWER = frozenset([char.lower() for char in EN_ALPHABET_UPPER]) EN_ALPHABET_FULL = EN_ALPHABET_UPPER | EN_ALPHABET_LOWER # --- Специальные символы --- -NBSP_CHAR = '\u00A0' # Неразрывный пробел ( ) -SHY_CHAR = '\u00AD' # Мягкий перенос (­) -RU_QUOT1_OPEN = '«' -RU_QUOT1_CLOSE = '»' -RU_QUOT2_OPEN = '„' -RU_QUOT2_CLOSE = '“' -EN_QUOT1_OPEN = '“' -EN_QUOT1_CLOSE = '”' -EN_QUOT2_OPEN = '‘' -EN_QUOT2_CLOSE = '’' +CHAR_NBSP = '\u00a0' # Неразрывный пробел ( ) +CHAR_SHY = '\u00ad' # Мягкий перенос (­) +CHAR_NDASH = '\u2013' # Cреднее тире (– / –) +CHAR_MDASH = '\u2014' # Длинное тире (— / —) +CHAR_HELLIP = '\u2026' # Многоточие (… / …) +CHAR_RU_QUOT1_OPEN = '«' # Русские кавычки открывающие (« / «) +CHAR_RU_QUOT1_CLOSE = '»' +CHAR_RU_QUOT2_OPEN = '„' +CHAR_RU_QUOT2_CLOSE = '“' +CHAR_EN_QUOT1_OPEN = '“' +CHAR_EN_QUOT1_CLOSE = '”' +CHAR_EN_QUOT2_OPEN = '‘' +CHAR_EN_QUOT2_CLOSE = '’' +CHAR_COPY = '\u00a9' # Символ авторского права / © / © +CHAR_REG = '\u00ae' # Зарегистрированная торговая марка / ® / ® +CHAR_COPYP = '\u2117' # Знак звуковой записи / ℗ / ©p; +CHAR_TRADE = '\u2122' # Знак торговой марки / ™ / ™ +CHAR_ARROW_LR_DOUBLE = '\u21d4' # Двойная двунаправленная стрелка / ⇔ / ⇔ +CHAR_ARROW_L_DOUBLE = '\u21d0' # Двойная стрелка влево / ⇐ / ⇐ +CHAR_ARROW_R_DOUBLE = '\u21d2' # Двойная стрелка вправо / ⇒ / ⇒ +CHAR_AP = '\u2248' # Приблизительно равно / ≈ / ≈ +CHAR_ARROW_L = '\u27f5' # Стрелка влево / ← / ← +CHAR_ARROW_R = '\u27f6' # Стрелка вправо / → / → +CHAR_ARROW_LR = '\u27f7' # Длинная двунаправленная стрелка ↔ / ↔ +CHAR_ARROW_L_LONG_DOUBLE = '\u27f8' # Длинная двойная стрелка влево +CHAR_ARROW_R_LONG_DOUBLE = '\u27f9' # Длинная двойная стрелка вправо +CHAR_ARROW_LR_LONG_DOUBLE = '\u27fa' # Длинная двойная двунаправленная стрелка + +# === КОНСТАНТЫ ПСЕВДОГРАФИКИ === +# Для простых замен "строка -> символ" используем список кортежей. +# Порядок важен: более длинные последовательности должны идти раньше более коротких, которые +# могут быть их частью (например, '<---' до '---', а та, в свою очередь, до '--'). +STR_TO_SYMBOL_REPLACEMENTS = [ + # 5-символьные последовательности + ('<===>', CHAR_ARROW_LR_LONG_DOUBLE), # Длинная двойная двунаправленная стрелка + # 4-символьные последовательности + ('<===', CHAR_ARROW_L_LONG_DOUBLE), # Длинная двойная стрелка влево + ('===>', CHAR_ARROW_R_LONG_DOUBLE), # Длинная двойная стрелка вправо + ('<==>', CHAR_ARROW_LR_DOUBLE), # Двойная двунаправленная стрелка + ('(tm)', CHAR_TRADE), ('(TM)', CHAR_TRADE), # Знак торговой марки (нижний и верхний регистр) + ('<-->', CHAR_ARROW_LR), # Длинная двунаправленная стрелка + # 3-символьные последовательности + ('<--', CHAR_ARROW_L), # Стрелка влево + ('-->', CHAR_ARROW_R), # Стрелка вправо + ('==>', CHAR_ARROW_R_DOUBLE), # Двойная стрелка вправо + ('<==', CHAR_ARROW_L_DOUBLE), # Двойная стрелка влево + ('---', CHAR_MDASH), # Длинное тире + ('...', CHAR_HELLIP), # Многоточие + ('(c)', CHAR_COPY), ('(C)', CHAR_COPY), # Знак авторского права (нижний и верхний регистр) + ('(r)', CHAR_REG), ('(R)', CHAR_REG), # Знак зарегистрированной торговой марки (нижний и верхний регистр) + ('(p)', CHAR_COPYP), ('(P)', CHAR_COPYP), # Знак права на звукозапись (нижний и верхний регистр) + # 2-символьные последовательности + ('--', CHAR_NDASH), # Среднее тире (дефисные соединения и диапазоны) + ('~=', CHAR_AP), # Приблизительно равно (≈) +] # === КОНСТАНТЫ ДЛЯ КОДИРОВАНИЯ HTML-МНЕМНОИКОВ === # --- ЧЕРНЫЙ СПИСОК: Символы, которые НИКОГДА не нужно кодировать в мнемоники --- @@ -57,8 +102,8 @@ NEVER_ENCODE_CHARS = (frozenset(['!', '#', '%', '(', ')', '*', ',', '.', '/', ': # которые не видны, на глаз и не отличимы друг от друга в обычном тексте, или очень специфичные SAFE_MODE_CHARS_TO_MNEMONIC = frozenset([ '<', '>', '&', '"', '\'', - SHY_CHAR, # Мягкий перенос (Soft Hyphen) -- ­ - NBSP_CHAR, # Неразрывный пробел (Non-Breaking Space) --   + CHAR_SHY, # Мягкий перенос (Soft Hyphen) -- ­ + CHAR_NBSP, # Неразрывный пробел (Non-Breaking Space) --   '\u2002', # Полужирный пробел (En Space) --   '\u2003', # Широкий пробел (Em Space) --   '\u2007', # Цифровой пробел --   @@ -109,13 +154,13 @@ CUSTOM_ENCODE_MAP = { # '\u007b': '{', # { / { / { # '\u007d': '}', # } / } / } # '\u007c': '|', # | / | / | / | - # '\u0026': '&', # & / & / & - # NBSP_CHAR: ' ', # /   /   + CHAR_NBSP: ' ', # /   /   + CHAR_REG: '®', # ® / ® / ® / ® + CHAR_COPY: '©', # © / © / © '\u0022': '"', # " / " / " '\u0026': '&', # & / & / & '\u003e': '>', # > / > / > - '\u003c': '<', # < / < / < - '\u00ae': '®', # ® / ® / ® / ® + '\u003c': '<', # < / < / < '\u00b7': '·', # · / · / · / · '\u0060': '`', # ` / ` / ` '\u00a8': '¨', # ¨ / ¨ / ¨ / ¨ / ¨ @@ -127,7 +172,7 @@ CUSTOM_ENCODE_MAP = { '\u2207': '∇', # ∇ / ∇ / ∇ '\u2061': '⁡', # / ⁡ / ⁡ '\u2221': '∡', # ∡ / ∡ / ∡ - '\u2248': '≈', # ≈ / ≈ / ≈ / ≈ / ≈ / ≈ + CHAR_AP: '≈', # ≈ / ≈ / ≈ / ≈ / ≈ / ≈ '\u224a': '≊', # ≊ / ≊ / ≊ '\u2254': '≔', # ≔ / ≔ / ≔ / ≔ '\u224d': '≍', # ≍ / ≍ / ≍ @@ -228,12 +273,12 @@ CUSTOM_ENCODE_MAP = { '\u2214': '∔', # ∔ / ∔ / ∔ '\u22a1': '⊡', # ⊡ / ⊡ / ⊡ '\u21d3': '⇓', # ⇓ / ⇓ / ⇓ / ⇓ - '\u21d0': '⇐', # ⇐ / ⇐ / ⇐ / ⇐ - '\u21d4': '⇔', # ⇔ / ⇔ / ⇔ / ⇔ / ⇔ - '\u27f8': '⟸', # ⟸ / ⟸ / ⟸ / ⟸ - '\u27fa': '⟺', # ⟺ / ⟺ / ⟺ / ⟺ - '\u27f9': '⟹', # ⟹ / ⟹ / ⟹ / ⟹ - '\u21d2': '⇒', # ⇒ / ⇒ / ⇒ / ⇒ / ⇒ + CHAR_ARROW_R_DOUBLE: '⇒', # ⇒ / ⇒ / ⇒ / ⇒ / ⇒ + CHAR_ARROW_L_DOUBLE: '⇐', # ⇐ / ⇐ / ⇐ / ⇐ + CHAR_ARROW_LR_DOUBLE: '⇔', # ⇔ / ⇔ / ⇔ / ⇔ / ⇔ + CHAR_ARROW_L_LONG_DOUBLE: '⟸', # ⟸ / ⟸ / ⟸ / ⟸ + CHAR_ARROW_R_LONG_DOUBLE: '⟹', # ⟹ / ⟹ / ⟹ / ⟹ + CHAR_ARROW_LR_LONG_DOUBLE: '⟺', # ⟺ / ⟺ / ⟺ / ⟺ '\u22a8': '⊨', # ⊨ / ⊨ / ⊨ '\u21d1': '⇑', # ⇑ / ⇑ / ⇑ / ⇑ '\u2202': '∂', # ∂ / ∂ / ∂ @@ -337,10 +382,10 @@ CUSTOM_ENCODE_MAP = { '\u2a89': '⪉', # ⪉ / ⪉ / ⪉ '\u2268': '≨', # ≨ / ≨ / ≨ '\u2a87': '⪇', # ⪇ / ⪇ / ⪇ - '\u27f5': '⟵', # ⟵ / ⟵ / ⟵ / ⟵ - '\u27f7': '⟷', # ⟷ / ⟷ / ⟷ / ⟷ + CHAR_ARROW_L: '⟵', # ⟵ / ⟵ / ⟵ / ⟵ + CHAR_ARROW_R: '⟶', # ⟶ / ⟶ / ⟶ / ⟶ + CHAR_ARROW_LR: '⟷', # ⟷ / ⟷ / ⟷ / ⟷ '\u27fc': '⟼', # ⟼ / ⟼ / ⟼ - '\u27f6': '⟶', # ⟶ / ⟶ / ⟶ / ⟶ '\u21ac': '↬', # ↬ / ↬ / ↬ '\u201e': '„', # „ / „ / „ '\u2199': '↙', # ↙ / ↙ / ↙ / ↙ @@ -353,7 +398,7 @@ CUSTOM_ENCODE_MAP = { '\u2133': 'ℳ', # ℳ / ℳ / ℳ / ℳ '\u2223': '∣', # ∣ / ∣ / ∣ / ∣ / ∣ '\u2213': '∓', # ∓ / ∓ / ∓ / ∓ - '\u2026': '…', # … / … / … + CHAR_HELLIP: '…', # … / … / … '\u22b8': '⊸', # ⊸ / ⊸ / ⊸ '\u2249': '≉', # ≉ / ≉ / ≉ / ≉ '\u266e': '♮', # ♮ / ♮ / ♮ @@ -486,7 +531,7 @@ CUSTOM_ENCODE_MAP = { '\u20db': '⃛', # ⃛ / ⃛ / ⃛ '\u2234': '∴', # ∴ / ∴ / ∴ / ∴ '\u03d1': 'ϑ', # ϑ / ϑ / ϑ / ϑ - '\u2122': '™', # ™ / ™ / ™ + CHAR_TRADE: '™', # ™ / ™ / ™ '\u25b5': '▵', # ▵ / ▵ / ▵ '\u225c': '≜', # ≜ / ≜ / ≜ '\u21c5': '⇅', # ⇅ / ⇅ / ⇅ diff --git a/etpgrf/hyphenation.py b/etpgrf/hyphenation.py index cacb885..f9d3c26 100755 --- a/etpgrf/hyphenation.py +++ b/etpgrf/hyphenation.py @@ -8,7 +8,7 @@ import regex import logging import html from etpgrf.config import ( - SHY_CHAR, LANG_RU, LANG_RU_OLD, LANG_EN, + CHAR_SHY, LANG_RU, LANG_RU_OLD, LANG_EN, RU_VOWELS_UPPER, RU_CONSONANTS_UPPER, RU_J_SOUND_UPPER, RU_SIGNS_UPPER, # RU_ALPHABET_UPPER, EN_VOWELS_UPPER, EN_CONSONANTS_UPPER # , EN_ALPHABET_UPPER ) @@ -214,7 +214,7 @@ class Hyphenator: left_part = word_to_split[:hyphen_idx] right_part = word_to_split[hyphen_idx:] # Рекурсивно делим левую и правую части и соединяем их через символ переноса - return split_word_ru(left_part) + SHY_CHAR + split_word_ru(right_part) + return split_word_ru(left_part) + CHAR_SHY + split_word_ru(right_part) # Основная логика return split_word_ru(word) # Рекурсивно делим слово на части с переносами @@ -316,7 +316,7 @@ class Hyphenator: # Рекурсивно обрабатываем обе части и объединяем их символом переноса return (split_word_en(word_to_split[:hyphen_idx]) + - SHY_CHAR + split_word_en(word_to_split[hyphen_idx:])) + CHAR_SHY + split_word_en(word_to_split[hyphen_idx:])) # --- Конец логики для английского языка --- return split_word_en(word) diff --git a/etpgrf/quotes.py b/etpgrf/quotes.py index 3d6ad19..01cee3e 100644 --- a/etpgrf/quotes.py +++ b/etpgrf/quotes.py @@ -3,8 +3,9 @@ import regex import logging -from .config import LANG_RU, LANG_EN, RU_QUOT1_OPEN, RU_QUOT1_CLOSE, EN_QUOT1_OPEN, EN_QUOT1_CLOSE, \ - RU_QUOT2_OPEN, RU_QUOT2_CLOSE, EN_QUOT2_OPEN, EN_QUOT2_CLOSE +from .config import (LANG_RU, LANG_EN, CHAR_RU_QUOT1_OPEN, CHAR_RU_QUOT1_CLOSE, CHAR_EN_QUOT1_OPEN, + CHAR_EN_QUOT1_CLOSE, CHAR_RU_QUOT2_OPEN, CHAR_RU_QUOT2_CLOSE, CHAR_EN_QUOT2_OPEN, + CHAR_EN_QUOT2_CLOSE) from .comutil import parse_and_validate_langs # --- Настройки логирования --- @@ -13,8 +14,8 @@ logger = logging.getLogger(__name__) # Определяем стили кавычек для разных языков # Формат: (('открывающая_ур1', 'закрывающая_ур1'), ('открывающая_ур2', 'закрывающая_ур2')) _QUOTE_STYLES = { - LANG_RU: ((RU_QUOT1_OPEN, RU_QUOT1_CLOSE), (RU_QUOT2_OPEN, RU_QUOT2_CLOSE)), - LANG_EN: ((EN_QUOT1_OPEN, EN_QUOT1_CLOSE), (EN_QUOT2_OPEN, EN_QUOT2_CLOSE)), + LANG_RU: ((CHAR_RU_QUOT1_OPEN, CHAR_RU_QUOT1_CLOSE), (CHAR_RU_QUOT2_OPEN, CHAR_RU_QUOT2_CLOSE)), + LANG_EN: ((CHAR_EN_QUOT1_OPEN, CHAR_EN_QUOT1_CLOSE), (CHAR_EN_QUOT2_OPEN, CHAR_EN_QUOT2_CLOSE)), } diff --git a/etpgrf/unbreakables.py b/etpgrf/unbreakables.py index 00e8e12..3ba7be3 100644 --- a/etpgrf/unbreakables.py +++ b/etpgrf/unbreakables.py @@ -9,7 +9,7 @@ import logging import html from etpgrf.config import LANG_RU, LANG_RU_OLD, LANG_EN # , KEY_NBSP, ALL_ENTITIES from etpgrf.comutil import parse_and_validate_langs -from etpgrf.config import NBSP_CHAR +from etpgrf.config import CHAR_NBSP from etpgrf.defaults import etpgrf_settings # --- Наборы коротких слов для разных языков --- @@ -114,11 +114,11 @@ class Unbreakables: # 1. Обработка слов, ПОСЛЕ которых нужен неразрывный пробел ("в дом" -> "в дом") if self._pre_pattern: - processed_text = self._pre_pattern.sub(r"\g<1>" + NBSP_CHAR, processed_text) + processed_text = self._pre_pattern.sub(r"\g<1>" + CHAR_NBSP, processed_text) # 2. Обработка частиц, ПЕРЕД которыми нужен неразрывный пробел ("сказал бы" -> "сказал бы") if self._post_pattern: # \g<1> - это пробел, \g<2> - это частица - processed_text = self._post_pattern.sub(NBSP_CHAR + r"\g<2>", processed_text) + processed_text = self._post_pattern.sub(CHAR_NBSP + r"\g<2>", processed_text) return processed_text diff --git a/tests/test_hyphenation.py b/tests/test_hyphenation.py index c9089cf..2c061b2 100644 --- a/tests/test_hyphenation.py +++ b/tests/test_hyphenation.py @@ -1,35 +1,35 @@ # tests/test_hyphenation.py import pytest from etpgrf import Hyphenator -from tests.test_unbreakables import ENGLISH_PREPOSITIONS_TO_TEST +from etpgrf.config import CHAR_SHY # --- Тестовые данные для русского языка --- # Формат: (входное_слово, ожидаемый_результат_с_переносами) -# Используем \u00AD - это Unicode-представление мягкого переноса (­) +# Используем {CHAR_SHY} - это Unicode-представление мягкого переноса (­) RUSSIAN_HYPHENATION_CASES = [ ("дом", "дом"), # Сочень короткое (короче max_unhyphenated_len) не должно меняться - ("проверка", "про\u00ADверка"), - ("тестирование", "тести\u00ADрова\u00ADние"), - ("благотворительностью", "бла\u00ADготво\u00ADритель\u00ADностью"), # Слово с переносом на мягкий знак - ("фотоаппаратура", "фотоап\u00ADпара\u00ADтура"), # проверка слова со сдвоенной согласной - ("программирование", "про\u00ADграм\u00ADмиро\u00ADвание"), # слова со сдвоенной согласной - ("сверхзвуковой", "сверх\u00ADзву\u00ADковой"), - ("автомобиль", "авто\u00ADмобиль"), - ("интернационализация", "инте\u00ADрнаци\u00ADонали\u00ADзация"), - ("электронный", "элек\u00ADтрон\u00ADный"), - ("информационный", "инфо\u00ADрма\u00ADцион\u00ADный"), - ("автоматизация", "автома\u00ADтиза\u00ADция"), - ("многоклеточный", "мно\u00ADгокле\u00ADточный"), - ("многофункциональный", "мно\u00ADгофун\u00ADкцио\u00ADналь\u00ADный"), - ("непрерывность", "непре\u00ADрывно\u00ADсть"), - ("сверхпроводимость", "сверх\u00ADпрово\u00ADдимо\u00ADсть"), - ("многообразие", "мно\u00ADгоо\u00ADбра\u00ADзие"), - ("противоречивость", "про\u00ADтиво\u00ADречи\u00ADвость"), - ("непревзойденный", "непре\u00ADвзой\u00ADден\u00ADный"), - ("многослойный", "мно\u00ADгослой\u00ADный"), - ("суперкомпьютер", "супе\u00ADрко\u00ADмпью\u00ADтер"), # Неправильный перенос (нужен словарь "приставок/корней/суффиксов") - ("сверхчувствительный", "свер\u00ADхчув\u00ADстви\u00ADтель\u00ADный"), # Неправильный перенос - ("гиперподъездной", "гипе\u00ADрпо\u00ADдъез\u00ADдной"), # Неправильный перенос + ("проверка", f"про{CHAR_SHY}верка"), + ("тестирование", f"тести{CHAR_SHY}рова{CHAR_SHY}ние"), + ("благотворительностью", f"бла{CHAR_SHY}готво{CHAR_SHY}ритель{CHAR_SHY}ностью"), # Слово с переносом на мягкий знак + ("фотоаппаратура", f"фотоап{CHAR_SHY}пара{CHAR_SHY}тура"), # проверка слова со сдвоенной согласной + ("программирование", f"про{CHAR_SHY}грам{CHAR_SHY}миро{CHAR_SHY}вание"), # слова со сдвоенной согласной + ("сверхзвуковой", f"сверх{CHAR_SHY}зву{CHAR_SHY}ковой"), + ("автомобиль", f"авто{CHAR_SHY}мобиль"), + ("интернационализация", f"инте{CHAR_SHY}рнаци{CHAR_SHY}онали{CHAR_SHY}зация"), + ("электронный", f"элек{CHAR_SHY}трон{CHAR_SHY}ный"), + ("информационный", f"инфо{CHAR_SHY}рма{CHAR_SHY}цион{CHAR_SHY}ный"), + ("автоматизация", f"автома{CHAR_SHY}тиза{CHAR_SHY}ция"), + ("многоклеточный", f"мно{CHAR_SHY}гокле{CHAR_SHY}точный"), + ("многофункциональный", f"мно{CHAR_SHY}гофун{CHAR_SHY}кцио{CHAR_SHY}наль{CHAR_SHY}ный"), + ("непрерывность", f"непре{CHAR_SHY}рывно{CHAR_SHY}сть"), + ("сверхпроводимость", f"сверх{CHAR_SHY}прово{CHAR_SHY}димо{CHAR_SHY}сть"), + ("многообразие", f"мно{CHAR_SHY}гоо{CHAR_SHY}бра{CHAR_SHY}зие"), + ("противоречивость", f"про{CHAR_SHY}тиво{CHAR_SHY}речи{CHAR_SHY}вость"), + ("непревзойденный", f"непре{CHAR_SHY}взой{CHAR_SHY}ден{CHAR_SHY}ный"), + ("многослойный", f"мно{CHAR_SHY}гослой{CHAR_SHY}ный"), + ("суперкомпьютер", f"супе{CHAR_SHY}рко{CHAR_SHY}мпью{CHAR_SHY}тер"), # Неправильный перенос (нужен словарь "приставок/корней/суффиксов") + ("сверхчувствительный", f"свер{CHAR_SHY}хчув{CHAR_SHY}стви{CHAR_SHY}тель{CHAR_SHY}ный"), # Неправильный перенос + ("гиперподъездной", f"гипе{CHAR_SHY}рпо{CHAR_SHY}дъез{CHAR_SHY}дной"), # Неправильный перенос ] @@ -49,17 +49,17 @@ def test_russian_word_hyphenation(input_word, expected_output): ENGLISH_HYPHENATION_CASES = [ ("color", "color"), # Короткое слово, не должно меняться ("throughout", "throughout"), # Длинное слово, но из-за икс-графа "ough" не будет переноситься - ("ambrella", "amb\u00ADrella"), - ("unbelievable", "unbel\u00ADiev\u00ADable"), # Проверка переноса перед суффиксом "able" - ("acknowledgment", "ack\u00ADnow\u00ADledg\u00ADment"), # Проверка переноса перед суффиксом "ment" - ("friendship", "frien\u00ADdship"), # Проверка переноса перед суффиксом "ship" - ("thoughtful", "though\u00ADtful"), # - ("psychology", "psy\u00ADcho\u00ADlogy"), # Проверка переноса после "psy" - ("extraordinary", "ext\u00ADraor\u00ADdin\u00ADary"), # Проверка сложного слова - ("unbreakable", "unb\u00ADrea\u00ADkable"), # Проверка переноса перед "able" - ("acknowledgement", "ack\u00ADnow\u00ADledge\u00ADment"), # Проверка икс-графа "dge" - ("misunderstanding", "mis\u00ADunder\u00ADstan\u00ADding"), # Проверка сложного слова - ("floccinaucinihilipilification", "floc\u00ADcin\u00ADauc\u00ADinih\u00ADili\u00ADpili\u00ADfica\u00ADtion"), + ("ambrella", f"amb{CHAR_SHY}rella"), + ("unbelievable", f"unbel{CHAR_SHY}iev{CHAR_SHY}able"), # Проверка переноса перед суффиксом "able" + ("acknowledgment", f"ack{CHAR_SHY}now{CHAR_SHY}ledg{CHAR_SHY}ment"), # Проверка переноса перед суффиксом "ment" + ("friendship", f"frien{CHAR_SHY}dship"), # Проверка переноса перед суффиксом "ship" + ("thoughtful", f"though{CHAR_SHY}tful"), # + ("psychology", f"psy{CHAR_SHY}cho{CHAR_SHY}logy"), # Проверка переноса после "psy" + ("extraordinary", f"ext{CHAR_SHY}raor{CHAR_SHY}din{CHAR_SHY}ary"), # Проверка сложного слова + ("unbreakable", f"unb{CHAR_SHY}rea{CHAR_SHY}kable"), # Проверка переноса перед "able" + ("acknowledgement", f"ack{CHAR_SHY}now{CHAR_SHY}ledge{CHAR_SHY}ment"), # Проверка икс-графа "dge" + ("misunderstanding", f"mis{CHAR_SHY}under{CHAR_SHY}stan{CHAR_SHY}ding"), # Проверка сложного слова + ("floccinaucinihilipilification", f"floc{CHAR_SHY}cin{CHAR_SHY}auc{CHAR_SHY}inih{CHAR_SHY}ili{CHAR_SHY}pili{CHAR_SHY}fica{CHAR_SHY}tion"), ] @pytest.mark.parametrize("input_word, expected_output", ENGLISH_HYPHENATION_CASES)