create-portfoliable 1.2.13 → 1.2.15
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/package.json
CHANGED
|
@@ -27,6 +27,14 @@ export function resolveConsumerRuntimeAliases(projectRoot = process.cwd()) {
|
|
|
27
27
|
find: templateSpecifier,
|
|
28
28
|
replacement: consumerAbsolutePath
|
|
29
29
|
});
|
|
30
|
+
|
|
31
|
+
// Keep raw markdown imports in sync with consumer content overrides.
|
|
32
|
+
if (templateSpecifier.endsWith('.md')) {
|
|
33
|
+
aliases.push({
|
|
34
|
+
find: `${templateSpecifier}?raw`,
|
|
35
|
+
replacement: `${consumerAbsolutePath}?raw`
|
|
36
|
+
});
|
|
37
|
+
}
|
|
30
38
|
}
|
|
31
39
|
|
|
32
40
|
return aliases;
|
|
@@ -10,11 +10,13 @@ import { readLocaleConfigFromI18nConfig, resolveI18nConfigPath } from '../templa
|
|
|
10
10
|
|
|
11
11
|
// MARK: DEFAULTS
|
|
12
12
|
// Defines default output path used when no known case root can be resolved.
|
|
13
|
-
const DEFAULT_OUTPUT = 'src/content/cases/my-case/case.md';
|
|
13
|
+
const DEFAULT_OUTPUT = 'src/content/cases/my-case/my-case.md';
|
|
14
14
|
// Defines default case name used when no name is provided.
|
|
15
15
|
const DEFAULT_NAME = 'My Case';
|
|
16
16
|
// Defines candidate case roots in priority order for local repo and consumer apps.
|
|
17
17
|
const DEFAULT_CASES_ROOTS = ['templates/src/content/cases', 'src/content/cases'];
|
|
18
|
+
// Defines order increment applied when choosing the next generated case order value.
|
|
19
|
+
const CASE_ORDER_STEP = 10;
|
|
18
20
|
|
|
19
21
|
// MARK: DEFAULT CASE TEMPLATE
|
|
20
22
|
// Centralized defaults used when scaffolding new cases.
|
|
@@ -178,15 +180,110 @@ function resolveCasesRoots(cwd) {
|
|
|
178
180
|
}
|
|
179
181
|
|
|
180
182
|
// Computes default output markdown path from first discovered cases root.
|
|
181
|
-
function
|
|
182
|
-
const caseSlug = toSlug(name);
|
|
183
|
+
function resolvePrimaryCasesRoot(cwd) {
|
|
183
184
|
const roots = resolveCasesRoots(cwd);
|
|
184
185
|
if (roots.length > 0) {
|
|
185
|
-
|
|
186
|
-
return path.relative(cwd, target);
|
|
186
|
+
return roots[0];
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
return
|
|
189
|
+
return path.resolve(cwd, DEFAULT_CASES_ROOTS[0]);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function walkMarkdownFiles(rootDir, files = []) {
|
|
193
|
+
if (!fs.existsSync(rootDir)) {
|
|
194
|
+
return files;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const entries = fs.readdirSync(rootDir, { withFileTypes: true });
|
|
198
|
+
entries.forEach((entry) => {
|
|
199
|
+
const entryPath = path.join(rootDir, entry.name);
|
|
200
|
+
if (entry.isDirectory()) {
|
|
201
|
+
walkMarkdownFiles(entryPath, files);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (entry.isFile() && entry.name.toLowerCase().endsWith('.md')) {
|
|
206
|
+
files.push(entryPath);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
return files;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function collectExistingCaseMetadata(caseRoot) {
|
|
214
|
+
const usedSlugs = new Set();
|
|
215
|
+
const caseOrders = [];
|
|
216
|
+
const markdownFiles = walkMarkdownFiles(caseRoot, []);
|
|
217
|
+
|
|
218
|
+
markdownFiles.forEach((filePath) => {
|
|
219
|
+
const relativePath = path.relative(caseRoot, filePath);
|
|
220
|
+
const pathSegments = relativePath.split(path.sep).filter(Boolean);
|
|
221
|
+
const folderSlug = pathSegments.length > 1 ? pathSegments[0] : '';
|
|
222
|
+
if (folderSlug) {
|
|
223
|
+
usedSlugs.add(toSlug(folderSlug));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const fileSlug = toSlug(path.basename(filePath, '.md'));
|
|
227
|
+
if (fileSlug) {
|
|
228
|
+
usedSlugs.add(fileSlug);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
let source = '';
|
|
232
|
+
try {
|
|
233
|
+
source = fs.readFileSync(filePath, 'utf8');
|
|
234
|
+
} catch {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const idMatch = source.match(/"id"\s*:\s*"([^"]+)"/);
|
|
239
|
+
if (idMatch?.[1]) {
|
|
240
|
+
usedSlugs.add(toSlug(idMatch[1]));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const slugBlockMatch = source.match(/"slugByLocale"\s*:\s*\{([\s\S]*?)\}/);
|
|
244
|
+
if (slugBlockMatch?.[1]) {
|
|
245
|
+
const slugValues = slugBlockMatch[1].matchAll(/:\s*"([^"]+)"/g);
|
|
246
|
+
for (const slugMatch of slugValues) {
|
|
247
|
+
if (slugMatch?.[1]) {
|
|
248
|
+
usedSlugs.add(toSlug(slugMatch[1]));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const orderMatch = source.match(/"caseOrder"\s*:\s*(\d+)/);
|
|
254
|
+
if (orderMatch?.[1]) {
|
|
255
|
+
const parsedOrder = Number.parseInt(orderMatch[1], 10);
|
|
256
|
+
if (Number.isFinite(parsedOrder)) {
|
|
257
|
+
caseOrders.push(parsedOrder);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
return { usedSlugs, caseOrders };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function resolveUniqueSlug(baseSlug, usedSlugs) {
|
|
266
|
+
if (!usedSlugs.has(baseSlug)) {
|
|
267
|
+
return baseSlug;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
let index = 2;
|
|
271
|
+
while (usedSlugs.has(`${baseSlug}-${index}`)) {
|
|
272
|
+
index += 1;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return `${baseSlug}-${index}`;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function resolveDefaultScaffoldValues(cwd, name) {
|
|
279
|
+
const caseRoot = resolvePrimaryCasesRoot(cwd);
|
|
280
|
+
const { usedSlugs, caseOrders } = collectExistingCaseMetadata(caseRoot);
|
|
281
|
+
const baseSlug = toSlug(name);
|
|
282
|
+
const slug = resolveUniqueSlug(baseSlug, usedSlugs);
|
|
283
|
+
const maxOrder = caseOrders.length > 0 ? Math.max(...caseOrders) : DEFAULT_CASE_TEMPLATE.caseOrder - CASE_ORDER_STEP;
|
|
284
|
+
const caseOrder = maxOrder + CASE_ORDER_STEP;
|
|
285
|
+
const outFile = path.relative(cwd, path.join(caseRoot, slug, `${slug}.md`));
|
|
286
|
+
return { outFile, slug, caseOrder };
|
|
190
287
|
}
|
|
191
288
|
|
|
192
289
|
// Derives case slug from output path patterns or fallback case name.
|
|
@@ -277,7 +374,7 @@ function formatCaseConfigBlock(caseConfig) {
|
|
|
277
374
|
}
|
|
278
375
|
|
|
279
376
|
// Build the markdown scaffold body used for new cases.
|
|
280
|
-
function buildTemplate({ name, slug, localeCodes }) {
|
|
377
|
+
function buildTemplate({ name, slug, caseOrder, localeCodes }) {
|
|
281
378
|
// Derives normalized title for localized title fields.
|
|
282
379
|
const title = toTitle(name);
|
|
283
380
|
// Derives normalized slug for id and localized route slug fields.
|
|
@@ -292,7 +389,7 @@ function buildTemplate({ name, slug, localeCodes }) {
|
|
|
292
389
|
|
|
293
390
|
const caseConfig = {
|
|
294
391
|
id: cleanSlug,
|
|
295
|
-
caseOrder
|
|
392
|
+
caseOrder,
|
|
296
393
|
slugByLocale: localizedValue({ default: cleanSlug }),
|
|
297
394
|
socialImage: localizedValue({ default: DEFAULT_CASE_TEMPLATE.socialImage }),
|
|
298
395
|
title: {
|
|
@@ -421,11 +518,24 @@ function buildTemplate({ name, slug, localeCodes }) {
|
|
|
421
518
|
export function runCaseScaffold(options = {}) {
|
|
422
519
|
// Resolves working directory used for output file path calculation.
|
|
423
520
|
const cwd = options.cwd || process.cwd();
|
|
424
|
-
// Resolves output filename using option or context-aware default fallback.
|
|
425
|
-
const outFile = options.outFile || resolveDefaultOutFile(cwd, options.name || DEFAULT_NAME);
|
|
426
521
|
// Resolves case display name using option or default fallback.
|
|
427
522
|
const name = options.name || DEFAULT_NAME;
|
|
428
|
-
const
|
|
523
|
+
const hasExplicitOutFile = typeof options.outFile === 'string' && options.outFile.trim().length > 0;
|
|
524
|
+
|
|
525
|
+
const defaultScaffold = hasExplicitOutFile
|
|
526
|
+
? null
|
|
527
|
+
: resolveDefaultScaffoldValues(cwd, name);
|
|
528
|
+
|
|
529
|
+
// Resolves output filename using option or context-aware default fallback.
|
|
530
|
+
const outFile = hasExplicitOutFile
|
|
531
|
+
? options.outFile
|
|
532
|
+
: (defaultScaffold?.outFile || DEFAULT_OUTPUT);
|
|
533
|
+
|
|
534
|
+
const caseSlug = hasExplicitOutFile
|
|
535
|
+
? resolveCaseSlugFromOutput(outFile, name)
|
|
536
|
+
: defaultScaffold.slug;
|
|
537
|
+
|
|
538
|
+
const caseOrder = defaultScaffold?.caseOrder ?? DEFAULT_CASE_TEMPLATE.caseOrder;
|
|
429
539
|
// Coerces force flag to explicit boolean.
|
|
430
540
|
const force = Boolean(options.force);
|
|
431
541
|
// Resolves absolute output path for scaffold file.
|
|
@@ -444,7 +554,7 @@ export function runCaseScaffold(options = {}) {
|
|
|
444
554
|
}
|
|
445
555
|
|
|
446
556
|
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
447
|
-
fs.writeFileSync(outputPath, buildTemplate({ name, slug: caseSlug, localeCodes }), 'utf8');
|
|
557
|
+
fs.writeFileSync(outputPath, buildTemplate({ name, slug: caseSlug, caseOrder, localeCodes }), 'utf8');
|
|
448
558
|
console.log(`[scaffold-case] Created starter case file: ${outputPath}`);
|
|
449
559
|
return 0;
|
|
450
560
|
}
|
|
@@ -127,10 +127,14 @@ function readSupportedLocales(cwd = process.cwd()) {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
// === DEFAULTS ===
|
|
130
|
-
// Defines the default output path used when
|
|
131
|
-
const DEFAULT_OUTPUT = 'src/content/cases/my-case/case.md';
|
|
130
|
+
// Defines the default output path fallback used when no cases root is available.
|
|
131
|
+
const DEFAULT_OUTPUT = 'src/content/cases/my-case/my-case.md';
|
|
132
132
|
// Defines fallback title text used when callers do not provide --name.
|
|
133
133
|
const DEFAULT_NAME = 'My Case';
|
|
134
|
+
// Defines candidate case roots in priority order for local repo and consumer apps.
|
|
135
|
+
const DEFAULT_CASES_ROOTS = ['src/content/cases', 'templates/src/content/cases'];
|
|
136
|
+
// Defines order increment applied when choosing the next generated case order value.
|
|
137
|
+
const CASE_ORDER_STEP = 10;
|
|
134
138
|
|
|
135
139
|
// === STRING NORMALIZATION HELPERS ===
|
|
136
140
|
// Converts arbitrary text into a markdown-safe slug used for id and localized slug fields.
|
|
@@ -165,7 +169,7 @@ function parseArgs(argv) {
|
|
|
165
169
|
const args = argv.slice(2);
|
|
166
170
|
// Initializes parser output with defaults so missing flags still produce valid output.
|
|
167
171
|
const options = {
|
|
168
|
-
outFile:
|
|
172
|
+
outFile: '',
|
|
169
173
|
name: DEFAULT_NAME,
|
|
170
174
|
force: false
|
|
171
175
|
};
|
|
@@ -194,9 +198,130 @@ function parseArgs(argv) {
|
|
|
194
198
|
return options;
|
|
195
199
|
}
|
|
196
200
|
|
|
201
|
+
function resolveCasesRoots(cwd) {
|
|
202
|
+
return DEFAULT_CASES_ROOTS
|
|
203
|
+
.map((relativeRoot) => path.resolve(cwd, relativeRoot))
|
|
204
|
+
.filter((absoluteRoot) => fs.existsSync(absoluteRoot) && fs.statSync(absoluteRoot).isDirectory());
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function resolvePrimaryCasesRoot(cwd) {
|
|
208
|
+
const discoveredRoots = resolveCasesRoots(cwd);
|
|
209
|
+
if (discoveredRoots.length > 0) {
|
|
210
|
+
return discoveredRoots[0];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return path.resolve(cwd, DEFAULT_CASES_ROOTS[0]);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function walkMarkdownFiles(rootDir, files = []) {
|
|
217
|
+
if (!fs.existsSync(rootDir)) {
|
|
218
|
+
return files;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const entries = fs.readdirSync(rootDir, { withFileTypes: true });
|
|
222
|
+
entries.forEach((entry) => {
|
|
223
|
+
const entryPath = path.join(rootDir, entry.name);
|
|
224
|
+
if (entry.isDirectory()) {
|
|
225
|
+
walkMarkdownFiles(entryPath, files);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (entry.isFile() && entry.name.toLowerCase().endsWith('.md')) {
|
|
230
|
+
files.push(entryPath);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
return files;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function collectExistingCaseMetadata(caseRoot) {
|
|
238
|
+
const usedSlugs = new Set();
|
|
239
|
+
const caseOrders = [];
|
|
240
|
+
const markdownFiles = walkMarkdownFiles(caseRoot, []);
|
|
241
|
+
|
|
242
|
+
markdownFiles.forEach((filePath) => {
|
|
243
|
+
const relativePath = path.relative(caseRoot, filePath);
|
|
244
|
+
const pathSegments = relativePath.split(path.sep).filter(Boolean);
|
|
245
|
+
const folderSlug = pathSegments.length > 1 ? pathSegments[0] : '';
|
|
246
|
+
if (folderSlug) {
|
|
247
|
+
usedSlugs.add(toSlug(folderSlug));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const fileSlug = toSlug(path.basename(filePath, '.md'));
|
|
251
|
+
if (fileSlug) {
|
|
252
|
+
usedSlugs.add(fileSlug);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
let source = '';
|
|
256
|
+
try {
|
|
257
|
+
source = fs.readFileSync(filePath, 'utf8');
|
|
258
|
+
} catch {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const idMatch = source.match(/"id"\s*:\s*"([^"]+)"/);
|
|
263
|
+
if (idMatch?.[1]) {
|
|
264
|
+
usedSlugs.add(toSlug(idMatch[1]));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const slugBlockMatch = source.match(/"slugByLocale"\s*:\s*\{([\s\S]*?)\}/);
|
|
268
|
+
if (slugBlockMatch?.[1]) {
|
|
269
|
+
const slugValues = slugBlockMatch[1].matchAll(/:\s*"([^"]+)"/g);
|
|
270
|
+
for (const slugMatch of slugValues) {
|
|
271
|
+
if (slugMatch?.[1]) {
|
|
272
|
+
usedSlugs.add(toSlug(slugMatch[1]));
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const orderMatch = source.match(/"caseOrder"\s*:\s*(\d+)/);
|
|
278
|
+
if (orderMatch?.[1]) {
|
|
279
|
+
const parsedOrder = Number.parseInt(orderMatch[1], 10);
|
|
280
|
+
if (Number.isFinite(parsedOrder)) {
|
|
281
|
+
caseOrders.push(parsedOrder);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
return { usedSlugs, caseOrders };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function resolveUniqueSlug(baseSlug, usedSlugs) {
|
|
290
|
+
if (!usedSlugs.has(baseSlug)) {
|
|
291
|
+
return baseSlug;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
let index = 2;
|
|
295
|
+
while (usedSlugs.has(`${baseSlug}-${index}`)) {
|
|
296
|
+
index += 1;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return `${baseSlug}-${index}`;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function resolveCaseSlugFromOutput(outFile, name) {
|
|
303
|
+
const basename = path.basename(outFile || '');
|
|
304
|
+
if (basename.toLowerCase() === 'case.md') {
|
|
305
|
+
return toSlug(path.basename(path.dirname(outFile || '')) || name);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return toSlug(path.basename(outFile || '', '.md') || name);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function resolveDefaultScaffoldValues(cwd, name) {
|
|
312
|
+
const caseRoot = resolvePrimaryCasesRoot(cwd);
|
|
313
|
+
const { usedSlugs, caseOrders } = collectExistingCaseMetadata(caseRoot);
|
|
314
|
+
const baseSlug = toSlug(name);
|
|
315
|
+
const slug = resolveUniqueSlug(baseSlug, usedSlugs);
|
|
316
|
+
const maxOrder = caseOrders.length > 0 ? Math.max(...caseOrders) : DEFAULT_CASE_TEMPLATE.caseOrder - CASE_ORDER_STEP;
|
|
317
|
+
const caseOrder = maxOrder + CASE_ORDER_STEP;
|
|
318
|
+
const outFile = path.relative(cwd, path.join(caseRoot, slug, `${slug}.md`));
|
|
319
|
+
return { outFile, slug, caseOrder };
|
|
320
|
+
}
|
|
321
|
+
|
|
197
322
|
// === TEMPLATE CONSTRUCTION ===
|
|
198
323
|
// Produces localized starter markdown content for a new case study.
|
|
199
|
-
function buildTemplate({ name, slug }) {
|
|
324
|
+
function buildTemplate({ name, slug, caseOrder }) {
|
|
200
325
|
// Derives a normalized visible title from provided input.
|
|
201
326
|
const title = toTitle(name);
|
|
202
327
|
// Derives a safe slug fallback from either explicit slug or case name.
|
|
@@ -212,7 +337,7 @@ function buildTemplate({ name, slug }) {
|
|
|
212
337
|
|
|
213
338
|
const caseConfig = {
|
|
214
339
|
id: cleanSlug,
|
|
215
|
-
caseOrder
|
|
340
|
+
caseOrder,
|
|
216
341
|
slugByLocale: localizedValue({ default: cleanSlug }),
|
|
217
342
|
socialImage: localizedValue({ default: DEFAULT_CASE_TEMPLATE.socialImage }),
|
|
218
343
|
title: {
|
|
@@ -397,25 +522,29 @@ function formatCaseConfigBlock(caseConfig) {
|
|
|
397
522
|
return lines.join('\n');
|
|
398
523
|
}
|
|
399
524
|
|
|
400
|
-
function resolveCaseSlugFromOutput(outFile, name) {
|
|
401
|
-
const basename = path.basename(outFile || '');
|
|
402
|
-
if (basename.toLowerCase() === 'case.md') {
|
|
403
|
-
return toSlug(path.basename(path.dirname(outFile || '')) || name);
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
return toSlug(path.basename(outFile || '', '.md') || name);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
525
|
// === SCAFFOLD EXECUTION ===
|
|
410
526
|
// Creates a new case markdown file, respecting overwrite safety rules.
|
|
411
527
|
export function runCaseScaffold(options = {}) {
|
|
412
528
|
// Resolves working directory so script can be invoked from any location.
|
|
413
529
|
const cwd = options.cwd || process.cwd();
|
|
414
|
-
// Reads desired output file path from options or uses default path.
|
|
415
|
-
const outFile = options.outFile || DEFAULT_OUTPUT;
|
|
416
530
|
// Reads desired case display name from options or uses default title.
|
|
417
531
|
const name = options.name || DEFAULT_NAME;
|
|
418
|
-
const
|
|
532
|
+
const hasExplicitOutFile = typeof options.outFile === 'string' && options.outFile.trim().length > 0;
|
|
533
|
+
|
|
534
|
+
const defaultScaffold = hasExplicitOutFile
|
|
535
|
+
? null
|
|
536
|
+
: resolveDefaultScaffoldValues(cwd, name);
|
|
537
|
+
|
|
538
|
+
// Reads desired output file path from options or uses resolved default path.
|
|
539
|
+
const outFile = hasExplicitOutFile
|
|
540
|
+
? options.outFile
|
|
541
|
+
: (defaultScaffold?.outFile || DEFAULT_OUTPUT);
|
|
542
|
+
|
|
543
|
+
const caseSlug = hasExplicitOutFile
|
|
544
|
+
? resolveCaseSlugFromOutput(outFile, name)
|
|
545
|
+
: defaultScaffold.slug;
|
|
546
|
+
|
|
547
|
+
const caseOrder = defaultScaffold?.caseOrder ?? DEFAULT_CASE_TEMPLATE.caseOrder;
|
|
419
548
|
// Converts force option to explicit boolean for overwrite checks.
|
|
420
549
|
const force = Boolean(options.force);
|
|
421
550
|
// Resolves absolute output path to avoid relative path ambiguity.
|
|
@@ -428,7 +557,7 @@ export function runCaseScaffold(options = {}) {
|
|
|
428
557
|
}
|
|
429
558
|
|
|
430
559
|
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
431
|
-
fs.writeFileSync(outputPath, buildTemplate({ name, slug: caseSlug }), 'utf8');
|
|
560
|
+
fs.writeFileSync(outputPath, buildTemplate({ name, slug: caseSlug, caseOrder }), 'utf8');
|
|
432
561
|
console.log(`[scaffold-case] Created starter case file: ${outputPath}`);
|
|
433
562
|
return 0;
|
|
434
563
|
}
|