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.
Files changed (2) hide show
  1. package/bin/init.js +201 -0
  2. 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.15",
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"