core-maugli 1.2.15 → 1.2.16
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/bin/init.js +201 -0
- package/package.json +3 -2
package/bin/init.js
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
import { execSync } from 'child_process';
|
4
|
+
import { cpSync, existsSync, readFileSync, writeFileSync } from 'fs';
|
5
|
+
import path from 'path';
|
6
|
+
import readline from 'readline';
|
7
|
+
import { fileURLToPath } from 'url';
|
8
|
+
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
10
|
+
const __dirname = path.dirname(__filename);
|
11
|
+
const templateRoot = path.join(__dirname, '..');
|
12
|
+
|
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]);
|
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
|
+
}
|
33
|
+
|
34
|
+
function promptRepo() {
|
35
|
+
return new Promise(resolve => {
|
36
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
37
|
+
rl.question('Repository URL: ', answer => {
|
38
|
+
rl.close();
|
39
|
+
resolve(answer.trim());
|
40
|
+
});
|
41
|
+
});
|
42
|
+
}
|
43
|
+
|
44
|
+
async function getRepoUrl(targetDir, repoOption) {
|
45
|
+
if (repoOption) return repoOption;
|
46
|
+
try {
|
47
|
+
const url = execSync('git remote get-url origin', {
|
48
|
+
cwd: targetDir,
|
49
|
+
stdio: ['ignore', 'pipe', 'ignore']
|
50
|
+
})
|
51
|
+
.toString()
|
52
|
+
.trim();
|
53
|
+
if (url) return url;
|
54
|
+
} catch {
|
55
|
+
// ignore
|
56
|
+
}
|
57
|
+
return await promptRepo();
|
58
|
+
}
|
59
|
+
|
60
|
+
function updateReadme(targetDir, repoUrl) {
|
61
|
+
if (!repoUrl) return;
|
62
|
+
const readmePath = path.join(targetDir, 'README.md');
|
63
|
+
if (!existsSync(readmePath)) return;
|
64
|
+
let content = readFileSync(readmePath, 'utf8');
|
65
|
+
const pattern = /https:\/\/app\.netlify\.com\/start\/deploy\?repository=[^\)\s]+/;
|
66
|
+
content = content.replace(
|
67
|
+
pattern,
|
68
|
+
`https://app.netlify.com/start/deploy?repository=${repoUrl}`
|
69
|
+
);
|
70
|
+
writeFileSync(readmePath, content);
|
71
|
+
console.log('Updated Netlify link in README.md');
|
72
|
+
}
|
73
|
+
|
74
|
+
function updateConfig(targetDir, lang, repoUrl) {
|
75
|
+
const configPath = path.join(targetDir, 'src', 'config', 'maugli.config.ts');
|
76
|
+
if (!existsSync(configPath)) return;
|
77
|
+
let content = readFileSync(configPath, 'utf8');
|
78
|
+
content = content.replace(/defaultLang:\s*'[^']*'/, `defaultLang: '${lang}'`);
|
79
|
+
const multiMatch = content.match(/enableMultiLang:\s*(true|false)/);
|
80
|
+
const multi = multiMatch ? multiMatch[1] === 'true' : false;
|
81
|
+
content = content.replace(/showLangSwitcher:\s*(true|false)/, `showLangSwitcher: ${multi}`);
|
82
|
+
|
83
|
+
// Update repository URL if provided
|
84
|
+
if (repoUrl) {
|
85
|
+
content = content.replace(
|
86
|
+
/repository:\s*{[^}]*url:\s*'[^']*'/,
|
87
|
+
`repository: {\n url: '${repoUrl}'`
|
88
|
+
);
|
89
|
+
}
|
90
|
+
|
91
|
+
writeFileSync(configPath, content);
|
92
|
+
console.log(`Configured default language to ${lang}`);
|
93
|
+
if (repoUrl) {
|
94
|
+
console.log(`Configured repository URL to ${repoUrl}`);
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
export default async function init(targetName, langOption, repoOption) {
|
99
|
+
const targetDir = targetName ? path.resolve(targetName) : process.cwd();
|
100
|
+
const codes = getLanguageCodes();
|
101
|
+
const lang = langOption && codes.includes(langOption) ? langOption : await promptLang(codes);
|
102
|
+
|
103
|
+
function copyItem(item) {
|
104
|
+
const src = path.join(templateRoot, item);
|
105
|
+
const dest = path.join(targetDir, item);
|
106
|
+
|
107
|
+
if (!existsSync(src)) {
|
108
|
+
console.log(`Skipped ${item} (not found)`);
|
109
|
+
return;
|
110
|
+
}
|
111
|
+
|
112
|
+
cpSync(src, dest, { recursive: true });
|
113
|
+
console.log(`Copied ${item}`);
|
114
|
+
}
|
115
|
+
|
116
|
+
// Copy package files first so npm install works correctly
|
117
|
+
['package.json', 'package-lock.json'].forEach(file => {
|
118
|
+
if (existsSync(path.join(templateRoot, file))) {
|
119
|
+
copyItem(file);
|
120
|
+
}
|
121
|
+
});
|
122
|
+
|
123
|
+
const items = [
|
124
|
+
'astro.config.mjs',
|
125
|
+
'tsconfig.json',
|
126
|
+
'vite.config.js',
|
127
|
+
'public',
|
128
|
+
'src',
|
129
|
+
'scripts',
|
130
|
+
'typograf-batch.js',
|
131
|
+
'resize-all.cjs',
|
132
|
+
'README.md',
|
133
|
+
'LICENSE'
|
134
|
+
];
|
135
|
+
items.forEach(copyItem);
|
136
|
+
|
137
|
+
const repoUrl = await getRepoUrl(targetDir, repoOption);
|
138
|
+
updateReadme(targetDir, repoUrl);
|
139
|
+
|
140
|
+
// Create essential config files
|
141
|
+
const gitignoreContent = `
|
142
|
+
# Dependencies
|
143
|
+
node_modules/
|
144
|
+
.pnpm-debug.log*
|
145
|
+
|
146
|
+
# Environment
|
147
|
+
.env
|
148
|
+
.env.local
|
149
|
+
.env.production
|
150
|
+
|
151
|
+
# Build outputs
|
152
|
+
dist/
|
153
|
+
.astro/
|
154
|
+
|
155
|
+
# Generated files
|
156
|
+
.DS_Store
|
157
|
+
.vscode/settings.json
|
158
|
+
|
159
|
+
# Cache
|
160
|
+
.typograf-cache.json
|
161
|
+
`;
|
162
|
+
|
163
|
+
const prettierrcContent = `{
|
164
|
+
"semi": true,
|
165
|
+
"singleQuote": true,
|
166
|
+
"tabWidth": 2,
|
167
|
+
"trailingComma": "es5",
|
168
|
+
"printWidth": 100,
|
169
|
+
"plugins": ["prettier-plugin-tailwindcss"]
|
170
|
+
}
|
171
|
+
`;
|
172
|
+
|
173
|
+
writeFileSync(path.join(targetDir, '.gitignore'), gitignoreContent.trim());
|
174
|
+
console.log('Created .gitignore');
|
175
|
+
|
176
|
+
writeFileSync(path.join(targetDir, '.prettierrc'), prettierrcContent);
|
177
|
+
console.log('Created .prettierrc');
|
178
|
+
|
179
|
+
execSync('npm install', { cwd: targetDir, stdio: 'inherit' });
|
180
|
+
updateConfig(targetDir, lang, repoUrl);
|
181
|
+
}
|
182
|
+
|
183
|
+
// Если скрипт запускается напрямую
|
184
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
185
|
+
const args = process.argv.slice(2);
|
186
|
+
let targetName;
|
187
|
+
let lang;
|
188
|
+
let repo;
|
189
|
+
for (let i = 0; i < args.length; i++) {
|
190
|
+
if (args[i] === '--lang' && i + 1 < args.length) {
|
191
|
+
lang = args[i + 1];
|
192
|
+
i++;
|
193
|
+
} else if (args[i] === '--repo' && i + 1 < args.length) {
|
194
|
+
repo = args[i + 1];
|
195
|
+
i++;
|
196
|
+
} else {
|
197
|
+
targetName = args[i];
|
198
|
+
}
|
199
|
+
}
|
200
|
+
await init(targetName, lang, repo);
|
201
|
+
}
|
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.16",
|
6
6
|
"license": "GPL-3.0-or-later OR Commercial",
|
7
7
|
"repository": {
|
8
8
|
"type": "git",
|
@@ -64,7 +64,8 @@
|
|
64
64
|
"files": [
|
65
65
|
"src",
|
66
66
|
"public",
|
67
|
-
"scripts"
|
67
|
+
"scripts",
|
68
|
+
"bin"
|
68
69
|
],
|
69
70
|
"bin": {
|
70
71
|
"core-maugli": "bin/index.js"
|