From 738bf0bf4cdb382c79f9e5620e0d36e70f6eda4a Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Mon, 4 Aug 2025 15:36:18 +0400 Subject: [PATCH] vault backup: 2025-08-04 15:36:18 --- .../Hugo миграция и настройка.md | 764 ------------------ .../Миграция контента на Hugo.md | 136 ++++ 2 files changed, 136 insertions(+), 764 deletions(-) delete mode 100644 Идеи/Оптимизация ресурсов VPS/Hugo миграция и настройка.md create mode 100644 Идеи/Оптимизация ресурсов VPS/Миграция контента на Hugo.md diff --git a/Идеи/Оптимизация ресурсов VPS/Hugo миграция и настройка.md b/Идеи/Оптимизация ресурсов VPS/Hugo миграция и настройка.md deleted file mode 100644 index d1a9a58..0000000 --- a/Идеи/Оптимизация ресурсов VPS/Hugo миграция и настройка.md +++ /dev/null @@ -1,764 +0,0 @@ -# Hugo миграция и настройка - -## 1. Миграция контента - -### 1.1 Структура контента - -**Текущая структура (Quartz):** -``` -content/ -├── notes/ -│ ├── Идеи/ -│ ├── Мой сервер/ -│ └── index.md -├── daily/ -└── templates/ -``` - -**Новая структура (Hugo):** -``` -content/ -├── notes/ -│ ├── идеи/ -│ │ ├── obsidian-telegram-bot/ -│ │ │ ├── mvp-telegram-bota.md -│ │ │ └── telegram-bot-dlya-obsidian.md -│ │ └── pereezd-na-hugo/ -│ │ ├── plan-pereezda-na-hugo.md -│ │ ├── webhook-server-na-go.md -│ │ └── hugo-migratsiya-i-nastrojka.md -│ ├── мой-сервер/ -│ │ ├── authelia-authentication/ -│ │ ├── git-service/ -│ │ ├── second-mind-setup/ -│ │ └── traefik-reverse-proxy/ -│ └── _index.md -├── daily/ -│ └── _index.md -└── templates/ - └── _index.md -``` - -### 1.2 Скрипт миграции - -```python -#!/usr/bin/env python3 -# scripts/migrate_content.py - -import os -import re -import shutil -from pathlib import Path - -def slugify(text): - """Преобразование текста в slug для URL""" - text = text.lower() - text = re.sub(r'[^\w\s-]', '', text) - text = re.sub(r'[-\s]+', '-', text) - return text.strip('-') - -def migrate_content(): - """Миграция контента из Quartz в Hugo""" - - # Пути - quartz_content = "quartz/content" - hugo_content = "hugo-site/content" - - # Создание структуры Hugo - os.makedirs(hugo_content, exist_ok=True) - - # Обработка каждой директории - for root, dirs, files in os.walk(quartz_content): - # Пропускаем служебные директории - if any(skip in root for skip in ['.obsidian', '.git', '__pycache__']): - continue - - # Определяем относительный путь - rel_path = os.path.relpath(root, quartz_content) - - # Создаем соответствующую структуру в Hugo - hugo_path = os.path.join(hugo_content, rel_path) - os.makedirs(hugo_path, exist_ok=True) - - # Обрабатываем файлы - for file in files: - if file.endswith('.md'): - migrate_markdown_file( - os.path.join(root, file), - os.path.join(hugo_path, file) - ) - -def migrate_markdown_file(src_path, dst_path): - """Миграция отдельного Markdown файла""" - - with open(src_path, 'r', encoding='utf-8') as f: - content = f.read() - - # Обработка frontmatter - content = process_frontmatter(content) - - # Обработка внутренних ссылок - content = process_internal_links(content) - - # Обработка изображений - content = process_images(content) - - # Сохранение файла - with open(dst_path, 'w', encoding='utf-8') as f: - f.write(content) - -def process_frontmatter(content): - """Обработка YAML frontmatter для Hugo""" - - # Проверяем наличие frontmatter - if content.startswith('---'): - # Извлекаем frontmatter - parts = content.split('---', 2) - if len(parts) >= 3: - frontmatter = parts[1] - body = parts[2] - - # Добавляем Hugo-специфичные поля - frontmatter = add_hugo_frontmatter(frontmatter) - - return f"---\n{frontmatter}\n---\n{body}" - - # Если frontmatter отсутствует, создаем базовый - title = extract_title_from_content(content) - return f"""--- -title: "{title}" -date: {get_current_date()} -draft: false ---- - -{content}""" - -def add_hugo_frontmatter(frontmatter): - """Добавление Hugo-специфичных полей в frontmatter""" - - # Добавляем базовые поля если их нет - if 'draft' not in frontmatter: - frontmatter += '\ndraft: false' - - if 'date' not in frontmatter: - frontmatter += f'\ndate: {get_current_date()}' - - return frontmatter - -def process_internal_links(content): - """Обработка внутренних ссылок для Hugo""" - - # Заменяем [[wiki links]] на Hugo ссылки - content = re.sub(r'\[\[([^\]]+)\]\]', r'[{{< ref "\1" >}}]', content) - - # Обрабатываем обычные ссылки - content = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', process_link, content) - - return content - -def process_link(match): - """Обработка ссылок""" - text = match.group(1) - url = match.group(2) - - # Если это внутренняя ссылка на .md файл - if url.endswith('.md'): - # Преобразуем в Hugo ссылку - slug = slugify(url.replace('.md', '')) - return f'[{text}]({{{{< ref "{slug}" >}}}})' - - return match.group(0) - -def process_images(content): - """Обработка изображений""" - - # Перемещаем изображения в static директорию - # и обновляем ссылки - content = re.sub(r'!\[([^\]]*)\]\(([^)]+)\)', process_image, content) - - return content - -def process_image(match): - """Обработка изображений""" - alt = match.group(1) - src = match.group(2) - - # Если изображение локальное, перемещаем в static - if not src.startswith(('http://', 'https://')): - # Копируем изображение в static/images - static_path = f"static/images/{os.path.basename(src)}" - if os.path.exists(src): - shutil.copy2(src, static_path) - - # Обновляем ссылку - src = f"/images/{os.path.basename(src)}" - - return f'![{alt}]({src})' - -if __name__ == "__main__": - migrate_content() - print("Миграция контента завершена!") -``` - -## 2. Настройка Hugo - -### 2.1 Базовая конфигурация - -```toml -# config.toml -baseURL = "https://aepif.ru" -languageCode = "ru-ru" -title = "Second Mind" -theme = "custom-theme" - -[params] - description = "Персональная база знаний и заметки" - author = "AEP" - github = "https://github.com/username" - - # Настройки поиска - enableSearch = true - searchResultsLength = 10 - - # Настройки навигации - showBreadcrumb = true - showReadingTime = true - showWordCount = true - -[menu] - [[menu.main]] - identifier = "notes" - name = "Заметки" - url = "/notes/" - weight = 1 - - [[menu.main]] - identifier = "daily" - name = "Дневник" - url = "/daily/" - weight = 2 - - [[menu.main]] - identifier = "templates" - name = "Шаблоны" - url = "/templates/" - weight = 3 - -[markup] - [markup.goldmark] - [markup.goldmark.renderer] - unsafe = true - - [markup.highlight] - style = "dracula" - lineNos = true - lineNumbersInTable = true - -[outputs] - home = ["HTML", "RSS", "JSON"] - -[outputFormats] - [outputFormats.JSON] - mediaType = "application/json" - baseName = "index" - isPlainText = true - notAlternative = true -``` - -### 2.2 Структура темы - -``` -themes/custom-theme/ -├── assets/ -│ ├── css/ -│ │ ├── main.scss -│ │ └── _variables.scss -│ ├── js/ -│ │ └── main.js -│ └── images/ -├── layouts/ -│ ├── _default/ -│ │ ├── baseof.html -│ │ ├── list.html -│ │ └── single.html -│ ├── partials/ -│ │ ├── head.html -│ │ ├── header.html -│ │ ├── footer.html -│ │ ├── navigation.html -│ │ ├── search.html -│ │ └── breadcrumb.html -│ ├── shortcodes/ -│ │ ├── note.html -│ │ └── warning.html -│ └── index.html -├── static/ -│ ├── css/ -│ ├── js/ -│ └── images/ -└── theme.toml -``` - -### 2.3 Базовая тема - -```html - - - - - - - {{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ .Title }} | {{ .Site.Title }}{{ end }} - - {{ $style := resources.Get "css/main.scss" | resources.ToCSS | resources.Minify }} - - - {{ partial "head.html" . }} - - - {{ partial "header.html" . }} - -
- {{ block "main" . }}{{ end }} -
- - {{ partial "footer.html" . }} - - {{ $script := resources.Get "js/main.js" | resources.Minify }} - - - -``` - -```html - -{{ define "main" }} -
-
-

