1 Commits
Author SHA1 Message Date
erjemin 4604f6923a mod: улучшено SEO 2026-10-07 00:43:48 +03:00
7 changed files with 569 additions and 49 deletions
+12
View File
@@ -1,6 +1,18 @@
from django.contrib.sitemaps import Sitemap from django.contrib.sitemaps import Sitemap
from django.urls import reverse
from .models import Post from .models import Post
class StaticViewSitemap(Sitemap):
"""Карта сайта для статических страниц (главная и др.)."""
priority = 1.0
changefreq = "daily"
def items(self):
return ['index']
def location(self, item):
return reverse(item)
class PostSitemap(Sitemap): class PostSitemap(Sitemap):
changefreq = "weekly" # Как часто меняются страницы changefreq = "weekly" # Как часто меняются страницы
priority = 0.9 # Приоритет (от 0.0 до 1.0) priority = 0.9 # Приоритет (от 0.0 до 1.0)
+298 -35
View File
@@ -4,51 +4,314 @@
{% block title %}Песочница верстки — ETPGRF{% endblock %} {% block title %}Песочница верстки — ETPGRF{% endblock %}
{% block content %} {% block content %}
<div class="row">
{# Левая колонка: Дата и Картинка #} <div class="row align-items-start">
<div class="col-lg-2 align-self-start text-end mb-4"> <div class="col border-end">
<p class="small align-self-end"> <h3>Сайт typograph.cube2.ru</h3>
<small class="bg-secondary bg-opacity-10 p-2 text-nowrap">
12.фев.2026 <p>Исходный код сайта онланй-типографа <tt>etpgrf</tt> доступен в&nbsp;нескольких репози&shy;ториях (<a
</small> href="https://github.com/erjemin/etpgrf-site" target="_blank">GitHub</a>, <a
</p> href="https://gitverse.ru/erjemin/etpgrf-site" target="_blank">GitVerse</a> и&nbsp;<a
href="https://git.cube2.ru/erjemin/2026-etpgrf-site" target="_blank">Сube2</a>. Наиболее заметные изменения
сайта онлайн-типографа приводятся ниже в&nbsp;хронологическом порядке. Для&nbsp;полного списка изменений,
включая мелкие фиксы и&nbsp;коммиты, пожалуйста, обратитесь к&nbsp;истории репозитория.</p>
<h4>[0.2.8] - 2026–10–04</h4>
<h5>Добавлено</h5>
<ul>
<li>Локальная статика для&nbsp;внешних фронтенд-библиотек (Bootstrap&nbsp;5, Bootstrap Icons, HTMX, Alpine.js,
CodeMirror&nbsp;6) для&nbsp;работы интер&shy;фейса при&nbsp;недос&shy;тупности CDN.
</li>
<li>Стратегия fallback-подключения в&nbsp;шаблонах: автома&shy;тическое переклю&shy;чение на&nbsp;локальную
статику при&nbsp;сбое или&nbsp;блокировке CDN.
</li>
<li>Скрипт копиро&shy;вания production-ассетов <code>frontend-assembly/copy-vendor.js</code>
и&nbsp;обновление сборки через&nbsp;<code>frontend-assembly/assembly_via_npm.sh</code>.
</li>
<li>Автомати&shy;ческие тесты проверки наличия стати&shy;ческих вендорных ассетов и&nbsp;коррект&shy;ности
ренде&shy;ринга fallback-подключений в&nbsp;<code>typograph/tests.py</code>.
</li>
</ul>
<h5>Изменено</h5>
<ul>
<li>Обновлен и&nbsp;структу&shy;рирован <code>.gitignore</code> с&nbsp;подроб&shy;ными коммен&shy;тариями.</li>
</ul>
<h4>[0.2.7] - 2026–03–22</h4>
<h5>Изменено</h5>
<ul>
<li>Обновление всех пактов, включая <tt>etpgrf</tt> (v0.1.5&nbsp;→&nbsp;v0.1.6.post1).</li>
</ul>
<h4>Исправлено</h4>
<ul>
<li><code>canonical</code> для страниц учитывает https/http.</li>
</ul>
<h4>[0.2.6] - 2026–02–28</h4>
<h5>Изменено</h5>
<ul>
<li>Подключена новая версия библиотеки <tt>etpgrf</tt> (v0.1.4 → v0.1.5).</li>
</ul>
<h4>[0.2.5]&nbsp;— 2026–02–13</h4>
<h5>Добавлено</h5>
<ul>
<li>Редизайн списка постов в&nbsp;блоге: шахматный порядок, вертикальные разделители, улучшенная адаптивность
для&nbsp;мобильных
устройств.
</li>
<li>Поле <code>updated_at</code> (<em>Дата обновления</em>) в&nbsp;модели, админке, блогах, страницах, <tt>sitemaps.xml</tt>
и&nbsp;микро&shy;разметке <tt>Schema.org</tt> для&nbsp;улучшения <abbr
title="Search Engine Optimization / Поисковая оптимизация">SEO</abbr>, <abbr
title="Generative Engine Optimization / Оптимизацию для Генеративных нейросетей и ИИ-поисковиков">GEO</abbr>
и&nbsp;<abbr title="Large Language Model Optimization / Оптимизация под Большие Языковые Модели">LLMO</abbr>.
</li>
<li><tt>README.md</tt> с&nbsp;описанием проекта онлайн-типографа, его особенностей, технического стека и&nbsp;инструкциями
по&nbsp;установке и&nbsp;запуску.
</li>
<li>Отображение заголовков постов в&nbsp;списке админки без&nbsp;HTML-мнемоник (декоди&shy;рование <code>&amp;nbsp;</code>
и&nbsp;др.).
</li>
</ul>
<h5>Изменено</h5>
<ul>
<li>Исправлены ошибки в&nbsp;шаблоне <tt>post_list.html</tt> (и&nbsp;полностью переработан дизайн в&nbsp;целом).
<ul>
<li>Улучшено отображение даты и&nbsp;скрытие декоративных изображений в&nbsp;списке постов на&nbsp;мобильных
устройствах.
</li>
<li>Оптими&shy;зированы отступы и&nbsp;типографика в&nbsp;списке постов.</li>
</ul>
</li>
<li>Формирование <code>slug</code> из&nbsp;<code>title</code> при&nbsp;сохранении&nbsp;поста или страницы с&nbsp;исполь&shy;зованием
библиотеки <code>pytils</code> для&nbsp;трансли&shy;терации с&nbsp;очистикой от&nbsp;HTML-мнемоник и&nbsp;создания
<abbr title="Uniform Resource Locator / Унифицированный Указатель Ресурса">URL</abbr>-дружес&shy;твенных
строк.
</li>
<li>Дизайн и&nbsp;вёрстка страниц для&nbsp;постов блога и&nbsp;вспомо&shy;гательных страниц для&nbsp;мобильных
устройств (адаптивность, скрытие картинки-обложки).
</li>
</ul>
<h4>[0.2.4]&nbsp;— 2026–02–12</h4>
<h5>Добавлено</h5>
<ul>
<li>Микро&shy;разметка <code>Schema.org</code> (JSON-LD) для&nbsp;постов и&nbsp;страниц для&nbsp;улучшения
SEO и&nbsp;понимания контента поисковиками и&nbsp;ИИ.
</li>
<li>Файл <code>llms.txt</code> для&nbsp;предоста&shy;вления информации о&nbsp;сайте и&nbsp;API для&nbsp;больших
языковых моделей (<abbr title="Large Language Model">LLM</abbr>) в&nbsp;соответвиии со&nbsp;стандартом GEO
и&nbsp;LLMO.
</li>
<li>Кастомный фильтр <code>unescape</code> для&nbsp;очистки мета-тегов от&nbsp;HTML-сущностей и&nbsp;переводов
строк.
</li>
</ul>
<h5>Исправлено</h5>
<ul>
<li>Исправлена ошибка, при&nbsp;которой счетчик символов не&nbsp;обновлялся при&nbsp;восста&shy;новлении&nbsp;вкладки
из&nbsp;истории браузера.
</li>
<li>Исправлена ошибка экрани&shy;рования кавычек в&nbsp;<tt>JSON-LD</tt>, <tt>Title</tt>
и&nbsp;<tt>Description</tt>.
</li>
<li>В&nbsp;<code>docker-compose.yaml</code> додавлен перезапуск <code>watchtower</code> при&nbsp;его
остановке.
</li>
</ul>
<h4>[0.2.3]&nbsp;— 2026–02–11</h4>
<h5>Изменено</h5>
<ul>
<li>Добавлена кнопка очистки текста во&nbsp;вводном поле и&nbsp;счетчик вводимых символов.</li>
</ul>
<h4>[0.2.2]&nbsp;— 2026–02–03</h4>
<h5>Изменено</h5>
<ul>
<li>В&nbsp;онлайн-типографе подключена новая версия библиотеки <tt>etpgrf</tt> (v0.1.3 → v0.1.4).</li>
<li>Незначи&shy;тельные улучшения в&nbsp;оформлении.</li>
</ul>
<h4>v0.2.1&nbsp;— 2026–01–30</h4>
<h5>Исправлено</h5>
<ul>
<li>Исправление ошибок при&nbsp;формировании&nbsp;мета-тегов, картинок, <code>alt</code> под&nbsp;картинками
и&nbsp;т.&thinsp;п.
</li>
<li>Исправлена ошибка в&nbsp;настройках nginx внутри docker-контейнера возникавшая при&nbsp;отдаче
media-файлов.
</li>
</ul>
<h5>Изменено</h5>
<ul>
<li>При&nbsp;создании&nbsp;записи в&nbsp;блог или страницы «тизер» обязателен!</li>
</ul>
<h4>v0.2.0&nbsp;— 2026–01–28</h4>
<h5>Добавлено</h5>
<ul>
<li>Приложение blog (для&nbsp;страниц и&nbsp;постов) и&nbsp;соответ&shy;ствующие изменения в&nbsp;моделях базы,
добавление новых view и&nbsp;шаблонов.
</li>
<li>Песочница (шаблон <code>blog/templates/blog/tmp.html</code> для&nbsp;тестирования верстки (доступен только в&nbsp;режиме
debug).
</li>
<li>Динамическое создание sitemap.xml</li>
<li>robots.txt</li>
<li>Изменения в&nbsp;шапке сайта (меню и&nbsp;бургер)</li>
</ul>
<h5>Изменено</h5>
<ul>
<li>Спрятан <code>url</code> админки типографа. Его расположение теперь задается через&nbsp;переменные окружения
в&nbsp;<code>.env</code>.
</li>
<li><code>favicon.ico</code> оптими&shy;зирована для&nbsp;Яндекс (120х120px).</li>
<li>Исправлено поведение шапки и&nbsp;логотива для&nbsp;мобильных устройств.</li>
</ul>
<h4>v0.1.8&nbsp;— 2026–01–23</h4>
Коммит:
846c066
<h4>v0.1.7&nbsp;— 2026–01–23</h4>
Коммит:
d74bee2
<h4>v0.1.6&nbsp;— 2026–01–23</h4>
Коммит:
6b4dbaf
<h4>v0.1.5&nbsp;— 2026–01–21</h4>
Коммит:
78174a8
<h4>v0.1.4&nbsp;— 2026–01–20</h4>
Коммит:
2d09aef
<h4>v0.1.3&nbsp;— 2026–01–19</h4>
Коммит:
66f2228
<h4>v0.1.2&nbsp;— 2026–01–18</h4>
Коммит:
92711f5
<h4>v0.1.1&nbsp;— 2026–01–16</h4>v0.1.1
Коммит:
5d5d48d
<h4>v0.1.0&nbsp;— 2026–01–16</h4>
Коммит:
3a7bb29
</div>
<div class="col border-start">
<h3>Библиотека etpgrf</h3>
<p> <p>
<img src="{% static 'img/etpgrf-logo-for-fb-vk-x.gif' %}" class="w-100" alt="Django Admin" /> Исходный код etpgrf-типографа доступен в&nbsp;нескольких репози&shy;ториях (<a
</p> href="https://github.com/erjemin/etpgrf" target="_blank">GitHub</a>, <a
</div> href="https://gitverse.ru/erjemin/etpgrf" target="_blank">GitVerse</a>, <a
href="https://git.cube2.ru/erjemin/2025-etpgrf" target="_blank">Сube2</a>, и&nbsp;<a
{# Правая колонка: Контент #} href="https://pypi.org/project/etpgrf/" target="_blank">PyPI</a>), распрос&shy;траняется под&nbsp;лицензией <a
<div class="col-lg-10 border-start ps-lg-4 post-page-content"> href="https://opensource.org/licenses/MIT" target="_blank">MIT</a>, может быть установлен локально, на&nbsp;ваш
сайт или&nbsp;интегри&shy;рован в&nbsp;ваши проекты как&nbsp;Python-библиотека.</p>
<h1>Массовая типографика контента в&nbsp;Django: пользова&shy;тельские команды управления (Custom Management Commands)</h1>
<div class="lead bg-secondary bg-opacity-10 p-3 rounded">
<p>Если вы&nbsp;работали с&nbsp;Django, вы&nbsp;наверняка использовали команду <code>manage.py</code> сотни раз: <code>python manage.py runserver</code>, <code>migrate</code>, <code>createsuperuser</code>.</p>
<p>Но&nbsp;знаете&nbsp;ли вы, что можете легко создавать <strong>свои собственные</strong> команды? Это один из&nbsp;самых мощных и&nbsp;недоо&shy;цененных инструментов Django для&nbsp;автома&shy;тизации рутины. В&nbsp;этом посте я&nbsp;расскажу, что такое <strong>Management Command</strong>, зачем она нужна и&nbsp;как&nbsp;её использовать на&nbsp;примере реальной задачи: массовой типографики контента в&nbsp;базе данных.</p>
</div>
<hr>
<div class="post-content mt-4">
<h4>[0.1.6.post1] - 2026–03–19</h4> <h4>[0.1.6.post1] - 2026–03–19</h4>
<h5>Изменено</h5> <h5>Изменено</h5>
<ul> <ul>
<li>Новый алгоритм «висячей пунктуации» (<em>HangingPunctuationProcessor</em>). Добавлены компенси­рующие пробелы для висячих символов, чтобы избежать наложения на соседние слова. Теперь «висячие символы» (кавычки, скобки и т. п.) обора­чиваются в <code>&lt;span&gt;</code> вместе с ближайшим словом и пробелом, что обеспечивает отсутствие визуальных смещений внутри строки. Режим <code>both</code> (для одновре­менного вывешивания в обе стороны) отключен из-за потенци­альных конфликтов компенси­рующих пробелов и проблем с выравни­ванием при исполь­зовании CSS <code>text-justify</code>.</span></li> <li>Новый алгоритм «висячей пунктуации» (<em>HangingPunctuationProcessor</em>). Добавлены компенси­рующие
пробелы для висячих символов, чтобы избежать наложения на соседние слова. Теперь «висячие символы» (кавычки,
скобки и т. п.) обора­чиваются в <code>&lt;span&gt;</code> вместе с ближайшим словом и пробелом, что
обеспечивает отсутствие визуальных смещений внутри строки. Режим <code>both</code> (для одновре­менного
вывешивания в обе стороны) отключен из-за потенци­альных конфликтов компенси­рующих пробелов и проблем
с&nbsp;выравни&shy;ванием при&nbsp;исполь&shy;зовании&nbsp;CSS <code>text-justify</code>.</li>
</ul> </ul>
<h4>Исправлено</h4> <h4>Исправлено</h4>
<ul> <ul>
<li>Автоматическая замена символов <code>x</code>, <code>X</code>, <code>х</code>, <code>Х</code>, стоящих между числами, на&nbsp;знак умножения&nbsp;<code>×</code>, чтобы выражения вида <code>100x100</code> или <code>100&nbsp;х &nbsp;100` корректно обрабатывались и выглядели типографски правильными (<code>100×100</code> или <code>100&amp;nbsp;×&amp;nbsp;100</code>).</li> <li>Автоматическая замена символов <code>x</code>, <code>X</code>, <code>х</code>, <code>Х</code>, стоящих между
числами, на&nbsp;знак умножения&nbsp;<code>×</code>, чтобы выражения вида <code>100x100</code> или&nbsp;<code>100&nbsp;х&nbsp;100</code>
корректно обрабатывались и&nbsp;выглядели типографски правильными (<code>100×100</code> или&nbsp;<code>100&amp;nbsp;×&amp;nbsp;100</code>).
</li>
</ul> </ul>
## [0.1.6] - 2024-03-19 <h4>[0.1.5] - 2026–02–27</h4>
### Изменено <h5>Исправлено</h5>
- Н <ul>
### <li>Исправлена ошибка, из-за которой <code>&amp;amp;</code> в&nbsp;исходном тексте некорректно преобразовывался
- в&nbsp;<code>&amp;</code>. Теперь <code>&amp;amp;</code>; и&nbsp;его маскирование (<code>&amp;amp;amp;</code>,
<code>&amp;amp;lt;</code>&nbsp;и&nbsp;т.&thinsp;д.) сохраняются в&nbsp;итоговом HTML.
</li>
<li>Исправлена (частично) расстановка неразрывных пробелов <code>&amp;nbsp;</code> на&nbsp;границах закрывающих
тегов (например, <code>&lt;b&gt;Текст&lt;/b&gt; — слово</code> теперь корректно обрабатывается, в <code>&lt;b&gt;Текст&lt;/b&gt;&amp;nbsp;—
слово)</code>.
</li>
</ul>
<h4>[0.1.4] - 2026–02–03</h4>
<h5>Изменено</h5>
<ul>
<li><b>Архите&shy;ктурное улучшение:</b> Полностью переработан механизм обработки HTML.</li>
<li>Внедрены <b>маркеры границ узлов</b> (<code>\uFFFF</code>) при&nbsp;сборке текста. Это позволяет корректно
восста&shy;навливать структуру HTML даже если длина текста изменилась в&nbsp;процессе обработки (например, при&nbsp;удалении&nbsp;лишних
пробелов).
</li>
<li>Внедрены <b>плейсхолдеры</b> (<code>\uFFFC</code>) для&nbsp;защищенных тегов (<code>&lt;code&gt;</code>,
<code>&lt;script&gt;</code> и&nbsp;др.). Теперь содержимое этих тегов физически изолируется перед&nbsp;обработкой,
что предот&shy;вращает «протекание» контекста (например, склеивание слов, разделенных кодом).
</li>
</ul>
<h5>Исправлено</h5>
<ul>
<li>Исправлена ошибка смещения текста при&nbsp;наличии спецсимволов (мнемоник) или при&nbsp;изменении&nbsp;длины
строки.
</li>
<li>Исправлена обработка кавычек, стоящих вплотную к&nbsp;границам тегов (например, <code>"&lt;b&gt;Текст&lt;/b&gt;"</code>).
</li>
</ul>
<h4>v0.1.3&nbsp;— 2026–01–11</h4>
<h5>Исправлено</h5>
<ul>
<li>Исправлена проблема с&nbsp;появлением лишних тегов <code>&lt;html&gt;</code>
и&nbsp;<code>&lt;body&gt;</code> при&nbsp;обработке фрагментов HTML (когда исполь&shy;зуется парсер
<code>lxml</code>). Теперь типограф автома&shy;тически определяет, был&nbsp;ли на&nbsp;входе полноценный
документ или&nbsp;фрагмент, и&nbsp;возвращает соответ&shy;ствующий результат.
</li>
</ul>
<h4>v0.1.2&nbsp;— 2025–12–27</h4>
<h5>Исправлено</h5>
<ul>
<li><strong>Критическое исправление:</strong> Добавлена отсут&shy;ствующая зависимость <code>regex</code> в&nbsp;<code>pyproject.toml</code>.
Без&nbsp;неё библиотека падала при&nbsp;импорте.
</li>
</ul>
<h4>v0.1.1&nbsp;— 2025–12–23</h4>
<h5>Добавлено</h5>
<ul>
<li>Ссылки на&nbsp;зеркала репозитория (GitVerse, Gitea) в&nbsp;<code>pyproject.toml</code> и&nbsp;<code>README.md</code>.
</li>
<li>Раздел Credits в&nbsp;документации.</li>
</ul>
<h4>v0.1.0&nbsp;— 2025–12–23</h4>
<h5>Добавлено</h5>
<ul>
<li>Первый публичный релиз библиотеки <code>etpgrf</code>.</li>
<li>
Основные модули:
<ul>
<li><code>Typographer</code>: основной класс-оркестратор.</li>
<li><code>Hyphenator</code>: расстановка мягких переносов (алгоритм Ляна-Кнута).</li>
<li><code>QuotesProcessor</code>: замена кавычек («ёлочки», „лапки“).</li>
<li><code>Unbreakables</code>: неразрывные пробелы для&nbsp;предлогов, союзов и&nbsp;частиц.</li>
<li><code>LayoutProcessor</code>: типографика тире, инициалов, акронимов, единиц измерения, устойчивых
сокращений (постпо&shy;зиционных и&nbsp;препози&shy;ционных).</li>
<li><code>SymbolsProcessor</code>: псевдо&shy;графика (тире, стрелочки, копирайт и&nbsp;т.&thinsp;п.)</li>
<li><code>HangingPunctuationProcessor</code>: висячая пунктуация.</li>
<li><code>SanitizerProcessor</code>: очистка HTML перед&nbsp;обработкой.</li>
</ul>
</li>
<li>Поддержка русского, русского дорефо&shy;рменного и&nbsp;английского языков.</li>
<li>Поддержка обработки HTML (через&nbsp;BeautifulSoup).</li>
</ul>
</div> </div>
</div>
{% endblock %} {% endblock %}
+2 -1
View File
@@ -4,10 +4,11 @@ from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
from django.contrib.sitemaps.views import sitemap # Импортируем view для sitemap from django.contrib.sitemaps.views import sitemap # Импортируем view для sitemap
from blog import views as blog_views from blog import views as blog_views
from blog.sitemaps import PostSitemap # Импортируем наш класс Sitemap from blog.sitemaps import PostSitemap, StaticViewSitemap # Импортируем классы Sitemap
# Словарь с картами сайта # Словарь с картами сайта
sitemaps = { sitemaps = {
'static': StaticViewSitemap,
'posts': PostSitemap, 'posts': PostSitemap,
} }
@@ -3,25 +3,25 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
{# SEO & Meta Tags #}<title>{% block title %}ETPGRF — единая типографика для веба{% endblock %}</title> {# SEO & Meta Tags #}<title>{% block title %}Онлайн-типограф для текста и HTML — ETPGRF{% endblock %}</title>
<meta name="description" content="{% block description %}Бесплатный онлайн-типограф для подготовки текстов к публикации в вебе. Расставка неразрывных пробелов, правильных кавычек («ёлочки»), тире, спецсимволы, отбивка, компоновка, висячая пунктуация. Идеально для верстки сайтов, статей и постов.{% endblock %}"> <meta name="description" content="{% block description %}Онлайн-типограф для подготовки HTML и публикаций на русском и английском: кавычки «ёлочки» и “лапки”, длинное тире, неразрывные пробелы (&amp;nbsp;), отбивка предлогов, артиклей и чисел, висячая пунктуация…{% endblock %}">
<meta name="keywords" content="{% block keywords %}типограф, типографика, онлайн типограф, подготовка текста для веба, html типограф, неразрывные пробелы, кавычки елочки, длинное тире, очистка текста от мусора, интернет верстка, муравьев{% endblock %}"> <meta name="keywords" content="{% block keywords %}онлайн типограф, типографика онлайн, типограф для текста, html типограф, неразрывные пробелы, кавычки елочки, длинное тире, подготовка текста для веба, висячая пунктуация, python etpgrf, типограф лебедева муравьева{% endblock %}">
<meta name="author" content="Sergei Erjemin"> <meta name="author" content="Sergei Erjemin">
{# Schema.org (JSON-LD) #}{% block schema %}{% endblock %} {# Schema.org (JSON-LD) #}{% block schema %}{% endblock %}
{# Open Graph (Facebook, VK, LinkedIn, Telegram) #}<meta property="og:type" content="website" /> {# Open Graph (Facebook, VK, LinkedIn, Telegram) #}<meta property="og:type" content="website" />
<meta property="og:site_name" content="ETPGRF" /> <meta property="og:site_name" content="ETPGRF" />
<meta property="og:url" content="{{ request.build_absolute_uri }}" /> <meta property="og:url" content="{% block og_url %}{{ request.scheme }}://{{ request.get_host }}{{ request.path }}{% endblock %}" />
<meta property="og:title" content="{% block og_title %}ETPGRF — единая типографика для веба{% endblock %}" /> <meta property="og:title" content="{% block og_title %}Онлайн-типограф для текста и HTML — ETPGRF{% endblock %}" />
<meta property="og:description" content="{% block og_description %}Сделайте ваш текст профессиональным и готовым к публикации в интернете за один клик. Умная типографика для веб-дизайнеров, редакторов и контент-менеджеров.{% endblock %}" /> <meta property="og:description" content="{% block og_description %}Бесплатный онлайн-типограф для подготовки текстов и HTML к публикации: кавычки «ёлочки», неразрывные пробелы, длинное тире и висячая пунктуация.{% endblock %}" />
<meta property="og:image" content="{% block og_image %}{{ request.scheme }}://{{ request.get_host }}{% static 'img/etpgrf-logo-for-fb-vk-x.gif' %}{% endblock %}" /> <meta property="og:image" content="{% block og_image %}{{ request.scheme }}://{{ request.get_host }}{% static 'img/etpgrf-logo-for-fb-vk-x.gif' %}{% endblock %}" />
<meta property="og:image:width" content="1200" /> <meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" /> <meta property="og:image:height" content="630" />
{# --- Twitter Cards (X) --- #}<meta name="twitter:card" content="summary_large_image"> {# --- Twitter Cards (X) --- #}<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{% block twitter_title %}ETPGRF — единая типографика для веба{% endblock %}" /> <meta name="twitter:title" content="{% block twitter_title %}Онлайн-типограф для текста и HTML — ETPGRF{% endblock %}" />
<meta name="twitter:description" content="{% block twitter_description %}Сделайте ваш текст профессиональным и готовым к публикации в интернете за один клик.{% endblock %}" /> <meta name="twitter:description" content="{% block twitter_description %}Бесплатный онлайн-типограф для подготовки текстов и HTML к публикации в вебе.{% endblock %}" />
<meta name="twitter:image" content="{% block twitter_image %}{{ request.scheme }}://{{ request.get_host }}{% static 'img/etpgrf-logo-for-fb-vk-x.gif' %}{% endblock %}" /> <meta name="twitter:image" content="{% block twitter_image %}{{ request.scheme }}://{{ request.get_host }}{% static 'img/etpgrf-logo-for-fb-vk-x.gif' %}{% endblock %}" />
{# Шутка #}<meta name="generator" content="Microsoft FrontPage 1.0"/> {# Шутка #}<meta name="generator" content="Microsoft FrontPage 1.0"/>
{# Canonical #}<link rel="canonical" href="{{ request.build_absolute_uri }}"/> {# Canonical #}<link rel="canonical" href="{% block canonical %}{{ request.scheme }}://{{ request.get_host }}{{ request.path }}{% endblock %}"/>
{# Favicons #}<link rel="icon" href="{{ request.scheme }}://{{ request.get_host }}{% static 'favicon.ico' %}" type="image/x-icon" /> {# Favicons #}<link rel="icon" href="{{ request.scheme }}://{{ request.get_host }}{% static 'favicon.ico' %}" type="image/x-icon" />
{# Favicons #}<link rel="icon" type="image/png" href="{% static 'favicon-96x96.png' %}" /> {# Favicons #}<link rel="icon" type="image/png" href="{% static 'favicon-96x96.png' %}" />
{# Favicons #}<link rel="icon" href="{% static 'favicon-light.svg' %}" type="image/svg+xml" media="(prefers-color-scheme: light)" /> {# Favicons #}<link rel="icon" href="{% static 'favicon-light.svg' %}" type="image/svg+xml" media="(prefers-color-scheme: light)" />
@@ -1,11 +1,11 @@
{% extends 'typograph/base.html' %} {% extends 'typograph/base.html' %}
{% load static %} {% load static %}
{% block title %}ETPGRF — единая типографика для веба{% endblock %} {% block title %}Онлайн-типограф для текста и HTML — ETPGRF: кавычки «ёлочки», тире, неразрывные пробелы{% endblock %}
{% block description %}Бесплатный онлайн-типограф для подготовки публикаций в вебе: кавычки «ёлочки», тире, неразрывные пробелы, спецсимволы, отбивка/компоновка, висячая пунктуация… Идеально для верстки сайтов, статей и постов.{% endblock %} {% block og_title %}Онлайн-типограф для текста и HTML — ETPGRF{% endblock %}
{% block keywords %}типограф, типографика, онлайн типограф, подготовка текста для веба, html типограф, неразрывные пробелы, кавычки елочки, длинное тире, очистка текста от мусора, интернет верстка, муравьев{% endblock %} {% block og_description %}Бесплатный умный онлайн-типограф для подготовки текстов, статей и верстки к публикации в вебе за один клик.{% endblock %}
{% block content %} {% block content %}
<div class="row"> <div class="row">
@@ -13,7 +13,7 @@
{# SEO-текст и описание #} {# SEO-текст и описание #}
<div class="mb-4"> <div class="mb-4">
<h1 class="h3 mb-3">Онлайн-типограф для веба</h1> <h1 class="h3 mb-3">Онлайн-типограф для текста и веб-публикаций</h1>
<p> <p>
Интернет-типограф <strong>etpgrf</strong>&nbsp;— инструмент для&nbsp;подготовки текста для&nbsp;публикации Интернет-типограф <strong>etpgrf</strong>&nbsp;— инструмент для&nbsp;подготовки текста для&nbsp;публикации
в&nbsp;вебе. Расстановка неразрывных пробелов перед&nbsp;союзами и&nbsp;предлогами, замена кавычек в&nbsp;вебе. Расстановка неразрывных пробелов перед&nbsp;союзами и&nbsp;предлогами, замена кавычек
@@ -298,6 +298,192 @@
<div id="cm-result-wrapper" class="result-box p-0"></div> <div id="cm-result-wrapper" class="result-box p-0"></div>
<div id="result-area" style="display: none;"></div> <div id="result-area" style="display: none;"></div>
</div> </div>
{# ИНФОРМАЦИОННЫЙ И SEO-БЛОК #}
<div class="col-md-12 mt-4 pt-3 border-top">
<div class="text-center mb-3">
<button class="btn btn-sm btn-outline-secondary rounded-pill px-3 py-1 shadow-sm collapse-toggle-btn collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#seoDetailsCollapse"
aria-expanded="false"
aria-controls="seoDetailsCollapse">
<i class="bi bi-info-circle me-1"></i> О&nbsp;сервисе, возможности и&nbsp;правила
<i class="bi bi-chevron-down ms-1 collapse-icon"></i>
</button>
</div>
<div class="collapse" id="seoDetailsCollapse">
<section class="mb-5 pt-3">
<h2 class="h4 mb-4">Возможности онлайн-типографа etpgrf</h2>
<div class="row g-4">
<div class="col-md-6 col-lg-4">
<div class="p-3 border rounded bg-body-tertiary h-100 feature-card">
<h3 class="h6 fw-bold"><i class="bi bi-distribute-horizontal me-1"></i> Неразрывные пробелы (&amp;nbsp;)</h3>
<p class="small text-muted mb-0">
Автоматическая привязка предлогов, союзов, частиц (&laquo;в&raquo;, &laquo;на&raquo;, &laquo;с&raquo;, &laquo;и&raquo;, &laquo;не&raquo;, &laquo;бы&raquo;…) и&nbsp;артиклей (&bdquo;the&ldquo;, &bdquo;a&ldquo;, &bdquo;is&ldquo;…). Парсер &laquo;видит&raquo; и&nbsp;связывает их&nbsp;со&nbsp;словами даже сквозь кавычки и&nbsp;скобки (например, <code>и&amp;nbsp;&laquo;Беда&raquo; села на&nbsp;мель</code>).
</p>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="p-3 border rounded bg-body-tertiary h-100 feature-card">
<h3 class="h6 fw-bold"><i class="bi bi-quote me-1"></i> Кавычки «ёлочки» и&nbsp;„лапки“</h3>
<p class="small text-muted mb-0">
Замена машинных прямых кавычек (<code>&quot;</code>) на&nbsp;правильные русские &laquo;ёлочки&raquo; и&nbsp;французские &bdquo;лапки&ldquo; для&nbsp;вложенных цитат. Поддержка английской, современной русской и&nbsp;русской дореформенной типографики (&laquo;безъ&raquo;, &laquo;въ&raquo;, &laquo;надъ&raquo;, &laquo;сiя&raquo;…).
</p>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="p-3 border rounded bg-body-tertiary h-100 feature-card">
<h3 class="h6 fw-bold"><i class="bi bi-dash-lg me-1"></i> Тире, числа и&nbsp;диапазоны</h3>
<p class="small text-muted mb-0">
Замена дефисов на&nbsp;длинное тире (&mdash;) с&nbsp;языковой отбивкой, среднее тире (&ndash;) в&nbsp;числовых интервалах (1941&ndash;1945, 10&ndash;20&nbsp;кг). Корректная обработка арабских и&nbsp;римских чисел (например, XXI&nbsp;век, III&nbsp;в.&nbsp;н.&nbsp;э.).
</p>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="p-3 border rounded bg-body-tertiary h-100 feature-card">
<h3 class="h6 fw-bold"><i class="bi bi-person-badge me-1"></i> Инициалы и&nbsp;сокращения</h3>
<p class="small text-muted mb-0">
Связывание неразрывными пробелами инициалов (А.С.&nbsp;Пушкин), устойчивых сокращений (ЗАО&nbsp;&laquo;Рога и&nbsp;Копыта&raquo;, др.&nbsp;Барменталь), сокращений (&laquo;и&nbsp;т.д.&raquo;, &laquo;и&nbsp;др.&raquo;), знаков (&sect;&nbsp;5, &#8470;&nbsp;12) и&nbsp;единиц (100&nbsp;руб., 50&nbsp;м&sup2;).
</p>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="p-3 border rounded bg-body-tertiary h-100 feature-card">
<h3 class="h6 fw-bold"><i class="bi bi-layout-text-sidebar me-1"></i> Висячая пунктуация</h3>
<p class="small text-muted mb-0">
Оптическое выравнивание левого и&nbsp;правого края текстового блока за&nbsp;счет выноса кавычек, скобок и&nbsp;тире за&nbsp;границу полосы набора. Идеально для&nbsp;крупных заголовков, цитат, выносов и&nbsp;врезок.
</p>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="p-3 border rounded bg-body-tertiary h-100 feature-card">
<h3 class="h6 fw-bold"><i class="bi bi-shield-check me-1"></i> Санитайзер и&nbsp;спецсимволы</h3>
<p class="small text-muted mb-0">
Встроенный HTML-санитайзер: очистка текста от&nbsp;мусорных тегов при&nbsp;копировании из&nbsp;Word/Google Docs, сброс разметки висячей пунктуации. Обработка псевдографики (<code>(c)</code>&nbsp;&rarr;&nbsp;&copy;, <code>(tm)</code>&nbsp;&rarr;&nbsp;&trade;, <code>+/-</code>&nbsp;&rarr;&nbsp;&plusmn;).
</p>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="p-3 border rounded bg-body-tertiary h-100 feature-card">
<h3 class="h6 fw-bold"><i class="bi bi-fonts me-1"></i> Переносы в&nbsp;словах</h3>
<p class="small text-muted mb-0">
Автоматическая расстановка мягких переносов (<code>&amp;shy;</code>) в&nbsp;длинных словах с&nbsp;настраиваемым порогом длины (от&nbsp;12&nbsp;символов). Колонки текста аккуратно перено&shy;сятся в&nbsp;узких блоках и&nbsp;на&nbsp;мобильных экранах без&nbsp;разрыва вёрстки.
</p>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="p-3 border rounded bg-body-tertiary h-100 feature-card">
<h3 class="h6 fw-bold"><i class="bi bi-code-slash me-1"></i> Форматы вывода и&nbsp;гибкие правила</h3>
<p class="small text-muted mb-0">
Поддержка HTML с&nbsp;мнемониками, смешанного режима и&nbsp;Unicode (UTF-8) для&nbsp;постов в&nbsp;соцсетях (VK, Telegram, Reddit). Любые группы правил можно гибко комбинировать, включать или&nbsp;отключать под&nbsp;конкретную задачу или&nbsp;проект.
</p>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="p-3 border rounded bg-body-tertiary h-100 feature-card">
<h3 class="h6 fw-bold"><i class="bi bi-infinity me-1"></i> Бесплатно и&nbsp;безлимитно</h3>
<p class="small text-muted mb-0">
Полная свобода использования без&nbsp;ограничений по&nbsp;объёму текста, без&nbsp;регистрации, подписок и&nbsp;рекламы. Доступен как&nbsp;онлайн-сервис, так и&nbsp;в&nbsp;виде открытой библиотеки для&nbsp;Python по&nbsp;лицензии MIT.
</p>
</div>
</div>
</div>
</section>
<hr />
<section class="mb-5">
<h2 class="h4 mb-3">Кому подходит типограф ETPGRF</h2>
<div class="row g-3">
<div class="col-md-4">
<div class="border-start border-3 border-secondary ps-3">
<h3 class="h6 fw-bold">Контент-менеджерам и&nbsp;дизайнерам</h3>
<p class="small text-muted">
Профессиональный визуальный ритм и&nbsp;читаемость текста в&nbsp;веб-интерфейсах, блогах, SMM-публикациях в&nbsp;соцсетях и&nbsp;электронных рассылках.
</p>
</div>
</div>
<div class="col-md-4">
<div class="border-start border-3 border-secondary ps-3">
<h3 class="h6 fw-bold">Веб-разработчикам и&nbsp;верстальщикам</h3>
<p class="small text-muted">
Получайте чистый, валидный HTML-код с&nbsp;неразрывными пробелами и&nbsp;мнемониками, готовый к&nbsp;вставке в&nbsp;шаблоны, CMS и&nbsp;лендинги.
</p>
</div>
</div>
<div class="col-md-4">
<div class="border-start border-3 border-secondary ps-3">
<h3 class="h6 fw-bold">Редакторам и&nbsp;копирайтерам</h3>
<p class="small text-muted">
Быстрая автоматическая подготовка статей, колонок и&nbsp;постов для&nbsp;публикации без&nbsp;рутинной ручной расстановки спецсимволов.
</p>
</div>
</div>
</div>
</section>
<hr />
<section class="mb-5">
<h2 class="h4 mb-3">Интеграция в&nbsp;проекты: Python-библиотека etpgrf</h2>
<p class="small text-muted">
Вы&nbsp;можете свободно использовать движок etpgrf-типографа офлайн в&nbsp;своих Python-скриптах, Django-, FastAPI- или&nbsp;Flask-приложениях и&nbsp;сайтах:
</p>
<div class="bg-body-tertiary p-3 rounded border font-monospace small mb-3">
<div class="text-secondary mb-1"># Установка через pip:</div>
<div class="text-success fw-bold mb-3">pip install etpgrf</div>
<div class="text-secondary mb-1"># Пример использования в коде:</div>
<div><span class="text-primary">from</span> etpgrf.main <span class="text-primary">import</span> Typographer</div>
<div class="mt-1">tp = Typographer(lang=<span class="text-success">'ru'</span>, mode=<span class="text-success">'mixed'</span>)</div>
<div>formatted_html = tp.process(<span class="text-success">'Правильная вёрстка "кавычек" и отбивка тире -- улучшают читаемость текста на сайте!'</span>)</div>
</div>
<p class="small text-muted mb-0">
Подробная документация и&nbsp;исходный код библиотеки открыты на&nbsp;<a href="https://github.com/erjemin/etpgrf" target="_blank" rel="noopener">GitHub</a> и&nbsp;<a href="https://pypi.org/project/etpgrf/" target="_blank" rel="noopener">PyPI</a>.
</p>
</section>
<hr />
<section class="mb-5">
<h2 class="h4 mb-3">Часто задаваемые вопросы (FAQ)</h2>
<div class="accordion" id="faqAccordion">
<div class="accordion-item bg-body-tertiary">
<h3 class="accordion-header" id="faqHeadingOne">
<button class="accordion-button collapsed bg-body-tertiary" type="button" data-bs-toggle="collapse" data-bs-target="#faqOne" aria-expanded="false" aria-controls="faqOne">
Зачем типографировать текст перед публикацией на сайте?
</button>
</h3>
<div id="faqOne" class="accordion-collapse collapse" aria-labelledby="faqHeadingOne" data-bs-parent="#faqAccordion">
<div class="accordion-body small text-muted">
В&nbsp;вебе строки переносятся динамически в&nbsp;зависимости от&nbsp;экрана устройства. Без&nbsp;неразрывных пробелов предлоги и&nbsp;союзы часто &laquo;висят&raquo; на&nbsp;концах строк, а&nbsp;дефисы путаются с&nbsp;длинным тире. Типографика делает текст легким для&nbsp;восприятия и&nbsp;профессиональным.
</div>
</div>
</div>
<div class="accordion-item bg-body-tertiary">
<h3 class="accordion-header" id="faqHeadingTwo">
<button class="accordion-button collapsed bg-body-tertiary" type="button" data-bs-toggle="collapse" data-bs-target="#faqTwo" aria-expanded="false" aria-controls="faqTwo">
Чем ETPGRF отличается от Типографа Студии Лебедева или Типографа Муравьёва?
</button>
</h3>
<div id="faqTwo" class="accordion-collapse collapse" aria-labelledby="faqHeadingTwo" data-bs-parent="#faqAccordion">
<div class="accordion-body small text-muted">
ETPGRF разработан на&nbsp;современной открытой кодовой базе Python 3, активно поддерживается, умеет корректно обрабатывать смешанные русско-английские тексты (ru+en), имеет гибкий выбор режима кодирования (Unicode/HTML-мнемоники), настраиваемую висячую пунктуацию и&nbsp;может работать как&nbsp;локальный модуль или веб-микросервис.
</div>
</div>
</div>
<div class="accordion-item bg-body-tertiary">
<h3 class="accordion-header" id="faqHeadingThree">
<button class="accordion-button collapsed bg-body-tertiary" type="button" data-bs-toggle="collapse" data-bs-target="#faqThree" aria-expanded="false" aria-controls="faqThree">
Сохраняются ли введённые тексты на сервере?
</button>
</h3>
<div id="faqThree" class="accordion-collapse collapse" aria-labelledby="faqHeadingThree" data-bs-parent="#faqAccordion">
<div class="accordion-body small text-muted">
Нет, сервис соблюдает полную конфиденциальность. Тексты обрабатываются исключительно в&nbsp;памяти в&nbsp;момент отправки запроса и&nbsp;не&nbsp;сохраняются в&nbsp;базу данных и&nbsp;логи.
</div>
</div>
</div>
</div>
</section>
</div>
</div>
</div> </div>
{% endblock %} {% endblock %}
+17
View File
@@ -100,3 +100,20 @@ class TypographViewsTestCase(TestCase):
"""Проверка эндпоинта сводной статистики.""" """Проверка эндпоинта сводной статистики."""
response = self.client.get(reverse('stats_summary')) response = self.client.get(reverse('stats_summary'))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_seo_metadata_and_sitemap(self):
"""Проверка мета-тегов на главной странице и генерации sitemap.xml."""
response = self.client.get(reverse('index'))
self.assertEqual(response.status_code, 200)
content = response.content.decode('utf-8')
self.assertIn('<title>Онлайн-типограф', content)
self.assertIn('name="description"', content)
self.assertIn('name="keywords"', content)
self.assertIn('rel="canonical"', content)
# Проверка sitemap.xml
sitemap_res = self.client.get('/sitemap.xml')
self.assertEqual(sitemap_res.status_code, 200)
sitemap_content = sitemap_res.content.decode('utf-8')
self.assertIn('<loc>', sitemap_content)
self.assertIn('http://testserver/', sitemap_content)
+41
View File
@@ -410,3 +410,44 @@ footer.footer a:hover {
border-right: 1px solid var(--bs-border-color) !important; border-right: 1px solid var(--bs-border-color) !important;
} }
} }
/* --- Карточки возможностей (hover-эффект без потери читаемости) --- */
.feature-card {
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
}
.feature-card:hover {
transform: translateY(-2px);
border-color: rgba(var(--bs-primary-rgb), 0.5) !important;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.09), 0 2px 6px rgba(0, 0, 0, 0.04);
}
[data-bs-theme="dark"] .feature-card:hover {
border-color: rgba(176, 190, 197, 0.5) !important;
background-color: rgba(255, 255, 255, 0.03) !important;
box-shadow: 0 6px 22px rgba(255, 255, 255, 0.15), 0 2px 8px rgba(255, 255, 255, 0.08);
}
@media (prefers-color-scheme: dark) {
:root:not([data-bs-theme="light"]) .feature-card:hover {
border-color: rgba(176, 190, 197, 0.5) !important;
background-color: rgba(255, 255, 255, 0.03) !important;
box-shadow: 0 6px 22px rgba(255, 255, 255, 0.15), 0 2px 8px rgba(255, 255, 255, 0.08);
}
}
/* --- Кнопка раскрытия информационного блока --- */
.collapse-toggle-btn {
font-size: 0.875rem;
font-weight: 500;
transition: all 0.2s ease-in-out;
}
.collapse-toggle-btn .collapse-icon {
display: inline-block;
transition: transform 0.25s ease-in-out;
}
.collapse-toggle-btn:not(.collapsed) .collapse-icon {
transform: rotate(180deg);
}