core-maugli 1.2.41 → 1.2.43

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/netlify.toml ADDED
@@ -0,0 +1,58 @@
1
+ # Netlify configuration generated from maugli.config.ts
2
+
3
+ [build]
4
+ command = "npm run build"
5
+ publish = "dist"
6
+
7
+ [build.environment]
8
+ NODE_VERSION = "18"
9
+ NPM_FLAGS = "--legacy-peer-deps"
10
+
11
+ # Netlify plugins
12
+ [[plugins]]
13
+ package = "@netlify/plugin-lighthouse"
14
+
15
+ [[plugins]]
16
+ package = "netlify-plugin-submit-sitemap"
17
+
18
+ [[plugins]]
19
+ package = "netlify-plugin-checklinks"
20
+
21
+ [[plugins]]
22
+ package = "netlify-plugin-image-optim"
23
+
24
+ [[plugins]]
25
+ package = "netlify-plugin-minify-html"
26
+
27
+ [[plugins]]
28
+ package = "netlify-plugin-inline-critical-css"
29
+
30
+ [[plugins]]
31
+ package = "netlify-plugin-hashfiles"
32
+
33
+ # Redirects
34
+ [[redirects]]
35
+ from = "/blog/feed.xml"
36
+ to = "/rss.xml"
37
+ status = 301
38
+
39
+ # Headers
40
+ [[headers]]
41
+ for = "/*"
42
+ [headers.values]
43
+ "X-Frame-Options" = "DENY"
44
+ [headers.values]
45
+ "X-Content-Type-Options" = "nosniff"
46
+ [headers.values]
47
+ "Referrer-Policy" = "strict-origin-when-cross-origin"
48
+
49
+ [[headers]]
50
+ for = "/img/*"
51
+ [headers.values]
52
+ "Cache-Control" = "public, max-age=31536000, immutable"
53
+
54
+ [[headers]]
55
+ for = "/*.webp"
56
+ [headers.values]
57
+ "Cache-Control" = "public, max-age=31536000, immutable"
58
+
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.41",
5
+ "version": "1.2.43",
6
6
  "license": "GPL-3.0-or-later OR Commercial",
7
7
  "repository": {
8
8
  "type": "git",
@@ -39,7 +39,8 @@
39
39
  "check-version": "node scripts/check-version.js",
40
40
  "auto-update": "node scripts/auto-update.js",
41
41
  "build:ci": "SKIP_VERSION_CHECK=true npm run build",
42
- "postinstall": "node scripts/upgrade-config.js && node scripts/setup-user-images.js",
42
+ "generate-netlify": "node scripts/generate-netlify-config.js",
43
+ "postinstall": "node scripts/upgrade-config.js && node scripts/setup-user-images.js && node scripts/generate-netlify-config.js",
43
44
  "generate-previews": "node scripts/generate-previews.js"
44
45
  },
45
46
  "dependencies": {
@@ -85,7 +86,8 @@
85
86
  "public/blackbox*.webp",
86
87
  "scripts",
87
88
  "bin",
88
- ".gitignore"
89
+ ".gitignore",
90
+ "netlify.toml"
89
91
  ],
