feat: счётчики с consent, политика, фиксы дизайна
Дизайн-фиксы: - Перенесены картинки из старого WP в public/wp-content/uploads/ (header_bg.gif + 3 размера NY-baner.png 2014/12). migrate-wp.mjs обновлён: корректно обрабатывает <a><img></a>, переписывает абсолютные URL anotherreflections.ru/wp-content/... в относительные - Description в frontmatter теперь чистый plain text — без markdown-разметки - Слаги 11/95/152 → kto-my, s-23-fevralya-2011, s-nastupayushhim-novym-2012-godom - Hero-метрика: «N лет онлайн» → «с 2006 года» (последний пост 2015, активной жизни «20 лет» нет) - Drop cap (буквица) — только для постов длиннее 240 символов (короткие посты раньше выглядели обрезанными) Аналитика и конфиденциальность: - Яндекс.Метрика (counter 13938862, webvisor) и Google gtag (GT-PH39R3X) перенесены со старого WP - Cookie consent banner — самописный, без зависимостей: счётчики грузятся только после явного «Принять». Выбор хранится в localStorage + cookie ar-consent на 12 месяцев. Уведомление в духе 152-ФЗ - /privacy/ — полная политика конфиденциальности: что собираем (через Метрику и GA), для чего, как cookies устроены, права пользователя, контакт для запросов на удаление - В футере добавлены ссылки «Политика конфиденциальности» и «Контакты» - sitemap.txt + llms.txt включают /privacy/
This commit is contained in:
@@ -28,15 +28,22 @@ const decodeEntities = (s) => s
|
||||
.replace(/>/g, '>')
|
||||
.replace(/&/g, '&');
|
||||
|
||||
/** Заменить старые WP-uploads URL на относительные (мы скачали в public/wp-content/uploads/). */
|
||||
const rewriteWpUploads = (url) =>
|
||||
url.replace(/^https?:\/\/anotherreflections\.ru(\/wp-content\/uploads\/.+)$/i, '$1');
|
||||
|
||||
const htmlToMd = (html) => {
|
||||
if (!html) return '';
|
||||
let s = html;
|
||||
// images
|
||||
// Сначала "вложенные" <a href="..."><img src="..."></a> — превращаем в один markdown-image со ссылкой
|
||||
s = s.replace(/<a\s+[^>]*?href=["']([^"']+)["'][^>]*>\s*<img[^>]*?src=["']([^"']+)["'][^>]*?(?:alt=["']([^"']*)["'])?[^>]*?\/?>\s*<\/a>/gi,
|
||||
(_, href, src, alt) => `[})](${rewriteWpUploads(href)})`);
|
||||
// одиночные images
|
||||
s = s.replace(/<img[^>]*?src=["']([^"']+)["'][^>]*?(?:alt=["']([^"']*)["'])?[^>]*?\/?>/gi,
|
||||
(_, src, alt) => ``);
|
||||
(_, src, alt) => `})`);
|
||||
// links
|
||||
s = s.replace(/<a\s+[^>]*?href=["']([^"']+)["'][^>]*>([\s\S]*?)<\/a>/gi,
|
||||
(_, href, text) => `[${text.replace(/<[^>]+>/g,'').trim()}](${href})`);
|
||||
(_, href, text) => `[${text.replace(/<[^>]+>/g,'').trim()}](${rewriteWpUploads(href)})`);
|
||||
// bold
|
||||
s = s.replace(/<(strong|b)\b[^>]*>([\s\S]*?)<\/\1>/gi, '**$2**');
|
||||
// italic
|
||||
@@ -106,7 +113,12 @@ for (const p of data.posts) {
|
||||
categories: p.categories.map(c => c.name),
|
||||
categorySlugs: p.categories.map(c => c.slug),
|
||||
tags: p.tags.map(t => t.name),
|
||||
description: (htmlToMd(p.excerpt) || htmlToMd(p.content_html)).slice(0, 200).replace(/\s+/g,' ').trim(),
|
||||
description: (htmlToMd(p.excerpt) || htmlToMd(p.content_html))
|
||||
.replace(/!?\[([^\]]*)\]\([^)]+\)/g, '$1') // strip markdown images/links для excerpt
|
||||
.replace(/[*_>#]+/g, '') // strip md formatting символов
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
.slice(0, 200),
|
||||
};
|
||||
const body = htmlToMd(p.content_html);
|
||||
const out = `${fmtFrontmatter(fm)}\n\n${body}\n`;
|
||||
|
||||
Reference in New Issue
Block a user