{{ .Title }}

- {{ if .Params.date }} - - {{ end }} -
- - {{ partial "breadcrumb.html" . }} - -
- {{ .Content }} -
- - {{ if .Params.tags }} -
-
- {{ range .Params.tags }} - {{ . }} - {{ end }} -
-
- {{ end }} -
-{{ end }} -``` - -### 2.4 Стили - -```scss -// assets/css/main.scss -@import "variables"; - -// Базовые стили -body { - font-family: $font-family-base; - line-height: 1.6; - color: $text-color; - background-color: $bg-color; -} - -.container { - max-width: $container-width; - margin: 0 auto; - padding: 0 $spacing; -} - -// Заметки -.note { - background: $note-bg; - border-radius: $border-radius; - padding: $spacing * 2; - margin-bottom: $spacing * 2; - box-shadow: $box-shadow; - - &-header { - border-bottom: 1px solid $border-color; - padding-bottom: $spacing; - margin-bottom: $spacing * 2; - - h1 { - margin: 0 0 $spacing 0; - color: $heading-color; - } - - time { - color: $muted-color; - font-size: 0.9em; - } - } - - &-content { - font-size: 1.1em; - line-height: 1.7; - - h1, h2, h3, h4, h5, h6 { - color: $heading-color; - margin-top: $spacing * 2; - margin-bottom: $spacing; - } - - p { - margin-bottom: $spacing; - } - - code { - background: $code-bg; - padding: 0.2em 0.4em; - border-radius: 3px; - font-size: 0.9em; - } - - pre { - background: $code-bg; - padding: $spacing; - border-radius: $border-radius; - overflow-x: auto; - - code { - background: none; - padding: 0; - } - } - } -} - -// Навигация -.navigation { - background: $nav-bg; - padding: $spacing; - margin-bottom: $spacing * 2; - border-radius: $border-radius; - - ul { - list-style: none; - padding: 0; - margin: 0; - display: flex; - gap: $spacing; - } - - a { - color: $nav-link-color; - text-decoration: none; - - &:hover { - color: $nav-link-hover-color; - } - } -} - -// Поиск -.search { - margin-bottom: $spacing * 2; - - input { - width: 100%; - padding: $spacing; - border: 1px solid $border-color; - border-radius: $border-radius; - font-size: 1em; - - &:focus { - outline: none; - border-color: $primary-color; - } - } -} - -// Хлебные крошки -.breadcrumb { - margin-bottom: $spacing; - font-size: 0.9em; - color: $muted-color; - - a { - color: $link-color; - text-decoration: none; - - &:hover { - text-decoration: underline; - } - } -} -``` - -## 3. Оптимизации - -### 3.1 Производительность - -```toml -# config.toml (дополнительные настройки) -[build] - writeStats = true - -[imaging] - quality = 85 - resampleFilter = "Lanczos" - -[minify] - [minify.tdewolff] - [minify.tdewolff.css] - keepCSS2 = true - precision = 0 - [minify.tdewolff.html] - keepConditionalComments = true - keepDefaultDoctype = true - keepDocumentTags = true - keepEndTags = true - keepQuotes = false - keepWhitespace = false - [minify.tdewolff.js] - keepVarNames = false - precision = 0 - [minify.tdewolff.json] - keepNumbers = false - precision = 0 - [minify.tdewolff.svg] - keepComments = false - [minify.tdewolff.xml] - keepWhitespace = false -``` - -### 3.2 SEO оптимизация - -```html - -{{ if .IsHome }} - -{{ else }} - -{{ end }} - - - - - - - - - - - - - - - - - -``` - -### 3.3 Поиск - -```javascript -// assets/js/search.js -class Search { - constructor() { - this.searchIndex = null; - this.searchInput = document.getElementById('search-input'); - this.searchResults = document.getElementById('search-results'); - - this.init(); - } - - async init() { - await this.loadSearchIndex(); - this.bindEvents(); - } - - async loadSearchIndex() { - try { - const response = await fetch('/index.json'); - this.searchIndex = await response.json(); - } catch (error) { - console.error('Failed to load search index:', error); - } - } - - bindEvents() { - this.searchInput.addEventListener('input', (e) => { - this.search(e.target.value); - }); - } - - search(query) { - if (!this.searchIndex || !query.trim()) { - this.hideResults(); - return; - } - - const results = this.searchIndex.filter(item => { - const searchText = `${item.title} ${item.content}`.toLowerCase(); - return searchText.includes(query.toLowerCase()); - }); - - this.displayResults(results.slice(0, 10)); - } - - displayResults(results) { - if (results.length === 0) { - this.searchResults.innerHTML = '

