chisel-scripts 2.1.5 → 2.2.0

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/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  <!-- INSERT-NEW-ENTRIES-HERE -->
4
4
 
5
+ ## 2.2.0 (2026-02-09)
6
+
7
+ - chisel update scripts and husky precommit hooks ([31c1019](https://github.com/xfiveco/generator-chisel/commit/31c1019))
8
+ - Webpack config chnages: client ovarlay, nvmrc update, composer packages version update ([a07c16c](https://github.com/xfiveco/generator-chisel/commit/a07c16c))
9
+
5
10
  ## <small>2.1.5 (2026-01-02)</small>
6
11
 
7
12
  - wp-config-updates, wp/scripts lt, icons module define in functions.php ([3c97c63](https://github.com/xfiveco/generator-chisel/commit/3c97c63))
package/composer.phar CHANGED
Binary file
package/index.js CHANGED
@@ -60,6 +60,15 @@ function adjustWebpackConfig(baseConfig, directory) {
60
60
  })();
61
61
 
62
62
  const preparedConfig = (config, index = null) => {
63
+ const devSeverClient = config.devServer ? {
64
+ ...config.devServer.client,
65
+ overlay: {
66
+ errors: true,
67
+ warnings: false,
68
+ runtimeErrors: false,
69
+ },
70
+ } : {}
71
+
63
72
  return {
64
73
  ...config,
65
74
  output: {
@@ -80,17 +89,15 @@ function adjustWebpackConfig(baseConfig, directory) {
80
89
  },
81
90
  devServer: config.devServer && {
82
91
  ...config.devServer,
92
+ client: {
93
+ ...devSeverClient,
94
+ },
83
95
  allowedHosts: [new URL(getUrl()).host],
84
96
  ...(process.env.CHISEL_PORT && {
85
97
  host: '0.0.0.0',
86
98
  port: Number(process.env.CHISEL_PORT) + 1,
87
99
  client: {
88
- ...config.devServer.client,
89
- overlay: {
90
- errors: true,
91
- warnings: false,
92
- runtimeErrors: false,
93
- },
100
+ ...devSeverClient,
94
101
  webSocketURL: new URL(getUrl())
95
102
  .toString()
96
103
  .replace(process.env.CHISEL_PORT, Number(process.env.CHISEL_PORT) + 1),
package/lib/Service.js CHANGED
@@ -27,6 +27,8 @@ module.exports = class Service {
27
27
 
28
28
  const builtInPlugins = [
29
29
  'wp-scripts.mjs', // start, build
30
+ 'chisel-update.mjs', // check-chisel-update, chisel-update
31
+ 'husky-init.mjs', // husky-init
30
32
  'composer',
31
33
  'wp',
32
34
  'wp-config',
@@ -0,0 +1,282 @@
1
+ import https from 'https';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+
5
+ // GitHub repository configuration
6
+ const REPO = 'xfiveco/generator-chisel';
7
+ const REF = 'v2';
8
+ const THEME_PATH =
9
+ 'packages/generator-chisel/lib/commands/create/creators/app/chisel-starter-theme';
10
+
11
+ // URLs
12
+ const STYLE_REMOTE_PATH = `${THEME_PATH}/style.chisel-tpl.css`;
13
+ const STYLE_URL = `https://raw.githubusercontent.com/${REPO}/${REF}/${STYLE_REMOTE_PATH}`;
14
+
15
+ /**
16
+ * List of paths to update from the Chisel repository.
17
+ * Can be folders or files.
18
+ */
19
+ const PATHS_TO_UPDATE = [
20
+ 'core',
21
+ // Add more folders/files here in the future
22
+ ];
23
+
24
+ // Map of remote names to local names if they differ
25
+ const NAME_MAPPING = {
26
+ 'style.chisel-tpl.css': 'style.css',
27
+ };
28
+
29
+ const DEFAULT_OPTIONS = {
30
+ headers: {
31
+ 'User-Agent': 'Chisel-Update-Script',
32
+ },
33
+ };
34
+
35
+ const VERSION_REGEX = /(Version:\s*)([0-9]+\.[0-9]+\.[0-9]+)/i;
36
+
37
+ // ============================================================================
38
+ // HTTP Utilities
39
+ // ============================================================================
40
+
41
+ function request(url, options = {}) {
42
+ return new Promise((resolve, reject) => {
43
+ const req = https.get(url, { ...DEFAULT_OPTIONS, ...options }, (res) => {
44
+ if (res.statusCode === 301 || res.statusCode === 302) {
45
+ return resolve(request(res.headers.location, options));
46
+ }
47
+ if (res.statusCode < 200 || res.statusCode >= 300) {
48
+ return reject(new Error(`Status Code: ${res.statusCode} for ${url}`));
49
+ }
50
+ const data = [];
51
+ res.on('data', (chunk) => data.push(chunk));
52
+ res.on('end', () => resolve(Buffer.concat(data)));
53
+ });
54
+ req.on('error', reject);
55
+ });
56
+ }
57
+
58
+ async function fetchText(url) {
59
+ const buffer = await request(url);
60
+ return buffer.toString();
61
+ }
62
+
63
+ async function fetchJson(url) {
64
+ const buffer = await request(url);
65
+ return JSON.parse(buffer.toString());
66
+ }
67
+
68
+ // ============================================================================
69
+ // Version Utilities
70
+ // ============================================================================
71
+
72
+ function extractVersion(css) {
73
+ const match = css.match(VERSION_REGEX);
74
+ return match ? match[2] : null;
75
+ }
76
+
77
+ function readLocalVersion(filePath) {
78
+ if (!fs.existsSync(filePath)) return null;
79
+ return extractVersion(fs.readFileSync(filePath, 'utf8'));
80
+ }
81
+
82
+ function updateLocalVersion(filePath, newVersion) {
83
+ if (!fs.existsSync(filePath)) {
84
+ console.error(`File not found: ${filePath}`);
85
+ return false;
86
+ }
87
+
88
+ const content = fs.readFileSync(filePath, 'utf8');
89
+ if (!VERSION_REGEX.test(content)) {
90
+ console.error(`Version pattern not found in: ${filePath}`);
91
+ return false;
92
+ }
93
+
94
+ const updatedContent = content.replace(VERSION_REGEX, `$1${newVersion}`);
95
+ fs.writeFileSync(filePath, updatedContent);
96
+ return true;
97
+ }
98
+
99
+ function compareVersions(a, b) {
100
+ const pa = a.split('.').map(Number);
101
+ const pb = b.split('.').map(Number);
102
+
103
+ for (let i = 0; i < 3; i++) {
104
+ if ((pa[i] || 0) > (pb[i] || 0)) return 1;
105
+ if ((pa[i] || 0) < (pb[i] || 0)) return -1;
106
+ }
107
+
108
+ return 0;
109
+ }
110
+
111
+ // ============================================================================
112
+ // Update Functions
113
+ // ============================================================================
114
+
115
+ async function downloadFile(url, destPath) {
116
+ const buffer = await request(url);
117
+ fs.mkdirSync(path.dirname(destPath), { recursive: true });
118
+ fs.writeFileSync(destPath, buffer);
119
+ }
120
+
121
+ async function updateFolder(remoteFolderPath, localFolderPath) {
122
+ console.log(`📂 Updating folder: ${path.basename(remoteFolderPath)}`);
123
+
124
+ const apiUrl = `https://api.github.com/repos/${REPO}/contents/${remoteFolderPath}?ref=${REF}`;
125
+ let items;
126
+
127
+ try {
128
+ items = await fetchJson(apiUrl);
129
+ } catch (err) {
130
+ if (err.message.includes('404')) {
131
+ console.warn(`⚠️ Remote folder not found: ${remoteFolderPath}`);
132
+ return;
133
+ }
134
+ throw err;
135
+ }
136
+
137
+ if (!Array.isArray(items)) {
138
+ if (items.type === 'file') {
139
+ await downloadFile(items.download_url, localFolderPath);
140
+ return;
141
+ }
142
+ throw new Error(
143
+ `Expected array of items from GitHub API, got: ${typeof items}`,
144
+ );
145
+ }
146
+
147
+ for (const item of items) {
148
+ const localItemPath = path.join(localFolderPath, item.name);
149
+
150
+ if (item.type === 'file') {
151
+ console.log(` 📄 ${item.name}`);
152
+ await downloadFile(item.download_url, localItemPath);
153
+ } else if (item.type === 'dir') {
154
+ await updateFolder(item.path, localItemPath);
155
+ }
156
+ }
157
+ }
158
+
159
+ async function updateFile(remotePath, localPath) {
160
+ console.log(` 📄 Updating file: ${path.basename(remotePath)}`);
161
+ const downloadUrl = `https://raw.githubusercontent.com/${REPO}/${REF}/${remotePath}`;
162
+ await downloadFile(downloadUrl, localPath);
163
+ }
164
+
165
+ async function syncStyleVersion(localStylePath) {
166
+ console.log('\n📋 Syncing style.css version...');
167
+
168
+ const localVersion = readLocalVersion(localStylePath);
169
+ const remoteCss = await fetchText(STYLE_URL);
170
+ const remoteVersion = extractVersion(remoteCss);
171
+
172
+ if (!remoteVersion) {
173
+ console.warn('⚠️ Could not fetch remote version.');
174
+ return;
175
+ }
176
+
177
+ if (!localVersion) {
178
+ console.warn('⚠️ Local version not found in style.css.');
179
+ return;
180
+ }
181
+
182
+ if (compareVersions(remoteVersion, localVersion) > 0) {
183
+ if (updateLocalVersion(localStylePath, remoteVersion)) {
184
+ console.log(` ✔ Version updated: ${localVersion} → ${remoteVersion}`);
185
+ }
186
+ } else {
187
+ console.log(` ✔ Version is already up to date (${localVersion})`);
188
+ }
189
+ }
190
+
191
+ // ============================================================================
192
+ // Command Registration
193
+ // ============================================================================
194
+
195
+ export default function chiselUpdate(api) {
196
+ api.registerCommand(
197
+ 'check-chisel-update',
198
+ (command) =>
199
+ command.description('check if a new Chisel version is available'),
200
+ async () => {
201
+ const localStylePath = api.resolve('style.css');
202
+
203
+ try {
204
+ const localVersion = readLocalVersion(localStylePath);
205
+
206
+ if (!localVersion) {
207
+ console.log(
208
+ '⚠️ Local version not found. Consider running `chisel-scripts update`.',
209
+ );
210
+ return;
211
+ }
212
+
213
+ console.log(`Local version: ${localVersion}`);
214
+
215
+ const remoteCss = await fetchText(STYLE_URL);
216
+ const remoteVersion = extractVersion(remoteCss);
217
+
218
+ if (!remoteVersion) {
219
+ console.log('⚠️ Could not fetch remote version.');
220
+ return;
221
+ }
222
+
223
+ if (compareVersions(remoteVersion, localVersion) > 0) {
224
+ console.log(
225
+ `\n⬆️ Update available: ${localVersion} → ${remoteVersion}`,
226
+ );
227
+ console.log(`Run 'chisel-scripts update' to update.`);
228
+ } else {
229
+ console.log(`✔ Chisel is up to date (${localVersion})`);
230
+ }
231
+ } catch (err) {
232
+ console.error('❌ Version check failed:', err.message);
233
+ process.exit(1);
234
+ }
235
+ },
236
+ );
237
+
238
+ api.registerCommand(
239
+ 'chisel-update',
240
+ (command) =>
241
+ command
242
+ .description('update Chisel core files from the repository')
243
+ .option('--skip-version-sync', 'skip syncing version in style.css'),
244
+ async (options) => {
245
+ const localBasePath = api.resolve();
246
+ const localStylePath = api.resolve('style.css');
247
+
248
+ console.log('🚀 Starting Chisel update...\n');
249
+
250
+ try {
251
+ // Update configured paths
252
+ for (const item of PATHS_TO_UPDATE) {
253
+ const remotePath = `${THEME_PATH}/${item}`;
254
+ const localName = NAME_MAPPING[item] || item;
255
+ const localPath = path.join(localBasePath, localName);
256
+
257
+ if (item.includes('.')) {
258
+ await updateFile(remotePath, localPath);
259
+ } else {
260
+ await updateFolder(remotePath, localPath);
261
+ }
262
+ }
263
+
264
+ // Sync version in style.css
265
+ if (!options.skipVersionSync) {
266
+ await syncStyleVersion(localStylePath);
267
+ }
268
+
269
+ console.log('\n✅ Update completed successfully!');
270
+ console.log(
271
+ 'Note: Local files that do not exist in the repository (e.g., custom files) were preserved.',
272
+ );
273
+ } catch (err) {
274
+ console.error('\n❌ Update failed:', err.message);
275
+ if (err.message.includes('403')) {
276
+ console.error('Note: This might be due to GitHub API rate limits.');
277
+ }
278
+ process.exit(1);
279
+ }
280
+ },
281
+ );
282
+ }
@@ -15,7 +15,7 @@ module.exports = (api) => {
15
15
 
16
16
  const targetDir = api.resolve(
17
17
  'src',
18
- template === 'acf' ? 'acf-blocks' : 'blocks',
18
+ template === 'acf' ? 'blocks-acf' : 'blocks',
19
19
  );
20
20
 
21
21
  const maybeTemplatePath =
@@ -0,0 +1,123 @@
1
+ import { execSync } from 'child_process';
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+
5
+ /**
6
+ * Get the git root directory
7
+ * @param {string} cwd - Current working directory
8
+ * @returns {string|null} - Git root path or null if not in a git repo
9
+ */
10
+ function getGitRoot(cwd) {
11
+ try {
12
+ const result = execSync('git rev-parse --show-toplevel', {
13
+ cwd,
14
+ encoding: 'utf8',
15
+ stdio: ['pipe', 'pipe', 'pipe'],
16
+ });
17
+ return result.trim().replace(/\\/g, '/');
18
+ } catch {
19
+ return null;
20
+ }
21
+ }
22
+
23
+ /**
24
+ * Get relative path from git root to a target directory
25
+ * @param {string} gitRoot - Git root directory
26
+ * @param {string} targetDir - Target directory
27
+ * @returns {string} - Relative path
28
+ */
29
+ function getRelativePath(gitRoot, targetDir) {
30
+ // Normalize paths
31
+ const normalizedGitRoot = path.resolve(gitRoot).replace(/\\/g, '/');
32
+ const normalizedTarget = path.resolve(targetDir).replace(/\\/g, '/');
33
+
34
+ // Get relative path
35
+ return path.relative(normalizedGitRoot, normalizedTarget).replace(/\\/g, '/');
36
+ }
37
+
38
+ export default function huskyInit(api) {
39
+ api.registerCommand(
40
+ 'husky-init',
41
+ (command) =>
42
+ command
43
+ .description('initialize Husky git hooks for this theme')
44
+ .option('--force', 'force initialization even if already configured'),
45
+ async (options) => {
46
+ const themeDir = api.resolve();
47
+ const huskyDir = api.resolve('.husky');
48
+
49
+ // Check if .husky directory exists
50
+ if (!fs.existsSync(huskyDir)) {
51
+ console.error('❌ .husky directory not found in theme folder.');
52
+ console.error(' Make sure the theme was properly generated.');
53
+ process.exit(1);
54
+ }
55
+
56
+ // Find git root
57
+ const gitRoot = getGitRoot(themeDir);
58
+
59
+ if (!gitRoot) {
60
+ console.error('❌ Not inside a git repository.');
61
+ console.error(' Please run "git init" first at your project root.');
62
+ process.exit(1);
63
+ }
64
+
65
+ console.log(`📂 Git root: ${gitRoot}`);
66
+ console.log(`📁 Theme dir: ${themeDir}`);
67
+
68
+ // Calculate relative path from git root to .husky
69
+ const relativePath = getRelativePath(gitRoot, huskyDir);
70
+ console.log(`🔗 Husky path (relative to git root): ${relativePath}`);
71
+
72
+ // Check if husky is already configured
73
+ try {
74
+ const currentHooksPath = execSync('git config core.hooksPath', {
75
+ cwd: themeDir,
76
+ encoding: 'utf8',
77
+ stdio: ['pipe', 'pipe', 'pipe'],
78
+ }).trim();
79
+
80
+ if (currentHooksPath && !options.force) {
81
+ console.log(`\n✔ Husky is already configured.`);
82
+ console.log(` Current hooks path: ${currentHooksPath}`);
83
+ console.log(` Use --force to reconfigure.`);
84
+ return;
85
+ }
86
+ } catch {
87
+ // Not configured yet, continue
88
+ }
89
+
90
+ // Run husky from git root with the relative path
91
+ console.log('\n🚀 Initializing Husky...');
92
+
93
+ // Run husky with the relative path
94
+ try {
95
+ execSync(`npx husky ${relativePath}`, {
96
+ cwd: gitRoot,
97
+ stdio: 'inherit',
98
+ });
99
+ } catch (error) {
100
+ console.error('\n❌ Husky initialization failed.');
101
+ process.exit(1);
102
+ }
103
+
104
+
105
+ // Verify configuration
106
+ try {
107
+ const hooksPath = execSync('git config core.hooksPath', {
108
+ cwd: themeDir,
109
+ encoding: 'utf8',
110
+ stdio: ['pipe', 'pipe', 'pipe'],
111
+ }).trim();
112
+
113
+ console.log(`\n✅ Husky initialized successfully!`);
114
+ console.log(` Git hooks path: ${hooksPath}`);
115
+ console.log(
116
+ `\n Pre-commit hook will now protect core/ folder modifications.`,
117
+ );
118
+ } catch {
119
+ console.log(`\n✅ Husky initialized.`);
120
+ }
121
+ },
122
+ );
123
+ }
@@ -1 +1 @@
1
- 20.12.2
1
+ 24.11.1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chisel-scripts",
3
- "version": "2.1.5",
3
+ "version": "2.2.0",
4
4
  "description": "Chisel scripts",
5
5
  "bin": {
6
6
  "chisel-scripts": "bin/chisel-scripts.js"
@@ -39,5 +39,5 @@
39
39
  "peerDependencies": {
40
40
  "@wordpress/scripts": "^27.9.0 || ^31.0.0 || ^31.1.0 || ^31.2.0"
41
41
  },
42
- "gitHead": "116fc0781cdef419ebc0959289b1bae96a1198e9"
42
+ "gitHead": "259173a22a8cb7a7380936bfc01baf4b87f6afa3"
43
43
  }