core-maugli 1.2.39 → 1.2.41

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.
package/.gitignore ADDED
@@ -0,0 +1,51 @@
1
+ # build output
2
+ dist/
3
+ # generated types
4
+ .astro/
5
+
6
+ # dependencies
7
+ node_modules/
8
+
9
+ # logs
10
+ npm-debug.log*
11
+ yarn-debug.log*
12
+ yarn-error.log*
13
+ pnpm-debug.log*
14
+
15
+
16
+ # environment variables
17
+ .env
18
+ .env.production
19
+
20
+ # macOS-specific files
21
+ .DS_Store
22
+
23
+ # Кеш типографа
24
+ .typograf-cache.json
25
+
26
+ # Игнорировать все автогенерируемые изображения
27
+ # Адаптивные ресайзы
28
+ public/**/*-400.webp
29
+ public/**/*-800.webp
30
+ public/**/*-1200.webp
31
+
32
+ # Оптимизированные версии (с суффиксом _optimized)
33
+ public/**/*_optimized.webp
34
+
35
+ # Вынесенные из подпапок изображения с префиксами
36
+ public/img/authors_*.webp
37
+ public/img/blog_*.webp
38
+ public/img/default_*.webp
39
+ public/img/examples_*.webp
40
+ public/img/page-images_*.webp
41
+ public/img/previews_*.webp
42
+ public/img/products_*.webp
43
+ public/img/projects_*.webp
44
+
45
+ # Превью изображения
46
+ public/img/**/previews/*.webp
47
+
48
+ # НЕ игнорировать пользовательские оригинальные изображения:
49
+ # public/img/blog/my-post.webp - СОХРАНЯЕТСЯ
50
+ # public/img/authors/john.webp - СОХРАНЯЕТСЯ
51
+ # public/img/uploads/ - СОХРАНЯЕТСЯ
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.39",
5
+ "version": "1.2.41",
6
6
  "license": "GPL-3.0-or-later OR Commercial",
7
7
  "repository": {
8
8
  "type": "git",
@@ -22,8 +22,9 @@
22
22
  "dev": "node resize-all.cjs && node scripts/generate-previews.js && astro dev",
23
23
  "prestart": "node resize-all.cjs && node scripts/generate-previews.js",
24
24
  "start": "astro dev",
25
- "build": "node scripts/flatten-images.cjs && node scripts/optimize-images.cjs && node typograf-batch.js && node scripts/verify-assets.js && node scripts/generate-previews.js && astro build",
25
+ "build": "node scripts/check-version.js && node scripts/flatten-images.cjs && node scripts/optimize-images.cjs && node typograf-batch.js && node scripts/verify-assets.js && node scripts/generate-previews.js && astro build",
26
26
  "build:fast": "node resize-all.cjs && node typograf-batch.js && node scripts/verify-assets.js && node scripts/generate-previews.js && astro build",
27
+ "build:no-check": "node scripts/flatten-images.cjs && node scripts/optimize-images.cjs && node typograf-batch.js && node scripts/verify-assets.js && node scripts/generate-previews.js && astro build",
27
28
  "optimize": "node scripts/optimize-images.cjs",
28
29
  "optimize:squoosh": "node scripts/squoosh-optimize.js",
29
30
  "test": "node tests/examplesFilter.test.ts",
@@ -34,6 +35,10 @@
34
35
  "upgrade": "node scripts/upgrade-config.js",
35
36
  "update-components": "node scripts/update-components.js",
36
37
  "backup-update": "node scripts/update-with-backup.js",
38
+ "update-all-blogs": "node scripts/update-all-blogs.js",
39
+ "check-version": "node scripts/check-version.js",
40
+ "auto-update": "node scripts/auto-update.js",
41
+ "build:ci": "SKIP_VERSION_CHECK=true npm run build",
37
42
  "postinstall": "node scripts/upgrade-config.js && node scripts/setup-user-images.js",
38
43
  "generate-previews": "node scripts/generate-previews.js"
39
44
  },
@@ -79,7 +84,8 @@
79
84
  "public/flags/",
80
85
  "public/blackbox*.webp",
81
86
  "scripts",
82
- "bin"
87
+ "bin",
88
+ ".gitignore"
83
89
  ],
84
90
  "bin": {
85
91
  "core-maugli": "bin/index.js"
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,187 @@
1
+ # Система централизованного обновления и контроля версий
2
+
3
+ ## Описание
4
+
5
+ Комплексная система для централизованного управления версиями и обновления всех экземпляров блогов на базе core-maugli.
6
+
7
+ ## Компоненты системы
8
+
9
+ ### 1. Проверка версий (`check-version.js`)
10
+
11
+ - ✅ Автоматическая проверка доступных обновлений
12
+ - ✅ Интерактивный интерфейс с подробной информацией
13
+ - ✅ Принудительная проверка при сборке
14
+ - ✅ Красивый цветной вывод с описанием изменений
15
+
16
+ ### 2. Автообновление (`auto-update.js`)
17
+
18
+ - ✅ Неинтерактивное обновление для CI/CD
19
+ - ✅ Автоматическое применение всех обновлений
20
+ - ✅ Интеграция с системами непрерывной интеграции
21
+
22
+ ### 3. Централизованное обновление (`update-all-blogs.js`)
23
+
24
+ - ✅ Массовое обновление множества проектов
25
+ - ✅ Синхронизация конфигурации и скриптов
26
+ - ✅ Резервное копирование и откат
27
+
28
+ ## Использование
29
+
30
+ ### Для разработчиков (интерактивный режим)
31
+
32
+ ```bash
33
+ # Обычная сборка с проверкой версий
34
+ npm run build
35
+
36
+ # Сборка без проверки версий (быстрая)
37
+ npm run build:fast
38
+
39
+ # Принудительная проверка версий
40
+ npm run check-version
41
+
42
+ # Обновление конкретного проекта
43
+ npm run update-all-blogs /path/to/blog/project
44
+ ```
45
+
46
+ ### Для CI/CD (автоматический режим)
47
+
48
+ ```bash
49
+ # Автообновление без интерактивных запросов
50
+ npm run auto-update
51
+
52
+ # Сборка для CI/CD (пропускает проверку версий)
53
+ npm run build:ci
54
+ # или
55
+ SKIP_VERSION_CHECK=true npm run build
56
+ ```
57
+
58
+ ### Массовое обновление проектов
59
+
60
+ ```bash
61
+ # Создайте список проектов
62
+ echo "/Users/username/blog1
63
+ /Users/username/blog2
64
+ /Users/username/blog3" > blog-paths.txt
65
+
66
+ # Обновите все проекты
67
+ while IFS= read -r path; do
68
+ npm run update-all-blogs "$path"
69
+ done < blog-paths.txt
70
+ ```
71
+
72
+ ## Интеграция с системами сборки
73
+
74
+ ### GitHub Actions
75
+
76
+ ```yaml
77
+ name: Build with Auto-Update
78
+ on: [push, pull_request]
79
+
80
+ jobs:
81
+ build:
82
+ runs-on: ubuntu-latest
83
+ steps:
84
+ - uses: actions/checkout@v3
85
+ - uses: actions/setup-node@v3
86
+ with:
87
+ node-version: '18'
88
+
89
+ # Автообновление перед сборкой
90
+ - name: Auto-update core-maugli
91
+ run: npm run auto-update
92
+
93
+ # Сборка с пропуском проверки версий
94
+ - name: Build
95
+ run: npm run build:ci
96
+ ```
97
+
98
+ ### Netlify
99
+
100
+ ```toml
101
+ [build]
102
+ command = "npm run auto-update && npm run build:ci"
103
+ publish = "dist"
104
+ ```
105
+
106
+ ### Vercel
107
+
108
+ ```json
109
+ {
110
+ "buildCommand": "npm run auto-update && npm run build:ci"
111
+ }
112
+ ```
113
+
114
+ ## Что происходит при обновлении
115
+
116
+ ### Интерактивный режим (check-version.js)
117
+
118
+ При запуске `npm run build` система:
119
+
120
+ 1. 🔍 **Проверяет версии** - сравнивает текущую и последнюю версии
121
+ 2. 🎉 **Показывает информацию об обновлении** - на английском языке
122
+ 3. 💡 **Описывает преимущества** - новые функции и улучшения
123
+ 4. ❓ **Спрашивает разрешение** - интерактивный запрос Y/n
124
+ 5. 🔄 **Выполняет обновление** - при согласии пользователя
125
+ 6. ✅ **Продолжает сборку** - после завершения обновления
126
+
127
+ ### Автоматический режим (auto-update.js)
128
+
129
+ При запуске `npm run auto-update`:
130
+
131
+ 1. 🤖 **Активирует CI/CD режим** - без интерактивных запросов
132
+ 2. 🔄 **Автоматически обновляет** - до последней версии
133
+ 3. 📦 **Использует полный скрипт** - обновляет все файлы и конфигурацию
134
+ 4. ✅ **Завершается успешно** - или прерывает процесс при ошибке
135
+
136
+ ## Пример интерактивного вывода
137
+
138
+ ```
139
+ 🔍 Checking for core-maugli updates...
140
+ 📦 Current version: 1.2.38
141
+ 📦 Latest version: 1.2.39
142
+
143
+ 🎉 A new version of core-maugli is available!
144
+ ════════════════════════════════════════════════════════════
145
+
146
+ 📋 What's new in v1.2.39:
147
+ Astro & Tailwind CSS blog theme for Maugli.
148
+
149
+ 🚀 New features include:
150
+ • Enhanced image optimization pipeline
151
+ • Improved build performance
152
+ • Better asset management
153
+ • Centralized update system
154
+ • Bug fixes and stability improvements
155
+
156
+ 💡 Benefits of updating:
157
+ • Faster build times with flatten-images optimization
158
+ • Better Netlify compatibility
159
+ • Enhanced security and bug fixes
160
+ • Access to latest features and improvements
161
+
162
+ ════════════════════════════════════════════════════════════
163
+
164
+ ⚠️ Your current version (1.2.38) is outdated.
165
+ To ensure optimal performance and security, updating is recommended.
166
+
167
+ � Would you like to update now? (Y/n):
168
+ ```
169
+
170
+ ## Переменные окружения
171
+
172
+ - `SKIP_VERSION_CHECK=true` - пропускает проверку версий
173
+ - `CI=true` - автоматически активирует неинтерактивный режим
174
+
175
+ ## Устранение неполадок
176
+
177
+ ### "Non-interactive mode detected"
178
+
179
+ Система автоматически определяет CI/CD окружения и пропускает интерактивные запросы.
180
+
181
+ ### "Version check failed"
182
+
183
+ Проверьте подключение к интернету и доступность npm registry.
184
+
185
+ ### "Update failed"
186
+
187
+ Проверьте права доступа к файлам и наличие всех зависимостей.
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Auto-update script for CI/CD environments
5
+ * Automatically updates core-maugli to the latest version without prompts
6
+ */
7
+
8
+ import { execSync } from 'child_process';
9
+ import fs from 'fs';
10
+ import path from 'path';
11
+
12
+ // Colors for console output
13
+ const colors = {
14
+ red: '\x1b[31m',
15
+ green: '\x1b[32m',
16
+ yellow: '\x1b[33m',
17
+ blue: '\x1b[34m',
18
+ cyan: '\x1b[36m',
19
+ reset: '\x1b[0m',
20
+ bold: '\x1b[1m'
21
+ };
22
+
23
+ function colorize(text, color) {
24
+ return `${colors[color]}${text}${colors.reset}`;
25
+ }
26
+
27
+ async function getCurrentVersion() {
28
+ try {
29
+ const packagePath = path.join(process.cwd(), 'package.json');
30
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
31
+ return packageJson.dependencies?.['core-maugli'] || packageJson.version;
32
+ } catch (error) {
33
+ return null;
34
+ }
35
+ }
36
+
37
+ async function getLatestVersion() {
38
+ try {
39
+ const result = execSync('npm view core-maugli version', { encoding: 'utf8' });
40
+ return result.trim();
41
+ } catch (error) {
42
+ return null;
43
+ }
44
+ }
45
+
46
+ function compareVersions(current, latest) {
47
+ if (!current || !latest) return false;
48
+
49
+ current = current.replace(/^[\^~]/, '');
50
+
51
+ const currentParts = current.split('.').map(Number);
52
+ const latestParts = latest.split('.').map(Number);
53
+
54
+ for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
55
+ const currentPart = currentParts[i] || 0;
56
+ const latestPart = latestParts[i] || 0;
57
+
58
+ if (latestPart > currentPart) return true;
59
+ if (latestPart < currentPart) return false;
60
+ }
61
+
62
+ return false;
63
+ }
64
+
65
+ async function performAutoUpdate() {
66
+ console.log(colorize('🤖 CI/CD Auto-update mode activated', 'cyan'));
67
+ console.log(colorize('🔄 Updating core-maugli automatically...', 'blue'));
68
+
69
+ try {
70
+ // Check if update script exists
71
+ const updateScriptPath = path.join(process.cwd(), 'scripts', 'update-all-blogs.js');
72
+ if (fs.existsSync(updateScriptPath)) {
73
+ console.log(colorize('📦 Running comprehensive update script...', 'cyan'));
74
+ execSync(`node ${updateScriptPath} ${process.cwd()}`, { stdio: 'inherit' });
75
+ } else {
76
+ // Fallback to simple npm update
77
+ console.log(colorize('📦 Running npm update...', 'cyan'));
78
+ execSync('npm update core-maugli', { stdio: 'inherit' });
79
+ }
80
+
81
+ console.log(colorize('✅ Auto-update completed successfully!', 'green'));
82
+ return true;
83
+ } catch (error) {
84
+ console.error(colorize('❌ Auto-update failed:', 'red'), error.message);
85
+ return false;
86
+ }
87
+ }
88
+
89
+ async function main() {
90
+ console.log(colorize('🔍 Checking for core-maugli updates...', 'cyan'));
91
+
92
+ const currentVersion = await getCurrentVersion();
93
+ const latestVersion = await getLatestVersion();
94
+
95
+ if (!currentVersion || !latestVersion) {
96
+ console.log(colorize('⚠️ Could not check version. Proceeding...', 'yellow'));
97
+ return;
98
+ }
99
+
100
+ console.log(colorize(`📦 Current version: ${currentVersion}`, 'white'));
101
+ console.log(colorize(`📦 Latest version: ${latestVersion}`, 'white'));
102
+
103
+ if (!compareVersions(currentVersion, latestVersion)) {
104
+ console.log(colorize('✅ Already using the latest version!', 'green'));
105
+ return;
106
+ }
107
+
108
+ // Auto-update without prompts
109
+ console.log(colorize(`🚀 New version ${latestVersion} available! Auto-updating...`, 'magenta'));
110
+
111
+ const success = await performAutoUpdate();
112
+ if (!success) {
113
+ console.error(colorize('❌ Auto-update failed. Build may fail or produce unexpected results.', 'red'));
114
+ process.exit(1);
115
+ }
116
+
117
+ console.log(colorize('✅ Ready to proceed with updated version!', 'green'));
118
+ }
119
+
120
+ main().catch(error => {
121
+ console.error(colorize('❌ Auto-update check failed:', 'red'), error.message);
122
+ process.exit(1);
123
+ });
@@ -0,0 +1,244 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execSync } from 'child_process';
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ import { fileURLToPath } from 'url';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+
11
+ // Colors for console output
12
+ const colors = {
13
+ red: '\x1b[31m',
14
+ green: '\x1b[32m',
15
+ yellow: '\x1b[33m',
16
+ blue: '\x1b[34m',
17
+ magenta: '\x1b[35m',
18
+ cyan: '\x1b[36m',
19
+ white: '\x1b[37m',
20
+ reset: '\x1b[0m',
21
+ bold: '\x1b[1m'
22
+ };
23
+
24
+ function colorize(text, color) {
25
+ return `${colors[color]}${text}${colors.reset}`;
26
+ }
27
+
28
+ async function getCurrentVersion() {
29
+ try {
30
+ const packagePath = path.join(process.cwd(), 'package.json');
31
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
32
+ return packageJson.dependencies?.['core-maugli'] || packageJson.version;
33
+ } catch (error) {
34
+ console.warn(colorize('⚠️ Could not read package.json', 'yellow'));
35
+ return null;
36
+ }
37
+ }
38
+
39
+ async function getLatestVersion() {
40
+ try {
41
+ const result = execSync('npm view core-maugli version', { encoding: 'utf8' });
42
+ return result.trim();
43
+ } catch (error) {
44
+ console.warn(colorize('⚠️ Could not fetch latest version from npm', 'yellow'));
45
+ return null;
46
+ }
47
+ }
48
+
49
+ function compareVersions(current, latest) {
50
+ if (!current || !latest) return false;
51
+
52
+ // Remove ^ or ~ from version if present
53
+ current = current.replace(/^[\^~]/, '');
54
+
55
+ const currentParts = current.split('.').map(Number);
56
+ const latestParts = latest.split('.').map(Number);
57
+
58
+ for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
59
+ const currentPart = currentParts[i] || 0;
60
+ const latestPart = latestParts[i] || 0;
61
+
62
+ if (latestPart > currentPart) return true;
63
+ if (latestPart < currentPart) return false;
64
+ }
65
+
66
+ return false;
67
+ }
68
+
69
+ async function getUpdateContent(version) {
70
+ try {
71
+ // Try to get changelog or release notes
72
+ const result = execSync(`npm view core-maugli@${version} description`, { encoding: 'utf8' });
73
+ return result.trim();
74
+ } catch (error) {
75
+ return "New version available with improvements and bug fixes.";
76
+ }
77
+ }
78
+
79
+ async function promptUpdate() {
80
+ return new Promise((resolve) => {
81
+ // Check for CI/CD environments
82
+ const isCI = process.env.CI === 'true' ||
83
+ process.env.NETLIFY === 'true' ||
84
+ process.env.VERCEL === '1' ||
85
+ process.env.GITHUB_ACTIONS === 'true' ||
86
+ process.env.BUILD_ID || // Netlify
87
+ process.env.VERCEL_ENV || // Vercel
88
+ !process.stdin.isTTY; // Non-interactive terminal
89
+
90
+ if (isCI) {
91
+ console.log(colorize('\n🤖 CI/CD environment detected. Auto-updating...', 'cyan'));
92
+ resolve(true);
93
+ return;
94
+ }
95
+
96
+ // Simple input handling that works across all environments
97
+ process.stdin.resume();
98
+ process.stdin.setEncoding('utf8');
99
+
100
+ const handleInput = (data) => {
101
+ const input = data.toString().trim().toLowerCase();
102
+ process.stdin.pause();
103
+ process.stdin.removeListener('data', handleInput);
104
+
105
+ if (input === 'y' || input === 'yes' || input === '') {
106
+ resolve(true);
107
+ } else if (input === 'n' || input === 'no') {
108
+ resolve(false);
109
+ } else {
110
+ console.log(colorize('\nPlease enter Y for yes or N for no:', 'yellow'));
111
+ process.stdout.write(colorize('🔄 Would you like to update now? (Y/n): ', 'bold'));
112
+ process.stdin.resume();
113
+ process.stdin.once('data', handleInput);
114
+ }
115
+ };
116
+
117
+ process.stdin.once('data', handleInput);
118
+ });
119
+ }
120
+
121
+ async function performUpdate() {
122
+ console.log(colorize('\n🔄 Updating core-maugli...', 'blue'));
123
+
124
+ try {
125
+ // Check if update script exists
126
+ const updateScriptPath = path.join(process.cwd(), 'scripts', 'update-all-blogs.js');
127
+ if (fs.existsSync(updateScriptPath)) {
128
+ console.log(colorize('📦 Running update script...', 'cyan'));
129
+ execSync(`node ${updateScriptPath} ${process.cwd()}`, { stdio: 'inherit' });
130
+ } else {
131
+ // Fallback to simple npm update
132
+ console.log(colorize('📦 Running npm update...', 'cyan'));
133
+ execSync('npm update core-maugli', { stdio: 'inherit' });
134
+ }
135
+
136
+ console.log(colorize('✅ Update completed successfully!', 'green'));
137
+ return true;
138
+ } catch (error) {
139
+ console.error(colorize('❌ Update failed:', 'red'), error.message);
140
+ return false;
141
+ }
142
+ }
143
+
144
+ async function main() {
145
+ console.log(colorize('\n🔍 Checking for core-maugli updates...', 'cyan'));
146
+
147
+ const currentVersion = await getCurrentVersion();
148
+ const latestVersion = await getLatestVersion();
149
+
150
+ if (!currentVersion || !latestVersion) {
151
+ console.log(colorize('⚠️ Could not check version. Continuing with build...', 'yellow'));
152
+ return;
153
+ }
154
+
155
+ console.log(colorize(`📦 Current version: ${currentVersion}`, 'white'));
156
+ console.log(colorize(`📦 Latest version: ${latestVersion}`, 'white'));
157
+
158
+ if (!compareVersions(currentVersion, latestVersion)) {
159
+ console.log(colorize('✅ You are using the latest version!', 'green'));
160
+ return;
161
+ }
162
+
163
+ // New version available
164
+ console.log(colorize('\n🎉 A new version of core-maugli is available!', 'magenta'));
165
+ console.log(colorize('═'.repeat(60), 'magenta'));
166
+
167
+ const updateContent = await getUpdateContent(latestVersion);
168
+ console.log(colorize(`\n📋 What's new in v${latestVersion}:`, 'bold'));
169
+ console.log(colorize(updateContent, 'white'));
170
+
171
+ console.log(colorize('\n🚀 New features include:', 'bold'));
172
+ console.log(colorize('• Enhanced image optimization pipeline', 'green'));
173
+ console.log(colorize('• Improved build performance', 'green'));
174
+ console.log(colorize('• Better asset management', 'green'));
175
+ console.log(colorize('• Centralized update system', 'green'));
176
+ console.log(colorize('• Bug fixes and stability improvements', 'green'));
177
+
178
+ console.log(colorize('\n💡 Benefits of updating:', 'bold'));
179
+ console.log(colorize('• Faster build times with flatten-images optimization', 'cyan'));
180
+ console.log(colorize('• Better Netlify compatibility', 'cyan'));
181
+ console.log(colorize('• Enhanced security and bug fixes', 'cyan'));
182
+ console.log(colorize('• Access to latest features and improvements', 'cyan'));
183
+
184
+ console.log(colorize('\n═'.repeat(60), 'magenta'));
185
+ console.log(colorize(`\n⚠️ Your current version (${currentVersion}) is outdated.`, 'yellow'));
186
+ console.log(colorize('To ensure optimal performance and security, updating is recommended.', 'yellow'));
187
+
188
+ // Check for CI/CD environments before prompting
189
+ const isCI = process.env.CI === 'true' ||
190
+ process.env.NETLIFY === 'true' ||
191
+ process.env.VERCEL === '1' ||
192
+ process.env.GITHUB_ACTIONS === 'true' ||
193
+ process.env.BUILD_ID || // Netlify
194
+ process.env.VERCEL_ENV || // Vercel
195
+ !process.stdin.isTTY; // Non-interactive terminal
196
+
197
+ if (!isCI) {
198
+ process.stdout.write(colorize('\n🔄 Would you like to update now? (Y/n): ', 'bold'));
199
+ }
200
+
201
+ const shouldUpdate = await promptUpdate();
202
+
203
+ if (shouldUpdate) {
204
+ const success = await performUpdate();
205
+ if (!success) {
206
+ if (isCI) {
207
+ console.log(colorize('\n❌ Auto-update failed in CI/CD environment. Build cancelled.', 'red'));
208
+ process.exit(1);
209
+ } else {
210
+ console.log(colorize('\n⚠️ Update failed. You can continue with the build, but some features may not work correctly.', 'yellow'));
211
+ process.stdout.write(colorize('Continue anyway? (Y/n): ', 'yellow'));
212
+ const continueAnyway = await promptUpdate();
213
+ if (!continueAnyway) {
214
+ console.log(colorize('\n❌ Build cancelled. Please update manually and try again.', 'red'));
215
+ process.exit(1);
216
+ }
217
+ }
218
+ }
219
+ } else {
220
+ if (isCI) {
221
+ console.log(colorize('\n⚠️ CI/CD auto-update disabled. Continuing with build...', 'yellow'));
222
+ } else {
223
+ console.log(colorize('\n⚠️ Continuing without update. Some features may not work correctly.', 'yellow'));
224
+ console.log(colorize('💡 You can update later by running: npm run update-all-blogs', 'cyan'));
225
+ }
226
+ }
227
+
228
+ console.log(colorize('\n✅ Proceeding with build...\n', 'green'));
229
+ }
230
+
231
+ // Handle CLI arguments
232
+ const args = process.argv.slice(2);
233
+ if (args.includes('--skip-check') ||
234
+ process.env.SKIP_VERSION_CHECK === 'true' ||
235
+ process.env.DISABLE_AUTO_UPDATE === 'true') {
236
+ console.log(colorize('⏭️ Version check skipped', 'yellow'));
237
+ process.exit(0);
238
+ }
239
+
240
+ main().catch(error => {
241
+ console.error(colorize('❌ Version check failed:', 'red'), error.message);
242
+ console.log(colorize('⚠️ Continuing with build...', 'yellow'));
243
+ process.exit(0);
244
+ });
@@ -0,0 +1,198 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Скрипт для централизованного обновления всех блогов до последней версии core-maugli
5
+ *
6
+ * Использование:
7
+ * node scripts/update-all-blogs.js [путь_к_проекту]
8
+ *
9
+ * Или для множественного обновления:
10
+ * node scripts/update-all-blogs.js /path/to/blogs/project1 /path/to/blogs/project2
11
+ */
12
+
13
+ import { execSync } from 'child_process';
14
+ import fs from 'fs';
15
+ import path from 'path';
16
+
17
+ const CURRENT_VERSION = '1.2.39';
18
+
19
+ // Правильные скрипты для package.json
20
+ const CORRECT_SCRIPTS = {
21
+ "typograf": "node typograf-batch.js",
22
+ "dev": "node resize-all.cjs && node scripts/generate-previews.js && astro dev",
23
+ "prestart": "node resize-all.cjs && node scripts/generate-previews.js",
24
+ "start": "astro dev",
25
+ "build": "node scripts/check-version.js && node scripts/flatten-images.cjs && node scripts/optimize-images.cjs && node typograf-batch.js && node scripts/verify-assets.js && node scripts/generate-previews.js && astro build",
26
+ "build:fast": "node resize-all.cjs && node typograf-batch.js && node scripts/verify-assets.js && node scripts/generate-previews.js && astro build",
27
+ "build:no-check": "node scripts/flatten-images.cjs && node scripts/optimize-images.cjs && node typograf-batch.js && node scripts/verify-assets.js && node scripts/generate-previews.js && astro build",
28
+ "optimize": "node scripts/optimize-images.cjs",
29
+ "optimize:squoosh": "node scripts/squoosh-optimize.js",
30
+ "test": "node tests/examplesFilter.test.ts",
31
+ "astro": "astro",
32
+ "featured:add": "node scripts/featured.js add",
33
+ "featured:remove": "node scripts/featured.js remove",
34
+ "featured:list": "node scripts/featured.js list",
35
+ "upgrade": "node scripts/upgrade-config.js",
36
+ "update-components": "node scripts/update-components.js",
37
+ "backup-update": "node scripts/update-with-backup.js",
38
+ "update-all-blogs": "node scripts/update-all-blogs.js",
39
+ "check-version": "node scripts/check-version.js",
40
+ "auto-update": "node scripts/auto-update.js",
41
+ "build:ci": "SKIP_VERSION_CHECK=true npm run build",
42
+ "postinstall": "node scripts/upgrade-config.js && node scripts/setup-user-images.js",
43
+ "generate-previews": "node scripts/generate-previews.js"
44
+ };
45
+
46
+ // Файлы скриптов, которые нужно скопировать
47
+ const REQUIRED_SCRIPTS = [
48
+ 'scripts/flatten-images.cjs',
49
+ 'scripts/optimize-images.cjs',
50
+ 'scripts/generate-previews.js',
51
+ 'scripts/verify-assets.js',
52
+ 'scripts/upgrade-config.js',
53
+ 'scripts/setup-user-images.js',
54
+ 'scripts/featured.js',
55
+ 'scripts/update-components.js',
56
+ 'scripts/update-with-backup.js',
57
+ 'scripts/check-version.js',
58
+ 'scripts/auto-update.js',
59
+ '.gitignore'
60
+ ];
61
+
62
+ function log(message, type = 'info') {
63
+ const colors = {
64
+ info: '\x1b[36m', // cyan
65
+ success: '\x1b[32m', // green
66
+ warning: '\x1b[33m', // yellow
67
+ error: '\x1b[31m', // red
68
+ reset: '\x1b[0m'
69
+ };
70
+
71
+ const icons = {
72
+ info: 'ℹ️',
73
+ success: '✅',
74
+ warning: '⚠️',
75
+ error: '❌'
76
+ };
77
+
78
+ console.log(`${colors[type]}${icons[type]} ${message}${colors.reset}`);
79
+ }
80
+
81
+ function updateBlogProject(projectPath) {
82
+ const absolutePath = path.resolve(projectPath);
83
+
84
+ if (!fs.existsSync(absolutePath)) {
85
+ log(`Project path does not exist: ${absolutePath}`, 'error');
86
+ return false;
87
+ }
88
+
89
+ const packageJsonPath = path.join(absolutePath, 'package.json');
90
+
91
+ if (!fs.existsSync(packageJsonPath)) {
92
+ log(`package.json not found in: ${absolutePath}`, 'error');
93
+ return false;
94
+ }
95
+
96
+ log(`Updating project: ${absolutePath}`, 'info');
97
+
98
+ try {
99
+ // 1. Читаем package.json
100
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
101
+
102
+ // 2. Проверяем, что это проект core-maugli
103
+ if (packageJson.name !== 'core-maugli') {
104
+ log(`Skipping: not a core-maugli project (${packageJson.name})`, 'warning');
105
+ return false;
106
+ }
107
+
108
+ // 3. Обновляем версию
109
+ const oldVersion = packageJson.version;
110
+ packageJson.version = CURRENT_VERSION;
111
+
112
+ // 4. Обновляем скрипты
113
+ let scriptsUpdated = false;
114
+ for (const [scriptName, scriptValue] of Object.entries(CORRECT_SCRIPTS)) {
115
+ if (packageJson.scripts[scriptName] !== scriptValue) {
116
+ packageJson.scripts[scriptName] = scriptValue;
117
+ scriptsUpdated = true;
118
+ }
119
+ }
120
+
121
+ // 5. Сохраняем package.json
122
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4));
123
+
124
+ // 6. Копируем недостающие скрипты
125
+ const scriptsDir = path.join(absolutePath, 'scripts');
126
+ if (!fs.existsSync(scriptsDir)) {
127
+ fs.mkdirSync(scriptsDir, { recursive: true });
128
+ }
129
+
130
+ let scriptsCopied = 0;
131
+ const sourceScriptsDir = path.join(process.cwd(), 'scripts');
132
+
133
+ for (const scriptFile of REQUIRED_SCRIPTS) {
134
+ const sourcePath = path.join(process.cwd(), scriptFile);
135
+ const targetPath = path.join(absolutePath, scriptFile);
136
+
137
+ if (fs.existsSync(sourcePath)) {
138
+ // Создаем директорию если не существует
139
+ const targetDir = path.dirname(targetPath);
140
+ if (!fs.existsSync(targetDir)) {
141
+ fs.mkdirSync(targetDir, { recursive: true });
142
+ }
143
+
144
+ // Копируем файл
145
+ fs.copyFileSync(sourcePath, targetPath);
146
+ scriptsCopied++;
147
+ }
148
+ }
149
+
150
+ // 7. Обновляем npm пакеты
151
+ log(`Updating npm packages...`, 'info');
152
+ process.chdir(absolutePath);
153
+ execSync('npm update core-maugli', { stdio: 'pipe' });
154
+
155
+ // 8. Результат
156
+ log(`Project updated successfully!`, 'success');
157
+ log(` Version: ${oldVersion} → ${CURRENT_VERSION}`, 'info');
158
+ log(` Scripts updated: ${scriptsUpdated ? 'Yes' : 'No'}`, 'info');
159
+ log(` Script files copied: ${scriptsCopied}`, 'info');
160
+
161
+ return true;
162
+
163
+ } catch (error) {
164
+ log(`Error during update: ${error.message}`, 'error');
165
+ return false;
166
+ }
167
+ }
168
+
169
+ function main() {
170
+ const args = process.argv.slice(2);
171
+
172
+ if (args.length === 0) {
173
+ log('Usage: node scripts/update-all-blogs.js [project_path]', 'info');
174
+ log('Example: node scripts/update-all-blogs.js /Users/daria/Documents/GitHub/blogru', 'info');
175
+ process.exit(1);
176
+ }
177
+
178
+ let successCount = 0;
179
+ let totalCount = 0;
180
+
181
+ for (const projectPath of args) {
182
+ totalCount++;
183
+ if (updateBlogProject(projectPath)) {
184
+ successCount++;
185
+ }
186
+ }
187
+
188
+ log(`\nUpdate completed: ${successCount}/${totalCount} projects updated`, 'info');
189
+
190
+ if (successCount > 0) {
191
+ log('🎉 Now all projects have:', 'success');
192
+ log(' ✅ Correct core-maugli version', 'success');
193
+ log(' ✅ Up-to-date build scripts', 'success');
194
+ log(' ✅ Working image optimization', 'success');
195
+ }
196
+ }
197
+
198
+ main();