core-maugli 1.2.3 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +13 -0
  2. package/package.json +6 -13
  3. package/public/img/examples/blog/previews/post-1-avtomatizaciya-marketinga-kak-ii-osvobozhdaet-predprinimatelei-ot-cifrovogo-rabstva.webp +0 -0
  4. package/public/img/examples/blog/previews/post-2-avtomatizaciya-kontenta-kak-neiroseti-ubivayut-perfekcionizm-v-biznese.webp +0 -0
  5. package/public/img/examples/blog/previews/post-3-laik-ne-valyuta-kak-avtomatizaciya-marketinga-spasaet-ot-lozhnyh-metrik.webp +0 -0
  6. package/public/img/examples/blog/previews/post-5-5-fatalnyh-oshibok-marketinga-kotorye-ubivayut-startapy-na-starte.webp +0 -0
  7. package/public/img/examples/blog/previews/post-6-5-strategii-kontent-marketinga-dlya-startapov-avtomatizaciya-i-revolyuciya.webp +0 -0
  8. package/public/img/examples/blog/previews/post-7-viralnyi-kontent-ne-udacha-a-strategiya-avtomatizaciya-marketinga.webp +0 -0
  9. package/public/img/examples/blog/previews/post-agent-experience-mcp-biznes-v-epohu-ii-agentov.webp +0 -0
  10. package/public/img/examples/blog/previews/post_11.webp +0 -0
  11. package/public/img/examples/blog/previews/post_12.webp +0 -0
  12. package/public/img/examples/blog/previews/post_1_jsonld_guide.webp +0 -0
  13. package/public/img/examples/blog/previews/test-post.webp +0 -0
  14. package/public/img/examples/blog/previews/tr-post-1.webp +0 -0
  15. package/public/img/examples/products/previews/product_1.webp +0 -0
  16. package/public/img/examples/products/previews/product_2.webp +0 -0
  17. package/public/img/examples/projects/previews/project_1.webp +0 -0
  18. package/public/img/examples/projects/previews/project_2.webp +0 -0
  19. package/scripts/generate-previews.js +175 -0
  20. package/scripts/update-components.js +166 -0
  21. package/scripts/upgrade-config.js +23 -3
  22. package/src/components/LanguageSwitcher.astro +2 -16
  23. package/astro.config.mjs +0 -92
  24. package/bin/init.js +0 -201
  25. package/public/img/default/autor_default.webp +0 -0
  26. package/public/img/default/blog_default.webp +0 -0
  27. package/public/img/default/default.webp +0 -0
  28. package/public/img/default/product_default.webp +0 -0
  29. package/public/img/default/project_default.webp +0 -0
  30. package/public/img/default/rubric_default.webp +0 -0
  31. package/public/img/default/test.webp +0 -0
  32. package/public/img/default/test2.webp +0 -0
  33. package/resize-all.cjs +0 -29
  34. package/src/i18n/de.json +0 -126
  35. package/src/i18n/en.json +0 -126
  36. package/src/i18n/es.json +0 -126
  37. package/src/i18n/fr.json +0 -126
  38. package/src/i18n/index.ts +0 -10
  39. package/src/i18n/ja.json +0 -126
  40. package/src/i18n/languages.ts +0 -23
  41. package/src/i18n/pt.json +0 -126
  42. package/src/i18n/ru.json +0 -123
  43. package/src/i18n/zh.json +0 -126
  44. package/src/icons/ArrowLeft.astro +0 -13
  45. package/src/icons/ArrowRight.astro +0 -13
  46. package/src/icons/flags/brazil.svg +0 -14
  47. package/src/icons/flags/china.svg +0 -15
  48. package/src/icons/flags/france.svg +0 -12
  49. package/src/icons/flags/germany.svg +0 -12
  50. package/src/icons/flags/japan.svg +0 -11
  51. package/src/icons/flags/russia.svg +0 -12
  52. package/src/icons/flags/spain.svg +0 -12
  53. package/src/icons/flags/united arab emirates.svg +0 -13
  54. package/src/icons/flags/united states.svg +0 -15
  55. package/src/icons/socials/BlueskyIcon.astro +0 -9
  56. package/src/icons/socials/EmailIcon.astro +0 -8
  57. package/src/icons/socials/LinkedinIcon.astro +0 -9
  58. package/src/icons/socials/MastodonIcon.astro +0 -9
  59. package/src/icons/socials/MediumIcon.astro +0 -9
  60. package/src/icons/socials/RedditIcon.astro +0 -11
  61. package/src/icons/socials/TelegramIcon.astro +0 -11
  62. package/src/icons/socials/TwitterIcon.astro +0 -9
  63. package/src/layouts/BaseLayout.astro +0 -59
  64. package/src/pages/404.astro +0 -24
  65. package/src/pages/[...id].astro +0 -50
  66. package/src/pages/about.astro +0 -0
  67. package/src/pages/authors/[...page].astro +0 -105
  68. package/src/pages/authors/[id].astro +0 -175
  69. package/src/pages/blog/[...page].astro +0 -59
  70. package/src/pages/blog/[id].astro +0 -175
  71. package/src/pages/index.astro +0 -90
  72. package/src/pages/products/[...page].astro +0 -50
  73. package/src/pages/products/[id].astro +0 -221
  74. package/src/pages/projects/[...page].astro +0 -74
  75. package/src/pages/projects/[id].astro +0 -165
  76. package/src/pages/projects/tags/[id]/[...page].astro +0 -58
  77. package/src/pages/rss.xml.js +0 -5
  78. package/src/pages/tags/[id]/[...page].astro +0 -110
  79. package/src/pages/tags/index.astro +0 -124
  80. package/src/scripts/infoCardFadeIn.js +0 -22
  81. package/src/styles/global.css +0 -273
  82. package/src/utils/common-utils.ts +0 -0
  83. package/src/utils/content-loader.ts +0 -14
  84. package/src/utils/data-utils.ts +0 -49
  85. package/src/utils/featuredManager.ts +0 -118
  86. package/src/utils/posts.ts +0 -43
  87. package/src/utils/reading-time.ts +0 -28
  88. package/src/utils/remark-slugify.js +0 -8
  89. package/src/utils/rss.ts +0 -23
  90. package/tsconfig.json +0 -8
  91. package/typograf-batch.js +0 -49
  92. package/vite.config.js +0 -11
