new-s-block 1.0.0 → 1.0.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.
Files changed (2) hide show
  1. package/bin/cli.js +58 -19
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -29,6 +29,11 @@ function splitKeywords(blockName) {
29
29
  return blockName.split('-').filter(Boolean);
30
30
  }
31
31
 
32
+ // "new-block" -> "st_new_block_inner"
33
+ function toInnerClass(blockName) {
34
+ return 'st_' + blockName.replace(/-/g, '_') + '_inner';
35
+ }
36
+
32
37
  function ensureDir(dirPath) {
33
38
  if (!fs.existsSync(dirPath)) {
34
39
  fs.mkdirSync(dirPath, { recursive: true });
@@ -51,10 +56,39 @@ function prompt(rl, question) {
51
56
  });
52
57
  }
53
58
 
59
+
60
+
61
+ // ── Version check ─────────────────────────────────────────────────────────
62
+
63
+ function checkForUpdate() {
64
+ return new Promise(function (resolve) {
65
+ var https = require('https');
66
+ var pkg = require('../package.json');
67
+ var req = https.get('https://registry.npmjs.org/new-s-block/latest', { timeout: 3000 }, function (res) {
68
+ var data = '';
69
+ res.on('data', function (chunk) { data += chunk; });
70
+ res.on('end', function () {
71
+ try {
72
+ var latest = JSON.parse(data).version;
73
+ if (latest && latest !== pkg.version) {
74
+ var yellow = '\x1b[33m';
75
+ var reset = '\x1b[0m';
76
+ console.log(yellow + ' \u26A0 Update available: ' + pkg.version + ' \u2192 ' + latest + reset);
77
+ console.log(yellow + ' Run: npx new-s-block@latest' + reset + '\n');
78
+ }
79
+ } catch (e) { /* silently ignore */ }
80
+ resolve();
81
+ });
82
+ });
83
+ req.on('error', function () { resolve(); });
84
+ req.on('timeout', function () { req.destroy(); resolve(); });
85
+ });
86
+ }
54
87
  // ── Main ───────────────────────────────────────────────────────────────────
55
88
 
