add: minor .

This commit is contained in:
2025-05-11 02:22:26 +03:00
parent 30368cedfd
commit 9e5488ec26
2 changed files with 20 additions and 18 deletions

View File

@@ -19,10 +19,10 @@ class HyphenationRule:
""" """
def __init__(self, def __init__(self,
langs: frozenset[str], # Языки, которые обрабатываем в переносе слов langs: frozenset[str], # Языки, которые обрабатываем в переносе слов
max_len_hyphenation_not_required: int = 14, # Максимальная длина непереносимой группы max_unhyphenated_len: int = 14, # Максимальная длина непереносимой группы
min_chars_per_part: int = 3): # Минимальная длина после переноса (хвост, который разрешено переносить) min_chars_per_part: int = 3): # Минимальная длина после переноса (хвост, который разрешено переносить)
self.langs = langs self.langs = langs
self.max_len_hyphenation__not_required = max_len_hyphenation_not_required self.max_unhyphenated_len = max_unhyphenated_len
self.min_chars_per_part = min_chars_per_part self.min_chars_per_part = min_chars_per_part
# Внутренние языковые ресурсы, если нужны специфично для переносов # Внутренние языковые ресурсы, если нужны специфично для переносов
@@ -80,24 +80,24 @@ class HyphenationRule:
""" """
# Поиск допустимой позиции для переноса около заданного индекса # Поиск допустимой позиции для переноса около заданного индекса
def find_hyphen_point(word_2find_point: str, start_idx: int) -> int: def find_hyphen_point(word_segment: str, start_idx: int) -> int:
vow_indices = [i for i, char_w in enumerate(word_2find_point) if self._is_vow(char_w)] vow_indices = [i for i, char_w in enumerate(word_segment) if self._is_vow(char_w)]
if not vow_indices: if not vow_indices:
# Если в слове нет гласных, то перенос невозможен # Если в слове нет гласных, то перенос невозможен
return -1 return -1
# Ищем ближайшую гласную до или после start_idx # Ищем ближайшую гласную до или после start_idx
for i in vow_indices: for i in vow_indices:
if i >= start_idx - self.min_chars_per_part and i + self.min_chars_per_part < len(word_2find_point): if i >= start_idx - self.min_chars_per_part and i + self.min_chars_per_part < len(word_segment):
# Проверяем, что после гласной есть минимум символов "хвоста" # Проверяем, что после гласной есть минимум символов "хвоста"
ind = i + 1 ind = i + 1
if (self._is_cons(word_2find_point[ind]) or self._is_j_sound(word_2find_point[ind])) and not self._is_vow(word_2find_point[ind + 1]): if (self._is_cons(word_segment[ind]) or self._is_j_sound(word_segment[ind])) and not self._is_vow(word_segment[ind + 1]):
# Й -- полугласная. Перенос после неё только в случае, если дальше идет согласная # Й -- полугласная. Перенос после неё только в случае, если дальше идет согласная
# (например, "бой-кий"), но запретить, если идет гласная (например, "ма-йка" не переносится). # (например, "бой-кий"), но запретить, если идет гласная (например, "ма-йка" не переносится).
ind += 1 ind += 1
if ind <= self.min_chars_per_part or ind >= len(word_2find_point) - self.min_chars_per_part: if ind <= self.min_chars_per_part or ind >= len(word_segment) - self.min_chars_per_part:
# Не отделяем 3 символ с начала или конца (это некрасиво) # Не отделяем 3 символ с начала или конца (это некрасиво)
continue continue
if self._is_sign(word_2find_point[ind]) or self._is_sign(word_2find_point[-1]): if self._is_sign(word_segment[ind]) or self._is_sign(word_segment[-1]):
# Пропускаем мягкий/твердый знак. Согласно правилам русской типографики (например, ГОСТ 7.62-2008 # Пропускаем мягкий/твердый знак. Согласно правилам русской типографики (например, ГОСТ 7.62-2008
# или рекомендации по набору текста), перенос не должен разрывать слово так, чтобы мягкий или # или рекомендации по набору текста), перенос не должен разрывать слово так, чтобы мягкий или
# твердый знак оказывался в начале или конце строки # твердый знак оказывался в начале или конце строки
@@ -106,23 +106,23 @@ class HyphenationRule:
return -1 # Не нашли подходящую позицию return -1 # Не нашли подходящую позицию
# Рекурсивное деление слова # Рекурсивное деление слова
def split_word(word_to_hyphenation: str) -> str: def split_word(word_to_split: str) -> str:
if len(word_to_hyphenation) <= self.max_len_hyphenation__not_required: # Если длина укладывается в лимит, перенос не нужен if len(word_to_split) <= self.max_unhyphenated_len: # Если длина укладывается в лимит, перенос не нужен
return word_to_hyphenation return word_to_split
hyphen_idx = find_hyphen_point(word_to_hyphenation, len(word_to_hyphenation) // 2) # Ищем точку переноса около середины hyphen_idx = find_hyphen_point(word_to_split, len(word_to_split) // 2) # Ищем точку переноса около середины
if hyphen_idx == -1: # Если не нашли точку переноса if hyphen_idx == -1: # Если не нашли точку переноса
return word_to_hyphenation return word_to_split
left_part = word_to_hyphenation[:hyphen_idx] left_part = word_to_split[:hyphen_idx]
right_part = word_to_hyphenation[hyphen_idx:] right_part = word_to_split[hyphen_idx:]
# Рекурсивно делим левую и правую части # Рекурсивно делим левую и правую части
return split_word(left_part) + "-­" + split_word(right_part) return split_word(left_part) + "-­" + split_word(right_part)
# Основная логика # Основная логика
if len(word) <= self.max_len_hyphenation__not_required or not any(self._is_vow(c) for c in word): if len(word) <= self.max_unhyphenated_len or not any(self._is_vow(c) for c in word):
# Короткое слово или без гласных "делению не подлежит", выходим из рекурсии # Короткое слово или без гласных "делению не подлежит", выходим из рекурсии
return word return word
return split_word(word) # Рекурсивно делим слово на части с переносами return split_word(word) # Рекурсивно делим слово на части с переносами
@@ -136,7 +136,7 @@ class HyphenationRule:
""" """
rus_worlds = regex.findall(r'\b[а-яА-Я]+\b', text) # ищем все русскоязычные слова в тексте rus_worlds = regex.findall(r'\b[а-яА-Я]+\b', text) # ищем все русскоязычные слова в тексте
for word in rus_worlds: for word in rus_worlds:
if len(word) > self.max_len_hyphenation__not_required: if len(word) > self.max_unhyphenated_len:
hyphenated_word = self.hyphenation_in_word(word) hyphenated_word = self.hyphenation_in_word(word)
print(f'{word} -> {hyphenated_word}') print(f'{word} -> {hyphenated_word}')
text = text.replace(word, hyphenated_word) text = text.replace(word, hyphenated_word)

View File

@@ -6,10 +6,12 @@ if __name__ == '__main__':
# --- Пример использования --- # --- Пример использования ---
print("\n--- Пример использования класса---\n") print("\n--- Пример использования класса---\n")
# Определяем пользовательские правила переносов # Определяем пользовательские правила переносов
hyphen_settings = HyphenationRule(langs=frozenset(['ru']), max_len_hyphenation_not_required=8) hyphen_settings = HyphenationRule(langs=frozenset(['ru']), max_unhyphenated_len=8)
# Определяем пользовательские правила типографа # Определяем пользовательские правила типографа
typo = Typographer(langs='ru', code_out='utf-8', hyphenation_rule=hyphen_settings) typo = Typographer(langs='ru', code_out='utf-8', hyphenation_rule=hyphen_settings)
result = hyphen_settings.apply(text="Бармалейщина")
print(result, "\n\n")
result = typo.process(text="Какой-то длинный текст для проверки переносов. Перпердикюляция!") result = typo.process(text="Какой-то длинный текст для проверки переносов. Перпердикюляция!")
print(result, "\n\n") print(result, "\n\n")
result = typo.process(text="Привет, World! Это <i>тестовый текст для проверки расстановки</i> переносов в словах. Миллион 100-метровошеих жирножирафов.") result = typo.process(text="Привет, World! Это <i>тестовый текст для проверки расстановки</i> переносов в словах. Миллион 100-метровошеих жирножирафов.")