<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Markdown on kenji.blog</title><link>http://kenji.blog/ru/tags/markdown/</link><description>Recent content in Markdown on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ru</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 02:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ru/tags/markdown/index.xml" rel="self" type="application/rss+xml"/><item><title>Введение в генератор статических сайтов с использованием Hugo (руководство по миграции с WordPress)</title><link>http://kenji.blog/ru/p/hugo-static-site-generator-wordpress-migration/</link><pubDate>Sun, 13 Sep 2026 02:00:00 +0900</pubDate><guid>http://kenji.blog/ru/p/hugo-static-site-generator-wordpress-migration/</guid><description>&lt;img src="http://kenji.blog/p/hugo-static-site-generator-wordpress-migration/img/eyecatch.jpg" alt="Featured image of post Введение в генератор статических сайтов с использованием Hugo (руководство по миграции с WordPress)" />&lt;p>В современной веб-разработке и ведении блогов скорость загрузки сайта, его безопасность и простота обслуживания стали критически важными факторами. «WordPress», долгое время занимавший подавляющую долю рынка как основа для блогов и корпоративных сайтов, полюбился многим пользователям благодаря своей гибкой экосистеме плагинов и интуитивно понятной панели управления. Однако, поскольку он полагается на взаимодействие с базой данных и динамическую генерацию страниц на стороне сервера (обработка на PHP), он также подвержен уязвимостям при резком увеличении трафика и проблемам с задержками отображения (latency).&lt;/p>
&lt;p>Поэтому в последние годы стремительную популярность набирают «генераторы статических сайтов» (SSG: Static Site Generator). В этой статье мы подробно рассмотрим «&lt;strong>Hugo&lt;/strong>» — один из множества SSG, разработанный на языке Go и известный своей невероятной скоростью сборки. Мы досконально разберем всё: от сравнения технической архитектуры с динамическими CMS (Content Management System), такими как WordPress, до конкретных шагов по миграции, оценки производительности с использованием математических моделей, а также уникальной структуры каталогов Hugo и порядка поиска шаблонов.&lt;/p>
&lt;hr>
&lt;h2 id="1-технические-различия-между-динамическими-cms-wordpress-и-генераторами-статических-сайтов-hugo">1. Технические различия между динамическими CMS (WordPress) и генераторами статических сайтов (Hugo)
&lt;/h2>&lt;p>В механизмах доставки веб-сайтов WordPress и Hugo используют фундаментально разные подходы.&lt;/p>
&lt;h3 id="11-архитектура-wordpress-динамическая-генерация">1.1 Архитектура WordPress (Динамическая генерация)
&lt;/h3>&lt;p>WordPress — это типичный пример динамической CMS, которая собирает страницу на стороне сервера при каждом запросе. Когда пользователь (браузер) обращается к странице, веб-сервер (Apache, Nginx и т.д.) выполняет скрипт PHP и отправляет запрос к реляционной базе данных, такой как MySQL (или MariaDB). Полученный из базы данных контент (данные статей, категории, теги, настройки сайта и т.д.) объединяется с файлами шаблонов для генерации итогового HTML, который затем возвращается клиенту.&lt;/p>
&lt;p>Этот механизм имеет то преимущество, что позволяет генерировать различный контент для каждого посетителя в реальном времени (например, корзина в интернет-магазине или страницы только для авторизованных пользователей). Однако без правильно спроектированного механизма кэширования (обратный прокси-сервер, плагины и т.д.) он приводит к интенсивному потреблению ресурсов сервера.&lt;/p>
&lt;h3 id="12-архитектура-hugo-предварительная-генерация-во-время-сборки">1.2 Архитектура Hugo (Предварительная генерация во время сборки)
&lt;/h3>&lt;p>С другой стороны, Hugo, как следует из названия «генератор статических сайтов», генерирует контент не «во время запроса», а «во время сборки» (build time). Контент хранится не в базе данных, а в виде локальных файлов Markdown, которые версионируются с помощью Git или аналогичных систем.
Когда разработчик выполняет команду (&lt;code>hugo&lt;/code>), Hugo считывает файлы Markdown, подставляет данные в указанные HTML-шаблоны (файлы макетов) и генерирует набор готовых чистых файлов HTML/CSS/JS.&lt;/p>
&lt;p>Сгенерированный набор файлов (статические ресурсы) можно доставлять, просто разместив их в «средах статического хостинга», таких как Amazon S3, Cloudflare Pages, Netlify, Vercel или на простом сервере Nginx. Поскольку база данных и серверные языки (например, PHP) не требуются, риски безопасности (такие как SQL-инъекции или уязвимости PHP) резко снижаются, а скорость доставки максимизируется за счет кэширования на граничных узлах CDN (Content Delivery Network).&lt;/p>
&lt;p>Ниже на диаграмме Mermaid показаны различия в каждой из архитектур.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
subgraph WordPress[&amp;#34;Динамическая CMS (WordPress)&amp;#34;]
direction TB
Req1[&amp;#34;Запрос пользователя&amp;#34;] --&amp;gt; WebServer1[&amp;#34;Веб-сервер (Nginx/Apache)&amp;#34;]
WebServer1 --&amp;gt; PHP[&amp;#34;Среда выполнения PHP&amp;#34;]
PHP &amp;lt;--&amp;gt; DB[&amp;#34;База данных (MySQL)&amp;#34;]
PHP --&amp;gt; HTML1[&amp;#34;Генерация HTML&amp;#34;]
HTML1 --&amp;gt; Res1[&amp;#34;Возврат ответа&amp;#34;]
end
subgraph Hugo[&amp;#34;Генератор статических сайтов (Hugo)&amp;#34;]
direction TB
Dev[&amp;#34;Разработчик / CI/CD&amp;#34;] --&amp;gt; HugoBuild[&amp;#34;Процесс сборки Hugo&amp;#34;]
Markdown[&amp;#34;Файлы Markdown&amp;#34;] --&amp;gt; HugoBuild
Templates[&amp;#34;Шаблоны (HTML)&amp;#34;] --&amp;gt; HugoBuild
HugoBuild --&amp;gt; StaticFiles[&amp;#34;Статические файлы (HTML/CSS/JS)&amp;#34;]
StaticFiles --&amp;gt; CDN[&amp;#34;CDN / Статический хостинг&amp;#34;]
Req2[&amp;#34;Запрос пользователя&amp;#34;] --&amp;gt; CDN
CDN --&amp;gt; Res2[&amp;#34;Мгновенный возврат ответа&amp;#34;]
end
&lt;/pre>
&lt;hr>
&lt;h2 id="2-оценка-производительности-с-использованием-математических-моделей">2. Оценка производительности с использованием математических моделей
&lt;/h2>&lt;p>Одним из самых больших преимуществ перехода с WordPress на Hugo является улучшение производительности (скорости отображения). Чтобы понять это количественно, давайте выразим это с помощью простой математической модели.&lt;/p>
&lt;p>Время до завершения загрузки страницы (Load Time: $T_{load}$) можно в целом разделить на время ответа сервера (TTFB: Time To First Byte) и время, затрачиваемое браузером на рендеринг и получение ресурсов ($T_{render}$).&lt;/p>
$$ T_{load} = T_{ttfb} + T_{render} $$&lt;p>В случае динамической CMS (WordPress) $T_{ttfb}$ представляет собой сумму следующих компонентов: сетевой задержки ($T_{network}$), времени выполнения серверного скрипта ($T_{php}$) и времени обработки запросов к базе данных ($T_{db}$).&lt;/p>
$$ T_{ttfb\_wp} = T_{network} + T_{php} + T_{db} $$&lt;p>В условиях высокой концентрации доступа (при высокой нагрузке) $T_{php}$ и $T_{db}$ увеличиваются нелинейно, и вся система может стать узким местом. В математическом выражении мы можем наблюдать следующее ухудшение времени отклика по отношению к количеству запросов ($N$) (где $k$ — коэффициент накладных расходов на обработку):&lt;/p>
$$ T_{php}(N) \approx O(N^k), \quad T_{db}(N) \approx O(N^k) \quad \text{where } k > 1 $$&lt;p>С другой стороны, в архитектуре, объединяющей генератор статических сайтов (Hugo) и CDN, отсутствует динамическая обработка на стороне сервера (PHP и запросы к БД). Поскольку контент кэшируется на граничных серверах, распределенных по всему миру, $T_{ttfb}$ зависит исключительно от сетевой задержки от клиента до ближайшего граничного сервера ($T_{edge}$).&lt;/p>
$$ T_{ttfb\_hugo} = T_{edge} $$&lt;p>В результате выполняется условие $T_{edge} \ll (T_{network} + T_{php} + T_{db})$, и показатель TTFB кардинально сокращается до нескольких миллисекунд или десятков миллисекунд. Кроме того, даже при увеличении количества запросов $N$ время отклика остается практически постоянным ($O(1)$) благодаря функциям балансировки нагрузки граничных серверов.&lt;/p>
$$ \lim_{N \to \infty} T_{ttfb\_hugo}(N) \approx \text{Constant} $$&lt;p>В этом и заключается математическое обоснование того, почему Hugo (статические сайты) обладает чрезвычайной устойчивостью к всплескам трафика (например, при вирусном эффекте).&lt;/p>
&lt;hr>
&lt;h2 id="3-базовая-структура-и-принципы-работы-hugo">3. Базовая структура и принципы работы Hugo
&lt;/h2>&lt;p>Чтобы освоить Hugo, необходимо понять его уникальную структуру каталогов, а также концепции «Front Matter» и «Порядок поиска шаблонов» (Template Lookup Order).&lt;/p>
&lt;h3 id="31-подробное-объяснение-структуры-каталогов">3.1 Подробное объяснение структуры каталогов
&lt;/h3>&lt;p>При создании нового проекта Hugo (с помощью &lt;code>hugo new site mysite&lt;/code>) генерируется следующая структура каталогов:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">mysite/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── archetypes/ # Шаблоны для создания нового контента (заготовки Front Matter)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── assets/ # Файлы, обрабатываемые Hugo Pipes (SCSS/Sass, JavaScript и т.д.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── content/ # Фактический контент сайта (файлы Markdown). Служит заменой БД.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── data/ # Внешние данные и настройки, используемые на всем сайте (JSON, TOML, YAML, CSV и т.д.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── layouts/ # HTML-шаблоны, определяющие внешний вид сайта (используют Go html/template)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── public/ # Место вывода сгенерированных статических файлов после выполнения команды сборки
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── static/ # Статические файлы, публикуемые &amp;#34;как есть&amp;#34; (изображения, favicon, robots.txt и т.д.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── themes/ # Каталог для сторонних или собственных тем
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── hugo.toml # Файл конфигурации всего сайта (ранее основным был config.toml)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>В WordPress контент хранится в таблице &lt;code>wp_posts&lt;/code> MySQL, в то время как в Hugo всё управляется в виде текстовых файлов (преимущественно Markdown) в каталоге &lt;code>content/&lt;/code>. Это значительно упрощает версионирование контента с помощью Git.&lt;/p>
&lt;h3 id="32-управление-контентом-markdown-и-front-matter">3.2 Управление контентом: Markdown и Front Matter
&lt;/h3>&lt;p>Каждый файл статьи в Hugo имеет блок метаданных в самом верху, который называется «Front Matter», за которым следует основной текст (Markdown). Front Matter можно писать в форматах TOML, YAML или JSON, но чаще всего используется YAML.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Понимание таксономий в Hugo&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">date&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="ld">2026-09-13T10:00:00&lt;/span>&lt;span class="m">+09&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="m">00&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">draft&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">categories&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;Технические руководства&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">tags&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;Hugo&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;Go&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">aliases&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/old-category/hugo-taxonomy/&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">Здесь начинается основной текст. Он пишется на **Markdown**.&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">Мы объясним мощные возможности Hugo...&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Здесь стоит обратить внимание на ключ &lt;code>aliases&lt;/code>. При переходе с WordPress изменение постоянных ссылок (URL) будет иметь серьезные негативные последствия для SEO. Используя функцию алиасов в Hugo, достаточно указать старый URL, и Hugo автоматически сгенерирует HTML для перенаправления (переадресация через meta refresh). Это чрезвычайно удобно, так как избавляет от необходимости настраивать редиректы на стороне сервера (например, в .htaccess).&lt;/p>
&lt;h3 id="33-порядок-поиска-шаблонов-template-lookup-order">3.3 Порядок поиска шаблонов (Template Lookup Order)
&lt;/h3>&lt;p>Одной из мощных возможностей Hugo является его гибкий механизм поиска шаблонов (Template Lookup Order). При рендеринге определенной страницы Hugo осуществляет поиск по каталогам и именам файлов в определенном порядке, чтобы найти наиболее подходящий шаблон.&lt;/p>
&lt;p>Например, при рендеринге отдельной статьи (Single Page) &lt;code>content/post/hello-world.md&lt;/code> Hugo ищет файлы макетов примерно в следующем порядке:&lt;/p>
&lt;ol>
&lt;li>&lt;code>layouts/post/single.html&lt;/code>&lt;/li>
&lt;li>&lt;code>layouts/post/list.html&lt;/code> (Не ошибка, но обычно используется для списков)&lt;/li>
&lt;li>&lt;code>layouts/_default/single.html&lt;/code>&lt;/li>
&lt;li>&lt;code>themes/&amp;lt;THEME_NAME&amp;gt;/layouts/post/single.html&lt;/code>&lt;/li>
&lt;li>&lt;code>themes/&amp;lt;THEME_NAME&amp;gt;/layouts/_default/single.html&lt;/code>&lt;/li>
&lt;/ol>
&lt;p>Разработчики могут &lt;strong>переопределять (override)&lt;/strong> шаблоны темы, не изменяя исходный код темы напрямую, а просто создавая файл с тем же именем в каталоге &lt;code>layouts/&lt;/code> своего проекта. Это позволяет вносить собственные настройки, не мешая будущим обновлениям базовой темы.&lt;/p>
&lt;h3 id="34-таксономии-taxonomy">3.4 Таксономии (Taxonomy)
&lt;/h3>&lt;p>Система классификации, эквивалентная «Категориям» и «Тегам» в WordPress, в Hugo называется «Таксономией» (Taxonomy).
По умолчанию Hugo поддерживает таксономии &lt;code>categories&lt;/code> и &lt;code>tags&lt;/code>, но, отредактировав файл &lt;code>hugo.toml&lt;/code>, вы можете свободно добавлять пользовательские таксономии (например, &lt;code>series&lt;/code>, &lt;code>authors&lt;/code> и т.д.).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-toml" data-lang="toml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Пример hugo.toml&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">taxonomies&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">category&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;categories&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">tag&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;tags&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">series&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;series&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">author&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;authors&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Это позволяет упорядочивать контент и составлять списки по различным осям.&lt;/p>
&lt;hr>
&lt;h2 id="4-процесс-миграции-с-wordpress-на-hugo">4. Процесс миграции с WordPress на Hugo
&lt;/h2>&lt;p>Ключом к успешному переходу с WordPress на Hugo является то, насколько чисто вы сможете преобразовать динамический контент из базы данных в статические файлы (Markdown + Front Matter) с сохранением существующей структуры URL.&lt;/p>
&lt;p>Ниже показана типичная схема пайплайна миграции:&lt;/p>
&lt;pre class="mermaid">
flowchart LR
WPDB[&amp;#34;База данных WP&amp;#34;] --&amp;gt;|Плагин| Exporter[&amp;#34;Инструмент экспорта&amp;#34;]
Exporter --&amp;gt;| Извлечение текста, \nметаданных, изображений | ZipFile[&amp;#34;Zip-архив / Папка&amp;#34;]
ZipFile --&amp;gt;|Распаковка| MarkdownFiles[&amp;#34;Файлы Markdown \n(content/)&amp;#34;]
ZipFile --&amp;gt;|Распаковка| ImageFiles[&amp;#34;Изображения \n(static/wp-content/)&amp;#34;]
MarkdownFiles --&amp;gt; Formatting[&amp;#34;Проверка и форматирование \n(Исправление шорткодов)&amp;#34;]
Formatting --&amp;gt; Git[&amp;#34;Коммит в Git&amp;#34;]
&lt;/pre>
&lt;h3 id="41-извлечение-данных-и-преобразование-в-markdown">4.1 Извлечение данных и преобразование в Markdown
&lt;/h3>&lt;p>Для экспорта данных WordPress для использования в Hugo проще и надежнее всего использовать специальные плагины. Вот несколько типичных подходов:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Использование плагина Jekyll Exporter&lt;/strong>
Поскольку Hugo имеет очень схожую структуру данных с Jekyll (еще одним SSG), использование плагина «Jekyll Exporter» для WordPress является распространенной практикой. После установки и запуска этого плагина все записи и статические страницы конвертируются в файлы Markdown с Front Matter, которые можно загрузить в виде ZIP-архива вместе с изображениями.&lt;/li>
&lt;li>&lt;strong>Собственные скрипты с использованием WordPress API&lt;/strong>
Метод, при котором с помощью Python, Node.js и т.д. выполняются запросы к REST API WordPress (&lt;code>/wp-json/wp/v2/posts&lt;/code>), анализируются данные JSON и самостоятельно генерируются файлы Markdown. Этот метод эффективен для сайтов, интенсивно использующих сложные произвольные поля (например, ACF), с которыми плагины не могут справиться в полной мере.&lt;/li>
&lt;li>&lt;strong>Использование инструмента wp2hugo&lt;/strong>
Также существует подход с использованием инструментов командной строки (CLI), написанных на Go и т.д., для прямой конвертации из файла экспорта XML WordPress (WXR) в формат Hugo.&lt;/li>
&lt;/ol>
&lt;h3 id="42-сохранение-структуры-постоянных-ссылок-url">4.2 Сохранение структуры постоянных ссылок (URL)
&lt;/h3>&lt;p>Чтобы сохранить SEO-рейтинг, критически важно сохранить URL-адреса такими, какими они были во времена WordPress. Если в WordPress были настроены постоянные ссылки вида &lt;code>https://example.com/2026/09/13/my-post/&lt;/code>, необходимо указать аналогичную структуру постоянных ссылок в &lt;code>hugo.toml&lt;/code> для Hugo.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-toml" data-lang="toml">&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">permalinks&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">post&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;/:year/:month/:day/:slug/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>В качестве альтернативы можно принудительно зафиксировать URL-адреса, явно указав параметр &lt;code>url&lt;/code> во Front Matter для каждой статьи.
Кроме того, для страниц, чьи URL-адреса изменятся, следует настроить редиректы с помощью ранее упомянутого параметра &lt;code>aliases&lt;/code>.&lt;/p>
&lt;h3 id="43-конвертация-шорткодов">4.3 Конвертация шорткодов
&lt;/h3>&lt;p>Специфичные для WordPress шорткоды (например, &lt;code>[gallery]&lt;/code>, &lt;code>[caption]&lt;/code> или собственные коды различных плагинов) часто остаются в виде исходных строк при экспорте, поэтому требуется их обработка.
Их можно либо удалить все сразу с помощью скриптов замены (sed или Python), либо использовать мощную &lt;strong>функцию пользовательских шорткодов&lt;/strong> Hugo (путем создания собственных макетов в &lt;code>layouts/shortcodes/&lt;/code>), чтобы они корректно рендерились на стороне Hugo после миграции.&lt;/p>
&lt;hr>
&lt;h2 id="5-инструменты-cli-сборка-и-развертывание-в-hugo">5. Инструменты CLI, сборка и развертывание в Hugo
&lt;/h2>&lt;p>После завершения процесса миграции настало время собрать сайт с помощью Hugo и опубликовать его для всего мира. Поставляемый в виде бинарного файла на языке Go, Hugo может похвастаться удивительной скоростью, позволяющей собирать сайты из тысяч или даже десятков тысяч страниц всего за несколько секунд.&lt;/p>
&lt;h3 id="51-запуск-локального-сервера-разработки">5.1 Запуск локального сервера разработки
&lt;/h3>&lt;p>При написании статей или настройке дизайна необходимо запускать локальный сервер.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Команда запуска сервера разработки (используйте -D для включения черновиков)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">hugo server -D
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>После выполнения этой команды сайт будет доступен для предварительного просмотра по адресу &lt;code>http://localhost:1313/&lt;/code>. В Hugo встроена мощная функция «LiveReload»: как только вы отредактируете и сохраните файл Markdown, шаблон или CSS, экран браузера будет автоматически и мгновенно обновлен. Это делает процесс написания и разработки намного более комфортным, чем в панели администратора WordPress.&lt;/p>
&lt;h3 id="52-сборка-для-продакшена-и-оптимизация-производительности">5.2 Сборка для продакшена и оптимизация производительности
&lt;/h3>&lt;p>Чтобы сгенерировать статические файлы для развертывания в рабочей (продакшен) среде, просто введите команду &lt;code>hugo&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Выполнение сборки для продакшена. Опция --minify минимизирует HTML/CSS/JS&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">hugo --minify
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Эта команда выведет файлы всего сайта в каталог &lt;code>public/&lt;/code>. Добавление опции &lt;code>--minify&lt;/code> удаляет ненужные переносы строк и пробелы, еще больше сокращая размер файлов. Это напрямую способствует уменьшению сетевой задержки ($T_{network}$), описанной в математической модели ранее.&lt;/p>
&lt;h3 id="53-автоматизация-развертывания-cicd">5.3 Автоматизация развертывания (CI/CD)
&lt;/h3>&lt;p>Генерировать статические файлы каждый раз на локальном ПК и загружать их по FTP — неэффективно. В современной практике управления SSG лучшим подходом является создание среды CI/CD, в которой отправка (push) в репозиторий Git (например, на GitHub) служит триггером для автоматической сборки и развертывания.&lt;/p>
&lt;p>Например, базовая конфигурация (файл YAML) для развертывания на Cloudflare Pages или GitHub Pages с использованием GitHub Actions выглядит следующим образом:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Пример .github/workflows/hugo.yml&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Deploy Hugo site to GitHub Pages&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">push&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">branches&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;main&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">workflow_dispatch&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">permissions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">contents&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">read&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">pages&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">write&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">id-token&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">write&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">jobs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">build&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runs-on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ubuntu-latest&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">steps&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Checkout&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/checkout@v3&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">submodules&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">recursive&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Если темы управляются как подмодули&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">fetch-depth&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Setup Hugo&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">peaceiris/actions-hugo@v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">hugo-version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;latest&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">extended&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Build&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">hugo --minify&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Upload artifact&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/upload-pages-artifact@v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">path&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">./public&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">deploy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">github-pages&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">url&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">${{ steps.deployment.outputs.page_url }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runs-on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ubuntu-latest&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">needs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">build&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">steps&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Deploy to GitHub Pages&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">deployment&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/deploy-pages@v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>С такими настройками мы получаем автоматизированный пайплайн, в котором достаточно выполнить действие «написать статью в Markdown и отправить (push) на GitHub», и через несколько минут обновленный сайт будет опубликован в рабочей среде.&lt;/p>
&lt;hr>
&lt;h2 id="6-преимущества-seo-и-управления-после-миграции">6. Преимущества SEO и управления после миграции
&lt;/h2>&lt;p>Владельцы сайтов, завершившие переход с WordPress на Hugo, чаще всего отмечают три следующих существенных преимущества:&lt;/p>
&lt;h3 id="61-кардинальное-улучшение-скорости-сайта-и-показателей-core-web-vitals">6.1 Кардинальное улучшение скорости сайта и показателей Core Web Vitals
&lt;/h3>&lt;p>За счет устранения запросов к базе данных и рендеринга на стороне сервера время загрузки страницы сокращается до миллисекунд. Это напрямую приводит к значительному улучшению показателей «Core Web Vitals» (LCP, FID/INP, CLS), которые являются факторами ранжирования Google. Можно ожидать снижения показателя отказов пользователей и улучшения позиций в SEO.&lt;/p>
&lt;h3 id="62-освобождение-от-угроз-безопасности">6.2 Освобождение от угроз безопасности
&lt;/h3>&lt;p>Поскольку WordPress широко используется по всему миру, он постоянно является мишенью для атак. Всегда существуют риски взлома через уязвимости плагинов или обхода формы входа в систему с помощью атак методом перебора (brute force).
Однако статические сайты, сгенерированные с помощью Hugo, не имеют ни базы данных, ни среды PHP, ни даже панели управления (формы входа). У хакеров нет возможности проникнуть на сервер и изменить базу данных, поэтому риски безопасности сводятся практически к нулю.&lt;/p>
&lt;h3 id="63-эксплуатация-не-требующая-обслуживания">6.3 Эксплуатация, не требующая обслуживания
&lt;/h3>&lt;p>Эксплуатация WordPress требует постоянного обслуживания: обновления ядра, обновления плагинов, перехода на новые версии PHP и т.д. Вам всегда приходится опасаться риска того, что сайт сломается из-за проблем с совместимостью.
В случае с Hugo достаточно обновлять сам инструмент по мере необходимости, а код сайта представляет собой набор независимых текстовых файлов. Это дает подавляющее чувство уверенности в том, что «сайт не сломается, даже если его оставить в покое».&lt;/p>
&lt;hr>
&lt;h2 id="7-заключение">7. Заключение
&lt;/h2>&lt;p>В этой статье мы подробно рассмотрели переход с динамических CMS, таких как WordPress, на мощный генератор статических сайтов «Hugo» на базе языка Go: от различий в технической архитектуре и математического доказательства производительности до конкретных шагов по миграции.&lt;/p>
&lt;p>Хотя переход на генераторы статических сайтов требует начальных затрат на обучение (работа с Git, синтаксис Markdown, выполнение команд CLI из терминала, понимание спецификаций шаблонизатора и т.д.), он приносит отдачу в виде «подавляющей скорости загрузки», «надежной безопасности» и «отсутствия необходимости в обслуживании», которая с лихвой окупает эти затраты.&lt;/p>
&lt;p>Если вашему веб-сайту не требуются частые изменения дизайна или сложная динамическая обработка (например, функции только для зарегистрированных пользователей или продвинутые функции интернет-магазина), и он предназначен в первую очередь для распространения информации (блог, медиа, корпоративный сайт), то переход на Hugo станет одной из самых эффективных технических инвестиций. Обязательно воспользуйтесь этой статьей как руководством и сделайте первый шаг к управлению веб-сайтами нового поколения с использованием Hugo.&lt;/p></description></item><item><title>Технический блог на Markdown: Настройки редактора, удваивающие скорость написания</title><link>http://kenji.blog/ru/p/markdown-editor-setup-for-tech-blogs/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/ru/p/markdown-editor-setup-for-tech-blogs/</guid><description>&lt;img src="http://kenji.blog/p/markdown-editor-setup-for-tech-blogs/img/eyecatch.jpg" alt="Featured image of post Технический блог на Markdown: Настройки редактора, удваивающие скорость написания" />&lt;p>Для постоянного ведения технического блога оптимизация среды для написания является абсолютно необходимой. В этой статье мы подробно рассмотрим расширенные настройки редактора, которые радикально повысят скорость написания технических статей с использованием Markdown. Мы всесторонне обсудим максимальную кастомизацию Visual Studio Code (VS Code) и Neovim, использование сниппетов, внедрение инструмента проверки грамматики &lt;code>textlint&lt;/code>, автоматизацию через CI/CD-пайплайны, а также передовые методы написания с применением LLM, таких как GitHub Copilot.&lt;/p>
&lt;h2 id="1-математическая-модель-повышения-скорости-написания">1. Математическая модель повышения скорости написания
&lt;/h2>&lt;p>Давайте сначала смоделируем с помощью простой математической формулы, насколько оптимизация настроек редактора влияет на время написания. Пусть общее время ввода для написания одной статьи в блоге будет $T_{total}$.&lt;/p>
$$
T_{total} = T_{think} + T_{type} + T_{format} + T_{review}
$$&lt;p>Где $T_{think}$ — это время на обдумывание, $T_{type}$ — время на набор текста, $T_{format}$ — время на форматирование (например, Markdown), а $T_{review}$ — время на редактирование и вычитку.&lt;/p>
&lt;p>Сэкономленное время $T_{saved}$ за счет кастомизации редактора (например, внедрения сниппетов или настроек Linter&amp;rsquo;а) можно выразить следующим образом, используя количество появлений определенного паттерна $N$ (например, шорткодов Hugo или таблиц Markdown), время ручного ввода $t_{manual}$ и время при автоматизации через сниппеты $t_{snippet}$:&lt;/p>
$$
T_{saved} = \sum_{i=1}^{k} N_i \times (t_{manual, i} - t_{snippet, i}) + T_{review\_saved}
$$&lt;p>Кроме того, благодаря внедрению автоматических форматеров и инструментов Lint&amp;rsquo;инга, время, затрачиваемое на визуальную проверку человеком $T_{review}$, значительно сокращается. Максимизация этого значения $T_{saved}$ и является целью данной статьи.&lt;/p>
&lt;h2 id="2-ультимативные-настройки-visual-studio-code-vs-code">2. Ультимативные настройки Visual Studio Code (VS Code)
&lt;/h2>&lt;p>VS Code — один из самых популярных редакторов на сегодняшний день, обладающий мощной экосистемой расширений для написания в Markdown.&lt;/p>
&lt;h3 id="рекомендуемые-расширения">Рекомендуемые расширения
&lt;/h3>&lt;p>Для ускорения процесса написания мы настоятельно рекомендуем установить следующие расширения:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Markdown All in One&lt;/strong>: Предоставляет все основные функции, необходимые для написания в Markdown, такие как выделение жирным/курсивом с помощью горячих клавиш, автоматическое продолжение списков и автоматическая генерация оглавления (TOC).&lt;/li>
&lt;li>&lt;strong>markdownlint&lt;/strong>: В реальном времени предупреждает о синтаксических ошибках и нарушениях стиля в Markdown.&lt;/li>
&lt;li>&lt;strong>vscode-textlint&lt;/strong>: Применяет набор правил для японской технической документации, предотвращая несоответствия в терминологии и грамматические ошибки.&lt;/li>
&lt;/ol>
&lt;h3 id="настройка-пользовательских-сниппетов-для-hugo-markdownjson">Настройка пользовательских сниппетов для Hugo (&lt;code>markdown.json&lt;/code>)
&lt;/h3>&lt;p>Если для технического блога вы используете генераторы статических сайтов, такие как Hugo или Docusaurus, вам придется часто вводить Frontmatter или собственные шорткоды. Функция сниппетов в VS Code позволяет развернуть их в одно мгновение.&lt;/p>
&lt;p>Из палитры команд выберите &lt;code>Preferences: Configure User Snippets&lt;/code> и добавьте следующие настройки в &lt;code>markdown.json&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Hugo Frontmatter&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;prefix&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;frontmatter&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;body&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;---&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;title: \&amp;#34;${1:Заголовок}\&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;slug: \&amp;#34;${2:slug-name}\&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;date: \&amp;#34;$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE T$CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND+09:00\&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;image: \&amp;#34;img/eyecatch.jpg\&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;math: true&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;mermaid: true&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;categories: [\&amp;#34;${3:Category}\&amp;#34;]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;tags: [\&amp;#34;${4:Tag1}\&amp;#34;, \&amp;#34;${5:Tag2}\&amp;#34;]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;---&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;${0}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Разворачивает YAML Frontmatter для Hugo&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Hugo Figure Shortcode&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;prefix&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;hfig&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;body&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;{{&amp;lt; figure src=\&amp;#34;${1:image.jpg}\&amp;#34; title=\&amp;#34;${2:Заголовок изображения}\&amp;#34; &amp;gt;}}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Шорткод Figure для Hugo&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Markdown Table&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;prefix&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;mtable&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;body&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;| ${1:Header 1} | ${2:Header 2} | ${3:Header 3} |&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;| :--- | :---: | ---: |&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;| ${4:Row 1} | ${5:Data} | ${6:Data} |&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;| ${7:Row 2} | ${8:Data} | ${9:Data} |&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;$0&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Создает Markdown таблицу на 3 колонки&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Благодаря этой настройке, достаточно ввести &lt;code>frontmatter&lt;/code> и нажать клавишу Tab, чтобы мгновенно развернуть YAML Frontmatter с текущим временем, что значительно увеличит начальную скорость написания.&lt;/p>
&lt;h3 id="поддержка-написания-с-использованием-github-copilot">Поддержка написания с использованием GitHub Copilot
&lt;/h3>&lt;p>Если в VS Code включен GitHub Copilot, автодополнение AI с учетом контекста работает и в Markdown. В частности, для технического блога AI может предвидеть и предлагать «структуру, которую следует объяснить далее» или «связанные блоки кода», что позволяет существенно сократить время на набор текста $T_{type}$.&lt;/p>
&lt;h2 id="3-экстремальная-кастомизация-в-neovim">3. Экстремальная кастомизация в Neovim
&lt;/h2>&lt;p>Графический интерфейс VS Code отличный, но для любителей терминалов и виммеров (Vim-пользователей) Neovim, позволяющий делать всё без отрыва рук от клавиатуры, является наиболее мощным выбором.&lt;/p>
&lt;h3 id="архитектура-lsp-в-neovim">Архитектура LSP в Neovim
&lt;/h3>&lt;p>Архитектура LSP (Language Server Protocol) и Linter в Neovim для среды Markdown выглядит следующим образом:&lt;/p>
&lt;pre class="mermaid">
classDiagram
class Neovim {
+&amp;#34;Текстовый буфер&amp;#34;
+&amp;#34;Привязки клавиш&amp;#34;
}
class nvim_lspconfig {
+&amp;#34;marksman (LSP для Markdown)&amp;#34;
}
class null_ls_or_none_ls {
+&amp;#34;markdownlint&amp;#34;
+&amp;#34;textlint&amp;#34;
}
class LuaSnip {
+&amp;#34;Динамические сниппеты&amp;#34;
}
class CMP {
+&amp;#34;Движок автодополнения&amp;#34;
}
Neovim --&amp;gt; nvim_lspconfig : &amp;#34;Обеспечивает семантические функции&amp;#34;
Neovim --&amp;gt; null_ls_or_none_ls : &amp;#34;Диагностика и форматирование&amp;#34;
Neovim --&amp;gt; CMP : &amp;#34;Запрос автодополнения&amp;#34;
CMP --&amp;gt; nvim_lspconfig : &amp;#34;Источник LSP&amp;#34;
CMP --&amp;gt; LuaSnip : &amp;#34;Источник сниппетов&amp;#34;
&lt;/pre>
&lt;h3 id="продвинутое-развертывание-сниппетов-с-помощью-luasnip">Продвинутое развертывание сниппетов с помощью LuaSnip
&lt;/h3>&lt;p>Гораздо мощнее JSON-сниппетов VS Code является плагин для Neovim — &lt;code>LuaSnip&lt;/code>. Используя логику языка Lua, можно динамически вычислять и разворачивать содержимое сниппетов.&lt;/p>
&lt;p>Ниже приведен пример настройки LuaSnip, которая динамически получает текущую дату и время и разворачивает Frontmatter для Hugo.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">ls&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;luasnip&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">s&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ls.snippet&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ls.text_node&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ls.insert_node&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">f&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ls.function_node&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">-- Функция для получения текущего времени JST&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="kr">function&lt;/span> &lt;span class="nf">get_current_date_jst&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">return&lt;/span> &lt;span class="n">os.date&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;!%Y-%m-%dT%H:%M:%S&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">..&lt;/span> &lt;span class="s2">&amp;#34;+09:00&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ls.add_snippets&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;markdown&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">s&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;frontmatter&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;---&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;title: &lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Title&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;slug: &lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;slug-name&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;date: &lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kr">function&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="kr">return&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="n">get_current_date_jst&lt;/span>&lt;span class="p">()}&lt;/span> &lt;span class="kr">end&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{}),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;image: &lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">img/eyecatch.jpg&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;math: true&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;mermaid: true&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;categories: [&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Category&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;tags: [&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Tag&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;---&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">s&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;mtable&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;| &amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Header 1&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34; | &amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Header 2&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34; |&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;|---|---|&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;| &amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Cell 1&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34; | &amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Cell 2&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34; |&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Таким образом, опираясь на мощь языка программирования (Lua), можно создавать невероятные сниппеты, которые вставляют не просто фиксированные строки, но и возвращаемые значения функций, или динамически увеличивают/уменьшают количество колонок в таблице в зависимости от количества введенных символов.&lt;/p>
&lt;h2 id="4-статический-анализ-для-совмещения-качества-и-скорости-написания-textlint-и-регулярные-выражения">4. Статический анализ для совмещения качества и скорости написания (textlint и регулярные выражения)
&lt;/h2>&lt;p>Для обеспечения качества блога необходимо предотвращать опечатки и несоответствия в терминологии. Если делать это вручную, время $T_{review}$ катастрофически возрастает, поэтому мы внедряем статический анализ с помощью &lt;code>textlint&lt;/code>.&lt;/p>
&lt;h3 id="внедрение-textlint-и-наборы-правил-для-японского-языка">Внедрение textlint и наборы правил для японского языка
&lt;/h3>&lt;p>Установите textlint в среде Node.js.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">npm install -D textlint textlint-rule-preset-ja-technical-writing textlint-rule-prh textlint-filter-rule-comments
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Создайте &lt;code>.textlintrc.json&lt;/code> в корне проекта и настройте его следующим образом:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;filters&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;comments&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;rules&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;preset-ja-technical-writing&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ja-no-mixed-period&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;periodMark&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;。&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;sentence-length&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;max&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">100&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;prh&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;rulePaths&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;./prh.yml&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Создайте &lt;code>prh.yml&lt;/code> и определите несоответствия в технических терминах. Например, можно стандартизировать написание «サーバー» (сервер) и «サーバ», «Javascript» и «JavaScript».&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">rules&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">expected&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;JavaScript&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">pattern&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Javascript&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">expected&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;サーバー&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">pattern&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;サーバ&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">expected&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;インターフェース&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">pattern&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;インターフェイス&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Благодаря этому при каждом наборе текста в редакторе будут выдаваться предупреждения о несоответствиях в реальном времени, что сведет время на вычитку почти к нулю.&lt;/p>
&lt;h3 id="пакетная-замена-и-структурные-паттерны-с-использованием-регулярных-выражений">Пакетная замена и структурные паттерны с использованием регулярных выражений
&lt;/h3>&lt;p>При переносе существующих статей в Markdown или копировании текста из внешних источников очень удобна пакетная замена с помощью регулярных выражений.&lt;/p>
&lt;p>Например, регулярное выражение для преобразования HTML-тегов &lt;code>&amp;lt;b&amp;gt;выделение&amp;lt;/b&amp;gt;&lt;/code> в Markdown &lt;code>**выделение**&lt;/code>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Шаблон поиска&lt;/strong>: &lt;code>&amp;lt;b&amp;gt;(.*?)&amp;lt;/b&amp;gt;&lt;/code>&lt;/li>
&lt;li>&lt;strong>Шаблон замены&lt;/strong>: &lt;code>**$1**&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>Если нужно объединить лишние переносы строк в один:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Шаблон поиска&lt;/strong>: &lt;code>\n{3,}&lt;/code>&lt;/li>
&lt;li>&lt;strong>Шаблон замены&lt;/strong>: &lt;code>\n\n&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>Выполнив их с помощью функции поиска и замены VS Code (в режиме регулярных выражений) или команды &lt;code>%s&lt;/code> в Neovim (&lt;code>:%s/&amp;lt;b&amp;gt;\(.*?\)&amp;lt;\/b&amp;gt;/**\1**/g&lt;/code>), вы сможете мгновенно унифицировать формат.&lt;/p>
&lt;h3 id="автоматическая-проверка-с-помощью-cicd-пайплайна">Автоматическая проверка с помощью CI/CD пайплайна
&lt;/h3>&lt;p>Кроме того, используя GitHub Actions, мы построим CI пайплайн, в котором &lt;code>textlint&lt;/code> будет автоматически запускаться при отправке (push) статей в блог. Это позволит предотвратить деплой статей, нарушающих правила.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Автор&amp;#34;] --&amp;gt;|Пуш изменений| B[&amp;#34;Репозиторий GitHub&amp;#34;]
B --&amp;gt; C{&amp;#34;Запуск GitHub Actions&amp;#34;}
C --&amp;gt; D[&amp;#34;Клонирование репозитория&amp;#34;]
D --&amp;gt; E[&amp;#34;Настройка Node.js&amp;#34;]
E --&amp;gt; F[&amp;#34;npm install&amp;#34;]
F --&amp;gt; G[&amp;#34;Запуск textlint&amp;#34;]
G --&amp;gt;|Успешно| H[&amp;#34;Сборка сайта Hugo&amp;#34;]
G --&amp;gt;|Ошибка| I[&amp;#34;Отчет об ошибке в PR/Коммит&amp;#34;]
H --&amp;gt; J[&amp;#34;Деплой на хостинг (Vercel/Netlify)&amp;#34;]
&lt;/pre>
&lt;h2 id="5-искусство-написания-markdown-в-эпоху-llm">5. Искусство написания Markdown в эпоху LLM
&lt;/h2>&lt;p>В современном написании технических блогов невозможно обойтись без использования LLM (Large Language Model). Использование встроенных в редактор инструментов ИИ еще больше удваивает скорость написания.&lt;/p>
&lt;h3 id="инженерия-промптов-внутри-редактора">Инженерия промптов внутри редактора
&lt;/h3>&lt;p>Используя GitHub Copilot Chat в VS Code или &lt;code>ChatGPT.nvim&lt;/code> и &lt;code>Copilot.vim&lt;/code> в Neovim, не покидая редактор, можно отправлять следующие промпты:&lt;/p>
&lt;blockquote>
&lt;p>«Создай структуру в виде иерархии Markdown для начинающих по следующим технологиям: Docker, Kubernetes, CI/CD»&lt;/p>
&lt;/blockquote>
&lt;p>После этого мгновенно генерируется разметка Markdown с заголовками и маркированными списками. Нам остается лишь добавить содержание на этот каркас.&lt;/p>
&lt;p>Кроме того, написание сложных диаграмм Mermaid или математических формул (LaTeX) также можно доверить ИИ, который сгенерирует точный синтаксис по вашим указаниям. Например, основы верстки формул и диаграмм в этой статье также были ускорены за счет совместного написания с LLM.&lt;/p>
&lt;h2 id="6-заключение">6. Заключение
&lt;/h2>&lt;p>В этой статье мы рассмотрели настройки редактора, которые удваивают скорость написания технических блогов на Markdown.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Осознание математической модели&lt;/strong>: Устранение повторяющихся задач для максимизации $T_{saved}$.&lt;/li>
&lt;li>&lt;strong>Использование VS Code&lt;/strong>: Сокращение ввода с помощью расширений и сниппетов в &lt;code>markdown.json&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Экстремальная кастомизация Neovim&lt;/strong>: Динамические сниппеты с помощью &lt;code>LuaSnip&lt;/code> и полностью клавиатурное управление.&lt;/li>
&lt;li>&lt;strong>textlint и статический анализ&lt;/strong>: Интеграция CI/CD и локального Linter&amp;rsquo;а для сведения времени вычитки к нулю.&lt;/li>
&lt;li>&lt;strong>Интеграция LLM&lt;/strong>: Вывод структуры Markdown и кода для диаграмм непосредственно ИИ внутри редактора.&lt;/li>
&lt;/ol>
&lt;p>Внедрив эти настройки в свою рабочую среду, вы избавитесь от «рутины» при написании, а количество и качество ваших технических публикаций кардинально возрастут. Почему бы не начать с малого — например, с регистрации одного простого сниппета?&lt;/p></description></item></channel></rss>