package/README.md CHANGED
@@ -87,6 +87,19 @@ Your blog will be available at `http://localhost:4321/`
87
87
  npm run build
88
88
  ```
89
89
 
90
+ ## Component Updates & Customization
91
+
92
+ **Important**: Maugli Blog is designed for centralized component updates. All components (`src/components/`, `src/layouts/`, `src/pages/`, etc.) are automatically updated to the latest version when you update the package with `npm install --save core-maugli@latest`. This ensures you always receive the latest features, bug fixes, and improvements.
93
+
94
+ This centralized update approach **does not affect**:
95
+
96
+ - Your content (`src/content/`)
97
+ - Your Maugli configuration (`src/config/maugli.config.ts`)
98
+ - Your custom styles (`src/styles/global.css` - preserved if customized)
99
+ - Your project settings (`package.json`, `astro.config.mjs`, etc.)
100
+
101
+ Only the core blog components are updated, while your customizations and settings remain intact.
102
+
90
103
  `npm run build` runs [`scripts/verify-assets.js`](scripts/verify-assets.js)
91
104
  before the Astro build. This script checks the SHA-256 hashes of the
92
105
  floating label component and footer badge to ensure they haven't been
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "core-maugli",
3
3
  "description": "Astro & Tailwind CSS blog theme for Maugli.",
4
4
  "type": "module",
5
- "version": "1.2.3",
5
+ "version": "1.2.4",
6
6
  "license": "GPL-3.0-or-later OR Commercial",
7
7
  "repository": {
8
8
  "type": "git",
@@ -21,15 +21,17 @@
21
21
  "typograf": "node typograf-batch.js",
22
22
  "dev": "astro dev",
23
23
  "start": "astro dev",
24
- "build": "node typograf-batch.js && node scripts/verify-assets.js && astro build",
24
+ "build": "node typograf-batch.js && node scripts/generate-previews.js && node scripts/verify-assets.js && astro build",
25
25
  "test": "node tests/examplesFilter.test.ts",
26
26
  "astro": "astro",
27
27
  "featured:add": "node scripts/featured.js add",
28
28
  "featured:remove": "node scripts/featured.js remove",
29
29
  "featured:list": "node scripts/featured.js list",
30
30
  "upgrade": "node scripts/upgrade-config.js",
31
+ "update-components": "node scripts/update-components.js",
31
32
  "backup-update": "node scripts/update-with-backup.js",
32
- "postinstall": "node scripts/upgrade-config.js"
33
+ "postinstall": "node scripts/upgrade-config.js",
34
+ "generate-previews": "node scripts/generate-previews.js"
33
35
  },
34
36
  "dependencies": {
35
37
  "@astrojs/mdx": "^4.3.0",
@@ -61,17 +63,8 @@
61
63
  "files": [
62
64
  "src",
63
65
  "public",
64
- "scripts",
65
- "typograf-batch.js",
66
- "resize-all.cjs",
67
- "bin",
68
- "astro.config.mjs",
69
- "tsconfig.json",
70
- "vite.config.js",
71
- "LICENSE",
72
- "README.md"
66
+ "scripts"
73
67
  ],
74
- "main": "bin/index.js",
75
68
  "bin": {
76
69
  "core-maugli": "bin/index.js"
77
70
  }
@@ -0,0 +1,175 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import sharp from 'sharp';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+
9
+ // Универсальное определение корня проекта
10
+ const rootDir = __dirname.includes('node_modules')
11
+ ? path.join(__dirname, '../../..')
12
+ : path.join(__dirname, '..');
13
+
14
+ const previewWidth = 400;
15
+ const previewHeight = 210;
16
+
17
+ // Функция для извлечения путей изображений из markdown файлов
18
+ function extractImagePaths() {
19
+ const imagePaths = new Set();
20
+ const contentDir = path.join(rootDir, 'src/content');
21
+
22
+ function scanDirectory(dir) {
23
+ if (!fs.existsSync(dir)) return;
24
+
25
+ const items = fs.readdirSync(dir);
26
+
27
+ for (const item of items) {
28
+ const itemPath = path.join(dir, item);
29
+ const stat = fs.statSync(itemPath);
30
+
31
+ if (stat.isDirectory()) {
32
+ scanDirectory(itemPath);
33
+ } else if (item.endsWith('.md') || item.endsWith('.mdx')) {
34
+ const content = fs.readFileSync(itemPath, 'utf-8');
35
+
36
+ // Извлекаем изображения из frontmatter (image: путь)
37
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
38
+ if (frontmatterMatch) {
39
+ const frontmatter = frontmatterMatch[1];
40
+ // Улучшенные регулярки для frontmatter
41
+ const imageMatches = frontmatter.match(/(?:^|\n)\s*(?:image|src):\s*['"]*([^'">\s\n]+)['"]*(?:\s|$)/g);
42
+ if (imageMatches) {
43
+ imageMatches.forEach(match => {
44
+ const imagePath = match.replace(/.*?(?:image|src):\s*['"]*/, '').replace(/['"]*\s*$/, '');
45
+ if (imagePath && !imagePath.startsWith('http') && imagePath.includes('/') && !imagePath.includes('authors/')) {
46
+ imagePaths.add(imagePath);
47
+ }
48
+ });
49
+ }
50
+ }
51
+
52
+ // Извлекаем изображения из содержимого markdown (![](путь) и <img src="путь">)
53
+ const imgMatches = content.match(/!\[.*?\]\(([^)]+)\)|<img[^>]+src\s*=\s*['"]*([^'">\s]+)['"]*[^>]*>/g);
54
+ if (imgMatches) {
55
+ imgMatches.forEach(match => {
56
+ let imagePath;
57
+ if (match.startsWith('![')) {
58
+ imagePath = match.match(/!\[.*?\]\(([^)]+)\)/)?.[1];
59
+ } else {
60
+ imagePath = match.match(/src\s*=\s*['"]*([^'">\s]+)['"]*/)?.[1];
61
+ }
62
+ if (imagePath && !imagePath.startsWith('http') && imagePath.includes('/') && !imagePath.includes('authors/')) {
63
+ imagePaths.add(imagePath);
64
+ }
65
+ });
66
+ }
67
+ }
68
+ }
69
+ }
70
+
71
+ scanDirectory(contentDir);
72
+
73
+ // Также добавляем изображения из public/img/examples/ кроме авторов
74
+ const examplesDir = path.join(rootDir, 'public/img/examples');
75
+ if (fs.existsSync(examplesDir)) {
76
+ function addExampleImages(dir, relativePath = '') {
77
+ // Пропускаем папку authors - аватары не нужно обрабатывать
78
+ if (relativePath.includes('authors/')) return;
79
+
80
+ const items = fs.readdirSync(dir);
81
+ for (const item of items) {
82
+ const itemPath = path.join(dir, item);
83
+ const stat = fs.statSync(itemPath);
84
+
85
+ if (stat.isDirectory()) {
86
+ // Пропускаем папку authors
87
+ if (item === 'authors') continue;
88
+ addExampleImages(itemPath, `${relativePath}${item}/`);
89
+ } else if (item.match(/\.(webp|jpg|jpeg|png)$/i) && !dir.includes('previews')) {
90
+ imagePaths.add(`/img/examples/${relativePath}${item}`);
91
+ }
92
+ }
93
+ }
94
+ addExampleImages(examplesDir);
95
+ }
96
+
97
+ return Array.from(imagePaths);
98
+ }
99
+
100
+ // Функция для очистки всех существующих превьюшек
101
+ function cleanupExistingPreviews() {
102
+ const publicDir = path.join(rootDir, 'public');
103
+
104
+ function removePreviewDirs(dir) {
105
+ if (!fs.existsSync(dir)) return;
106
+
107
+ const items = fs.readdirSync(dir);
108
+
109
+ for (const item of items) {
110
+ const itemPath = path.join(dir, item);
111
+ const stat = fs.statSync(itemPath);
112
+
113
+ if (stat.isDirectory()) {
114
+ if (item === 'previews') {
115
+ console.log(`Removing existing preview directory: ${itemPath}`);
116
+ fs.rmSync(itemPath, { recursive: true, force: true });
117
+ } else {
118
+ removePreviewDirs(itemPath);
119
+ }
120
+ }
121
+ }
122
+ }
123
+
124
+ removePreviewDirs(publicDir);
125
+ }
126
+
127
+ // Функция для создания превьюшки
128
+ async function createPreview(imagePath) {
129
+ const fullImagePath = path.join(rootDir, 'public', imagePath.replace(/^\//, ''));
130
+
131
+ if (!fs.existsSync(fullImagePath)) {
132
+ console.warn(`Image not found: ${fullImagePath}`);
133
+ return;
134
+ }
135
+
136
+ const dir = path.dirname(fullImagePath);
137
+ const ext = path.extname(fullImagePath);
138
+ const name = path.basename(fullImagePath, ext);
139
+ const previewPath = path.join(dir, 'previews', `${name}${ext}`);
140
+
141
+ // Создаем папку previews если её нет
142
+ const previewDir = path.dirname(previewPath);
143
+ if (!fs.existsSync(previewDir)) {
144
+ fs.mkdirSync(previewDir, { recursive: true });
145
+ }
146
+
147
+ try {
148
+ await sharp(fullImagePath)
149
+ .resize(previewWidth, previewHeight, { fit: 'cover' })
150
+ .toFile(previewPath);
151
+
152
+ console.log(`Preview created: ${previewPath}`);
153
+ } catch (error) {
154
+ console.error(`Error processing ${fullImagePath}:`, error.message);
155
+ }
156
+ }
157
+
158
+ // Основная функция
159
+ async function generatePreviews() {
160
+ console.log('Cleaning up existing previews...');
161
+ cleanupExistingPreviews();
162
+
163
+ console.log('Scanning content for images...');
164
+ const imagePaths = extractImagePaths();
165
+
166
+ console.log(`Found ${imagePaths.length} images to process`);
167
+
168
+ for (const imagePath of imagePaths) {
169
+ await createPreview(imagePath);
170
+ }
171
+
172
+ console.log('Preview generation completed!');
173
+ }
174
+
175
+ generatePreviews().catch(console.error);
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs/promises';
4
+ import path from 'path';
5
+ import { fileURLToPath, pathToFileURL } from 'url';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
10
+ // Определяем корневые папки
11
+ const packageRoot = __dirname.includes('node_modules')
12
+ ? path.join(__dirname, '../../..', 'node_modules', 'core-maugli') // из node_modules
13
+ : path.join(__dirname, '..'); // из исходников (для разработки)
14
+
15
+ const userRoot = __dirname.includes('node_modules')
16
+ ? path.join(__dirname, '../../..') // корень пользовательского проекта
17
+ : process.env.INIT_CWD || process.cwd(); // для разработки
18
+
19
+ // Список папок и файлов для полного обновления (перезаписи)
20
+ const FORCE_UPDATE_PATHS = [
21
+ 'src/components',
22
+ 'src/layouts',
23
+ 'src/pages',
24
+ 'src/utils',
25
+ 'src/scripts',
26
+ 'src/icons',
27
+ 'src/i18n',
28
+ 'public/flags',
29
+ 'public/img/default'
30
+ // Исключили src/styles - может содержать пользовательские стили
31
+ ];
32
+
33
+ // Список файлов, которые НЕ должны перезаписываться (пользовательские)
34
+ const PRESERVE_PATHS = [
35
+ 'src/content',
36
+ 'src/config/maugli.config.ts', // обновляется через upgrade-config.js
37
+ 'src/styles/global.css', // может быть кастомизирован пользователем
38
+ 'package.json',
39
+ 'astro.config.mjs',
40
+ 'tailwind.config.js',
41
+ 'tsconfig.json'
42
+ ];
43
+
44
+ async function copyDirectory(src, dest) {
45
+ try {
46
+ await fs.mkdir(dest, { recursive: true });
47
+
48
+ const entries = await fs.readdir(src, { withFileTypes: true });
49
+
50
+ for (const entry of entries) {
51
+ const srcPath = path.join(src, entry.name);
52
+ const destPath = path.join(dest, entry.name);
53
+
54
+ if (entry.isDirectory()) {
55
+ await copyDirectory(srcPath, destPath);
56
+ } else {
57
+ await fs.copyFile(srcPath, destPath);
58
+ console.log(`Updated: ${path.relative(userRoot, destPath)}`);
59
+ }
60
+ }
61
+ } catch (error) {
62
+ console.warn(`Warning: Could not copy ${src} to ${dest}:`, error.message);
63
+ }
64
+ }
65
+
66
+ async function updateStyles() {
67
+ const srcStylesPath = path.join(packageRoot, 'src/styles');
68
+ const destStylesPath = path.join(userRoot, 'src/styles');
69
+
70
+ try {
71
+ // Проверяем, существует ли папка styles в пакете
72
+ await fs.stat(srcStylesPath);
73
+
74
+ // Проверяем, есть ли уже пользовательские стили
75
+ try {
76
+ const userGlobalCss = path.join(destStylesPath, 'global.css');
77
+ await fs.stat(userGlobalCss);
78
+ console.log('📝 Preserving user styles (global.css exists)');
79
+
80
+ // Копируем только новые файлы стилей, не трогая global.css
81
+ const entries = await fs.readdir(srcStylesPath, { withFileTypes: true });
82
+ await fs.mkdir(destStylesPath, { recursive: true });
83
+
84
+ for (const entry of entries) {
85
+ if (entry.name !== 'global.css') {
86
+ const srcFile = path.join(srcStylesPath, entry.name);
87
+ const destFile = path.join(destStylesPath, entry.name);
88
+ await fs.copyFile(srcFile, destFile);
89
+ console.log(`Updated style: ${entry.name}`);
90
+ }
91
+ }
92
+ } catch {
93
+ // Пользовательских стилей нет, копируем все
94
+ await copyDirectory(srcStylesPath, destStylesPath);
95
+ console.log('📝 Copied default styles');
96
+ }
97
+ } catch (error) {
98
+ console.warn('Warning: Could not update styles:', error.message);
99
+ }
100
+ }
101
+
102
+ async function updateComponents() {
103
+ console.log('🔄 Updating Maugli components and assets...');
104
+
105
+ // Проверяем, что мы не в том же проекте (чтобы не удалить исходники)
106
+ if (packageRoot === userRoot) {
107
+ console.log('⚠️ Skipping component update (running in source project)');
108
+ return;
109
+ }
110
+
111
+ let updatedCount = 0;
112
+
113
+ for (const updatePath of FORCE_UPDATE_PATHS) {
114
+ const srcPath = path.join(packageRoot, updatePath);
115
+ const destPath = path.join(userRoot, updatePath);
116
+
117
+ try {
118
+ // Проверяем, существует ли исходная папка/файл
119
+ const stats = await fs.stat(srcPath);
120
+
121
+ if (stats.isDirectory()) {
122
+ // Удаляем существующую папку и копируем новую
123
+ try {
124
+ await fs.rm(destPath, { recursive: true, force: true });
125
+ } catch (e) {
126
+ // Папки может не быть - это нормально
127
+ }
128
+
129
+ await copyDirectory(srcPath, destPath);
130
+ updatedCount++;
131
+ } else if (stats.isFile()) {
132
+ // Копируем отдельный файл
133
+ await fs.mkdir(path.dirname(destPath), { recursive: true });
134
+ await fs.copyFile(srcPath, destPath);
135
+ console.log(`Updated: ${path.relative(userRoot, destPath)}`);
136
+ updatedCount++;
137
+ }
138
+ } catch (error) {
139
+ if (error.code !== 'ENOENT') {
140
+ console.warn(`Warning: Could not update ${updatePath}:`, error.message);
141
+ }
142
+ }
143
+ }
144
+
145
+ // Обрабатываем стили отдельно
146
+ await updateStyles();
147
+
148
+ console.log(`✅ Updated ${updatedCount} component directories/files`);
149
+ }
150
+
151
+ async function main() {
152
+ try {
153
+ await updateComponents();
154
+ console.log('🎉 Component update completed successfully!');
155
+ } catch (error) {
156
+ console.error('❌ Component update failed:', error);
157
+ process.exit(1);
158
+ }
159
+ }
160
+
161
+ // Запускаем только если вызывается напрямую
162
+ if (import.meta.url === pathToFileURL(process.argv[1]).href) {
163
+ main();
164
+ }
165
+
166
+ export { updateComponents };
@@ -1,14 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import fs from 'fs/promises';
4
- import path from 'path';
5
4
  import os from 'os';
6
- import { fileURLToPath, pathToFileURL } from 'url';
5
+ import path from 'path';
7
6
  import ts from 'typescript';
7
+ import { fileURLToPath, pathToFileURL } from 'url';
8
8
 
9
9
  const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = path.dirname(__filename);
11
11
 
12
+ // Импортируем функцию обновления компонентов
13
+ async function importUpdateComponents() {
14
+ try {
15
+ const { updateComponents } = await import('./update-components.js');
16
+ return updateComponents;
17
+ } catch (error) {
18
+ console.warn('Could not load update-components.js:', error.message);
19
+ return null;
20
+ }
21
+ }
22
+
12
23
  const defaultConfigPath = path.join(__dirname, '../src/config/maugli.config.ts');
13
24
  const userRoot = process.env.INIT_CWD || process.cwd();
14
25
  const userConfigPath = path.join(userRoot, 'src/config/maugli.config.ts');
@@ -43,6 +54,15 @@ function mergeMissing(target, source) {
43
54
  }
44
55
 
45
56
  async function main() {
57
+ console.log('🔄 Starting Maugli upgrade process...');
58
+
59
+ // Сначала обновляем компоненты
60
+ const updateComponents = await importUpdateComponents();
61
+ if (updateComponents) {
62
+ await updateComponents();
63
+ }
64
+
65
+ // Затем обновляем конфиг
46
66
  const pkg = await loadTsModule(defaultConfigPath);
47
67
  const defCfg = pkg.maugliConfig;
48
68
  const newVersion = pkg.MAUGLI_CONFIG_VERSION || defCfg.configVersion;
@@ -50,7 +70,7 @@ async function main() {
50
70
  try {
51
71
  await fs.access(userConfigPath);
52
72
  } catch {
53
- console.warn(`User config not found at ${userConfigPath}, skipping upgrade`);
73
+ console.warn(`User config not found at ${userConfigPath}, skipping config upgrade`);
54
74
  return;
55
75
  }
56
76
 
@@ -24,15 +24,7 @@ const current = availableLanguages.find((l) => l.code === currentLang) || availa
24
24
  class="flag-box flex items-center justify-center w-7 h-7 rounded-[var(--radius-main)] shadow-[var(--shadow-main)]"
25
25
  style="min-width:28px; min-height:28px; max-width:28px; max-height:28px;"
26
26
  >
27
- {current && (
28
- <img
29
- src={current.icon.replace(/^\/public\/|^\/|^flags\//, '/src/icons/flags/')}
30
- alt={current.code.toUpperCase()}
31
- width="28"
32
- height="28"
33
- style="pointer-events:none;"
34
- />
35
- )}
27
+ {current && <img src={current.icon} alt={current.code.toUpperCase()} width="28" height="28" style="pointer-events:none;" />}
36
28
  </span>
37
29
  <svg class="w-4 h-4" viewBox="0 0 20 20" fill="currentColor">
38
30
  <path
@@ -65,13 +57,7 @@ const current = availableLanguages.find((l) => l.code === currentLang) || availa
65
57
  class="flag-box flex items-center justify-center w-7 h-7 rounded-[var(--radius-main)] shadow-[var(--shadow-main)]"
66
58
  style="min-width:28px; min-height:28px; max-width:28px; max-height:28px;"
67
59
  >
68
- <img
69
- src={lang.icon.replace(/^\/public\/|^\/|^flags\//, '/src/icons/flags/')}
70
- alt={lang.code.toUpperCase()}
71
- width="28"
72
- height="28"
73
- style="pointer-events:none;"
74
- />
60
+ <img src={lang.icon} alt={lang.code.toUpperCase()} width="28" height="28" style="pointer-events:none;" />
75
61
  </span>
76
62
  <span class="text-heading">{lang.label}</span>
77
63
  </a>
package/astro.config.mjs DELETED
@@ -1,92 +0,0 @@
1
- import mdx from '@astrojs/mdx';
2
- import sitemap from '@astrojs/sitemap';
3
- import tailwindcss from '@tailwindcss/vite';
4
- import { defineConfig } from 'astro/config';
5
- import { imagetools } from 'vite-imagetools';
6
- import { VitePWA } from 'vite-plugin-pwa';
7
- import siteConfig from './src/data/site-config';
8
- import remarkSlug from 'remark-slug';
9
- import customSlugify from './src/utils/remark-slugify';
10
- import { maugliConfig } from './src/config/maugli.config';
11
-
12
- export const pwaOptions = {
13
- registerType: 'autoUpdate',
14
- includeAssets: ['favicon.svg', 'favicon.ico', 'robots.txt', 'apple-touch-icon.png'],
15
- manifest: {
16
- name: "Maugli Blog",
17
- short_name: "Maugli",
18
- start_url: "/",
19
- display: "standalone",
20
- background_color: maugliConfig.pwa?.backgroundColor ?? '#ffffff',
21
- theme_color: maugliConfig.pwa?.themeColor ?? '#0cbf11',
22
- icons: maugliConfig.pwa?.icons ?? [
23
- {
24
- src: "/icon-192.png",
25
- sizes: "192x192",
26
- type: "image/png",
27
- purpose: "any maskable",
28
- },
29
- {
30
- src: "/icon-512.png",
31
- sizes: "512x512",
32
- type: "image/png",
33
- },
34
- ],
35
- },
36
- workbox: {
37
- navigateFallback: '/index.html',
38
- cleanupOutdatedCaches: true,
39
- navigateFallbackDenylist: [/^\/api\//],
40
- clientsClaim: true,
41
- globPatterns: ['**/*.{js,css,html,png,jpg,jpeg,webp,svg}'],
42
- runtimeCaching: [
43
- {
44
- urlPattern: ({ request }) => request.destination === 'image',
45
- handler: 'CacheFirst',
46
- options: {
47
- cacheName: 'images-cache',
48
- expiration: {
49
- maxEntries: 50,
50
- maxAgeSeconds: 30 * 24 * 60 * 60 // 30 дней
51
- }
52
- }
53
- },
54
- {
55
- urlPattern: ({ request }) => request.destination === 'font',
56
- handler: 'CacheFirst',
57
- options: {
58
- cacheName: 'fonts-cache',
59
- expiration: {
60
- maxEntries: 20,
61
- maxAgeSeconds: 365 * 24 * 60 * 60 // 1 год
62
- }
63
- }
64
- }
65
- ]
66
- },
67
- devOptions: {
68
- enabled: true, // чтобы работал в деве
69
- type: 'module',
70
- }
71
- };
72
-
73
- // https://astro.build/config
74
- export default defineConfig({
75
- site: siteConfig.website,
76
- integrations: [
77
- mdx(),
78
- sitemap()
79
- ],
80
- vite: {
81
- plugins: [
82
- tailwindcss(),
83
- imagetools(),
84
- VitePWA(pwaOptions)
85
- ]
86
- },
87
- markdown: {
88
- remarkPlugins: [
89
- [remarkSlug, { slug: customSlugify }]
90
- ]
91
- }
92
- });