@ncukondo/slide-generation 0.3.0 → 0.4.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/dist/cli/index.js CHANGED
@@ -941,7 +941,7 @@ var ReferenceManager = class {
941
941
  return map;
942
942
  }
943
943
  execCommand(cmd) {
944
- return new Promise((resolve7, reject) => {
944
+ return new Promise((resolve8, reject) => {
945
945
  exec(cmd, (error, stdout) => {
946
946
  if (error) {
947
947
  reject(
@@ -949,7 +949,7 @@ var ReferenceManager = class {
949
949
  );
950
950
  return;
951
951
  }
952
- resolve7(stdout.toString());
952
+ resolve8(stdout.toString());
953
953
  });
954
954
  });
955
955
  }
@@ -1688,7 +1688,7 @@ var Pipeline = class {
1688
1688
  };
1689
1689
 
1690
1690
  // src/index.ts
1691
- var VERSION = "0.3.0";
1691
+ var VERSION = "0.4.0";
1692
1692
 
1693
1693
  // src/cli/commands/convert.ts
1694
1694
  import { Command } from "commander";
@@ -3337,8 +3337,8 @@ import { tmpdir as tmpdir2 } from "os";
3337
3337
 
3338
3338
  // src/cli/commands/preview.ts
3339
3339
  import { Command as Command3 } from "commander";
3340
- import { access as access6, unlink as unlink2, readdir as readdir4, mkdir as mkdir2, writeFile as writeFile2, readFile as readFile10, rm } from "fs/promises";
3341
- import { basename as basename4, dirname as dirname4, join as join9, extname as extname2 } from "path";
3340
+ import { access as access6, readdir as readdir4, mkdir as mkdir2, writeFile as writeFile2, readFile as readFile10, rm } from "fs/promises";
3341
+ import { basename as basename4, dirname as dirname5, join as join9, extname as extname2 } from "path";
3342
3342
  import * as path6 from "path";
3343
3343
  import { tmpdir } from "os";
3344
3344
  import { createServer } from "http";
@@ -3347,16 +3347,24 @@ import { watch as chokidarWatch } from "chokidar";
3347
3347
 
3348
3348
  // src/cli/utils/marp-runner.ts
3349
3349
  import { existsSync } from "fs";
3350
- import { join as join8 } from "path";
3350
+ import { join as join8, resolve, dirname as dirname4 } from "path";
3351
3351
  import {
3352
3352
  execFileSync,
3353
3353
  spawn
3354
3354
  } from "child_process";
3355
3355
  function getMarpCommand(projectDir) {
3356
- const dir = projectDir ?? process.cwd();
3357
- const localMarp = join8(dir, "node_modules", ".bin", "marp");
3358
- if (existsSync(localMarp)) {
3359
- return localMarp;
3356
+ const startDir = resolve(projectDir ?? process.cwd());
3357
+ let currentDir = startDir;
3358
+ while (true) {
3359
+ const localMarp = join8(currentDir, "node_modules", ".bin", "marp");
3360
+ if (existsSync(localMarp)) {
3361
+ return localMarp;
3362
+ }
3363
+ const parentDir = dirname4(currentDir);
3364
+ if (parentDir === currentDir) {
3365
+ break;
3366
+ }
3367
+ currentDir = parentDir;
3360
3368
  }
3361
3369
  try {
3362
3370
  execFileSync("marp", ["--version"], { stdio: "ignore", timeout: 5e3 });
@@ -3513,23 +3521,19 @@ async function collectSlideInfo(dir, baseName, format) {
3513
3521
  async function checkMarpCliAvailable(projectDir) {
3514
3522
  return isMarpAvailable(projectDir);
3515
3523
  }
3516
- function getTempOutputPath(inputPath) {
3524
+ function getTempPreviewDir(inputPath) {
3517
3525
  const base = basename4(inputPath, ".yaml");
3518
- return join9(tmpdir(), `slide-gen-preview-${base}-${Date.now()}.md`);
3526
+ return join9(tmpdir(), `slide-gen-preview-${base}-${Date.now()}`);
3519
3527
  }
3520
- function buildMarpCommand(markdownPath, options) {
3521
- const parts = ["marp", "--preview"];
3522
- if (options.port) {
3523
- parts.push("-p", String(options.port));
3524
- }
3528
+ function buildMarpCommand(markdownDir, options) {
3529
+ const parts = ["marp", "--server", "-I", markdownDir];
3525
3530
  if (options.watch) {
3526
3531
  parts.push("--watch");
3527
3532
  }
3528
- parts.push(markdownPath);
3529
3533
  return parts.join(" ");
3530
3534
  }
3531
3535
  function startStaticServer(baseDir, port, options = {}) {
3532
- return new Promise((resolve7, reject) => {
3536
+ return new Promise((resolve8, reject) => {
3533
3537
  const mimeTypes = {
3534
3538
  ".html": "text/html",
3535
3539
  ".png": "image/png",
@@ -3566,7 +3570,7 @@ function startStaticServer(baseDir, port, options = {}) {
3566
3570
  const prefix = options.messagePrefix ?? "Server";
3567
3571
  console.log(`${prefix} running at ${chalk3.cyan(url)}`);
3568
3572
  }
3569
- resolve7(server);
3573
+ resolve8(server);
3570
3574
  });
3571
3575
  });
3572
3576
  }
@@ -3583,7 +3587,7 @@ async function executeGalleryPreview(inputPath, options) {
3583
3587
  return { success: false, errors };
3584
3588
  }
3585
3589
  console.log("Checking for Marp CLI...");
3586
- const projectDir = dirname4(inputPath);
3590
+ const projectDir = dirname5(inputPath);
3587
3591
  const marpAvailable = await checkMarpCliAvailable(projectDir);
3588
3592
  if (!marpAvailable) {
3589
3593
  console.error(
@@ -3600,7 +3604,7 @@ async function executeGalleryPreview(inputPath, options) {
3600
3604
  const configLoader = new ConfigLoader();
3601
3605
  let configPath = options.config;
3602
3606
  if (!configPath) {
3603
- configPath = await configLoader.findConfig(dirname4(inputPath));
3607
+ configPath = await configLoader.findConfig(dirname5(inputPath));
3604
3608
  }
3605
3609
  const config = await configLoader.load(configPath);
3606
3610
  console.log("Initializing pipeline...");
@@ -3698,11 +3702,11 @@ Showing ${slides.length} slides in gallery mode`);
3698
3702
  };
3699
3703
  process.on("SIGINT", signalHandler);
3700
3704
  process.on("SIGTERM", signalHandler);
3701
- await new Promise((resolve7) => {
3705
+ await new Promise((resolve8) => {
3702
3706
  if (options.signal) {
3703
- options.signal.addEventListener("abort", () => resolve7());
3707
+ options.signal.addEventListener("abort", () => resolve8());
3704
3708
  }
3705
- server.on("close", () => resolve7());
3709
+ server.on("close", () => resolve8());
3706
3710
  });
3707
3711
  return { success: true, errors };
3708
3712
  }
@@ -3736,7 +3740,7 @@ async function executePreview(inputPath, options) {
3736
3740
  return { success: false, errors };
3737
3741
  }
3738
3742
  console.log("Checking for Marp CLI...");
3739
- const marpAvailable = await checkMarpCliAvailable(dirname4(inputPath));
3743
+ const marpAvailable = await checkMarpCliAvailable(dirname5(inputPath));
3740
3744
  if (!marpAvailable) {
3741
3745
  console.error(
3742
3746
  chalk3.red(
@@ -3751,7 +3755,7 @@ async function executePreview(inputPath, options) {
3751
3755
  const configLoader = new ConfigLoader();
3752
3756
  let configPath = options.config;
3753
3757
  if (!configPath) {
3754
- configPath = await configLoader.findConfig(dirname4(inputPath));
3758
+ configPath = await configLoader.findConfig(dirname5(inputPath));
3755
3759
  }
3756
3760
  const config = await configLoader.load(configPath);
3757
3761
  console.log("Initializing pipeline...");
@@ -3765,7 +3769,9 @@ async function executePreview(inputPath, options) {
3765
3769
  process.exitCode = ExitCode.ConversionError;
3766
3770
  return { success: false, errors };
3767
3771
  }
3768
- const tempMarkdownPath = getTempOutputPath(inputPath);
3772
+ const tempDir = getTempPreviewDir(inputPath);
3773
+ await mkdir2(tempDir, { recursive: true });
3774
+ const tempMarkdownPath = join9(tempDir, "slides.md");
3769
3775
  console.log(`Converting ${chalk3.cyan(inputPath)}...`);
3770
3776
  try {
3771
3777
  await pipeline.runWithResult(inputPath, { outputPath: tempMarkdownPath });
@@ -3775,23 +3781,29 @@ async function executePreview(inputPath, options) {
3775
3781
  console.error(chalk3.red(`Error: Conversion failed: ${message}`));
3776
3782
  errors.push(message);
3777
3783
  process.exitCode = ExitCode.ConversionError;
3784
+ await rm(tempDir, { recursive: true, force: true });
3778
3785
  return { success: false, errors };
3779
3786
  }
3780
3787
  console.log(`
3781
3788
  Starting preview server on port ${chalk3.cyan(port)}...`);
3782
- const marpCommand = buildMarpCommand(tempMarkdownPath, {
3789
+ const marpCommand = buildMarpCommand(tempDir, {
3783
3790
  ...options,
3784
- port,
3785
- watch: false
3786
- // We handle watch ourselves if needed
3791
+ watch: options.watch ?? false
3787
3792
  });
3788
3793
  if (verbose) {
3789
3794
  console.log(`Running: ${marpCommand}`);
3790
3795
  }
3791
- const marpProcess = spawnMarp(["--preview", "-p", String(port), tempMarkdownPath], {
3792
- projectDir: dirname4(inputPath),
3796
+ const marpArgs = ["--server", "-I", tempDir];
3797
+ if (options.watch) {
3798
+ marpArgs.push("--watch");
3799
+ }
3800
+ const marpProcess = spawnMarp(marpArgs, {
3801
+ projectDir: dirname5(inputPath),
3793
3802
  stdio: "inherit"
3794
3803
  });
3804
+ console.log(`
3805
+ Preview available at ${chalk3.cyan(`http://localhost:${port}/slides.md`)}`);
3806
+ console.log("Open this URL in your browser to view the slides.");
3795
3807
  let watcher = null;
3796
3808
  let debounceTimer = null;
3797
3809
  if (options.watch) {
@@ -3829,7 +3841,7 @@ Watching ${chalk3.cyan(inputPath)} for changes...`);
3829
3841
  watcher?.close();
3830
3842
  marpProcess.kill();
3831
3843
  try {
3832
- await unlink2(tempMarkdownPath);
3844
+ await rm(tempDir, { recursive: true, force: true });
3833
3845
  } catch {
3834
3846
  }
3835
3847
  };
@@ -3845,13 +3857,13 @@ Watching ${chalk3.cyan(inputPath)} for changes...`);
3845
3857
  };
3846
3858
  process.on("SIGINT", signalHandler);
3847
3859
  process.on("SIGTERM", signalHandler);
3848
- await new Promise((resolve7) => {
3860
+ await new Promise((resolve8) => {
3849
3861
  marpProcess.on("exit", () => {
3850
3862
  cleanup();
3851
- resolve7();
3863
+ resolve8();
3852
3864
  });
3853
3865
  if (options.signal) {
3854
- options.signal.addEventListener("abort", () => resolve7());
3866
+ options.signal.addEventListener("abort", () => resolve8());
3855
3867
  }
3856
3868
  });
3857
3869
  return {
@@ -4396,8 +4408,8 @@ Showing ${templatePreviews.length} template preview(s)`);
4396
4408
  };
4397
4409
  process.on("SIGINT", signalHandler);
4398
4410
  process.on("SIGTERM", signalHandler);
4399
- await new Promise((resolve7) => {
4400
- server.on("close", () => resolve7());
4411
+ await new Promise((resolve8) => {
4412
+ server.on("close", () => resolve8());
4401
4413
  });
4402
4414
  }
4403
4415
  function createTemplatesCommand() {
@@ -5195,7 +5207,7 @@ import { mkdir as mkdir7, writeFile as writeFile7, access as access10, readdir a
5195
5207
  import { existsSync as existsSync2 } from "fs";
5196
5208
  import { execSync, spawnSync } from "child_process";
5197
5209
  import { createInterface } from "readline";
5198
- import { basename as basename7, dirname as dirname6, join as join16, resolve as resolve5, sep } from "path";
5210
+ import { basename as basename7, dirname as dirname7, join as join16, resolve as resolve6, sep } from "path";
5199
5211
  import { fileURLToPath } from "url";
5200
5212
  import chalk6 from "chalk";
5201
5213
  import ora3 from "ora";
@@ -6126,6 +6138,49 @@ The \`validate --format llm\` command provides:
6126
6138
  - Fix examples from template definitions
6127
6139
  - Contextual hints for unknown templates/icons
6128
6140
 
6141
+ ## Visual Feedback Loop
6142
+
6143
+ After creating or modifying slides, use this workflow to review and iterate:
6144
+
6145
+ ### Step 1: Take Screenshot
6146
+ \`\`\`bash
6147
+ # AI-optimized format (recommended)
6148
+ slide-gen screenshot presentation.yaml --format ai
6149
+
6150
+ # Or contact sheet for overview
6151
+ slide-gen screenshot presentation.yaml --contact-sheet
6152
+ \`\`\`
6153
+
6154
+ ### Step 2: Review Images
6155
+ Use the Read tool to view the generated screenshots:
6156
+ \`\`\`
6157
+ Read ./screenshots/presentation.001.jpeg
6158
+ \`\`\`
6159
+
6160
+ ### Step 3: Identify Issues
6161
+ Look for:
6162
+ - Layout problems (text overflow, alignment)
6163
+ - Visual balance (too much/little content)
6164
+ - Icon and color appropriateness
6165
+ - Readability of text and diagrams
6166
+
6167
+ ### Step 4: Make Adjustments
6168
+ Edit presentation.yaml to fix identified issues.
6169
+
6170
+ ### Step 5: Repeat
6171
+ Take new screenshots and verify improvements.
6172
+
6173
+ ### Example Iteration Cycle
6174
+
6175
+ 1. Create initial slides
6176
+ 2. \`slide-gen screenshot presentation.yaml --format ai --slide 3\`
6177
+ 3. \`Read ./screenshots/presentation.003.jpeg\`
6178
+ 4. Notice: "Title text is too long, wrapping awkwardly"
6179
+ 5. Edit presentation.yaml to shorten title
6180
+ 6. \`slide-gen screenshot presentation.yaml --format ai --slide 3\`
6181
+ 7. \`Read ./screenshots/presentation.003.jpeg\`
6182
+ 8. Verify fix, move to next slide
6183
+
6129
6184
  ## Reference Management
6130
6185
 
6131
6186
  For academic presentations, manage citations and references:
@@ -6212,7 +6267,24 @@ Read \`.skills/slide-assistant/SKILL.md\` for detailed instructions.
6212
6267
  - \`/slide-validate\` - Validate slide source file
6213
6268
  - \`/slide-preview\` - Preview slides in browser
6214
6269
  - \`/slide-screenshot\` - Take screenshots for review
6270
+ - \`/slide-review\` - Visual review and iteration workflow
6215
6271
  - \`/slide-theme\` - Adjust theme and styling
6272
+
6273
+ ## Important: Visual Review
6274
+
6275
+ **After creating or editing slides, always run visual review:**
6276
+
6277
+ \`\`\`bash
6278
+ /slide-review
6279
+ \`\`\`
6280
+
6281
+ Or manually:
6282
+ 1. \`slide-gen screenshot presentation.yaml --format ai\`
6283
+ 2. \`Read ./screenshots/presentation.001.jpeg\`
6284
+ 3. Check layout, text overflow, visual balance
6285
+ 4. Edit and repeat until satisfied
6286
+
6287
+ This ensures slides look correct before delivery.
6216
6288
  `;
6217
6289
  }
6218
6290
 
@@ -6528,6 +6600,69 @@ After user provides images:
6528
6600
 
6529
6601
  ### Phase 4: Iteration
6530
6602
  Handle adjustments (cropping, replacement) as needed.
6603
+
6604
+ ## Visual Review Flow
6605
+
6606
+ ### When to Use Visual Review
6607
+
6608
+ - After initial slide creation
6609
+ - When adjusting layouts or styling
6610
+ - Before final delivery
6611
+ - When user reports visual issues
6612
+
6613
+ ### Quick Review Workflow
6614
+
6615
+ 1. **Generate screenshots**:
6616
+ \`\`\`bash
6617
+ slide-gen screenshot presentation.yaml --format ai
6618
+ \`\`\`
6619
+
6620
+ 2. **Review each slide**:
6621
+ \`\`\`
6622
+ Read ./screenshots/presentation.001.jpeg
6623
+ Read ./screenshots/presentation.002.jpeg
6624
+ ...
6625
+ \`\`\`
6626
+
6627
+ 3. **Document issues** found in each slide
6628
+
6629
+ 4. **Make batch edits** to presentation.yaml
6630
+
6631
+ 5. **Regenerate and verify**:
6632
+ \`\`\`bash
6633
+ slide-gen screenshot presentation.yaml --format ai
6634
+ \`\`\`
6635
+
6636
+ ### Contact Sheet Review
6637
+
6638
+ For quick overview of all slides:
6639
+
6640
+ 1. **Generate contact sheet**:
6641
+ \`\`\`bash
6642
+ slide-gen screenshot presentation.yaml --contact-sheet
6643
+ \`\`\`
6644
+
6645
+ 2. **Review overview**:
6646
+ \`\`\`
6647
+ Read ./screenshots/presentation-contact.png
6648
+ \`\`\`
6649
+
6650
+ 3. **Identify slides needing attention**
6651
+
6652
+ 4. **Deep dive on specific slides**:
6653
+ \`\`\`bash
6654
+ slide-gen screenshot presentation.yaml --format ai --slide 5
6655
+ \`\`\`
6656
+
6657
+ ### Common Visual Issues to Check
6658
+
6659
+ | Issue | What to Look For | Fix |
6660
+ |-------|------------------|-----|
6661
+ | Text overflow | Text cut off or wrapped | Shorten text, use bullet-list |
6662
+ | Empty space | Large blank areas | Add content or use different template |
6663
+ | Cluttered | Too much content | Split into multiple slides |
6664
+ | Poor contrast | Hard to read text | Adjust colors in theme |
6665
+ | Icon mismatch | Icon doesn't fit context | Search for better icon |
6531
6666
  `;
6532
6667
  }
6533
6668
 
@@ -6804,18 +6939,128 @@ slide-gen screenshot $ARGUMENTS
6804
6939
 
6805
6940
  If no argument provided:
6806
6941
  \`\`\`bash
6807
- slide-gen screenshot presentation.yaml -o screenshots/
6942
+ slide-gen screenshot presentation.yaml --format ai
6808
6943
  \`\`\`
6809
6944
 
6810
6945
  ## Options
6811
6946
 
6812
- - \`--slide <number>\`: Screenshot specific slide only
6813
- - \`--width <pixels>\`: Image width (default: 1280)
6814
- - \`--output <dir>\`: Output directory
6947
+ | Option | Description | Default |
6948
+ |--------|-------------|---------|
6949
+ | \`--format <fmt>\` | Output format (png/jpeg/ai) | png |
6950
+ | \`--slide <number>\` | Screenshot specific slide only | All |
6951
+ | \`--contact-sheet\` | Generate overview of all slides | false |
6952
+ | \`--columns <num>\` | Contact sheet columns | 2 |
6953
+ | \`--width <pixels>\` | Image width | 1280 (ai: 640) |
6954
+ | \`--quality <num>\` | JPEG quality (1-100) | 80 |
6955
+ | \`--output <dir>\` | Output directory | ./screenshots |
6956
+
6957
+ ## AI Optimization Mode
6958
+
6959
+ Use \`--format ai\` for token-efficient screenshots:
6960
+ - 640px width (75% token reduction)
6961
+ - JPEG format
6962
+ - Shows estimated token consumption
6963
+
6964
+ \`\`\`bash
6965
+ # AI-optimized screenshots
6966
+ slide-gen screenshot presentation.yaml --format ai
6967
+
6968
+ # Contact sheet for overview
6969
+ slide-gen screenshot presentation.yaml --contact-sheet
6970
+
6971
+ # AI-optimized contact sheet
6972
+ slide-gen screenshot presentation.yaml --format ai --contact-sheet
6973
+ \`\`\`
6974
+
6975
+ ## Token Efficiency
6815
6976
 
6816
- ## After Screenshot
6977
+ | Format | Width | Est. Tokens/slide |
6978
+ |--------|-------|-------------------|
6979
+ | png/jpeg | 1280 | ~1,229 |
6980
+ | ai | 640 | ~308 (~75% reduction) |
6817
6981
 
6818
- Read the screenshot images to review slide content and provide feedback.
6982
+ ## Visual Feedback Workflow
6983
+
6984
+ 1. Take screenshot: \`slide-gen screenshot presentation.yaml --format ai\`
6985
+ 2. Review image: \`Read ./screenshots/presentation.001.jpeg\`
6986
+ 3. Identify issues (layout, text, icons)
6987
+ 4. Edit presentation.yaml
6988
+ 5. Repeat until satisfied
6989
+ `;
6990
+ }
6991
+
6992
+ // src/cli/templates/ai/commands/slide-review.ts
6993
+ function generateSlideReviewCommand() {
6994
+ return `Review slides visually and iterate on improvements.
6995
+
6996
+ ## Workflow
6997
+
6998
+ 1. **Take AI-optimized screenshots**:
6999
+ \`\`\`bash
7000
+ slide-gen screenshot $ARGUMENTS --format ai
7001
+ \`\`\`
7002
+ If no argument: \`slide-gen screenshot presentation.yaml --format ai\`
7003
+
7004
+ 2. **Review each slide image**:
7005
+ \`\`\`
7006
+ Read ./screenshots/presentation.001.jpeg
7007
+ Read ./screenshots/presentation.002.jpeg
7008
+ ...
7009
+ \`\`\`
7010
+
7011
+ 3. **Check for issues**:
7012
+ - Text overflow or awkward wrapping
7013
+ - Poor visual balance (too empty / too cluttered)
7014
+ - Icon appropriateness
7015
+ - Color contrast and readability
7016
+ - Diagram clarity
7017
+
7018
+ 4. **Report findings** to user with specific slide numbers
7019
+
7020
+ 5. **If issues found**, edit presentation.yaml and repeat from step 1
7021
+
7022
+ ## Quick Overview
7023
+
7024
+ For a quick overview of all slides:
7025
+ \`\`\`bash
7026
+ slide-gen screenshot presentation.yaml --contact-sheet
7027
+ Read ./screenshots/presentation-contact.png
7028
+ \`\`\`
7029
+
7030
+ ## Token Efficiency
7031
+
7032
+ Always use \`--format ai\` for ~75% token reduction:
7033
+ - Default: ~1,229 tokens/slide
7034
+ - AI mode: ~308 tokens/slide
7035
+
7036
+ ## Common Issues Checklist
7037
+
7038
+ | Issue | What to Look For | Fix |
7039
+ |-------|------------------|-----|
7040
+ | Text overflow | Text cut off or wrapped | Shorten text, use bullet-list |
7041
+ | Empty space | Large blank areas | Add content or use different template |
7042
+ | Cluttered | Too much content | Split into multiple slides |
7043
+ | Poor contrast | Hard to read text | Adjust colors in theme |
7044
+ | Icon mismatch | Icon doesn't fit context | Search for better icon |
7045
+
7046
+ ## Example Session
7047
+
7048
+ \`\`\`bash
7049
+ # Initial review
7050
+ slide-gen screenshot presentation.yaml --format ai
7051
+
7052
+ # Check slide 3
7053
+ Read ./screenshots/presentation.003.jpeg
7054
+ # Notice: "Title text is too long"
7055
+
7056
+ # Edit presentation.yaml to shorten title
7057
+
7058
+ # Re-take screenshot for slide 3
7059
+ slide-gen screenshot presentation.yaml --format ai --slide 3
7060
+
7061
+ # Verify fix
7062
+ Read ./screenshots/presentation.003.jpeg
7063
+ \`\`\`
6819
7064
  `;
6820
7065
  }
6821
7066
 
@@ -6910,7 +7155,7 @@ slide-gen validate presentation.yaml
6910
7155
 
6911
7156
  // src/cli/commands/init.ts
6912
7157
  function getPackageRoot() {
6913
- const __dirname = dirname6(fileURLToPath(import.meta.url));
7158
+ const __dirname = dirname7(fileURLToPath(import.meta.url));
6914
7159
  if (__dirname.includes(`${sep}src${sep}`) || __dirname.includes("/src/")) {
6915
7160
  return join16(__dirname, "..", "..", "..");
6916
7161
  }
@@ -6923,7 +7168,7 @@ function createInitCommand() {
6923
7168
  }
6924
7169
  async function executeInit(directory, options) {
6925
7170
  const spinner = ora3();
6926
- const targetDir = resolve5(directory);
7171
+ const targetDir = resolve6(directory);
6927
7172
  const includeExamples = options.examples !== false;
6928
7173
  const includeAiConfig = options.aiConfig !== false;
6929
7174
  const includeSources = options.sources !== false;
@@ -6972,11 +7217,11 @@ async function executeInit(directory, options) {
6972
7217
  await sourcesManager.init({
6973
7218
  name: "Untitled Project",
6974
7219
  setup_pattern: options.fromDirectory ? "A" : void 0,
6975
- original_source: options.fromDirectory ? resolve5(options.fromDirectory) : void 0
7220
+ original_source: options.fromDirectory ? resolve6(options.fromDirectory) : void 0
6976
7221
  });
6977
7222
  if (options.fromDirectory) {
6978
7223
  const importer = new SourceImporter(targetDir, sourcesManager);
6979
- const result = await importer.importDirectory(resolve5(options.fromDirectory), {
7224
+ const result = await importer.importDirectory(resolve6(options.fromDirectory), {
6980
7225
  recursive: true
6981
7226
  });
6982
7227
  sourcesImported = result.imported;
@@ -6997,6 +7242,7 @@ async function executeInit(directory, options) {
6997
7242
  }
6998
7243
  if (includeAiConfig) {
6999
7244
  console.log(` ${chalk6.cyan(".skills/")} - AgentSkills configuration`);
7245
+ console.log(` ${chalk6.cyan(".claude/skills/")} - Claude Code skills`);
7000
7246
  console.log(` ${chalk6.cyan("CLAUDE.md")} - Claude Code configuration`);
7001
7247
  console.log(` ${chalk6.cyan("AGENTS.md")} - OpenCode configuration`);
7002
7248
  console.log(` ${chalk6.cyan(".cursorrules")} - Cursor configuration`);
@@ -7081,16 +7327,16 @@ async function promptMarpInstallChoice() {
7081
7327
  console.log(` ${chalk6.cyan("2)")} Local install ${chalk6.dim("(creates package.json)")}`);
7082
7328
  console.log(` ${chalk6.cyan("3)")} Skip ${chalk6.dim("(I'll install it later)")}`);
7083
7329
  console.log("");
7084
- return new Promise((resolve7) => {
7330
+ return new Promise((resolve8) => {
7085
7331
  rl.question("Choice [1]: ", (answer) => {
7086
7332
  rl.close();
7087
7333
  const normalized = answer.trim();
7088
7334
  if (normalized === "" || normalized === "1") {
7089
- resolve7("global");
7335
+ resolve8("global");
7090
7336
  } else if (normalized === "2") {
7091
- resolve7("local");
7337
+ resolve8("local");
7092
7338
  } else {
7093
- resolve7("skip");
7339
+ resolve8("skip");
7094
7340
  }
7095
7341
  });
7096
7342
  });
@@ -7204,30 +7450,35 @@ async function showMarpCliInfo(targetDir) {
7204
7450
  async function generateAiConfig(targetDir) {
7205
7451
  await mkdir7(join16(targetDir, ".skills", "slide-assistant", "references"), { recursive: true });
7206
7452
  await mkdir7(join16(targetDir, ".skills", "slide-assistant", "scripts"), { recursive: true });
7453
+ await mkdir7(join16(targetDir, ".claude", "skills", "slide-assistant", "references"), { recursive: true });
7207
7454
  await mkdir7(join16(targetDir, ".claude", "commands"), { recursive: true });
7208
7455
  await mkdir7(join16(targetDir, ".opencode", "agent"), { recursive: true });
7209
- await writeFileIfNotExists(
7210
- join16(targetDir, ".skills", "slide-assistant", "SKILL.md"),
7211
- generateSkillMd()
7212
- );
7213
- await writeFileIfNotExists(
7214
- join16(targetDir, ".skills", "slide-assistant", "references", "templates.md"),
7215
- generateTemplatesRef()
7216
- );
7217
- await writeFileIfNotExists(
7218
- join16(targetDir, ".skills", "slide-assistant", "references", "workflows.md"),
7219
- generateWorkflowsRef()
7220
- );
7221
- await writeFileIfNotExists(
7222
- join16(targetDir, ".skills", "slide-assistant", "references", "skill.md"),
7223
- generateReferenceSkillMd()
7224
- );
7456
+ const skillDirs = [
7457
+ join16(targetDir, ".skills", "slide-assistant"),
7458
+ join16(targetDir, ".claude", "skills", "slide-assistant")
7459
+ ];
7460
+ for (const skillDir of skillDirs) {
7461
+ await writeFileIfNotExists(join16(skillDir, "SKILL.md"), generateSkillMd());
7462
+ await writeFileIfNotExists(
7463
+ join16(skillDir, "references", "templates.md"),
7464
+ generateTemplatesRef()
7465
+ );
7466
+ await writeFileIfNotExists(
7467
+ join16(skillDir, "references", "workflows.md"),
7468
+ generateWorkflowsRef()
7469
+ );
7470
+ await writeFileIfNotExists(
7471
+ join16(skillDir, "references", "skill.md"),
7472
+ generateReferenceSkillMd()
7473
+ );
7474
+ }
7225
7475
  await writeFileIfNotExists(join16(targetDir, "CLAUDE.md"), generateClaudeMd());
7226
7476
  const commandGenerators = {
7227
7477
  "slide-create": generateSlideCreateCommand,
7228
7478
  "slide-validate": generateSlideValidateCommand,
7229
7479
  "slide-preview": generateSlidePreviewCommand,
7230
7480
  "slide-screenshot": generateSlideScreenshotCommand,
7481
+ "slide-review": generateSlideReviewCommand,
7231
7482
  "slide-theme": generateSlideThemeCommand,
7232
7483
  "slide-references": generateSlideReferencesCommand
7233
7484
  };
@@ -7340,7 +7591,7 @@ slides:
7340
7591
  // src/cli/commands/watch.ts
7341
7592
  import { Command as Command7 } from "commander";
7342
7593
  import { access as access11 } from "fs/promises";
7343
- import { basename as basename8, dirname as dirname7, join as join17 } from "path";
7594
+ import { basename as basename8, dirname as dirname8, join as join17 } from "path";
7344
7595
  import chalk7 from "chalk";
7345
7596
  import { watch as chokidarWatch2 } from "chokidar";
7346
7597
  var WatchState = class {
@@ -7373,7 +7624,7 @@ var WatchState = class {
7373
7624
  }
7374
7625
  };
7375
7626
  function getDefaultOutputPath2(inputPath) {
7376
- const dir = dirname7(inputPath);
7627
+ const dir = dirname8(inputPath);
7377
7628
  const base = basename8(inputPath, ".yaml");
7378
7629
  return join17(dir, `${base}.md`);
7379
7630
  }
@@ -7435,7 +7686,7 @@ async function executeWatch(inputPath, options) {
7435
7686
  const configLoader = new ConfigLoader();
7436
7687
  let configPath = options.config;
7437
7688
  if (!configPath) {
7438
- configPath = await configLoader.findConfig(dirname7(inputPath));
7689
+ configPath = await configLoader.findConfig(dirname8(inputPath));
7439
7690
  }
7440
7691
  const config = await configLoader.load(configPath);
7441
7692
  const pipeline = new Pipeline(config);
@@ -7504,9 +7755,9 @@ async function executeWatch(inputPath, options) {
7504
7755
  };
7505
7756
  process.on("SIGINT", signalHandler);
7506
7757
  process.on("SIGTERM", signalHandler);
7507
- await new Promise((resolve7) => {
7758
+ await new Promise((resolve8) => {
7508
7759
  if (options.signal) {
7509
- options.signal.addEventListener("abort", () => resolve7());
7760
+ options.signal.addEventListener("abort", () => resolve8());
7510
7761
  }
7511
7762
  });
7512
7763
  return {
@@ -7519,7 +7770,7 @@ async function executeWatch(inputPath, options) {
7519
7770
  // src/cli/commands/images.ts
7520
7771
  import { Command as Command8 } from "commander";
7521
7772
  import { readFile as readFile15, stat as stat2, mkdir as mkdir8 } from "fs/promises";
7522
- import { dirname as dirname8, basename as basename9, join as join18 } from "path";
7773
+ import { dirname as dirname9, basename as basename9, join as join18 } from "path";
7523
7774
  import chalk8 from "chalk";
7524
7775
  import { stringify as stringifyYaml3 } from "yaml";
7525
7776
  function createImagesCommand() {
@@ -7542,7 +7793,7 @@ function createImagesRequestCommand() {
7542
7793
  async function executeImagesStatus(inputPath) {
7543
7794
  try {
7544
7795
  const slides = await loadPresentation(inputPath);
7545
- const baseDir = dirname8(inputPath);
7796
+ const baseDir = dirname9(inputPath);
7546
7797
  const validator = new ImageValidator(baseDir);
7547
7798
  const imageRefs = validator.extractImageReferences(slides);
7548
7799
  if (imageRefs.length === 0) {
@@ -7642,7 +7893,7 @@ async function outputImageStatus(stats, imageRefs, _validator, baseDir) {
7642
7893
  async function executeImagesRequest(inputPath, options) {
7643
7894
  try {
7644
7895
  const slides = await loadPresentation(inputPath);
7645
- const baseDir = dirname8(inputPath);
7896
+ const baseDir = dirname9(inputPath);
7646
7897
  const validator = new ImageValidator(baseDir);
7647
7898
  const missingImages = await validator.getMissingImages(slides);
7648
7899
  if (missingImages.length === 0) {
@@ -7842,7 +8093,7 @@ async function processSingleFile(filePath, options) {
7842
8093
  return;
7843
8094
  }
7844
8095
  const processor = new ImageProcessor();
7845
- const dir = dirname8(filePath);
8096
+ const dir = dirname9(filePath);
7846
8097
  const filename = basename9(filePath);
7847
8098
  const outputDir = join18(dir, options.output);
7848
8099
  await mkdir8(outputDir, { recursive: true });
@@ -7940,10 +8191,11 @@ function parseBlurSpec(spec) {
7940
8191
 
7941
8192
  // src/cli/commands/screenshot.ts
7942
8193
  import { Command as Command9 } from "commander";
7943
- import { access as access12, mkdir as mkdir9, readdir as readdir7, unlink as unlink3 } from "fs/promises";
7944
- import { basename as basename10, dirname as dirname9, join as join19 } from "path";
8194
+ import { access as access12, mkdir as mkdir9, readdir as readdir7, unlink as unlink2 } from "fs/promises";
8195
+ import { basename as basename10, dirname as dirname10, join as join19 } from "path";
7945
8196
  import chalk9 from "chalk";
7946
8197
  import ora4 from "ora";
8198
+ import sharp2 from "sharp";
7947
8199
  async function filterToSpecificSlide(outputDir, baseName, slideNumber, format) {
7948
8200
  const slideStr = slideNumber.toString().padStart(3, "0");
7949
8201
  const targetFileName = `${baseName}.${slideStr}.${format}`;
@@ -7962,7 +8214,7 @@ async function filterToSpecificSlide(outputDir, baseName, slideNumber, format) {
7962
8214
  );
7963
8215
  for (const file of slideFiles) {
7964
8216
  if (file !== targetFileName) {
7965
- await unlink3(join19(outputDir, file));
8217
+ await unlink2(join19(outputDir, file));
7966
8218
  }
7967
8219
  }
7968
8220
  return {
@@ -7973,19 +8225,120 @@ async function filterToSpecificSlide(outputDir, baseName, slideNumber, format) {
7973
8225
  function checkMarpCliAvailable2(projectDir) {
7974
8226
  return isMarpAvailable(projectDir);
7975
8227
  }
8228
+ function estimateTokens(width, height) {
8229
+ return Math.ceil(width * height / 750);
8230
+ }
8231
+ function calculateGridDimensions(slideCount, columns) {
8232
+ const rows = Math.ceil(slideCount / columns);
8233
+ return { rows, columns };
8234
+ }
8235
+ function createNumberOverlay(number, width) {
8236
+ const svg = `
8237
+ <svg width="${width}" height="30">
8238
+ <rect width="${width}" height="30" fill="rgba(0,0,0,0.6)"/>
8239
+ <text x="10" y="22" font-family="system-ui, -apple-system, 'Segoe UI', sans-serif" font-size="16" fill="white">
8240
+ Slide ${number}
8241
+ </text>
8242
+ </svg>
8243
+ `;
8244
+ return Buffer.from(svg);
8245
+ }
8246
+ async function generateContactSheet(slides, options) {
8247
+ const {
8248
+ columns,
8249
+ padding = 10,
8250
+ showNumbers = true,
8251
+ slideWidth = 640,
8252
+ slideHeight = 360
8253
+ } = options;
8254
+ if (slides.length === 0) {
8255
+ return { success: false, error: "No slides provided" };
8256
+ }
8257
+ try {
8258
+ const { rows } = calculateGridDimensions(slides.length, columns);
8259
+ const canvasWidth = columns * slideWidth + (columns + 1) * padding;
8260
+ const canvasHeight = rows * slideHeight + (rows + 1) * padding;
8261
+ const composites = [];
8262
+ for (let i = 0; i < slides.length; i++) {
8263
+ const slide = slides[i];
8264
+ const col = i % columns;
8265
+ const row = Math.floor(i / columns);
8266
+ const x = padding + col * (slideWidth + padding);
8267
+ const y = padding + row * (slideHeight + padding);
8268
+ const resized = await sharp2(slide.path).resize(slideWidth, slideHeight, { fit: "contain", background: { r: 255, g: 255, b: 255 } }).toBuffer();
8269
+ composites.push({
8270
+ input: resized,
8271
+ left: x,
8272
+ top: y
8273
+ });
8274
+ if (showNumbers) {
8275
+ const numberOverlay = createNumberOverlay(slide.index, slideWidth);
8276
+ composites.push({
8277
+ input: numberOverlay,
8278
+ left: x,
8279
+ top: y + slideHeight - 30
8280
+ });
8281
+ }
8282
+ }
8283
+ await sharp2({
8284
+ create: {
8285
+ width: canvasWidth,
8286
+ height: canvasHeight,
8287
+ channels: 4,
8288
+ background: { r: 245, g: 245, b: 245, alpha: 1 }
8289
+ }
8290
+ }).composite(composites).png().toFile(options.outputPath);
8291
+ return {
8292
+ success: true,
8293
+ outputPath: options.outputPath
8294
+ };
8295
+ } catch (error) {
8296
+ return {
8297
+ success: false,
8298
+ error: error instanceof Error ? error.message : "Unknown error"
8299
+ };
8300
+ }
8301
+ }
8302
+ function formatAiOutput(options) {
8303
+ const { files, width, height, outputDir } = options;
8304
+ const tokensPerImage = estimateTokens(width, height);
8305
+ const totalTokens = tokensPerImage * files.length;
8306
+ const imageLabel = files.length === 1 ? "image" : "images";
8307
+ const lines = [
8308
+ "Screenshots saved (AI-optimized):",
8309
+ ""
8310
+ ];
8311
+ for (const file of files) {
8312
+ lines.push(` ${join19(outputDir, file)}`);
8313
+ }
8314
+ lines.push("");
8315
+ lines.push(`Estimated tokens: ~${totalTokens} (${files.length} ${imageLabel})`);
8316
+ if (files.length > 0) {
8317
+ lines.push("");
8318
+ lines.push("To review in Claude Code:");
8319
+ lines.push(` Read ${join19(outputDir, files[0])}`);
8320
+ }
8321
+ return lines.join("\n");
8322
+ }
7976
8323
  function buildMarpCommandArgs(markdownPath, outputDir, options) {
7977
- const format = options.format || "png";
7978
- const args = ["--images", format];
7979
- if (options.width && options.width !== 1280) {
7980
- const scale = options.width / 1280;
8324
+ const isAiFormat = options.format === "ai";
8325
+ const imageFormat = isAiFormat ? "jpeg" : options.format || "png";
8326
+ const width = isAiFormat ? 640 : options.width || 1280;
8327
+ const args = ["--images", imageFormat];
8328
+ if (width !== 1280) {
8329
+ const scale = width / 1280;
7981
8330
  args.push("--image-scale", String(scale));
7982
8331
  }
8332
+ if (imageFormat === "jpeg") {
8333
+ const quality = options.quality || 80;
8334
+ args.push("--jpeg-quality", String(quality));
8335
+ }
7983
8336
  args.push("-o", outputDir);
7984
8337
  args.push(markdownPath);
7985
8338
  return args;
7986
8339
  }
7987
8340
  function createScreenshotCommand() {
7988
- return new Command9("screenshot").description("Take screenshots of slides (requires Marp CLI)").argument("<input>", "Source YAML file").option("-o, --output <path>", "Output directory", "./screenshots").option("-s, --slide <number>", "Specific slide number (1-based)", parseInt).option("-w, --width <pixels>", "Image width", parseInt, 1280).option("-f, --format <fmt>", "Image format (png/jpeg)", "png").option("-c, --config <path>", "Config file path").option("-v, --verbose", "Verbose output").action(async (input, options) => {
8341
+ return new Command9("screenshot").description("Take screenshots of slides (requires Marp CLI)").argument("<input>", "Source YAML file").option("-o, --output <path>", "Output directory", "./screenshots").option("-s, --slide <number>", "Specific slide number (1-based)", parseInt).option("-w, --width <pixels>", "Image width", parseInt, 1280).option("-f, --format <fmt>", "Output format (png/jpeg/ai)", "png").option("-q, --quality <num>", "JPEG quality (1-100)", parseInt, 80).option("--contact-sheet", "Generate contact sheet").option("--columns <num>", "Contact sheet columns", parseInt, 2).option("-c, --config <path>", "Config file path").option("-v, --verbose", "Verbose output").action(async (input, options) => {
7989
8342
  await executeScreenshot(input, options);
7990
8343
  });
7991
8344
  }
@@ -8010,7 +8363,7 @@ async function executeScreenshot(inputPath, options) {
8010
8363
  return { success: false, errors };
8011
8364
  }
8012
8365
  spinner?.start("Checking for Marp CLI...");
8013
- if (!checkMarpCliAvailable2(dirname9(inputPath))) {
8366
+ if (!checkMarpCliAvailable2(dirname10(inputPath))) {
8014
8367
  spinner?.fail("Marp CLI not found");
8015
8368
  const message = "Marp CLI not found. Install it with: npm install -D @marp-team/marp-cli";
8016
8369
  console.error(chalk9.red(`Error: ${message}`));
@@ -8032,7 +8385,7 @@ async function executeScreenshot(inputPath, options) {
8032
8385
  const configLoader = new ConfigLoader();
8033
8386
  let configPath = options.config;
8034
8387
  if (!configPath) {
8035
- configPath = await configLoader.findConfig(dirname9(inputPath));
8388
+ configPath = await configLoader.findConfig(dirname10(inputPath));
8036
8389
  }
8037
8390
  const config = await configLoader.load(configPath);
8038
8391
  spinner?.succeed("Configuration loaded");
@@ -8053,7 +8406,7 @@ async function executeScreenshot(inputPath, options) {
8053
8406
  const tempMdPath = inputPath.replace(/\.ya?ml$/i, ".md");
8054
8407
  const cleanupTempFile = async () => {
8055
8408
  try {
8056
- await unlink3(tempMdPath);
8409
+ await unlink2(tempMdPath);
8057
8410
  } catch {
8058
8411
  }
8059
8412
  };
@@ -8076,7 +8429,7 @@ async function executeScreenshot(inputPath, options) {
8076
8429
  }
8077
8430
  try {
8078
8431
  runMarp(marpArgs, {
8079
- projectDir: dirname9(inputPath),
8432
+ projectDir: dirname10(inputPath),
8080
8433
  stdio: options.verbose ? "inherit" : "pipe"
8081
8434
  });
8082
8435
  spinner?.succeed(`Screenshots saved to ${outputDir}`);
@@ -8089,15 +8442,18 @@ async function executeScreenshot(inputPath, options) {
8089
8442
  await cleanupTempFile();
8090
8443
  return { success: false, errors };
8091
8444
  }
8445
+ const isAiFormat = options.format === "ai";
8446
+ const actualFormat = isAiFormat ? "jpeg" : options.format || "png";
8447
+ let actualWidth = isAiFormat ? 640 : options.width || 1280;
8448
+ let actualHeight = Math.round(actualWidth * 9 / 16);
8092
8449
  if (options.slide !== void 0) {
8093
8450
  spinner?.start(`Filtering to slide ${options.slide}...`);
8094
- const mdBaseName = basename10(tempMdPath, ".md");
8095
- const format = options.format || "png";
8451
+ const mdBaseName2 = basename10(tempMdPath, ".md");
8096
8452
  const filterResult = await filterToSpecificSlide(
8097
8453
  outputDir,
8098
- mdBaseName,
8454
+ mdBaseName2,
8099
8455
  options.slide,
8100
- format
8456
+ actualFormat
8101
8457
  );
8102
8458
  if (!filterResult.success) {
8103
8459
  spinner?.fail("Failed to filter slides");
@@ -8109,20 +8465,71 @@ async function executeScreenshot(inputPath, options) {
8109
8465
  }
8110
8466
  spinner?.succeed(`Kept slide ${options.slide}: ${filterResult.keptFile}`);
8111
8467
  }
8468
+ const allFiles = await readdir7(outputDir);
8469
+ const mdBaseName = basename10(tempMdPath, ".md");
8470
+ const generatedFiles = allFiles.filter((f) => f.startsWith(mdBaseName) && f.endsWith(`.${actualFormat}`)).sort();
8471
+ if (generatedFiles.length > 0) {
8472
+ try {
8473
+ const metadata = await sharp2(join19(outputDir, generatedFiles[0])).metadata();
8474
+ if (metadata.width && metadata.height) {
8475
+ actualWidth = metadata.width;
8476
+ actualHeight = metadata.height;
8477
+ }
8478
+ } catch {
8479
+ }
8480
+ }
8481
+ if (options.contactSheet && generatedFiles.length > 0) {
8482
+ spinner?.start("Generating contact sheet...");
8483
+ const slides = generatedFiles.map((file, index) => ({
8484
+ path: join19(outputDir, file),
8485
+ index: index + 1
8486
+ }));
8487
+ const contactSheetPath = join19(outputDir, `${mdBaseName}-contact.png`);
8488
+ const contactResult = await generateContactSheet(slides, {
8489
+ outputPath: contactSheetPath,
8490
+ columns: options.columns || 2,
8491
+ slideWidth: actualWidth,
8492
+ slideHeight: actualHeight
8493
+ });
8494
+ if (!contactResult.success) {
8495
+ spinner?.fail("Failed to generate contact sheet");
8496
+ console.error(chalk9.red(`Error: ${contactResult.error}`));
8497
+ errors.push(contactResult.error || "Contact sheet generation failed");
8498
+ } else {
8499
+ spinner?.succeed(`Contact sheet saved: ${basename10(contactSheetPath)}`);
8500
+ }
8501
+ }
8112
8502
  await cleanupTempFile();
8113
8503
  console.log("");
8114
- console.log(`Output: ${chalk9.cyan(outputDir)}`);
8504
+ if (isAiFormat && generatedFiles.length > 0) {
8505
+ const output = formatAiOutput({
8506
+ files: generatedFiles,
8507
+ width: actualWidth,
8508
+ height: actualHeight,
8509
+ outputDir
8510
+ });
8511
+ console.log(output);
8512
+ } else if (isAiFormat) {
8513
+ console.log(`Output: ${chalk9.cyan(outputDir)}`);
8514
+ console.log("No screenshots generated");
8515
+ } else {
8516
+ console.log(`Output: ${chalk9.cyan(outputDir)}`);
8517
+ if (generatedFiles.length > 0) {
8518
+ console.log(`Files: ${generatedFiles.length} screenshot(s)`);
8519
+ }
8520
+ }
8115
8521
  return {
8116
8522
  success: true,
8117
8523
  errors,
8118
- outputDir
8524
+ outputDir,
8525
+ files: generatedFiles
8119
8526
  };
8120
8527
  }
8121
8528
 
8122
8529
  // src/cli/commands/sources.ts
8123
8530
  import { Command as Command10 } from "commander";
8124
8531
  import { access as access13, stat as stat3 } from "fs/promises";
8125
- import { resolve as resolve6 } from "path";
8532
+ import { resolve as resolve7 } from "path";
8126
8533
  import chalk10 from "chalk";
8127
8534
  import ora5 from "ora";
8128
8535
  function createSourcesCommand() {
@@ -8171,7 +8578,7 @@ function createSourcesSyncCommand() {
8171
8578
  });
8172
8579
  }
8173
8580
  async function executeSourcesInit(projectDir, options) {
8174
- const resolvedDir = resolve6(projectDir);
8581
+ const resolvedDir = resolve7(projectDir);
8175
8582
  const spinner = ora5("Initializing sources...").start();
8176
8583
  try {
8177
8584
  const manager = new SourcesManager(resolvedDir);
@@ -8187,10 +8594,10 @@ async function executeSourcesInit(projectDir, options) {
8187
8594
  let originalSource;
8188
8595
  if (options.fromDirectory) {
8189
8596
  setupPattern = "A";
8190
- originalSource = resolve6(options.fromDirectory);
8597
+ originalSource = resolve7(options.fromDirectory);
8191
8598
  } else if (options.fromFile) {
8192
8599
  setupPattern = "B";
8193
- originalSource = resolve6(options.fromFile);
8600
+ originalSource = resolve7(options.fromFile);
8194
8601
  }
8195
8602
  await manager.init({
8196
8603
  name: projectName,
@@ -8201,14 +8608,14 @@ async function executeSourcesInit(projectDir, options) {
8201
8608
  if (options.fromDirectory) {
8202
8609
  const importer = new SourceImporter(resolvedDir, manager);
8203
8610
  const result = await importer.importDirectory(
8204
- resolve6(options.fromDirectory),
8611
+ resolve7(options.fromDirectory),
8205
8612
  { recursive: true }
8206
8613
  );
8207
8614
  filesImported = result.imported;
8208
8615
  }
8209
8616
  if (options.fromFile) {
8210
8617
  const importer = new SourceImporter(resolvedDir, manager);
8211
- await importer.importFile(resolve6(options.fromFile), {
8618
+ await importer.importFile(resolve7(options.fromFile), {
8212
8619
  type: "scenario"
8213
8620
  });
8214
8621
  filesImported = 1;
@@ -8233,8 +8640,8 @@ async function executeSourcesInit(projectDir, options) {
8233
8640
  }
8234
8641
  }
8235
8642
  async function executeSourcesImport(projectDir, sourcePath, options) {
8236
- const resolvedDir = resolve6(projectDir);
8237
- const resolvedSource = resolve6(sourcePath);
8643
+ const resolvedDir = resolve7(projectDir);
8644
+ const resolvedSource = resolve7(sourcePath);
8238
8645
  const spinner = ora5("Importing files...").start();
8239
8646
  try {
8240
8647
  const manager = new SourcesManager(resolvedDir);
@@ -8293,7 +8700,7 @@ async function executeSourcesImport(projectDir, sourcePath, options) {
8293
8700
  }
8294
8701
  }
8295
8702
  async function executeSourcesStatus(projectDir, _options) {
8296
- const resolvedDir = resolve6(projectDir);
8703
+ const resolvedDir = resolve7(projectDir);
8297
8704
  try {
8298
8705
  const manager = new SourcesManager(resolvedDir);
8299
8706
  if (!await manager.exists()) {
@@ -8380,7 +8787,7 @@ async function executeSourcesStatus(projectDir, _options) {
8380
8787
  }
8381
8788
  }
8382
8789
  async function executeSourcesSync(projectDir, options) {
8383
- const resolvedDir = resolve6(projectDir);
8790
+ const resolvedDir = resolve7(projectDir);
8384
8791
  try {
8385
8792
  const manager = new SourcesManager(resolvedDir);
8386
8793
  if (!await manager.exists()) {