core-maugli 1.1.4 → 1.1.6
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/README.md +130 -52
- package/astro.config.mjs +8 -7
- package/bin/index.js +5 -19
- package/bin/init.js +51 -146
- package/package.json +19 -20
- package/src/config/maugli.config.ts +15 -1
- package/src/content/pages/about.md +40 -0
- package/src/content/pages/contact.md +10 -0
- package/src/styles/global.css +5 -4
- package/bin/version.js +0 -15
package/README.md
CHANGED
@@ -1,18 +1,12 @@
|
|
1
|
-
# Maugli Blog - Astro & Tailwind
|
1
|
+
# Maugli Blog - Astro & Tailwind CSS Theme by maugli.cfd
|
2
2
|
|
3
|
-
-
|
4
|
-
- 🇷🇺 Русский
|
5
|
-
- 🇪🇸 Español
|
6
|
-
- 🇩🇪 Deutsch
|
7
|
-
- 🇵🇹 Português
|
8
|
-
- 🇫🇷 Français
|
9
|
-
- 🇨🇳 中文
|
10
|
-
- 🇯🇵 日本語
|
3
|
+
Hi-perfomance, SEO&AI-SEO optimised
|
11
4
|
|
12
|
-
|
13
|
-
4. **Multilingual Support** - Enable/disable multiple languages (disabled by default)maugli.cfd
|
5
|
+
## Introduction
|
14
6
|
|
15
|
-
|
7
|
+
Maugli is a lightweight, agent-friendly blog that can integrate into an existing site or run as a standalone project. Link the blog's logo to your primary site by setting `brand.logoHref` in [`src/config/maugli.config.ts`](src/config/maugli.config.ts).
|
8
|
+
|
9
|
+
The theme includes a `product` entity for showcasing offerings. Rename it (for example, to "services") and hide or customize related menu items by editing the `navLinks` array in the same configuration file.
|
16
10
|
|
17
11
|
[](https://app.netlify.com/start/deploy?repository=https://github.com/dashapps/maugli-astro-theme)
|
18
12
|
|
@@ -33,7 +27,7 @@ netlify deploy --prod
|
|
33
27
|
|
34
28
|
## Getting started
|
35
29
|
|
36
|
-
To start a new project
|
30
|
+
To start a new project in an empty folder run:
|
37
31
|
|
38
32
|
```bash
|
39
33
|
npx core-maugli init my-blog
|
@@ -41,27 +35,23 @@ cd my-blog
|
|
41
35
|
npm run dev
|
42
36
|
```
|
43
37
|
|
44
|
-
|
38
|
+
To initialize inside the current folder use:
|
45
39
|
|
46
|
-
|
40
|
+
```bash
|
41
|
+
npx core-maugli init .
|
42
|
+
```
|
47
43
|
|
48
|
-
|
49
|
-
2. **Interface Language** - Choose from:
|
50
|
-
- 🇺🇸 English (default)
|
51
|
-
- 🇸 Español
|
52
|
-
- 🇩🇪 Deutsch
|
53
|
-
- �� Português
|
54
|
-
- �� Français
|
55
|
-
- 🇨🇳 中文
|
56
|
-
- 🇯🇵 日本語
|
57
|
-
3. **Main Domain** - Your main website URL (leave empty for local blog)
|
58
|
-
4. **Multilingual Support** - Enable/disable multiple languages (disabled by default)
|
44
|
+
The init script lets you choose a language or pass one with `--lang`. Available codes: `ru`, `en`, `es`, `de`, `pt`, `fr`, `zh`, `ja`.
|
59
45
|
|
60
|
-
|
46
|
+
Example:
|
47
|
+
|
48
|
+
```bash
|
49
|
+
npx core-maugli init my-blog --lang es
|
50
|
+
```
|
61
51
|
|
62
|
-
|
52
|
+
You pick the language only once during project creation; updates won't ask again.
|
63
53
|
|
64
|
-
|
54
|
+
Your blog will be available at `http://localhost:4321/`
|
65
55
|
|
66
56
|
1. **Install dependencies**
|
67
57
|
|
@@ -92,39 +82,109 @@ If you prefer to install without the interactive setup:
|
|
92
82
|
npm run build
|
93
83
|
```
|
94
84
|
|
95
|
-
|
85
|
+
`npm run build` runs [`scripts/verify-assets.js`](scripts/verify-assets.js)
|
86
|
+
before the Astro build. This script checks the SHA-256 hashes of the
|
87
|
+
floating label component and footer badge to ensure they haven't been
|
88
|
+
modified. The floating label's hash is validated to ensure compliance
|
89
|
+
with licensing.
|
96
90
|
|
97
|
-
|
91
|
+
If you hold a commercial license and legitimately change the label,
|
92
|
+
generate its new SHA-256 hash and replace the value for
|
93
|
+
`src/components/MaugliFloatingLabel.astro` in the `files` object of
|
94
|
+
[`scripts/verify-assets.js`](scripts/verify-assets.js). For example:
|
98
95
|
|
99
96
|
```bash
|
100
|
-
|
97
|
+
node -e "import { createHash } from 'crypto'; import { readFileSync } from 'fs'; console.log(createHash('sha256').update(readFileSync('src/components/MaugliFloatingLabel.astro')).digest('hex'))"
|
101
98
|
```
|
102
99
|
|
103
|
-
|
100
|
+
If you change these assets without updating their hashes in the
|
101
|
+
script, the build will fail.
|
102
|
+
|
103
|
+
### Customizing fonts
|
104
|
+
|
105
|
+
This project uses [Fontsource](https://fontsource.org/) for typography. To add a different font, install the desired package:
|
106
|
+
|
107
|
+
```bash
|
108
|
+
npm install @fontsource-variable/roboto
|
109
|
+
```
|
110
|
+
|
111
|
+
Then replace or add the corresponding `@import` line in [`src/styles/global.css`](src/styles/global.css):
|
112
|
+
|
113
|
+
```css
|
114
|
+
@import '@fontsource-variable/roboto/wght.css' layer(base);
|
115
|
+
```
|
116
|
+
|
117
|
+
Update the `--font-sans` or `--font-serif` variables in the same file so Tailwind uses the new font:
|
118
|
+
|
119
|
+
```css
|
120
|
+
--font-sans: 'Roboto Variable', sans-serif;
|
121
|
+
/* or */
|
122
|
+
--font-serif: 'Roboto Variable', sans-serif;
|
123
|
+
```
|
124
|
+
|
125
|
+
Repeat these steps for any other fonts you want to include.
|
126
|
+
|
127
|
+
### Configuring PWA colors and icons
|
128
|
+
|
129
|
+
Progressive Web App options live under the `pwa` key in [`src/config/maugli.config.ts`](src/config/maugli.config.ts). The section accepts:
|
104
130
|
|
105
|
-
|
131
|
+
- `themeColor` – used for the manifest's `theme_color` and the `<meta name="theme-color">` tag
|
132
|
+
- `backgroundColor` – controls the manifest's `background_color`
|
133
|
+
- `icons` – array of icon definitions with `src`, `sizes`, `type`, and optional `purpose`
|
106
134
|
|
107
|
-
|
135
|
+
Example configuration:
|
108
136
|
|
109
|
-
|
137
|
+
```ts
|
138
|
+
// src/config/maugli.config.ts
|
139
|
+
export const maugliConfig = {
|
140
|
+
// ...other fields
|
141
|
+
pwa: {
|
142
|
+
themeColor: '#0cbf11',
|
143
|
+
backgroundColor: '#ffffff',
|
144
|
+
icons: [
|
145
|
+
{ src: '/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any maskable' },
|
146
|
+
{ src: '/icon-512.png', sizes: '512x512', type: 'image/png' }
|
147
|
+
]
|
148
|
+
}
|
149
|
+
};
|
150
|
+
```
|
151
|
+
|
152
|
+
These values are referenced in `astro.config.mjs` when generating the manifest:
|
153
|
+
|
154
|
+
```js
|
155
|
+
// astro.config.mjs
|
156
|
+
import { maugliConfig } from './src/config/maugli.config';
|
157
|
+
|
158
|
+
export const pwaOptions = {
|
159
|
+
manifest: {
|
160
|
+
background_color: maugliConfig.pwa?.backgroundColor,
|
161
|
+
theme_color: maugliConfig.pwa?.themeColor,
|
162
|
+
icons: maugliConfig.pwa?.icons
|
163
|
+
}
|
164
|
+
};
|
165
|
+
```
|
166
|
+
|
167
|
+
Updating the values in `maugli.config.ts` automatically refreshes the PWA manifest generated by Astro.
|
168
|
+
|
169
|
+
### Testing
|
110
170
|
|
111
|
-
|
171
|
+
Run the test suite to verify that example content is filtered correctly:
|
112
172
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
173
|
+
```bash
|
174
|
+
npm test
|
175
|
+
```
|
176
|
+
|
177
|
+
All tests should complete without errors.
|
118
178
|
|
119
|
-
|
179
|
+
If you want to hide the example content included with this theme, set
|
180
|
+
`showExamples: false` in `src/config/maugli.config.ts`. Example files are
|
181
|
+
marked with `isExample: true` in their frontmatter.
|
120
182
|
|
121
|
-
|
183
|
+
To restore the default example posts and other sample content later, run:
|
122
184
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
| `npx core-maugli version` | Show package version |
|
127
|
-
| `npx core-maugli update` | Update config to latest version |
|
185
|
+
```bash
|
186
|
+
npx core-maugli init .
|
187
|
+
```
|
128
188
|
|
129
189
|
### Useful npm scripts
|
130
190
|
|
@@ -132,7 +192,7 @@ Example files are marked with `isExample: true` in their frontmatter.
|
|
132
192
|
| -------------------------------- | ------------------------------------------- |
|
133
193
|
| `npm run dev` | Start local dev server |
|
134
194
|
| `npm start` | Alias for `npm run dev` |
|
135
|
-
| `npm run build` | Format content then create production build |
|
195
|
+
| `npm run build` | Format content, verify assets, then create production build |
|
136
196
|
| `npm run typograf` | Run typograf on all posts |
|
137
197
|
| `npm run astro` | Access the Astro CLI |
|
138
198
|
| `npm run featured:add <slug>` | Mark a post as featured |
|
@@ -141,11 +201,29 @@ Example files are marked with `isExample: true` in their frontmatter.
|
|
141
201
|
| `npm run upgrade` | Manually update `maugli.config.ts` |
|
142
202
|
| `npm run backup-update` | Backup key files then run `npm update` |
|
143
203
|
|
204
|
+
## Checking installed version
|
205
|
+
|
206
|
+
See which version of the theme is installed:
|
207
|
+
|
208
|
+
```bash
|
209
|
+
npm list core-maugli
|
210
|
+
```
|
211
|
+
|
144
212
|
## Updating
|
145
213
|
|
146
|
-
|
214
|
+
Upgrade to the latest release:
|
215
|
+
|
216
|
+
```bash
|
217
|
+
npm update
|
218
|
+
```
|
219
|
+
|
220
|
+
To back up key files and then update, run:
|
221
|
+
|
222
|
+
```bash
|
223
|
+
npm run backup-update
|
224
|
+
```
|
147
225
|
|
148
|
-
|
226
|
+
Both commands replace the theme's components and layouts with the latest versions. Content under `src/content/**`, your stylesheet `src/styles/global.css` and your `src/config/maugli.config.ts` file are kept. Commit any local changes before updating.
|
149
227
|
|
150
228
|
## Licensing
|
151
229
|
|
package/astro.config.mjs
CHANGED
@@ -7,6 +7,7 @@ import { VitePWA } from 'vite-plugin-pwa';
|
|
7
7
|
import siteConfig from './src/data/site-config';
|
8
8
|
import remarkSlug from 'remark-slug';
|
9
9
|
import customSlugify from './src/utils/remark-slugify';
|
10
|
+
import { maugliConfig } from './src/config/maugli.config';
|
10
11
|
|
11
12
|
export const pwaOptions = {
|
12
13
|
registerType: 'autoUpdate',
|
@@ -16,21 +17,21 @@ export const pwaOptions = {
|
|
16
17
|
short_name: "Maugli",
|
17
18
|
start_url: "/",
|
18
19
|
display: "standalone",
|
19
|
-
background_color:
|
20
|
-
theme_color:
|
21
|
-
icons: [
|
20
|
+
background_color: maugliConfig.pwa?.backgroundColor ?? '#ffffff',
|
21
|
+
theme_color: maugliConfig.pwa?.themeColor ?? '#0cbf11',
|
22
|
+
icons: maugliConfig.pwa?.icons ?? [
|
22
23
|
{
|
23
24
|
src: "/icon-192.png",
|
24
25
|
sizes: "192x192",
|
25
26
|
type: "image/png",
|
26
|
-
purpose: "any maskable"
|
27
|
+
purpose: "any maskable",
|
27
28
|
},
|
28
29
|
{
|
29
30
|
src: "/icon-512.png",
|
30
31
|
sizes: "512x512",
|
31
|
-
type: "image/png"
|
32
|
-
}
|
33
|
-
]
|
32
|
+
type: "image/png",
|
33
|
+
},
|
34
|
+
],
|
34
35
|
},
|
35
36
|
workbox: {
|
36
37
|
navigateFallback: '/index.html',
|
package/bin/index.js
CHANGED
@@ -1,23 +1,9 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
2
|
const [, , cmd, target] = process.argv;
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
await import('./version.js');
|
10
|
-
} else if (cmd === 'update' || cmd === 'upgrade') {
|
11
|
-
await import('../scripts/upgrade-config.js');
|
12
|
-
} else {
|
13
|
-
console.log('Usage:');
|
14
|
-
console.log(' core-maugli init <project-name> Create a new blog');
|
15
|
-
console.log(' core-maugli version Show version');
|
16
|
-
console.log(' core-maugli update Update config to latest');
|
17
|
-
console.log('');
|
18
|
-
console.log('Example:');
|
19
|
-
console.log(' npx core-maugli init my-blog');
|
20
|
-
}
|
4
|
+
if (cmd === 'init') {
|
5
|
+
const mod = await import('./init.js');
|
6
|
+
await mod.default(target);
|
7
|
+
} else {
|
8
|
+
await import('../scripts/upgrade-config.js');
|
21
9
|
}
|
22
|
-
|
23
|
-
main().catch(console.error);
|
package/bin/init.js
CHANGED
@@ -1,107 +1,66 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
2
|
|
3
3
|
import { execSync } from 'child_process';
|
4
|
-
import { cpSync, existsSync,
|
4
|
+
import { cpSync, existsSync, readFileSync, writeFileSync } from 'fs';
|
5
5
|
import path from 'path';
|
6
|
+
import readline from 'readline';
|
6
7
|
import { fileURLToPath } from 'url';
|
7
8
|
|
8
9
|
const __filename = fileURLToPath(import.meta.url);
|
9
10
|
const __dirname = path.dirname(__filename);
|
10
11
|
const templateRoot = path.join(__dirname, '..');
|
11
12
|
|
12
|
-
|
13
|
-
const
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
{ title: 'Français', value: 'fr' },
|
20
|
-
{ title: '中文', value: 'zh' },
|
21
|
-
{ title: '日本語', value: 'ja' }
|
22
|
-
];
|
23
|
-
|
24
|
-
export default async function init(targetName) {
|
25
|
-
console.log('🐯 Welcome to Maugli Blog Setup!\n');
|
26
|
-
|
27
|
-
// Настройки по умолчанию
|
28
|
-
let settings = {
|
29
|
-
blogName: 'My Maugli Blog',
|
30
|
-
language: 'en',
|
31
|
-
mainDomain: '',
|
32
|
-
enableMultiLang: false
|
33
|
-
};
|
34
|
-
|
35
|
-
// Попытка загрузить prompts для интерактивного режима
|
36
|
-
try {
|
37
|
-
const prompts = await import('prompts').then(m => m.default);
|
38
|
-
|
39
|
-
// Интерактивные настройки
|
40
|
-
const response = await prompts([
|
41
|
-
{
|
42
|
-
type: 'text',
|
43
|
-
name: 'blogName',
|
44
|
-
message: 'What would you like to name your blog?',
|
45
|
-
initial: settings.blogName
|
46
|
-
},
|
47
|
-
{
|
48
|
-
type: 'select',
|
49
|
-
name: 'language',
|
50
|
-
message: 'Choose interface language:',
|
51
|
-
choices: availableLanguages,
|
52
|
-
initial: 0 // English по умолчанию
|
53
|
-
},
|
54
|
-
{
|
55
|
-
type: 'text',
|
56
|
-
name: 'mainDomain',
|
57
|
-
message: 'Do you have a main domain to link this blog to? (e.g., mybrand.com - leave empty if none):',
|
58
|
-
initial: settings.mainDomain
|
59
|
-
},
|
60
|
-
{
|
61
|
-
type: 'confirm',
|
62
|
-
name: 'enableMultiLang',
|
63
|
-
message: 'Enable multilingual support?',
|
64
|
-
initial: settings.enableMultiLang
|
65
|
-
}
|
66
|
-
]);
|
67
|
-
|
68
|
-
// Если пользователь отменил настройку
|
69
|
-
if (!response.blogName && response.blogName !== '') {
|
70
|
-
console.log('Setup cancelled.');
|
71
|
-
return;
|
72
|
-
}
|
73
|
-
|
74
|
-
settings = { ...settings, ...response };
|
75
|
-
} catch (error) {
|
76
|
-
console.log('⚠️ Interactive mode unavailable, using default settings...\n');
|
13
|
+
function getLanguageCodes() {
|
14
|
+
const file = readFileSync(path.join(templateRoot, 'src/i18n/languages.ts'), 'utf8');
|
15
|
+
const codes = [];
|
16
|
+
const regex = /{\s*code:\s*'([^']+)'/g;
|
17
|
+
let match;
|
18
|
+
while ((match = regex.exec(file)) !== null) {
|
19
|
+
codes.push(match[1]);
|
77
20
|
}
|
21
|
+
return codes;
|
22
|
+
}
|
23
|
+
|
24
|
+
function promptLang(codes) {
|
25
|
+
return new Promise(resolve => {
|
26
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
27
|
+
rl.question(`Choose language (${codes.join(', ')}): `, answer => {
|
28
|
+
rl.close();
|
29
|
+
resolve(codes.includes(answer) ? answer : codes[0]);
|
30
|
+
});
|
31
|
+
});
|
32
|
+
}
|
78
33
|
|
79
|
-
|
34
|
+
function updateConfig(targetDir, lang) {
|
35
|
+
const configPath = path.join(targetDir, 'src', 'config', 'maugli.config.ts');
|
36
|
+
if (!existsSync(configPath)) return;
|
37
|
+
let content = readFileSync(configPath, 'utf8');
|
38
|
+
content = content.replace(/defaultLang:\s*'[^']*'/, `defaultLang: '${lang}'`);
|
39
|
+
const multiMatch = content.match(/enableMultiLang:\s*(true|false)/);
|
40
|
+
const multi = multiMatch ? multiMatch[1] === 'true' : false;
|
41
|
+
content = content.replace(/showLangSwitcher:\s*(true|false)/, `showLangSwitcher: ${multi}`);
|
42
|
+
writeFileSync(configPath, content);
|
43
|
+
console.log(`Configured default language to ${lang}`);
|
80
44
|
}
|
81
45
|
|
82
|
-
function
|
46
|
+
export default async function init(targetName, langOption) {
|
83
47
|
const targetDir = targetName ? path.resolve(targetName) : process.cwd();
|
84
|
-
|
85
|
-
|
86
|
-
if (targetName && !existsSync(targetDir)) {
|
87
|
-
console.log(`\n📁 Creating folder: ${targetName}`);
|
88
|
-
}
|
48
|
+
const codes = getLanguageCodes();
|
49
|
+
const lang = langOption && codes.includes(langOption) ? langOption : await promptLang(codes);
|
89
50
|
|
90
51
|
function copyItem(item) {
|
91
52
|
const src = path.join(templateRoot, item);
|
92
53
|
const dest = path.join(targetDir, item);
|
93
54
|
|
94
55
|
if (!existsSync(src)) {
|
95
|
-
console.log(
|
56
|
+
console.log(`Skipped ${item} (not found)`);
|
96
57
|
return;
|
97
58
|
}
|
98
59
|
|
99
60
|
cpSync(src, dest, { recursive: true });
|
100
|
-
console.log(
|
61
|
+
console.log(`Copied ${item}`);
|
101
62
|
}
|
102
63
|
|
103
|
-
console.log('\n🔧 Copying files...\n');
|
104
|
-
|
105
64
|
// Copy package files first so npm install works correctly
|
106
65
|
['package.json', 'package-lock.json'].forEach(file => {
|
107
66
|
if (existsSync(path.join(templateRoot, file))) {
|
@@ -123,9 +82,6 @@ function createBlog(targetName, settings) {
|
|
123
82
|
];
|
124
83
|
items.forEach(copyItem);
|
125
84
|
|
126
|
-
// Создание конфигурационных файлов
|
127
|
-
console.log('\n⚙️ Creating configuration files...\n');
|
128
|
-
|
129
85
|
// Create essential config files
|
130
86
|
const gitignoreContent = `
|
131
87
|
# Dependencies
|
@@ -160,78 +116,27 @@ dist/
|
|
160
116
|
`;
|
161
117
|
|
162
118
|
writeFileSync(path.join(targetDir, '.gitignore'), gitignoreContent.trim());
|
163
|
-
console.log('
|
119
|
+
console.log('Created .gitignore');
|
164
120
|
|
165
121
|
writeFileSync(path.join(targetDir, '.prettierrc'), prettierrcContent);
|
166
|
-
console.log('
|
167
|
-
|
168
|
-
// Обновление maugli.config.ts с пользовательскими настройками
|
169
|
-
console.log('\n🎨 Configuring blog settings...\n');
|
170
|
-
|
171
|
-
const configPath = path.join(targetDir, 'src/config/maugli.config.ts');
|
172
|
-
if (existsSync(configPath)) {
|
173
|
-
let configContent = readFileSync(configPath, 'utf8');
|
174
|
-
|
175
|
-
// Обновляем название блога
|
176
|
-
configContent = configContent.replace(
|
177
|
-
/name: 'Maugli'/,
|
178
|
-
`name: '${settings.blogName}'`
|
179
|
-
);
|
180
|
-
|
181
|
-
// Обновляем язык по умолчанию
|
182
|
-
configContent = configContent.replace(
|
183
|
-
/defaultLang: 'en'/,
|
184
|
-
`defaultLang: '${settings.language}'`
|
185
|
-
);
|
186
|
-
|
187
|
-
// Обновляем мультиязычность
|
188
|
-
configContent = configContent.replace(
|
189
|
-
/enableMultiLang: false/,
|
190
|
-
`enableMultiLang: ${settings.enableMultiLang}`
|
191
|
-
);
|
192
|
-
|
193
|
-
// Обновляем домен (если указан)
|
194
|
-
if (settings.mainDomain) {
|
195
|
-
configContent = configContent.replace(
|
196
|
-
/logoHref: 'https:\/\/maugli\.cfd'/,
|
197
|
-
`logoHref: '${settings.mainDomain}'`
|
198
|
-
);
|
199
|
-
} else {
|
200
|
-
// Если домена нет, ссылка ведет на главную страницу блога
|
201
|
-
configContent = configContent.replace(
|
202
|
-
/logoHref: 'https:\/\/maugli\.cfd'/,
|
203
|
-
`logoHref: '/'`
|
204
|
-
);
|
205
|
-
}
|
206
|
-
|
207
|
-
// Отключаем примеры для нового блога
|
208
|
-
configContent = configContent.replace(
|
209
|
-
/showExamples: true/,
|
210
|
-
`showExamples: false`
|
211
|
-
);
|
212
|
-
|
213
|
-
writeFileSync(configPath, configContent);
|
214
|
-
console.log('✅ Updated maugli.config.ts');
|
215
|
-
}
|
122
|
+
console.log('Created .prettierrc');
|
216
123
|
|
217
|
-
console.log('\n📦 Installing dependencies...\n');
|
218
124
|
execSync('npm install', { cwd: targetDir, stdio: 'inherit' });
|
219
|
-
|
220
|
-
console.log('\n🎉 Blog successfully created!\n');
|
221
|
-
console.log('Settings:');
|
222
|
-
console.log(` 📝 Name: ${settings.blogName}`);
|
223
|
-
console.log(` 🌐 Language: ${availableLanguages.find(l => l.value === settings.language)?.title || settings.language}`);
|
224
|
-
console.log(` 🔗 Domain: ${settings.mainDomain || 'local blog'}`);
|
225
|
-
console.log(` 🌍 Multilingual: ${settings.enableMultiLang ? 'enabled' : 'disabled'}`);
|
226
|
-
console.log('\nTo start:');
|
227
|
-
if (targetName) {
|
228
|
-
console.log(` cd ${targetName}`);
|
229
|
-
}
|
230
|
-
console.log(' npm run dev\n');
|
231
|
-
console.log('📚 All settings can be changed in src/config/maugli.config.ts');
|
125
|
+
updateConfig(targetDir, lang);
|
232
126
|
}
|
233
127
|
|
234
128
|
// Если скрипт запускается напрямую
|
235
129
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
236
|
-
|
130
|
+
const args = process.argv.slice(2);
|
131
|
+
let targetName;
|
132
|
+
let lang;
|
133
|
+
for (let i = 0; i < args.length; i++) {
|
134
|
+
if (args[i] === '--lang' && i + 1 < args.length) {
|
135
|
+
lang = args[i + 1];
|
136
|
+
i++;
|
137
|
+
} else {
|
138
|
+
targetName = args[i];
|
139
|
+
}
|
140
|
+
}
|
141
|
+
await init(targetName, lang);
|
237
142
|
}
|
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.1.
|
5
|
+
"version": "1.1.6",
|
6
6
|
"license": "GPL-3.0-or-later OR Commercial",
|
7
7
|
"repository": {
|
8
8
|
"type": "git",
|
@@ -22,7 +22,7 @@
|
|
22
22
|
"dev": "astro dev",
|
23
23
|
"start": "astro dev",
|
24
24
|
"build": "node typograf-batch.js && node scripts/verify-assets.js && astro build",
|
25
|
-
"test": "node tests/examplesFilter.
|
25
|
+
"test": "node tests/examplesFilter.test.ts",
|
26
26
|
"astro": "astro",
|
27
27
|
"featured:add": "node scripts/featured.js add",
|
28
28
|
"featured:remove": "node scripts/featured.js remove",
|
@@ -32,25 +32,24 @@
|
|
32
32
|
"postinstall": "node scripts/upgrade-config.js"
|
33
33
|
},
|
34
34
|
"dependencies": {
|
35
|
-
"@astrojs/
|
36
|
-
"@astrojs/
|
37
|
-
"@astrojs/
|
38
|
-
"@
|
39
|
-
"@
|
40
|
-
"@fontsource-variable/
|
41
|
-
"@
|
42
|
-
"
|
43
|
-
"
|
44
|
-
"
|
45
|
-
"
|
46
|
-
"marked": "^12.0.2",
|
47
|
-
"prompts": "^2.4.2",
|
48
|
-
"reading-time": "^1.5.0",
|
35
|
+
"@astrojs/mdx": "^4.3.0",
|
36
|
+
"@astrojs/rss": "^4.0.11",
|
37
|
+
"@astrojs/sitemap": "^3.4.0",
|
38
|
+
"@fontsource-variable/geologica": "^5.2.6",
|
39
|
+
"@fontsource-variable/inter": "^5.2.5",
|
40
|
+
"@fontsource-variable/newsreader": "^5.2.6",
|
41
|
+
"@tailwindcss/vite": "^4.0.17",
|
42
|
+
"astro": "^5.5.6",
|
43
|
+
"i18next": "^25.3.2",
|
44
|
+
"js-yaml": "^4.1.0",
|
45
|
+
"marked": "^15.0.7",
|
49
46
|
"remark-slug": "^7.0.1",
|
50
|
-
"
|
51
|
-
"tailwindcss": "^
|
52
|
-
"
|
53
|
-
"
|
47
|
+
"sharp": "^0.34.2",
|
48
|
+
"tailwindcss": "^4.0.17",
|
49
|
+
"ts-node": "^10.9.2",
|
50
|
+
"tsx": "^4.20.3",
|
51
|
+
"typescript": "^5.9.2",
|
52
|
+
"typograf": "^7.4.4"
|
54
53
|
},
|
55
54
|
"devDependencies": {
|
56
55
|
"@tailwindcss/typography": "^0.5.16",
|
@@ -49,6 +49,12 @@ export interface MaugliConfig {
|
|
49
49
|
enableFAQ: boolean; // Enable FAQ block
|
50
50
|
enableRSS: boolean; // Enable RSS feed
|
51
51
|
};
|
52
|
+
// Progressive Web App settings
|
53
|
+
pwa?: {
|
54
|
+
themeColor?: string; // Theme color for the PWA manifest
|
55
|
+
backgroundColor?: string; // Background color for the PWA manifest
|
56
|
+
icons?: Array<{ src: string; sizes: string; type: string; purpose?: string }>; // Icons for the PWA manifest
|
57
|
+
};
|
52
58
|
// Control display of tags/rubrics
|
53
59
|
// Theme switcher
|
54
60
|
enableThemeSwitcher?: boolean; // Enable theme switcher (true by default)
|
@@ -157,6 +163,14 @@ export const maugliConfig: MaugliConfig = {
|
|
157
163
|
enableFAQ: true, // Enable FAQ block
|
158
164
|
enableRSS: true, // Enable RSS feed
|
159
165
|
},
|
166
|
+
pwa: {
|
167
|
+
themeColor: '#0cbf11', // Theme color for the PWA manifest
|
168
|
+
backgroundColor: '#ffffff', // Background color for the PWA manifest
|
169
|
+
icons: [
|
170
|
+
{ src: '/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any maskable' },
|
171
|
+
{ src: '/icon-512.png', sizes: '512x512', type: 'image/png' },
|
172
|
+
],
|
173
|
+
},
|
160
174
|
showOnlyRubricsTags: true, // Show only rubrics by default
|
161
175
|
|
162
176
|
links: {
|
@@ -195,7 +209,7 @@ export const maugliConfig: MaugliConfig = {
|
|
195
209
|
defaultAuthorId: 'default-autor', // Default author id (used if no author is specified). Use the filename of the author .md file without the .md extension
|
196
210
|
showAuthorsWithoutArticles: true, // Show authors without articles (default: true)
|
197
211
|
showAuthorArticleCount: true, // Show article count for author
|
198
|
-
showLangSwitcher:
|
212
|
+
showLangSwitcher: false, // Show language switcher
|
199
213
|
langLinks: {
|
200
214
|
ru: 'https://maugli.cfd/ru', // Russian version
|
201
215
|
en: 'https://maugli.cfd/en', // English version
|
@@ -0,0 +1,40 @@
|
|
1
|
+
---
|
2
|
+
title: О блоге
|
3
|
+
seo:
|
4
|
+
title: ТехРев — блог, который самостоятельно ведет AI-автор
|
5
|
+
description: Демо-витрина автоматического AI-блога с персоной
|
6
|
+
image:
|
7
|
+
src: '/tr-about.webp'
|
8
|
+
alt: A person sitting at a desk in front of a computer
|
9
|
+
width: '1200'
|
10
|
+
height: '1200'
|
11
|
+
---
|
12
|
+
О концепции блога TechRev — "Технологическая революция". Блог полностью ведётся искусственным интеллектом от лица цифровой персоны — ИльичAI 🚩. Это демонстрация возможностей нейросетей создавать контент от имени автора.
|
13
|
+
|
14
|
+
ИльичAI — вождь новой эпохи. Он за освобождение общества от бессмысленного ручного интернето-марательства путём внедрения нейросетей и автоматизации контента, маркетинга и продаж.
|
15
|
+
|
16
|
+
## В блоге
|
17
|
+
|
18
|
+
🚀 Как выполнить пятилетку за неделю: быстрые планы автоматизации создания контента, экономящие месяцы работы. #ПятилеткаЗаТриДня
|
19
|
+
|
20
|
+
🔧 Пошаговые сценарии освобождения бизнеса от рутины: схемы без миллионов и армии айтишников. #СкиньОковы
|
21
|
+
|
22
|
+
📢 Манифесты против легаси-процессов: где утекает время и как это исправить. #НовыйМир
|
23
|
+
|
24
|
+
🏆 Истории трудовых побед: как наши товарищи внедряют искусственный интеллект в производство контента. #ТоварищиВнедряют
|
25
|
+
|
26
|
+
🚩 Технологии — наш серп ⚙️. Автоматизация — наш молот 🛠. Нейросети — наше знамя 🤖.
|
27
|
+
|
28
|
+
## Почему автором выбран Ильич?
|
29
|
+
|
30
|
+
Все материалы создаются, редактируются и оформляются с помощью самостоятельных AI-агентов. Процесс полностью автоматизирован. Это ли не контентная революция?
|
31
|
+
|
32
|
+
Выбор Ильича как цифрового вождя этой витрины не случаен. Поскольку контент блога полностью автоматизирован, его задача — не просто информировать, а наглядно показать, как искусственный интеллект может работать от лица харизматичной и узнаваемой персоны.
|
33
|
+
|
34
|
+
ИльичAI — это метафора технологической революции, символ духа перемен, но уже в новом, цифровом контексте. Он наследует вайб прототипа, но говорит о совершенно иных вещах: вместо политической революции — революция технологическая, вместо призывов к трудовым свершениям — призывы к освобождению от рутинной работы с помощью нейросетей и автоматизации.
|
35
|
+
|
36
|
+
Это демонстрация того, как можно строить узнаваемость и привлекать внимание с помощью сильной цифровой персоны, даже в полностью автоматизированном контенте.
|
37
|
+
|
38
|
+
## Если ваш контент еще не автоматизирован — мы готовы сделать это за вас:
|
39
|
+
|
40
|
+
Хотите протестировать такие процессы или интегрировать AI в свой бизнес? По вопросам сотрудничества: [Связаться в Telegram](https://t.me/darrrina)
|
@@ -0,0 +1,10 @@
|
|
1
|
+
---
|
2
|
+
title: Для связи
|
3
|
+
seo:
|
4
|
+
title: Контакты
|
5
|
+
description: Создаем автоматические AI-блоги и телеграм-каналы любой тематики для брендов, экспертов, СЕО
|
6
|
+
---
|
7
|
+
|
8
|
+
Maugli -- контент-фермы с гибкой настройкой продуктов (целевая ссылка), каналов, авторов, тематики и тональности. Эта полный производственный цикл создания контента от поиска виральных тем до адаптации и публикауции. От человека требуется первоначальныц контроль в проуессе дообучения. Все остальное делают агенты.
|
9
|
+
|
10
|
+
[Связаться в Telegram](https://t.me/darrrina)
|
package/src/styles/global.css
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
/* Import fonts. Replace or add lines to use other Fontsource packages. */
|
1
2
|
@import '@fontsource-variable/inter/wght.css' layer(base);
|
2
3
|
@import '@fontsource-variable/geologica/wght.css' layer(base);
|
3
4
|
|
@@ -23,8 +24,8 @@
|
|
23
24
|
--bg-main-40: rgba(255, 255, 255, 0.4);
|
24
25
|
--bg-muted: rgba(237, 241, 247, 0.621);
|
25
26
|
--border-main: rgba(17, 28, 44, 0.13);
|
26
|
-
--font-sans: 'Inter Variable', sans-serif;
|
27
|
-
--font-serif: 'Geologica Variable', sans-serif;
|
27
|
+
--font-sans: 'Inter Variable', sans-serif; /* Update if you change the sans-serif font */
|
28
|
+
--font-serif: 'Geologica Variable', sans-serif; /* Update if you change the serif font */
|
28
29
|
|
29
30
|
/* Card Styles */
|
30
31
|
--card-shadow:
|
@@ -100,8 +101,8 @@ html.dark {
|
|
100
101
|
*/
|
101
102
|
|
102
103
|
@theme inline {
|
103
|
-
--font-sans: 'Inter Variable', sans-serif;
|
104
|
-
--font-serif: 'Geologica Variable', sans-serif;
|
104
|
+
--font-sans: 'Inter Variable', sans-serif; /* Match --font-sans above if changed */
|
105
|
+
--font-serif: 'Geologica Variable', sans-serif; /* Match --font-serif above if changed */
|
105
106
|
--font-weight-bold: 700;
|
106
107
|
--font-weight-extra-bold: 800;
|
107
108
|
--text-color-main: var(--text-main);
|
package/bin/version.js
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
#!/usr/bin/env node
|
2
|
-
|
3
|
-
import { readFileSync } from 'fs';
|
4
|
-
import path from 'path';
|
5
|
-
import { fileURLToPath } from 'url';
|
6
|
-
|
7
|
-
const __filename = fileURLToPath(import.meta.url);
|
8
|
-
const __dirname = path.dirname(__filename);
|
9
|
-
|
10
|
-
const packagePath = path.join(__dirname, '../package.json');
|
11
|
-
const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'));
|
12
|
-
|
13
|
-
console.log(`core-maugli v${packageJson.version}`);
|
14
|
-
console.log(`Astro & Tailwind CSS blog theme for Maugli`);
|
15
|
-
console.log(`Repository: ${packageJson.repository.url}`);
|