56
89
  async function main() {
57
90
  console.log('\n\uD83E\uDDF1 ACF Block Generator\n');
91
+ var updateCheck = checkForUpdate();
58
92
 
59
93
  const rl = readline.createInterface({
60
94
  input: process.stdin,
@@ -71,9 +105,11 @@ async function main() {
71
105
  }
72
106
  }
73
107
 
74
- // 2. Block label
108
+ await updateCheck;
109
+
110
+ // 2. Block title
75
111
  const defaultLabel = toTitleCase(blockName);
76
- const labelRaw = await prompt(rl, 'Block label [' + defaultLabel + ']: ');
112
+ const labelRaw = await prompt(rl, 'Block title [' + defaultLabel + ']: ');
77
113
  const blockLabel = labelRaw.trim() || defaultLabel;
78
114
 
79
115
  // 3. Description
@@ -88,21 +124,25 @@ async function main() {
88
124
 
89
125
  // 5. Blocks folder
90
126
  const folderRaw = await prompt(rl, 'Blocks folder [blocks]: ');
91
- const blocksDir = 'blocks/' + (folderRaw.trim() || '');
92
127
 
93
128
  rl.close();
94
129
 
95
130
  // ── Resolve paths ────────────────────────────────────────────────────────
96
131
 
97
- // Normalise: strip any trailing slash and duplicate 'blocks/' the user may have typed
98
- const subFolder = folderRaw.trim().replace(/^blocks[\/\\]?/i, '').replace(/[\/\\]+$/, '');
99
- const blockDir = subFolder
132
+ // Strip any trailing slash and leading 'blocks/' the user may have typed
133
+ const subFolder = folderRaw.trim().replace(/^blocks[\/\\]?/i, '').replace(/[\/\\]+$/, '');
134
+ const blockDir = subFolder
100
135
  ? path.join(cwd, 'blocks', subFolder, blockName)
101
136
  : path.join(cwd, 'blocks', blockName);
102
137
 
138
+ // Relative block path from 'blocks/' used in end messages e.g. "cards/new-block"
139
+ const blockRelPath = subFolder ? subFolder + '/' + blockName : blockName;
140
+
103
141
  const renderFile = path.join(blockDir, blockName + '.php');
104
142
  const blockJsonFile = path.join(blockDir, 'block.json');
105
- const scssFile = path.join(cwd, 'assets', 'sass', 'blocks', blockName + '.scss');
143
+ const scssFile = subFolder
144
+ ? path.join(cwd, 'assets', 'sass', 'blocks', subFolder, blockName + '.scss')
145
+ : path.join(cwd, 'assets', 'sass', 'blocks', blockName + '.scss');
106
146
 
107
147
  if (fs.existsSync(blockDir)) {
108
148
  console.error('\n\u274C Block folder already exists: ' + path.relative(cwd, blockDir) + '\n');
@@ -119,12 +159,10 @@ async function main() {
119
159
  var autoKeywords = splitKeywords(blockName);
120
160
  autoKeywords.push('stier');
121
161
  var allKeywords = autoKeywords.concat(extraKeywords);
122
- // Deduplicate
123
162
  allKeywords = allKeywords.filter(function (v, i, a) { return a.indexOf(v) === i; });
124
163
 
125
164
  var keywordsJson = '["' + allKeywords.join('", "') + '"]';
126
165
 
127
- // Build block.json as a string to keep keywords on one line
128
166
  const blockJsonStr = '{\n' +
129
167
  ' "name": "acf/' + blockName + '",\n' +
130
168
  ' "title": "' + blockLabel + '",\n' +
@@ -147,12 +185,12 @@ async function main() {
147
185
 
148
186
  // ── render.php ───────────────────────────────────────────────────────────
149
187
 
150
- const innerClass = 'st' + blockName.replace(/-/g, '') + '_inner';
188
+ const innerClass = toInnerClass(blockName);
151
189
 
152
190
  const renderPhp = '<?php\n' +
153
191
  "$padding = get_field('padding');\n" +
154
192
  '\n' +
155
- "$class = 'st_block st_" + blockName + "';\n" +
193
+ "$class = 'st_block st_" + blockName.replace(/-/g, '_') + "';\n" +
156
194
  "if ( ! empty( $block['className'] ) ) {\n" +
157
195
  " $class .= ' ' . $block['className'];\n" +
158
196
  '}\n' +
@@ -179,28 +217,29 @@ async function main() {
179
217
 
180
218
  // ── block-name.scss ──────────────────────────────────────────────────────
181
219
 
182
- const scssContent = '.st_' + blockName + ' {\n\n}\n';
220
+ const scssContent = '.st_' + blockName.replace(/-/g, '_') + ' {\n\n}\n';
183
221
 
184
222
  writeFile(scssFile, scssContent);
185
223
 
186
224
  // ── Summary ──────────────────────────────────────────────────────────────
187
225
 
226
+ var cyan = '\x1b[36m';
227
+ var reset = '\x1b[0m';
228
+
188
229
  console.log('\n\u2705 Block "' + blockLabel + '" created successfully!\n');
189
230
  console.log(' \uD83D\uDCC1 ' + path.relative(cwd, blockDir) + '/');
190
231
  console.log(' \u251C\u2500\u2500 block.json');
191
232
  console.log(' \u2514\u2500\u2500 ' + blockName + '.php');
192
- console.log(' \uD83D\uDCC1 assets/sass/blocks/');
233
+ var sassDisplay = subFolder ? 'assets/sass/blocks/' + subFolder + '/' : 'assets/sass/blocks/';
234
+ console.log(' \uD83D\uDCC1 ' + sassDisplay);
193
235
  console.log(' \u2514\u2500\u2500 ' + blockName + '.scss');
194
236
  console.log('');
195
- var cyan = '\x1b[36m';
196
- var reset = '\x1b[0m';
197
- console.log('');
198
- console.log(" Don't forget to add " + cyan + "@import 'blocks/" + blockName + "';" + reset + " in 'assets/sass/theme.scss'");
199
- console.log(" Don't forget to add " + cyan + "register_block_type( __DIR__ . '/../blocks/" + blockName + "' );" + reset + " in 'includes/template-functions.php'");
237
+ console.log(" Don't forget to add " + cyan + "@import 'blocks/" + (subFolder ? subFolder + '/' : '') + blockName + "';" + reset + " in 'assets/sass/theme.scss'");
238
+ console.log(" Don't forget to add " + cyan + "register_block_type( __DIR__ . '/../blocks/" + blockRelPath + "' );" + reset + " in 'includes/template-functions.php'");
200
239
  console.log('');
201
240
  }
202
241
 
203
242
  main().catch(function (err) {
204
243
  console.error('\n\u274C Error: ' + err.message);
205
244
  process.exit(1);
206
- });
245
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "new-s-block",
3
- "version": "1.0.0",
3
+ "version": "1.0.6",
4
4
  "description": "CLI tool to scaffold ACF Gutenberg blocks",
5
5
  "bin": {
6
6
  "new-s-block": "./bin/cli.js"