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 +51 -0
- package/package.json +9 -3
- package/public/blackbox-1200.webp +0 -0
- package/public/blackbox-400.webp +0 -0
- package/public/blackbox-800.webp +0 -0
- package/public/blackbox.webp +0 -0
- package/scripts/README-update-system.md +187 -0
- package/scripts/auto-update.js +123 -0
- package/scripts/check-version.js +244 -0
- package/scripts/update-all-blogs.js +198 -0
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.
|
|
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
|
package/public/blackbox-400.webp
CHANGED
|
Binary file
|
package/public/blackbox-800.webp
CHANGED
|
Binary file
|
package/public/blackbox.webp
CHANGED
|
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();
|