улучшение логики форматирования ВК текста для публикации
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
+35
-11
@@ -1,7 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
def truncate_text(text, max_length):
|
def truncate_text(text, max_length):
|
||||||
"""Обрезает текст до максимальной длины с учетом границ слов"""
|
"""Обрезает текст до максимальной длины с учетом границ слов и HTML-тегов"""
|
||||||
if text is None or not text:
|
if text is None or not text:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@@ -12,6 +12,18 @@ def truncate_text(text, max_length):
|
|||||||
truncated = text[:max_length]
|
truncated = text[:max_length]
|
||||||
last_space = truncated.rfind(' ')
|
last_space = truncated.rfind(' ')
|
||||||
|
|
||||||
|
# Проверяем, не обрезали ли мы HTML-тег
|
||||||
|
# Если после обрезки есть незакрытый тег <a, нужно найти его начало и обрезать до него
|
||||||
|
open_tag_pos = truncated.rfind('<a ')
|
||||||
|
if open_tag_pos > 0:
|
||||||
|
# Проверяем, закрыт ли тег
|
||||||
|
after_tag = truncated[open_tag_pos:]
|
||||||
|
if '</a>' not in after_tag:
|
||||||
|
# Тег не закрыт, обрезаем до начала тега
|
||||||
|
truncated = truncated[:open_tag_pos]
|
||||||
|
# Ищем последний пробел перед обрезанным тегом
|
||||||
|
last_space = truncated.rfind(' ')
|
||||||
|
|
||||||
if last_space > 0:
|
if last_space > 0:
|
||||||
return truncated[:last_space] + "..."
|
return truncated[:last_space] + "..."
|
||||||
return truncated[:max_length-3] + "..."
|
return truncated[:max_length-3] + "..."
|
||||||
@@ -30,22 +42,34 @@ def replace_vk_links(text):
|
|||||||
if not text:
|
if not text:
|
||||||
return text
|
return text
|
||||||
|
|
||||||
# Сначала обрабатываем ссылки формата [url|текст] и преобразуем их в HTML-ссылки
|
# Сначала обрабатываем ВК-специфичные ссылки [club*|текст] и [id*|текст]
|
||||||
|
# Это нужно сделать до обработки обычных URL, чтобы не перехватывать их
|
||||||
|
vk_pattern = r'\[(?:club|id)\d+\|([^\]]+)\]'
|
||||||
|
text = re.sub(vk_pattern, r'\1', text)
|
||||||
|
|
||||||
|
# Затем обрабатываем ссылки формата [url|текст] и преобразуем их в HTML-ссылки
|
||||||
def replace_url_link(match):
|
def replace_url_link(match):
|
||||||
url = match.group(1)
|
url = match.group(1).strip()
|
||||||
link_text = match.group(2)
|
link_text = match.group(2).strip()
|
||||||
|
|
||||||
|
# Проверяем, что URL похож на ссылку (содержит http://, https://, или начинается с /)
|
||||||
|
# Это предотвращает обработку обычного текста в квадратных скобках как ссылки
|
||||||
|
if not (url.startswith('http://') or url.startswith('https://') or url.startswith('/') or url.startswith('#')):
|
||||||
|
# Если это не похоже на URL, возвращаем исходный текст без изменений
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
|
# Экранируем кавычки в URL для безопасности
|
||||||
|
url = url.replace('"', '"')
|
||||||
|
# Экранируем HTML-сущности в тексте ссылки
|
||||||
|
link_text = link_text.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||||
return f'<a href="{url}">{link_text}</a>'
|
return f'<a href="{url}">{link_text}</a>'
|
||||||
|
|
||||||
# Регулярное выражение для поиска ссылок формата [url|текст]
|
# Регулярное выражение для поиска ссылок формата [url|текст]
|
||||||
# Исключаем случаи, когда url начинается с club или id и цифр, за которыми сразу следует | (это обрабатывается отдельно)
|
# URL должен содержать хотя бы один символ, не быть пустым
|
||||||
url_pattern = r'\[(?!club\d+\||id\d+\|)([^\|]+)\|([^\]]+)\]'
|
url_pattern = r'\[([^\|\]]+)\|([^\]]+)\]'
|
||||||
text = re.sub(url_pattern, replace_url_link, text)
|
text = re.sub(url_pattern, replace_url_link, text)
|
||||||
|
|
||||||
# Регулярное выражение для поиска ссылок формата [типID|Текст] (ВК-специфичные)
|
return text
|
||||||
vk_pattern = r'\[(?:club|id)\d+\|([^\]]+)\]'
|
|
||||||
|
|
||||||
# Заменяем все вхождения на текст внутри ссылки
|
|
||||||
return re.sub(vk_pattern, r'\1', text)
|
|
||||||
|
|
||||||
def remove_html_tags(text):
|
def remove_html_tags(text):
|
||||||
"""Удаляет HTML-теги с учетом специальной обработки <p> и <a>"""
|
"""Удаляет HTML-теги с учетом специальной обработки <p> и <a>"""
|
||||||
|
|||||||
Reference in New Issue
Block a user