Ничего не найдено

'; - } else { - const html = results.map(item => ` -
-

${item.title}

-

${item.content.substring(0, 150)}...

-
- `).join(''); - this.searchResults.innerHTML = html; - } - - this.showResults(); - } - - showResults() { - this.searchResults.style.display = 'block'; - } - - hideResults() { - this.searchResults.style.display = 'none'; - } -} - -// Инициализация поиска -document.addEventListener('DOMContentLoaded', () => { - new Search(); -}); -``` - -## 4. Тестирование - -### 4.1 Локальная разработка - -```bash -#!/bin/bash -# scripts/dev.sh - -echo "Запуск Hugo в режиме разработки..." - -# Установка зависимостей -hugo mod get - -# Запуск сервера разработки -hugo server \ - --bind 0.0.0.0 \ - --port 1313 \ - --disableFastRender \ - --noHTTPCache \ - --buildDrafts \ - --buildFuture -``` - -### 4.2 Тестирование сборки - -```bash -#!/bin/bash -# scripts/test-build.sh - -set -e - -echo "Тестирование сборки Hugo..." - -# Очистка предыдущей сборки -rm -rf public/ - -# Сборка сайта -hugo --minify - -# Проверка размера -echo "Размер сборки:" -du -sh public/ - -# Проверка количества страниц -echo "Количество страниц:" -find public/ -name "*.html" | wc -l - -echo "Сборка завершена успешно!" -``` - -## 5. Развертывание - -### 5.1 Скрипт сборки для production - -```bash -#!/bin/bash -# scripts/build-production.sh - -set -e - -echo "Сборка Hugo для production..." - -# Очистка -rm -rf public/ - -# Сборка с оптимизациями -hugo \ - --minify \ - --gc \ - --cleanDestinationDir \ - --environment production - -# Оптимизация изображений -find public/ -name "*.jpg" -o -name "*.png" | xargs -I {} convert {} -strip -quality 85 {} - -# Сжатие статических файлов -find public/ -name "*.css" -o -name "*.js" | xargs gzip -9 - -echo "Production сборка завершена!" -``` - -### 5.2 Nginx конфигурация - -```nginx -# configs/nginx.conf -server { - listen 80; - server_name aepif.ru www.aepif.ru; - - root /var/www/html; - index index.html; - - # Gzip сжатие - gzip on; - gzip_vary on; - gzip_min_length 1024; - gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json; - - # Кэширование статических файлов - location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ { - expires 1y; - add_header Cache-Control "public, immutable"; - } - - # Обработка Hugo страниц - location / { - try_files $uri $uri/ $uri.html =404; - } - - # Обработка 404 ошибок - error_page 404 /404.html; - - # Безопасность - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-Content-Type-Options "nosniff" always; - add_header X-XSS-Protection "1; mode=block" always; -} -``` \ No newline at end of file diff --git a/Идеи/Оптимизация ресурсов VPS/Миграция контента на Hugo.md b/Идеи/Оптимизация ресурсов VPS/Миграция контента на Hugo.md new file mode 100644 index 0000000..b58c6d9 --- /dev/null +++ b/Идеи/Оптимизация ресурсов VPS/Миграция контента на Hugo.md @@ -0,0 +1,136 @@ +# Миграция контента на Hugo + +## 1. Миграция контента + +### 1.1 Структура контента + +**Текущая структура (Quartz):** +``` +content/ +├── notes/ +│ ├── Идеи/ +│ ├── Мой сервер/ +│ └── index.md +├── daily/ +└── templates/ +``` + +**Новая структура (Hugo):** +``` +content/ +├── notes/ +│ ├── идеи/ +│ │ ├── obsidian-telegram-bot/ +│ │ └── optimizatsiya-resursov-vps/ +│ ├── мой-сервер/ +│ └── _index.md +├── daily/ +│ └── _index.md +└── templates/ + └── _index.md +``` + +### 1.2 Основные изменения при миграции + +**Frontmatter:** +- Добавление Hugo-специфичных полей +- Преобразование дат в стандартный формат +- Добавление метаданных для SEO + +**Внутренние ссылки:** +- Замена `[[wiki links]]` на Hugo ссылки +- Обновление путей к файлам +- Обработка относительных ссылок + +**Изображения:** +- Перемещение в `static/images/` +- Обновление путей в контенте +- Оптимизация размера файлов + +## 2. Базовая настройка Hugo + +### 2.1 Конфигурация + +**Основные параметры:** +- `baseURL` - адрес сайта +- `languageCode` - язык контента +- `title` - название сайта +- `theme` - используемая тема + +**Настройки контента:** +- Структура меню +- Параметры поиска +- Настройки навигации +- SEO параметры + +### 2.2 Структура проекта + +``` +hugo-site/ +├── config.toml # Основная конфигурация +├── content/ # Контент сайта +├── layouts/ # Шаблоны темы +├── static/ # Статические файлы +├── themes/ # Темы +└── public/ # Собранный сайт +``` + +## 3. Оптимизации + +### 3.1 Производительность + +**Сборка:** +- Минификация CSS/JS +- Оптимизация изображений +- Сжатие статических файлов +- Кэширование ресурсов + +**SEO:** +- Мета-теги +- Open Graph разметка +- Sitemap генерация +- Canonical URLs + +### 3.2 Поиск + +**Функциональность:** +- Поиск по контенту +- Фильтрация результатов +- Подсветка найденного текста +- Быстрый поиск + +## 4. Развертывание + +### 4.1 Локальная разработка + +**Команды:** +- `hugo server` - запуск сервера разработки +- `hugo --minify` - сборка для production +- `hugo --gc` - очистка неиспользуемых файлов + +### 4.2 Production + +**Оптимизации:** +- Минификация всех ресурсов +- Оптимизация изображений +- Gzip сжатие +- Кэширование статических файлов + +## 5. Преимущества миграции + +### 5.1 Производительность +- **Время сборки**: С 30-60 секунд до 5-10 секунд +- **Размер файлов**: Снижение на 40-60% +- **Время загрузки**: Улучшение на 50-70% + +### 5.2 Операционные +- **Простота развертывания**: Один бинарник +- **Низкое потребление ресурсов**: Минимальные требования +- **Надежность**: Меньше зависимостей +- **Безопасность**: Меньше уязвимостей + +### 5.3 Функциональность +- **SEO оптимизация**: Встроенные возможности +- **Адаптивность**: Современные темы +- **Поиск**: Быстрый и точный +- **Кастомизация**: Полный контроль \ No newline at end of file