rewrite: Vite+React → Astro 5 + Content Collections
Some checks failed
deploy / deploy (push) Failing after 12s

- Бэкап старой версии на ветке vite-react-backup
- Stack: Astro 5 + nginx:alpine runtime, образ ~50 МБ (был ~600 МБ)
- @astrojs/rss заменён ручным buildRss() — гарантия CDATA в content:encoded для IPB Importer
- @astrojs/sitemap → sitemap-index.xml + sitemap.txt
- 152-ФЗ cookie consent + privacy.astro + Analytics с gating
- AI-файлы: robots.txt с явным allow для AI-краулеров, ai.txt, llms.txt
- Гибридный визуал: фото-фон шапки (аэрофото Пушкино) + PT Serif + IBM Plex Sans
- Иерархия: hero "Главная история" с рамкой + "Ещё из истории" + "Хроника"
- Категория "main" (псевдо) скрыта из плашек и из Рубрик в сайдбаре
- hideFromList: true для технических постов
- featuredImage в frontmatter для постов без хорошей первой <img>
- WP resized-URL (-WxH.ext) автоматически → оригинал
- CI/CD: .gitea/workflows/deploy.yml (push → SSH-build)
- Внешние RSS: scripts/pull-external-rss.mjs пишет news.json в bind-mount, фронт фетчит client-side
This commit is contained in:
striker
2026-05-21 03:21:31 +03:00
parent a0219ee8f3
commit c65e07cd98
75 changed files with 5926 additions and 4142 deletions

35
src/lib/extract.ts Normal file
View File

@@ -0,0 +1,35 @@
/** Утилиты: извлечение превью-картинки и текстового excerpt из HTML-тела поста. */
const IMG_RE = /<img[^>]+src=["']([^"']+)["'][^>]*>/i;
const TAG_RE = /<[^>]+>/g;
const WS_RE = /\s+/g;
export function firstImage(html: string): string | null {
const m = IMG_RE.exec(html);
return m ? m[1] : null;
}
export function plainText(html: string, max = 320): string {
const txt = html
.replace(/<style[\s\S]*?<\/style>/gi, ' ')
.replace(/<script[\s\S]*?<\/script>/gi, ' ')
.replace(/<!--[\s\S]*?-->/g, ' ')
.replace(TAG_RE, ' ')
.replace(/&nbsp;/g, ' ')
.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&quot;/g, '"')
.replace(WS_RE, ' ')
.trim();
if (txt.length <= max) return txt;
return txt.slice(0, max).replace(/\s+\S*$/, '') + '…';
}
export function formatDateRu(d: Date): string {
return d.toLocaleDateString('ru-RU', {
day: 'numeric',
month: 'long',
year: 'numeric',
});
}