90
92
  "bin": {
91
93
  "core-maugli": "bin/index.js"
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Generate netlify.toml from maugli.config.ts
5
+ * This script creates a Netlify configuration file based on the Maugli configuration
6
+ */
7
+
8
+ import fs from 'fs';
9
+ import os from 'os';
10
+ import path from 'path';
11
+ import ts from 'typescript';
12
+ import { fileURLToPath, pathToFileURL } from 'url';
13
+
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = path.dirname(__filename);
16
+
17
+ async function loadTsModule(filePath) {
18
+ const code = await fs.promises.readFile(filePath, 'utf8');
19
+ const js = ts.transpileModule(code, {
20
+ compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ES2020 }
21
+ }).outputText;
22
+ const tmp = path.join(os.tmpdir(), `netlify-gen-${Date.now()}.mjs`);
23
+ await fs.promises.writeFile(tmp, js, 'utf8');
24
+ const mod = await import(pathToFileURL(tmp).href);
25
+ await fs.promises.unlink(tmp);
26
+ return mod;
27
+ }
28
+
29
+ async function loadMaugliConfig() {
30
+ try {
31
+ // Try to load from user project first
32
+ const userConfigPath = path.join(process.cwd(), 'src/config/maugli.config.ts');
33
+ if (fs.existsSync(userConfigPath)) {
34
+ const mod = await loadTsModule(userConfigPath);
35
+ return mod.maugliConfig;
36
+ }
37
+
38
+ // Fallback to default config
39
+ const defaultConfigPath = path.join(__dirname, '../src/config/maugli.config.ts');
40
+ const mod = await loadTsModule(defaultConfigPath);
41
+ return mod.maugliConfig;
42
+ } catch (error) {
43
+ console.warn('Could not load maugli.config.ts:', error.message);
44
+ return null;
45
+ }
46
+ }
47
+
48
+ function generateNetlifyToml(config) {
49
+ const netlifyConfig = config.netlify || {};
50
+
51
+ let toml = `# Netlify configuration generated from maugli.config.ts\n\n`;
52
+
53
+ // Build settings
54
+ toml += `[build]\n`;
55
+ toml += ` command = "${netlifyConfig.buildCommand || 'npm run build'}"\n`;
56
+ toml += ` publish = "${netlifyConfig.publishDir || 'dist'}"\n\n`;
57
+
58
+ // Environment variables
59
+ if (netlifyConfig.environment) {
60
+ toml += `[build.environment]\n`;
61
+
62
+ // Add auto-update control
63
+ if (netlifyConfig.autoUpdate === false) {
64
+ toml += ` DISABLE_AUTO_UPDATE = "true"\n`;
65
+ }
66
+
67
+ for (const [key, value] of Object.entries(netlifyConfig.environment)) {
68
+ toml += ` ${key} = "${value}"\n`;
69
+ }
70
+ toml += `\n`;
71
+ } else if (netlifyConfig.autoUpdate === false) {
72
+ toml += `[build.environment]\n`;
73
+ toml += ` DISABLE_AUTO_UPDATE = "true"\n\n`;
74
+ }
75
+
76
+ // Plugins
77
+ if (netlifyConfig.plugins && netlifyConfig.plugins.length > 0) {
78
+ toml += `# Netlify plugins\n`;
79
+ netlifyConfig.plugins.forEach(plugin => {
80
+ toml += `[[plugins]]\n`;
81
+ toml += ` package = "${plugin}"\n\n`;
82
+ });
83
+ }
84
+
85
+ // Redirects
86
+ if (netlifyConfig.redirects && netlifyConfig.redirects.length > 0) {
87
+ toml += `# Redirects\n`;
88
+ netlifyConfig.redirects.forEach(redirect => {
89
+ toml += `[[redirects]]\n`;
90
+ toml += ` from = "${redirect.from}"\n`;
91
+ toml += ` to = "${redirect.to}"\n`;
92
+ toml += ` status = ${redirect.status || 301}\n`;
93
+ if (redirect.force) {
94
+ toml += ` force = true\n`;
95
+ }
96
+ toml += `\n`;
97
+ });
98
+ }
99
+
100
+ // Headers
101
+ if (netlifyConfig.headers && netlifyConfig.headers.length > 0) {
102
+ toml += `# Headers\n`;
103
+ netlifyConfig.headers.forEach(header => {
104
+ toml += `[[headers]]\n`;
105
+ toml += ` for = "${header.for}"\n`;
106
+ for (const [key, value] of Object.entries(header.values)) {
107
+ toml += ` [headers.values]\n`;
108
+ toml += ` "${key}" = "${value}"\n`;
109
+ }
110
+ toml += `\n`;
111
+ });
112
+ }
113
+
114
+ return toml;
115
+ }
116
+
117
+ async function main() {
118
+ console.log('🔧 Generating netlify.toml from maugli.config.ts...');
119
+
120
+ const config = await loadMaugliConfig();
121
+ if (!config) {
122
+ console.warn('⚠️ Could not load maugli configuration, skipping netlify.toml generation');
123
+ return;
124
+ }
125
+
126
+ const tomlContent = generateNetlifyToml(config);
127
+ const outputPath = path.join(process.cwd(), 'netlify.toml');
128
+
129
+ // Check if netlify.toml already exists
130
+ if (fs.existsSync(outputPath)) {
131
+ // Read existing content to check if it's auto-generated
132
+ const existingContent = fs.readFileSync(outputPath, 'utf8');
133
+ if (existingContent.includes('# Netlify configuration generated from maugli.config.ts')) {
134
+ console.log('🔄 Updating auto-generated netlify.toml...');
135
+ } else {
136
+ console.log('⚠️ Custom netlify.toml detected. Creating backup...');
137
+ fs.copyFileSync(outputPath, `${outputPath}.backup`);
138
+ }
139
+ }
140
+
141
+ fs.writeFileSync(outputPath, tomlContent, 'utf8');
142
+ console.log('✅ netlify.toml generated successfully!');
143
+
144
+ if (config.netlify?.autoUpdate === false) {
145
+ console.log('🚫 Auto-update disabled in Netlify configuration');
146
+ } else {
147
+ console.log('🔄 Auto-update enabled for Netlify builds');
148
+ }
149
+
150
+ // List installed plugins
151
+ if (config.netlify?.plugins && config.netlify.plugins.length > 0) {
152
+ console.log('🔌 Netlify plugins configured:');
153
+ config.netlify.plugins.forEach(plugin => {
154
+ console.log(` • ${plugin}`);
155
+ });
156
+ }
157
+
158
+ console.log('📁 File location:', outputPath);
159
+ }
160
+
161
+ main().catch(error => {
162
+ console.error('❌ Failed to generate netlify.toml:', error.message);
163
+ process.exit(1);
164
+ });
@@ -14,7 +14,7 @@ import { execSync } from 'child_process';
14
14
  import fs from 'fs';
