Skip to content

Commit 93a0275

Browse files
authored
Add a new command: trb new theme theme-name that uploads and unzips the theme (#7)
1 parent c5f7fb2 commit 93a0275

5 files changed

Lines changed: 732 additions & 130 deletions

File tree

commands/setup_theme.js

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import fetch from 'node-fetch';
4+
import AdmZip from 'adm-zip';
5+
import ProgressBar from 'progress';
6+
import ora from 'ora';
7+
import chalk from 'chalk';
8+
9+
function isKebabCase(str) {
10+
return /^[a-z]+(-[a-z]+)*$/.test(str);
11+
}
12+
13+
async function downloadFile(url, outputPath) {
14+
const response = await fetch(url);
15+
16+
if (!response.ok) {
17+
throw new Error(`Failed to download: ${response.statusText}`);
18+
}
19+
20+
const fileStream = fs.createWriteStream(outputPath);
21+
const totalSize = parseInt(response.headers.get('content-length'), 10);
22+
const progressBar = new ProgressBar('Downloading [:bar] :percent :etas', {
23+
complete: '=',
24+
incomplete: ' ',
25+
width: 40,
26+
total: totalSize,
27+
});
28+
29+
response.body.on('data', (chunk) => {
30+
progressBar.tick(chunk.length);
31+
});
32+
33+
await new Promise((resolve, reject) => {
34+
response.body.pipe(fileStream);
35+
response.body.on('error', reject);
36+
fileStream.on('finish', resolve);
37+
});
38+
}
39+
40+
export default async function setup_theme(themeName) {
41+
try {
42+
// Check if theme name is in kebab-case
43+
if (!isKebabCase(themeName)) {
44+
console.error(
45+
chalk.orange('Theme name must be in kebab-case (example-theme-name).')
46+
);
47+
return;
48+
}
49+
50+
// Ensure the current working directory ends with wp-themes
51+
const cwd = process.cwd();
52+
if (!cwd.endsWith('wp-themes')) {
53+
console.error(
54+
chalk.orange('This command needs to be run inside a wp-themes folder.')
55+
);
56+
return;
57+
}
58+
59+
// Check if theme directory already exists
60+
const newThemePath = path.join('.', themeName);
61+
if (fs.existsSync(newThemePath)) {
62+
console.error(chalk.orange('A theme with this name already exists.'));
63+
return;
64+
}
65+
66+
// Fetch the latest release URL from GitHub API
67+
const apiUrl =
68+
'https://api.github.com/repos/webredone/theme-redone/releases/latest';
69+
const apiResponse = await fetch(apiUrl);
70+
const apiData = await apiResponse.json();
71+
const zipUrl = apiData.zipball_url;
72+
73+
// Download the zip file
74+
await downloadFile(zipUrl, 'theme-redone.zip');
75+
76+
// Unzip the file
77+
const spinner = ora('Unzipping the file...').start();
78+
const zip = new AdmZip('theme-redone.zip');
79+
zip.extractAllTo('theme-redone', true); // Extract to current directory
80+
spinner.succeed('Unzipping completed');
81+
82+
// Rename the extracted folder
83+
// Note: You need to adjust the logic here to determine the correct extracted folder name
84+
spinner.start('Renaming the folder...');
85+
const extractedFolderName = 'theme-redone'; // Placeholder, replace with actual logic
86+
fs.renameSync(extractedFolderName, newThemePath);
87+
spinner.succeed('Renaming completed');
88+
89+
// Modify style.css in the theme folder
90+
const styleCssPath = path.join(newThemePath, 'style.css');
91+
let styleCss = fs.readFileSync(styleCssPath, 'utf8');
92+
styleCss = styleCss.replace(
93+
/Theme Name: theme-redone/g,
94+
`Theme Name: ${themeName}`
95+
);
96+
fs.writeFileSync(styleCssPath, styleCss);
97+
98+
// Delete the zip file
99+
fs.unlinkSync('theme-redone.zip');
100+
101+
console.log(
102+
'Theme has been set up. Please activate the theme from the WordPress admin panel.'
103+
);
104+
105+
// Read package.json and extract Node version
106+
const packageJsonPath = path.join(newThemePath, 'package.json');
107+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
108+
const nodeVersion = packageJson.engines.node;
109+
110+
console.log(
111+
`Please ensure you have Node version ${nodeVersion} installed.`
112+
);
113+
console.log(
114+
'Then, run "npm i" and "composer i" from the theme root directory.'
115+
);
116+
} catch (error) {
117+
console.error(chalk.orange(`Error setting up theme: ${error.message}`));
118+
}
119+
}

index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { program } from 'commander';
44
import list_created_blocks from './commands/list_created_blocks.js';
55

6+
import setup_theme from './commands/setup_theme.js';
67
import create_new_block from './commands/create_new_block.js';
78
import remove_existing_block from './commands/remove_existing_block.js';
89
import { help } from './CONFIG.js';
@@ -11,6 +12,13 @@ import copy_existing_block from './commands/copy_existing_block.js';
1112

1213
program.command('list').description(help.list).action(list_created_blocks);
1314

15+
program
16+
.command('new theme <theme-name>')
17+
.description(
18+
'Download and set up a new theme from the latest theme-redone release'
19+
)
20+
.action(setup_theme);
21+
1422
program
1523
.command('add <block-name-kebab-case>')
1624
.description(help.add)

0 commit comments

Comments
 (0)