core-maugli 1.2.81 → 1.2.82

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/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.81",
5
+ "version": "1.2.82",
6
6
  "license": "GPL-3.0-or-later OR Commercial",
7
7
  "repository": {
8
8
  "type": "git",
@@ -42,12 +42,13 @@
42
42
  "build:ci": "SKIP_VERSION_CHECK=true npm run build",
43
43
  "init-netlify": "node scripts/copy-netlify-config.js",
44
44
  "set-force-update": "node scripts/set-force-update.js",
45
- "postinstall": "node scripts/upgrade-config.js && node scripts/setup-user-images.js",
45
+ "postinstall": "node scripts/postinstall.js",
46
46
  "generate-previews": "node scripts/generate-previews.js",
47
47
  "generate-netlify": "node scripts/generate-netlify-config.js",
48
- "verify-pack": "node scripts/verify-pack.js"
48
+ "verify-pack": "node scripts/verify-pack.js",
49
+ "clean:duplicates": "node scripts/cleanup-duplicates.js"
49
50
  },
50
- "prepublishOnly": "npm run verify-pack",
51
+ "prepublishOnly": "npm run clean:duplicates && npm run verify-pack",
51
52
  "dependencies": {
52
53
  "@astrojs/mdx": "^4.3.0",
53
54
  "@astrojs/rss": "^4.0.11",
@@ -46,20 +46,20 @@ async function getLatestVersion() {
46
46
 
47
47
  function compareVersions(current, latest) {
48
48
  if (!current || !latest) return false;
49
-
49
+
50
50
  current = current.replace(/^[\^~]/, '');
51
-
51
+
52
52
  const currentParts = current.split('.').map(Number);
53
53
  const latestParts = latest.split('.').map(Number);
54
-
54
+
55
55
  for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
56
56
  const currentPart = currentParts[i] || 0;
57
57
  const latestPart = latestParts[i] || 0;
58
-
58
+
59
59
  if (latestPart > currentPart) return true;
60
60
  if (latestPart < currentPart) return false;
61
61
  }
62
-
62
+
63
63
  return false;
64
64
  }
65
65
 
@@ -80,7 +80,7 @@ async function syncHelperFiles() {
80
80
  'scripts/check-version.js',
81
81
  'scripts/auto-update.js',
82
82
  'scripts/set-force-update.js',
83
- '.gitignore',
83
+ '.gitignore'
84
84
  ];
85
85
 
86
86
  async function sha256(p) {
@@ -117,28 +117,31 @@ async function syncHelperFiles() {
117
117
  }
118
118
 
119
119
  async function cleanupDuplicates() {
120
+ let removed = 0;
120
121
  async function walk(dir) {
121
122
  const ents = await fs.promises.readdir(dir, { withFileTypes: true });
122
123
  for (const e of ents) {
123
124
  const p = path.join(dir, e.name);
124
125
  if (e.isDirectory()) await walk(p);
125
- else if (/\s2(\.[^.]+)?$/i.test(e.name)) {
126
+ else if (/\s\d+(\.[^.]+)?$/i.test(e.name) || /\s?\(\d+\)(\.[^.]+)?$/i.test(e.name)) {
126
127
  await fs.promises.unlink(p).catch(() => {});
128
+ removed++;
127
129
  console.log(`✖ removed duplicate: ${path.relative(root, p)}`);
128
130
  }
129
131
  }
130
132
  }
131
133
  await walk(root);
134
+ console.log(`✖ total duplicates removed: ${removed}`);
132
135
  }
133
136
 
134
137
  await copyItems();
135
- await cleanupDuplicates().catch(e => console.warn('cleanup warning:', e.message));
138
+ await cleanupDuplicates().catch((e) => console.warn('cleanup warning:', e.message));
136
139
  }
137
140
 
138
141
  async function performAutoUpdate() {
139
142
  console.log(colorize('🤖 CI/CD Auto-update mode activated', 'cyan'));
140
143
  console.log(colorize('🔄 Updating core-maugli automatically...', 'blue'));
141
-
144
+
142
145
  try {
143
146
  // Check if update script exists
144
147
  const updateScriptPath = path.join(process.cwd(), 'scripts', 'update-all-blogs.js');
@@ -151,7 +154,7 @@ async function performAutoUpdate() {
151
154
  execSync('npm update core-maugli', { stdio: 'inherit' });
152
155
  await syncHelperFiles();
153
156
  }
154
-
157
+
155
158
  console.log(colorize('✅ Auto-update completed successfully!', 'green'));
156
159
  return true;
157
160
  } catch (error) {
@@ -162,36 +165,36 @@ async function performAutoUpdate() {
162
165
 
163
166
  async function main() {
164
167
  console.log(colorize('🔍 Checking for core-maugli updates...', 'cyan'));
165
-
168
+
166
169
  const currentVersion = await getCurrentVersion();
167
170
  const latestVersion = await getLatestVersion();
168
-
171
+
169
172
  if (!currentVersion || !latestVersion) {
170
173
  console.log(colorize('⚠️ Could not check version. Proceeding...', 'yellow'));
171
174
  return;
172
175
  }
173
-
176
+
174
177
  console.log(colorize(`📦 Current version: ${currentVersion}`, 'white'));
175
178
  console.log(colorize(`📦 Latest version: ${latestVersion}`, 'white'));
176
-
179
+
177
180
  if (!compareVersions(currentVersion, latestVersion)) {
178
181
  console.log(colorize('✅ Already using the latest version!', 'green'));
179
182
  return;
180
183
  }
181
-
184
+
182
185
  // Auto-update without prompts
183
186
  console.log(colorize(`🚀 New version ${latestVersion} available! Auto-updating...`, 'magenta'));
184
-
187
+
185
188
  const success = await performAutoUpdate();
186
189
  if (!success) {
187
190
  console.error(colorize('❌ Auto-update failed. Build may fail or produce unexpected results.', 'red'));
188
191
  process.exit(1);
189
192
  }
190
-
193
+
191
194
  console.log(colorize('✅ Ready to proceed with updated version!', 'green'));
192
195
  }
193
196
 
194
- main().catch(error => {
197
+ main().catch((error) => {
195
198
  console.error(colorize('❌ Auto-update check failed:', 'red'), error.message);
196
199
  process.exit(1);
197
200
  });
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ import { promises as fs } from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ const dirs = ['src/components', 'src/utils', 'public/flags'];
6
+ const patterns = [/\(\d+\)$/i, /\s\d+$/i, /- copy$/i, /_copy$/i];
7
+
8
+ async function scan(dir) {
9
+ let entries;
10
+ try {
11
+ entries = await fs.readdir(dir, { withFileTypes: true });
12
+ } catch {
13
+ return;
14
+ }
15
+ for (const entry of entries) {
16
+ const fullPath = path.join(dir, entry.name);
17
+ if (entry.isDirectory()) {
18
+ await scan(fullPath);
19
+ continue;
20
+ }
21
+ const base = path.basename(entry.name, path.extname(entry.name));
22
+ if (patterns.some((p) => p.test(base))) {
23
+ await fs.unlink(fullPath);
24
+ console.log(`Removed duplicate: ${fullPath}`);
25
+ }
26
+ }
27
+ }
28
+
29
+ for (const dir of dirs) {
30
+ await scan(dir);
31
+ }
@@ -0,0 +1,47 @@
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
+ async function runUpgrade() {
11
+ const upgradePath = path.join(__dirname, 'upgrade-config.js');
12
+ await import(pathToFileURL(upgradePath).href);
13
+ }
14
+
15
+ async function runSetupImages() {
16
+ const { setupUserImages } = await import('./setup-user-images.js');
17
+ await setupUserImages();
18
+ }
19
+
20
+ async function main() {
21
+ const pkgPath = path.join(__dirname, '..', 'package.json');
22
+ const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf8'));
23
+ const currentVersion = pkg.version;
24
+
25
+ const userRoot = process.env.INIT_CWD || process.cwd();
26
+ const versionFile = path.join(userRoot, '.core-maugli-version');
27
+
28
+ let previousVersion = null;
29
+ try {
30
+ previousVersion = (await fs.readFile(versionFile, 'utf8')).trim();
31
+ } catch {}
32
+
33
+ if (previousVersion !== currentVersion) {
34
+ console.log(`Detected core-maugli version change (${previousVersion || 'none'} -> ${currentVersion}).`);
35
+ await runUpgrade();
36
+ await fs.writeFile(versionFile, currentVersion, 'utf8');
37
+ } else {
38
+ console.log(`core-maugli version ${currentVersion} unchanged, skipping upgrade.`);
39
+ }
40
+
41
+ await runSetupImages();
42
+ }
43
+
44
+ main().catch((err) => {
45
+ console.error('Postinstall failed:', err);
46
+ process.exit(1);
47
+ });
@@ -63,7 +63,12 @@ const PRESERVE_PATHS = [
63
63
  ];
64
64
 
65
65
  // Дополнительные паттерны для мусорных файлов
66
- const EXTRA_STALE_PATTERNS = [/\s[0-9]+\.(astro|jsx?|tsx?|mjs|cjs|css|json)$/i, /~$/i];
66
+ const EXTRA_STALE_PATTERNS = [
67
+ /\s[0-9]+\.(astro|jsx?|tsx?|mjs|cjs|css|json)$/i, // "file 1.js"
68
+ /\(\d+\)\.(astro|tsx?|jsx?|mjs|cjs|css|json)$/i, // "file(1).js"
69
+ /(?:[\s_-](?:копия|copy))\.(astro|tsx?|jsx?|mjs|cjs|css|json)$/i, // "file - копия.js" или "file_copy.js"
70
+ /~$/i
71
+ ];
67
72
 
68
73
  // Рекурсивный обход проекта
69
74
  async function walk(dir, visitor) {
@@ -103,12 +108,16 @@ async function cleanup() {
103
108
 
104
109
  // Удаляем дубликаты и временные файлы внутри FORCE_UPDATE_PATHS
105
110
  await walk(userRoot, async (p, dir) => {
111
+ const base = path.basename(p);
106
112
  if (dir) {
107
- if (isInsideForcePaths(p) && /\s[0-9]+$/.test(path.basename(p))) {
113
+ if (
114
+ isInsideForcePaths(p) &&
115
+ (/\s[0-9]+$/.test(base) || /\(\d+\)$/.test(base) || /(?:[\s_-](?:копия|copy))$/i.test(base))
116
+ ) {
108
117
  await fs.rm(p, { recursive: true, force: true });
109
118
  removed.push(path.relative(userRoot, p));
110
119
  }
111
- } else if (isInsideForcePaths(p) && EXTRA_STALE_PATTERNS.some((rx) => rx.test(path.basename(p)))) {
120
+ } else if (isInsideForcePaths(p) && EXTRA_STALE_PATTERNS.some((rx) => rx.test(base))) {
112
121
  await fs.rm(p, { force: true });
113
122
  removed.push(path.relative(userRoot, p));
114
123
  }
@@ -9,17 +9,6 @@ import { fileURLToPath, pathToFileURL } from 'url';
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
-
23
12
  const defaultConfigPath = path.join(__dirname, '../src/config/maugli.config.ts');
24
13
  const userRoot = process.env.INIT_CWD || process.cwd();
25
14
  const userConfigPath = path.join(userRoot, 'src/config/maugli.config.ts');
@@ -55,14 +44,6 @@ function mergeMissing(target, source) {
55
44
 
56
45
  async function main() {
57
46
  console.log('🔄 Starting Maugli upgrade process...');
58
-
59
- // Сначала обновляем компоненты
60
- const updateComponents = await importUpdateComponents();
61
- if (updateComponents) {
62
- await updateComponents();
63
- }
64
-
65
- // Затем обновляем конфиг
66
47
  const pkg = await loadTsModule(defaultConfigPath);
67
48
  const defCfg = pkg.maugliConfig;
68
49
  const newVersion = pkg.MAUGLI_CONFIG_VERSION || defCfg.configVersion;
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { execSync } from 'node:child_process';
3
- import { readFileSync, statSync } from 'node:fs';
3
+ import { readFileSync, statSync, readdirSync } from 'node:fs';
4
+ import path from 'node:path';
4
5
 
5
6
  // Run `npm pack --dry-run` and capture JSON output describing package contents
6
7
  const env = { ...process.env, npm_config_loglevel: 'error' };
@@ -44,4 +45,31 @@ if (missing.length > 0) {
44
45
  process.exit(1);
45
46
  }
46
47
 
48
+ const duplicatePatterns = [/\(\d+\)$/i, /\s\d+$/i, /- copy$/i, /_copy$/i];
49
+ const duplicateDirs = ['src/components', 'src/utils', 'public/flags'];
50
+
51
+ function findDuplicates(dir, results = []) {
52
+ let entries;
53
+ try {
54
+ entries = readdirSync(dir, { withFileTypes: true });
55
+ } catch {
56
+ return results;
57
+ }
58
+ for (const entry of entries) {
59
+ const full = path.join(dir, entry.name);
60
+ if (entry.isDirectory()) {
61
+ findDuplicates(full, results);
62
+ } else {
63
+ const base = path.basename(entry.name, path.extname(entry.name));
64
+ if (duplicatePatterns.some((p) => p.test(base))) results.push(full);
65
+ }
66
+ }
67
+ return results;
68
+ }
69
+
70
+ const duplicates = duplicateDirs.flatMap((d) => findDuplicates(d));
71
+ if (duplicates.length > 0) {
72
+ console.warn('Warning: duplicate files detected:', duplicates.join(', '));
73
+ }
74
+
47
75
  console.log('All required package files are present.');
@@ -175,7 +175,7 @@ let defaultAuthorName = defaultAuthor.data.name;
175
175
  if ('serviceWorker' in navigator) {
176
176
  window.addEventListener('load', async () => {
177
177
  try {
178
- const registration = await navigator.serviceWorker.register('/sw.js');
178
+ const registration = await navigator.serviceWorker.register(`${import.meta.env.BASE_URL}sw.js`);
179
179
  console.log('SW registered: ', registration);
180
180
  } catch (registrationError) {
181
181
  console.log('SW registration failed: ', registrationError);
@@ -56,7 +56,7 @@ jsonld:
56
56
  '@type': 'Offer'
57
57
  'priceCurrency': 'USD'
58
58
  'price': '0'
59
- 'url': 'https://freeblog.maugli.ru'
59
+ 'url': 'https://www.npmjs.com/package/core-maugli'
60
60
 
61
61
  isExample: true
62
62
  ---
@@ -157,6 +157,6 @@ Maugli Free Blog спроектирован для лёгкой развертк
157
157
 
158
158
  ## **Где взять?**
159
159
 
160
- - **GitHub:** [ссылка].
160
+ - **NPM:** [core-maugli](https://www.npmjs.com/package/core-maugli)
161
161
 
162
162
  **Maugli Free Blog — это платформа, созданная для автоматизации, SEO и AI-интеграций.**
@@ -0,0 +1,6 @@
1
+ import { buildSW } from 'virtual:pwa-register';
2
+
3
+ export const GET = async () =>
4
+ new Response(await buildSW(), {
5
+ headers: { 'Content-Type': 'application/javascript' }
6
+ });
@@ -157,7 +157,13 @@
157
157
  --tw-prose-captions: var(--text-muted);
158
158
  }
159
159
 
160
- .prose p,
160
+ .prose p {
161
+ font-size: 1em;
162
+ margin: 0 0 0.9em;
163
+ color: var(--text-main) 85%;
164
+ line-height: 1.65 !important;
165
+ }
166
+
161
167
  .prose li {
162
168
  line-height: 1.65 !important;
163
169
  }
@@ -188,6 +194,44 @@
188
194
  }
189
195
 
190
196
  /* Ссылки — читаемые и неядрёные */
197
+
198
+ /* Таблицы — перегородки (границы) в цвет мутед-бэкграунда */
199
+ .prose table {
200
+ border-collapse: collapse;
201
+ margin-top: 16px;
202
+ }
203
+ .prose th,
204
+ .prose td {
205
+ border-top: 1px solid var(--bg-muted);
206
+ border-bottom: 1px solid var(--bg-muted);
207
+ border-left: none;
208
+ border-right: none;
209
+ }
210
+ .prose thead th {
211
+ background: none !important;
212
+ font-size: 1em;
213
+ color: var(--text-heading);
214
+ border-top: none !important;
215
+ font-weight: 700;
216
+ }
217
+ .prose th,
218
+ .prose td {
219
+ font-size: 1em;
220
+ color: color-mix(in srgb, var(--text-main) 80%, transparent);
221
+ }
222
+ html.dark .prose thead th {
223
+ background: none;
224
+ }
225
+ html.dark .prose th,
226
+ html.dark .prose td {
227
+ border-top-color: none;
228
+ border-bottom-color: var(--bg-muted);
229
+ border-left: none;
230
+ border-right: none;
231
+ }
232
+ html.dark .prose thead th {
233
+ background: none !important;
234
+ }
191
235
  .prose a {
192
236
  color: color-mix(in srgb, var(--color-brand) 80%, var(--text-main));
193
237
  text-decoration: underline;