15
15
  import path from 'path';
16
16
 
17
- const CURRENT_VERSION = '1.2.39';
17
+ const CURRENT_VERSION = '1.2.43';
18
18
 
19
19
  // Правильные скрипты для package.json
20
20
  const CORRECT_SCRIPTS = {
@@ -39,6 +39,7 @@ const CORRECT_SCRIPTS = {
39
39
  "check-version": "node scripts/check-version.js",
40
40
  "auto-update": "node scripts/auto-update.js",
41
41
  "build:ci": "SKIP_VERSION_CHECK=true npm run build",
42
+ "generate-netlify": "node scripts/generate-netlify-config.js",
42
43
  "postinstall": "node scripts/upgrade-config.js && node scripts/setup-user-images.js",
43
44
  "generate-previews": "node scripts/generate-previews.js"
44
45
  };
@@ -56,7 +57,9 @@ const REQUIRED_SCRIPTS = [
56
57
  'scripts/update-with-backup.js',
57
58
  'scripts/check-version.js',
58
59
  'scripts/auto-update.js',
59
- '.gitignore'
60
+ 'scripts/generate-netlify-config.js',
61
+ '.gitignore',
62
+ 'netlify.toml'
60
63
  ];
61
64
 
62
65
  function log(message, type = 'info') {
@@ -152,7 +155,23 @@ function updateBlogProject(projectPath) {
152
155
  process.chdir(absolutePath);
153
156
  execSync('npm update core-maugli', { stdio: 'pipe' });
154
157
 
155
- // 8. Результат
158
+ // 8. Генерируем netlify.toml
159
+ log('Generating netlify.toml configuration...', 'info');
160
+ const generateNetlifyScript = path.join(process.cwd(), 'scripts/generate-netlify-config.js');
161
+ if (fs.existsSync(generateNetlifyScript)) {
162
+ try {
163
+ const { execSync } = require('child_process');
164
+ execSync(`node "${generateNetlifyScript}"`, {
165
+ stdio: 'pipe',
166
+ cwd: absolutePath
167
+ });
168
+ log(' ✅ netlify.toml generated', 'success');
169
+ } catch (error) {
170
+ log(` ⚠️ netlify.toml generation failed: ${error.message}`, 'warn');
171
+ }
172
+ }
173
+
174
+ // 9. Результат
156
175
  log(`Project updated successfully!`, 'success');
157
176
  log(` Version: ${oldVersion} → ${CURRENT_VERSION}`, 'info');
158
177
  log(` Scripts updated: ${scriptsUpdated ? 'Yes' : 'No'}`, 'info');
@@ -192,6 +211,7 @@ function main() {
192
211
  log(' ✅ Correct core-maugli version', 'success');
193
212
  log(' ✅ Up-to-date build scripts', 'success');
194
213
  log(' ✅ Working image optimization', 'success');
214
+ log(' ✅ Auto-generated netlify.toml', 'success');
195
215
  }
196
216
  }
197
217
 
@@ -24,6 +24,24 @@ export interface MaugliConfig {
24
24
  url?: string; // User's repository URL for Netlify deployment button
25
25
  netlifyEnabled?: boolean; // Enable Netlify deployment button (default: true)
26
26
  };
27
+ // Netlify deployment configuration
28
+ netlify?: {
29
+ autoUpdate?: boolean; // Enable auto-update on Netlify (default: true)
30
+ plugins?: string[]; // Netlify plugins to install
31
+ buildCommand?: string; // Custom build command for Netlify
32
+ publishDir?: string; // Publish directory (default: "dist")
33
+ environment?: Record<string, string>; // Environment variables for Netlify
34
+ redirects?: Array<{
35
+ from: string;
36
+ to: string;
37
+ status?: number;
38
+ force?: boolean;
39
+ }>; // Custom redirects
40
+ headers?: Array<{
41
+ for: string;
42
+ values: Record<string, string>;
43
+ }>; // Custom headers
44
+ };
27
45
  // Brand and logo settings
28
46
  brand: {
29
47
  name: string; // Brand name
@@ -122,6 +140,54 @@ export const maugliConfig: MaugliConfig = {
122
140
  url: 'https://github.com/dashapps/core-maugli-blog', // User's repository URL for Netlify deployment button
123
141
  netlifyEnabled: true, // Enable Netlify deployment button (default: true)
124
142
  },
143
+ // Netlify deployment configuration
144
+ netlify: {
145
+ autoUpdate: true, // Enable auto-update on Netlify (default: true)
146
+ plugins: [
147
+ '@netlify/plugin-lighthouse', // Lighthouse performance audits
148
+ 'netlify-plugin-submit-sitemap', // Auto-submit sitemap to search engines
149
+ 'netlify-plugin-checklinks', // Check for broken links
150
+ 'netlify-plugin-image-optim', // Image optimization
151
+ 'netlify-plugin-minify-html', // HTML minification
152
+ 'netlify-plugin-inline-critical-css', // Inline critical CSS
153
+ 'netlify-plugin-hashfiles' // Cache optimization with file hashing
154
+ ], // Recommended Netlify plugins from UI
155
+ buildCommand: 'npm run build', // Default build command
156
+ publishDir: 'dist', // Astro output directory
157
+ environment: {
158
+ NODE_VERSION: '18',
159
+ NPM_FLAGS: '--legacy-peer-deps'
160
+ }, // Default environment variables
161
+ redirects: [
162
+ {
163
+ from: '/blog/feed.xml',
164
+ to: '/rss.xml',
165
+ status: 301
166
+ }
167
+ ], // Common redirects
168
+ headers: [
169
+ {
170
+ for: '/*',
171
+ values: {
172
+ 'X-Frame-Options': 'DENY',
173
+ 'X-Content-Type-Options': 'nosniff',
174
+ 'Referrer-Policy': 'strict-origin-when-cross-origin'
175
+ }
176
+ },
177
+ {
178
+ for: '/img/*',
179
+ values: {
180
+ 'Cache-Control': 'public, max-age=31536000, immutable'
181
+ }
182
+ },
183
+ {
184
+ for: '/*.webp',
185
+ values: {
186
+ 'Cache-Control': 'public, max-age=31536000, immutable'
187
+ }
188
+ }
189
+ ] // Security and performance headers
190
+ },
125
191
  enableThemeSwitcher: true, // Enable theme switcher (true by default)
126
192
  defaultTheme: 'dark', // Default theme (dark by default)
127
193
  seo: {