@ncukondo/slide-generation 0.2.3 → 0.2.5
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 +267 -98
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1515,7 +1515,7 @@ var Pipeline = class {
|
|
|
1515
1515
|
};
|
|
1516
1516
|
|
|
1517
1517
|
// src/index.ts
|
|
1518
|
-
var VERSION = "0.2.
|
|
1518
|
+
var VERSION = "0.2.5";
|
|
1519
1519
|
|
|
1520
1520
|
// src/cli/commands/convert.ts
|
|
1521
1521
|
import { Command } from "commander";
|
|
@@ -2947,20 +2947,60 @@ import { Command as Command4 } from "commander";
|
|
|
2947
2947
|
import chalk4 from "chalk";
|
|
2948
2948
|
import * as yaml2 from "yaml";
|
|
2949
2949
|
import { mkdir as mkdir3, writeFile as writeFile3, rm as rm2 } from "fs/promises";
|
|
2950
|
-
import { join as
|
|
2950
|
+
import { join as join10, basename as basename5 } from "path";
|
|
2951
2951
|
import { tmpdir as tmpdir2 } from "os";
|
|
2952
|
-
import { execFileSync as execFileSync2 } from "child_process";
|
|
2953
2952
|
|
|
2954
2953
|
// src/cli/commands/preview.ts
|
|
2955
2954
|
import { Command as Command3 } from "commander";
|
|
2956
2955
|
import { access as access6, unlink as unlink2, readdir as readdir4, mkdir as mkdir2, writeFile as writeFile2, readFile as readFile10, rm } from "fs/promises";
|
|
2957
|
-
import { basename as basename4, dirname as dirname4, join as
|
|
2956
|
+
import { basename as basename4, dirname as dirname4, join as join9, extname as extname2 } from "path";
|
|
2958
2957
|
import * as path6 from "path";
|
|
2959
2958
|
import { tmpdir } from "os";
|
|
2960
|
-
import { spawn, execSync, execFileSync } from "child_process";
|
|
2961
2959
|
import { createServer } from "http";
|
|
2962
2960
|
import chalk3 from "chalk";
|
|
2963
2961
|
import { watch as chokidarWatch } from "chokidar";
|
|
2962
|
+
|
|
2963
|
+
// src/cli/utils/marp-runner.ts
|
|
2964
|
+
import { existsSync } from "fs";
|
|
2965
|
+
import { join as join8 } from "path";
|
|
2966
|
+
import {
|
|
2967
|
+
execFileSync,
|
|
2968
|
+
spawn
|
|
2969
|
+
} from "child_process";
|
|
2970
|
+
function getMarpCommand(projectDir) {
|
|
2971
|
+
const dir = projectDir ?? process.cwd();
|
|
2972
|
+
const localMarp = join8(dir, "node_modules", ".bin", "marp");
|
|
2973
|
+
if (existsSync(localMarp)) {
|
|
2974
|
+
return localMarp;
|
|
2975
|
+
}
|
|
2976
|
+
try {
|
|
2977
|
+
execFileSync("marp", ["--version"], { stdio: "ignore", timeout: 5e3 });
|
|
2978
|
+
return "marp";
|
|
2979
|
+
} catch {
|
|
2980
|
+
return null;
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
function isMarpAvailable(projectDir) {
|
|
2984
|
+
return getMarpCommand(projectDir) !== null;
|
|
2985
|
+
}
|
|
2986
|
+
function runMarp(args, options = {}) {
|
|
2987
|
+
const { projectDir, ...execOptions } = options;
|
|
2988
|
+
const marpCmd = getMarpCommand(projectDir);
|
|
2989
|
+
if (!marpCmd) {
|
|
2990
|
+
throw new Error("Marp CLI not found. Install it with: npm install -D @marp-team/marp-cli");
|
|
2991
|
+
}
|
|
2992
|
+
execFileSync(marpCmd, args, execOptions);
|
|
2993
|
+
}
|
|
2994
|
+
function spawnMarp(args, options = {}) {
|
|
2995
|
+
const { projectDir, ...spawnOptions } = options;
|
|
2996
|
+
const marpCmd = getMarpCommand(projectDir);
|
|
2997
|
+
if (!marpCmd) {
|
|
2998
|
+
throw new Error("Marp CLI not found. Install it with: npm install -D @marp-team/marp-cli");
|
|
2999
|
+
}
|
|
3000
|
+
return spawn(marpCmd, args, spawnOptions);
|
|
3001
|
+
}
|
|
3002
|
+
|
|
3003
|
+
// src/cli/commands/preview.ts
|
|
2964
3004
|
function escapeHtml(str) {
|
|
2965
3005
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
2966
3006
|
}
|
|
@@ -3074,7 +3114,7 @@ async function collectSlideInfo(dir, baseName, format) {
|
|
|
3074
3114
|
if (match) {
|
|
3075
3115
|
const index = parseInt(match[1], 10);
|
|
3076
3116
|
slides.push({
|
|
3077
|
-
path:
|
|
3117
|
+
path: join9(dir, file),
|
|
3078
3118
|
title: `Slide ${index}`,
|
|
3079
3119
|
index
|
|
3080
3120
|
});
|
|
@@ -3085,20 +3125,15 @@ async function collectSlideInfo(dir, baseName, format) {
|
|
|
3085
3125
|
return [];
|
|
3086
3126
|
}
|
|
3087
3127
|
}
|
|
3088
|
-
async function checkMarpCliAvailable() {
|
|
3089
|
-
|
|
3090
|
-
execSync("marp --version", { stdio: "ignore", timeout: 5e3 });
|
|
3091
|
-
return true;
|
|
3092
|
-
} catch {
|
|
3093
|
-
return false;
|
|
3094
|
-
}
|
|
3128
|
+
async function checkMarpCliAvailable(projectDir) {
|
|
3129
|
+
return isMarpAvailable(projectDir);
|
|
3095
3130
|
}
|
|
3096
3131
|
function getTempOutputPath(inputPath) {
|
|
3097
3132
|
const base = basename4(inputPath, ".yaml");
|
|
3098
|
-
return
|
|
3133
|
+
return join9(tmpdir(), `slide-gen-preview-${base}-${Date.now()}.md`);
|
|
3099
3134
|
}
|
|
3100
3135
|
function buildMarpCommand(markdownPath, options) {
|
|
3101
|
-
const parts = ["
|
|
3136
|
+
const parts = ["marp", "--preview"];
|
|
3102
3137
|
if (options.port) {
|
|
3103
3138
|
parts.push("-p", String(options.port));
|
|
3104
3139
|
}
|
|
@@ -3153,7 +3188,7 @@ function startStaticServer(baseDir, port, options = {}) {
|
|
|
3153
3188
|
async function executeGalleryPreview(inputPath, options) {
|
|
3154
3189
|
const errors = [];
|
|
3155
3190
|
const port = Number(options.port) || 8080;
|
|
3156
|
-
const galleryDir =
|
|
3191
|
+
const galleryDir = join9(tmpdir(), `slide-gen-gallery-${Date.now()}`);
|
|
3157
3192
|
try {
|
|
3158
3193
|
await access6(inputPath);
|
|
3159
3194
|
} catch {
|
|
@@ -3163,11 +3198,12 @@ async function executeGalleryPreview(inputPath, options) {
|
|
|
3163
3198
|
return { success: false, errors };
|
|
3164
3199
|
}
|
|
3165
3200
|
console.log("Checking for Marp CLI...");
|
|
3166
|
-
const
|
|
3201
|
+
const projectDir = dirname4(inputPath);
|
|
3202
|
+
const marpAvailable = await checkMarpCliAvailable(projectDir);
|
|
3167
3203
|
if (!marpAvailable) {
|
|
3168
3204
|
console.error(
|
|
3169
3205
|
chalk3.red(
|
|
3170
|
-
"Error: Marp CLI not found. Install it with: npm install -
|
|
3206
|
+
"Error: Marp CLI not found. Install it with: npm install -D @marp-team/marp-cli"
|
|
3171
3207
|
)
|
|
3172
3208
|
);
|
|
3173
3209
|
errors.push("Marp CLI not available");
|
|
@@ -3194,7 +3230,7 @@ async function executeGalleryPreview(inputPath, options) {
|
|
|
3194
3230
|
await rm(galleryDir, { recursive: true, force: true });
|
|
3195
3231
|
return { success: false, errors };
|
|
3196
3232
|
}
|
|
3197
|
-
const tempMdPath =
|
|
3233
|
+
const tempMdPath = join9(galleryDir, "slides.md");
|
|
3198
3234
|
console.log(`Converting ${chalk3.cyan(inputPath)}...`);
|
|
3199
3235
|
try {
|
|
3200
3236
|
await pipeline.runWithResult(inputPath, { outputPath: tempMdPath });
|
|
@@ -3209,7 +3245,8 @@ async function executeGalleryPreview(inputPath, options) {
|
|
|
3209
3245
|
}
|
|
3210
3246
|
console.log("Taking screenshots...");
|
|
3211
3247
|
try {
|
|
3212
|
-
|
|
3248
|
+
runMarp(["--images", "png", "-o", galleryDir, tempMdPath], {
|
|
3249
|
+
projectDir,
|
|
3213
3250
|
stdio: options.verbose ? "inherit" : "pipe"
|
|
3214
3251
|
});
|
|
3215
3252
|
console.log(chalk3.green("\u2713") + " Screenshots generated");
|
|
@@ -3234,7 +3271,7 @@ async function executeGalleryPreview(inputPath, options) {
|
|
|
3234
3271
|
path: basename4(s.path)
|
|
3235
3272
|
}));
|
|
3236
3273
|
const galleryHtml = generateGalleryHtml(relativeSlides);
|
|
3237
|
-
await writeFile2(
|
|
3274
|
+
await writeFile2(join9(galleryDir, "index.html"), galleryHtml);
|
|
3238
3275
|
console.log(`
|
|
3239
3276
|
Starting gallery server on port ${chalk3.cyan(port)}...`);
|
|
3240
3277
|
let server;
|
|
@@ -3314,11 +3351,11 @@ async function executePreview(inputPath, options) {
|
|
|
3314
3351
|
return { success: false, errors };
|
|
3315
3352
|
}
|
|
3316
3353
|
console.log("Checking for Marp CLI...");
|
|
3317
|
-
const marpAvailable = await checkMarpCliAvailable();
|
|
3354
|
+
const marpAvailable = await checkMarpCliAvailable(dirname4(inputPath));
|
|
3318
3355
|
if (!marpAvailable) {
|
|
3319
3356
|
console.error(
|
|
3320
3357
|
chalk3.red(
|
|
3321
|
-
"Error: Marp CLI not found. Install it with: npm install -
|
|
3358
|
+
"Error: Marp CLI not found. Install it with: npm install -D @marp-team/marp-cli"
|
|
3322
3359
|
)
|
|
3323
3360
|
);
|
|
3324
3361
|
errors.push("Marp CLI not available");
|
|
@@ -3366,9 +3403,9 @@ Starting preview server on port ${chalk3.cyan(port)}...`);
|
|
|
3366
3403
|
if (verbose) {
|
|
3367
3404
|
console.log(`Running: ${marpCommand}`);
|
|
3368
3405
|
}
|
|
3369
|
-
const marpProcess =
|
|
3370
|
-
|
|
3371
|
-
|
|
3406
|
+
const marpProcess = spawnMarp(["--preview", "-p", String(port), tempMarkdownPath], {
|
|
3407
|
+
projectDir: dirname4(inputPath),
|
|
3408
|
+
stdio: "inherit"
|
|
3372
3409
|
});
|
|
3373
3410
|
let watcher = null;
|
|
3374
3411
|
let debounceTimer = null;
|
|
@@ -3849,7 +3886,7 @@ async function executeTemplatePreview(name, options) {
|
|
|
3849
3886
|
return;
|
|
3850
3887
|
}
|
|
3851
3888
|
const port = Number(options.port) || 8080;
|
|
3852
|
-
const previewDir =
|
|
3889
|
+
const previewDir = join10(tmpdir2(), `slide-gen-template-preview-${Date.now()}`);
|
|
3853
3890
|
console.log("Checking for Marp CLI...");
|
|
3854
3891
|
const marpAvailable = await checkMarpCliAvailable();
|
|
3855
3892
|
if (!marpAvailable) {
|
|
@@ -3902,9 +3939,9 @@ async function executeTemplatePreview(name, options) {
|
|
|
3902
3939
|
for (const template of templates) {
|
|
3903
3940
|
console.log(`Processing template: ${chalk4.cyan(template.name)}...`);
|
|
3904
3941
|
const sampleYaml = generateSampleYaml(template);
|
|
3905
|
-
const yamlPath =
|
|
3942
|
+
const yamlPath = join10(previewDir, `${template.name}.yaml`);
|
|
3906
3943
|
await writeFile3(yamlPath, sampleYaml);
|
|
3907
|
-
const mdPath =
|
|
3944
|
+
const mdPath = join10(previewDir, `${template.name}.md`);
|
|
3908
3945
|
try {
|
|
3909
3946
|
await pipeline.runWithResult(yamlPath, { outputPath: mdPath });
|
|
3910
3947
|
} catch (error) {
|
|
@@ -3913,7 +3950,8 @@ async function executeTemplatePreview(name, options) {
|
|
|
3913
3950
|
continue;
|
|
3914
3951
|
}
|
|
3915
3952
|
try {
|
|
3916
|
-
|
|
3953
|
+
runMarp(["--images", "png", "-o", previewDir, mdPath], {
|
|
3954
|
+
projectDir: process.cwd(),
|
|
3917
3955
|
stdio: "pipe"
|
|
3918
3956
|
});
|
|
3919
3957
|
} catch {
|
|
@@ -3936,7 +3974,7 @@ async function executeTemplatePreview(name, options) {
|
|
|
3936
3974
|
return;
|
|
3937
3975
|
}
|
|
3938
3976
|
const previewHtml = generateTemplatePreviewHtml(templatePreviews);
|
|
3939
|
-
await writeFile3(
|
|
3977
|
+
await writeFile3(join10(previewDir, "index.html"), previewHtml);
|
|
3940
3978
|
console.log(`
|
|
3941
3979
|
Starting preview server on port ${chalk4.cyan(port)}...`);
|
|
3942
3980
|
let server;
|
|
@@ -4769,9 +4807,10 @@ function createIconsCommand() {
|
|
|
4769
4807
|
// src/cli/commands/init.ts
|
|
4770
4808
|
import { Command as Command6 } from "commander";
|
|
4771
4809
|
import { mkdir as mkdir7, writeFile as writeFile7, access as access10, readdir as readdir6, cp } from "fs/promises";
|
|
4772
|
-
import { existsSync } from "fs";
|
|
4773
|
-
import { execSync
|
|
4774
|
-
import {
|
|
4810
|
+
import { existsSync as existsSync2 } from "fs";
|
|
4811
|
+
import { execSync, spawnSync } from "child_process";
|
|
4812
|
+
import { createInterface } from "readline";
|
|
4813
|
+
import { basename as basename7, dirname as dirname6, join as join16, resolve as resolve5, sep } from "path";
|
|
4775
4814
|
import { fileURLToPath } from "url";
|
|
4776
4815
|
import chalk6 from "chalk";
|
|
4777
4816
|
import ora3 from "ora";
|
|
@@ -6035,9 +6074,9 @@ function generateSlideThemeCommand() {
|
|
|
6035
6074
|
function getPackageRoot() {
|
|
6036
6075
|
const __dirname = dirname6(fileURLToPath(import.meta.url));
|
|
6037
6076
|
if (__dirname.includes(`${sep}src${sep}`) || __dirname.includes("/src/")) {
|
|
6038
|
-
return
|
|
6077
|
+
return join16(__dirname, "..", "..", "..");
|
|
6039
6078
|
}
|
|
6040
|
-
return
|
|
6079
|
+
return join16(__dirname, "..", "..");
|
|
6041
6080
|
}
|
|
6042
6081
|
function createInitCommand() {
|
|
6043
6082
|
return new Command6("init").description("Initialize a new project").argument("[directory]", "Target directory", ".").option("--template <name>", "Initial template").option("--no-examples", "Do not create sample files").option("--no-ai-config", "Do not create AI assistant config files").option("--no-sources", "Do not create sources directory").option("--from-directory <path>", "Import materials from directory").option("--skip-marp-install", "Skip Marp CLI installation prompt").action(async (directory, options) => {
|
|
@@ -6061,29 +6100,29 @@ async function executeInit(directory, options) {
|
|
|
6061
6100
|
} catch {
|
|
6062
6101
|
}
|
|
6063
6102
|
await mkdir7(targetDir, { recursive: true });
|
|
6064
|
-
await mkdir7(
|
|
6065
|
-
await mkdir7(
|
|
6103
|
+
await mkdir7(join16(targetDir, "themes"), { recursive: true });
|
|
6104
|
+
await mkdir7(join16(targetDir, "icons", "custom"), { recursive: true });
|
|
6066
6105
|
const packageRoot = getPackageRoot();
|
|
6067
|
-
const sourceTemplatesDir =
|
|
6068
|
-
const targetTemplatesDir =
|
|
6106
|
+
const sourceTemplatesDir = join16(packageRoot, "templates");
|
|
6107
|
+
const targetTemplatesDir = join16(targetDir, "templates");
|
|
6069
6108
|
try {
|
|
6070
6109
|
await access10(targetTemplatesDir);
|
|
6071
6110
|
} catch {
|
|
6072
6111
|
await cp(sourceTemplatesDir, targetTemplatesDir, { recursive: true });
|
|
6073
6112
|
}
|
|
6074
|
-
const sourceIconsRegistry =
|
|
6075
|
-
const targetIconsRegistry =
|
|
6113
|
+
const sourceIconsRegistry = join16(packageRoot, "icons", "registry.yaml");
|
|
6114
|
+
const targetIconsRegistry = join16(targetDir, "icons", "registry.yaml");
|
|
6076
6115
|
await copyFileIfNotExists(sourceIconsRegistry, targetIconsRegistry);
|
|
6077
|
-
const sourceDefaultTheme =
|
|
6078
|
-
const targetDefaultTheme =
|
|
6116
|
+
const sourceDefaultTheme = join16(packageRoot, "themes", "default.css");
|
|
6117
|
+
const targetDefaultTheme = join16(targetDir, "themes", "default.css");
|
|
6079
6118
|
await copyFileIfNotExists(sourceDefaultTheme, targetDefaultTheme);
|
|
6080
6119
|
const configContent = generateConfigContent();
|
|
6081
|
-
await writeFileIfNotExists(
|
|
6120
|
+
await writeFileIfNotExists(join16(targetDir, "config.yaml"), configContent);
|
|
6082
6121
|
const customCssContent = generateCustomCssContent();
|
|
6083
|
-
await writeFileIfNotExists(
|
|
6122
|
+
await writeFileIfNotExists(join16(targetDir, "themes", "custom.css"), customCssContent);
|
|
6084
6123
|
if (includeExamples) {
|
|
6085
6124
|
const presentationContent = generatePresentationContent(options.template);
|
|
6086
|
-
await writeFileIfNotExists(
|
|
6125
|
+
await writeFileIfNotExists(join16(targetDir, "presentation.yaml"), presentationContent);
|
|
6087
6126
|
}
|
|
6088
6127
|
if (includeAiConfig) {
|
|
6089
6128
|
await generateAiConfig(targetDir);
|
|
@@ -6138,7 +6177,7 @@ async function executeInit(directory, options) {
|
|
|
6138
6177
|
console.log(` 1. Edit ${chalk6.yellow("presentation.yaml")} to add your slides`);
|
|
6139
6178
|
console.log(` 2. Run ${chalk6.yellow("slide-gen convert presentation.yaml")} to generate markdown`);
|
|
6140
6179
|
if (options.skipMarpInstall !== true) {
|
|
6141
|
-
showMarpCliInfo(targetDir);
|
|
6180
|
+
await showMarpCliInfo(targetDir);
|
|
6142
6181
|
}
|
|
6143
6182
|
} catch (error) {
|
|
6144
6183
|
spinner.fail("Failed to initialize project");
|
|
@@ -6162,53 +6201,186 @@ async function copyFileIfNotExists(source, dest) {
|
|
|
6162
6201
|
await cp(source, dest);
|
|
6163
6202
|
}
|
|
6164
6203
|
}
|
|
6165
|
-
function
|
|
6204
|
+
function isMarpCliInstalledGlobally() {
|
|
6166
6205
|
try {
|
|
6167
|
-
|
|
6206
|
+
execSync("marp --version", { stdio: "pipe", timeout: 5e3 });
|
|
6168
6207
|
return true;
|
|
6169
6208
|
} catch {
|
|
6170
6209
|
return false;
|
|
6171
6210
|
}
|
|
6172
6211
|
}
|
|
6212
|
+
function isMarpCliInstalledLocally(targetDir) {
|
|
6213
|
+
const dir = targetDir ?? process.cwd();
|
|
6214
|
+
const marpBinPath = join16(dir, "node_modules", ".bin", "marp");
|
|
6215
|
+
return existsSync2(marpBinPath);
|
|
6216
|
+
}
|
|
6173
6217
|
function detectPackageManager(targetDir) {
|
|
6174
6218
|
const dir = targetDir ?? process.cwd();
|
|
6175
|
-
if (
|
|
6176
|
-
if (
|
|
6219
|
+
if (existsSync2(join16(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
6220
|
+
if (existsSync2(join16(dir, "yarn.lock"))) return "yarn";
|
|
6177
6221
|
return "npm";
|
|
6178
6222
|
}
|
|
6179
|
-
function
|
|
6180
|
-
|
|
6181
|
-
|
|
6223
|
+
function getMarpInstallCommand(pm) {
|
|
6224
|
+
switch (pm) {
|
|
6225
|
+
case "pnpm":
|
|
6226
|
+
return "pnpm add -D @marp-team/marp-cli";
|
|
6227
|
+
case "yarn":
|
|
6228
|
+
return "yarn add -D @marp-team/marp-cli";
|
|
6229
|
+
default:
|
|
6230
|
+
return "npm install -D @marp-team/marp-cli";
|
|
6231
|
+
}
|
|
6232
|
+
}
|
|
6233
|
+
async function promptMarpInstallChoice() {
|
|
6234
|
+
if (!process.stdin.isTTY) {
|
|
6235
|
+
return "skip";
|
|
6182
6236
|
}
|
|
6237
|
+
const rl = createInterface({
|
|
6238
|
+
input: process.stdin,
|
|
6239
|
+
output: process.stdout
|
|
6240
|
+
});
|
|
6241
|
+
console.log("How would you like to install Marp CLI?");
|
|
6242
|
+
console.log(` ${chalk6.cyan("1)")} Global install ${chalk6.dim("(recommended - works everywhere)")}`);
|
|
6243
|
+
console.log(` ${chalk6.cyan("2)")} Local install ${chalk6.dim("(creates package.json)")}`);
|
|
6244
|
+
console.log(` ${chalk6.cyan("3)")} Skip ${chalk6.dim("(I'll install it later)")}`);
|
|
6245
|
+
console.log("");
|
|
6246
|
+
return new Promise((resolve7) => {
|
|
6247
|
+
rl.question("Choice [1]: ", (answer) => {
|
|
6248
|
+
rl.close();
|
|
6249
|
+
const normalized = answer.trim();
|
|
6250
|
+
if (normalized === "" || normalized === "1") {
|
|
6251
|
+
resolve7("global");
|
|
6252
|
+
} else if (normalized === "2") {
|
|
6253
|
+
resolve7("local");
|
|
6254
|
+
} else {
|
|
6255
|
+
resolve7("skip");
|
|
6256
|
+
}
|
|
6257
|
+
});
|
|
6258
|
+
});
|
|
6259
|
+
}
|
|
6260
|
+
function installMarpCliGlobally() {
|
|
6261
|
+
const spinner = ora3("Installing Marp CLI globally...").start();
|
|
6262
|
+
try {
|
|
6263
|
+
const result = spawnSync("npm", ["install", "-g", "@marp-team/marp-cli"], {
|
|
6264
|
+
stdio: "pipe",
|
|
6265
|
+
shell: true,
|
|
6266
|
+
timeout: 12e4
|
|
6267
|
+
// 2 minutes timeout
|
|
6268
|
+
});
|
|
6269
|
+
if (result.status === 0) {
|
|
6270
|
+
spinner.succeed("Marp CLI installed globally");
|
|
6271
|
+
return true;
|
|
6272
|
+
} else {
|
|
6273
|
+
const stderr = result.stderr?.toString() || "Unknown error";
|
|
6274
|
+
spinner.fail(`Failed to install Marp CLI: ${stderr}`);
|
|
6275
|
+
console.log(chalk6.dim("You can install it manually with: npm install -g @marp-team/marp-cli"));
|
|
6276
|
+
return false;
|
|
6277
|
+
}
|
|
6278
|
+
} catch (error) {
|
|
6279
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
6280
|
+
spinner.fail(`Failed to install Marp CLI: ${message}`);
|
|
6281
|
+
console.log(chalk6.dim("You can install it manually with: npm install -g @marp-team/marp-cli"));
|
|
6282
|
+
return false;
|
|
6283
|
+
}
|
|
6284
|
+
}
|
|
6285
|
+
async function installMarpCliLocally(targetDir) {
|
|
6183
6286
|
const pm = detectPackageManager(targetDir);
|
|
6184
|
-
const installCmd = pm
|
|
6287
|
+
const installCmd = getMarpInstallCommand(pm);
|
|
6288
|
+
const packageJsonPath = join16(targetDir, "package.json");
|
|
6289
|
+
if (!existsSync2(packageJsonPath)) {
|
|
6290
|
+
const packageJsonContent = generatePackageJsonContent(targetDir);
|
|
6291
|
+
await writeFile7(packageJsonPath, packageJsonContent, "utf-8");
|
|
6292
|
+
}
|
|
6293
|
+
const spinner = ora3(`Installing Marp CLI locally with ${pm}...`).start();
|
|
6294
|
+
try {
|
|
6295
|
+
const result = spawnSync(pm, ["add", "-D", "@marp-team/marp-cli"], {
|
|
6296
|
+
cwd: targetDir,
|
|
6297
|
+
stdio: "pipe",
|
|
6298
|
+
shell: true,
|
|
6299
|
+
timeout: 12e4
|
|
6300
|
+
// 2 minutes timeout
|
|
6301
|
+
});
|
|
6302
|
+
if (result.status === 0) {
|
|
6303
|
+
spinner.succeed("Marp CLI installed locally");
|
|
6304
|
+
return true;
|
|
6305
|
+
} else {
|
|
6306
|
+
const stderr = result.stderr?.toString() || "Unknown error";
|
|
6307
|
+
spinner.fail(`Failed to install Marp CLI: ${stderr}`);
|
|
6308
|
+
console.log(chalk6.dim(`You can install it manually with: ${installCmd}`));
|
|
6309
|
+
return false;
|
|
6310
|
+
}
|
|
6311
|
+
} catch (error) {
|
|
6312
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
6313
|
+
spinner.fail(`Failed to install Marp CLI: ${message}`);
|
|
6314
|
+
console.log(chalk6.dim(`You can install it manually with: ${installCmd}`));
|
|
6315
|
+
return false;
|
|
6316
|
+
}
|
|
6317
|
+
}
|
|
6318
|
+
function generatePackageJsonContent(targetDir) {
|
|
6319
|
+
const projectName = basename7(targetDir) || "my-presentation";
|
|
6320
|
+
return JSON.stringify(
|
|
6321
|
+
{
|
|
6322
|
+
name: projectName,
|
|
6323
|
+
version: "1.0.0",
|
|
6324
|
+
private: true,
|
|
6325
|
+
description: "Presentation project created with slide-gen",
|
|
6326
|
+
scripts: {
|
|
6327
|
+
preview: "slide-gen preview presentation.yaml",
|
|
6328
|
+
build: "slide-gen convert presentation.yaml"
|
|
6329
|
+
}
|
|
6330
|
+
},
|
|
6331
|
+
null,
|
|
6332
|
+
2
|
|
6333
|
+
);
|
|
6334
|
+
}
|
|
6335
|
+
async function showMarpCliInfo(targetDir) {
|
|
6336
|
+
if (isMarpCliInstalledGlobally() || isMarpCliInstalledLocally(targetDir)) {
|
|
6337
|
+
console.log("");
|
|
6338
|
+
console.log(chalk6.green("\u2713") + " Marp CLI is available");
|
|
6339
|
+
return true;
|
|
6340
|
+
}
|
|
6185
6341
|
console.log("");
|
|
6342
|
+
console.log(chalk6.dim("\u2500".repeat(45)));
|
|
6186
6343
|
console.log(chalk6.yellow("Marp CLI is recommended for full features:"));
|
|
6187
|
-
console.log("
|
|
6188
|
-
console.log("
|
|
6189
|
-
console.log("
|
|
6344
|
+
console.log(" \u2022 Preview slides in browser");
|
|
6345
|
+
console.log(" \u2022 Take screenshots for AI review");
|
|
6346
|
+
console.log(" \u2022 Export to PDF/HTML/PPTX");
|
|
6190
6347
|
console.log("");
|
|
6191
|
-
console.log(chalk6.dim("
|
|
6192
|
-
console.log(
|
|
6348
|
+
console.log(chalk6.dim("Marp CLI is not currently installed."));
|
|
6349
|
+
console.log(chalk6.dim("\u2500".repeat(45)));
|
|
6350
|
+
console.log("");
|
|
6351
|
+
const choice = await promptMarpInstallChoice();
|
|
6352
|
+
switch (choice) {
|
|
6353
|
+
case "global":
|
|
6354
|
+
return installMarpCliGlobally();
|
|
6355
|
+
case "local":
|
|
6356
|
+
return await installMarpCliLocally(targetDir);
|
|
6357
|
+
case "skip":
|
|
6358
|
+
default:
|
|
6359
|
+
console.log("");
|
|
6360
|
+
console.log(chalk6.dim("You can install Marp CLI later with:"));
|
|
6361
|
+
console.log(` ${chalk6.cyan("npm install -g @marp-team/marp-cli")} ${chalk6.dim("(global)")}`);
|
|
6362
|
+
console.log(` ${chalk6.cyan("npm install -D @marp-team/marp-cli")} ${chalk6.dim("(local)")}`);
|
|
6363
|
+
return false;
|
|
6364
|
+
}
|
|
6193
6365
|
}
|
|
6194
6366
|
async function generateAiConfig(targetDir) {
|
|
6195
|
-
await mkdir7(
|
|
6196
|
-
await mkdir7(
|
|
6197
|
-
await mkdir7(
|
|
6198
|
-
await mkdir7(
|
|
6367
|
+
await mkdir7(join16(targetDir, ".skills", "slide-assistant", "references"), { recursive: true });
|
|
6368
|
+
await mkdir7(join16(targetDir, ".skills", "slide-assistant", "scripts"), { recursive: true });
|
|
6369
|
+
await mkdir7(join16(targetDir, ".claude", "commands"), { recursive: true });
|
|
6370
|
+
await mkdir7(join16(targetDir, ".opencode", "agent"), { recursive: true });
|
|
6199
6371
|
await writeFileIfNotExists(
|
|
6200
|
-
|
|
6372
|
+
join16(targetDir, ".skills", "slide-assistant", "SKILL.md"),
|
|
6201
6373
|
generateSkillMd()
|
|
6202
6374
|
);
|
|
6203
6375
|
await writeFileIfNotExists(
|
|
6204
|
-
|
|
6376
|
+
join16(targetDir, ".skills", "slide-assistant", "references", "templates.md"),
|
|
6205
6377
|
generateTemplatesRef()
|
|
6206
6378
|
);
|
|
6207
6379
|
await writeFileIfNotExists(
|
|
6208
|
-
|
|
6380
|
+
join16(targetDir, ".skills", "slide-assistant", "references", "workflows.md"),
|
|
6209
6381
|
generateWorkflowsRef()
|
|
6210
6382
|
);
|
|
6211
|
-
await writeFileIfNotExists(
|
|
6383
|
+
await writeFileIfNotExists(join16(targetDir, "CLAUDE.md"), generateClaudeMd());
|
|
6212
6384
|
const commandGenerators = {
|
|
6213
6385
|
"slide-create": generateSlideCreateCommand,
|
|
6214
6386
|
"slide-validate": generateSlideValidateCommand,
|
|
@@ -6218,16 +6390,16 @@ async function generateAiConfig(targetDir) {
|
|
|
6218
6390
|
};
|
|
6219
6391
|
for (const [name, generator] of Object.entries(commandGenerators)) {
|
|
6220
6392
|
await writeFileIfNotExists(
|
|
6221
|
-
|
|
6393
|
+
join16(targetDir, ".claude", "commands", `${name}.md`),
|
|
6222
6394
|
generator()
|
|
6223
6395
|
);
|
|
6224
6396
|
}
|
|
6225
|
-
await writeFileIfNotExists(
|
|
6397
|
+
await writeFileIfNotExists(join16(targetDir, "AGENTS.md"), generateAgentsMd());
|
|
6226
6398
|
await writeFileIfNotExists(
|
|
6227
|
-
|
|
6399
|
+
join16(targetDir, ".opencode", "agent", "slide.md"),
|
|
6228
6400
|
generateOpenCodeAgent()
|
|
6229
6401
|
);
|
|
6230
|
-
await writeFileIfNotExists(
|
|
6402
|
+
await writeFileIfNotExists(join16(targetDir, ".cursorrules"), generateAgentsMd());
|
|
6231
6403
|
}
|
|
6232
6404
|
function generateConfigContent() {
|
|
6233
6405
|
return `# slide-gen configuration
|
|
@@ -6325,7 +6497,7 @@ slides:
|
|
|
6325
6497
|
// src/cli/commands/watch.ts
|
|
6326
6498
|
import { Command as Command7 } from "commander";
|
|
6327
6499
|
import { access as access11 } from "fs/promises";
|
|
6328
|
-
import { basename as
|
|
6500
|
+
import { basename as basename8, dirname as dirname7, join as join17 } from "path";
|
|
6329
6501
|
import chalk7 from "chalk";
|
|
6330
6502
|
import { watch as chokidarWatch2 } from "chokidar";
|
|
6331
6503
|
var WatchState = class {
|
|
@@ -6359,8 +6531,8 @@ var WatchState = class {
|
|
|
6359
6531
|
};
|
|
6360
6532
|
function getDefaultOutputPath2(inputPath) {
|
|
6361
6533
|
const dir = dirname7(inputPath);
|
|
6362
|
-
const base =
|
|
6363
|
-
return
|
|
6534
|
+
const base = basename8(inputPath, ".yaml");
|
|
6535
|
+
return join17(dir, `${base}.md`);
|
|
6364
6536
|
}
|
|
6365
6537
|
function formatTime() {
|
|
6366
6538
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -6504,7 +6676,7 @@ async function executeWatch(inputPath, options) {
|
|
|
6504
6676
|
// src/cli/commands/images.ts
|
|
6505
6677
|
import { Command as Command8 } from "commander";
|
|
6506
6678
|
import { readFile as readFile15, stat as stat2, mkdir as mkdir8 } from "fs/promises";
|
|
6507
|
-
import { dirname as dirname8, basename as
|
|
6679
|
+
import { dirname as dirname8, basename as basename9, join as join18 } from "path";
|
|
6508
6680
|
import chalk8 from "chalk";
|
|
6509
6681
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
6510
6682
|
function createImagesCommand() {
|
|
@@ -6792,7 +6964,7 @@ async function executeImagesProcess(inputPath, options) {
|
|
|
6792
6964
|
}
|
|
6793
6965
|
async function processDirectory(dirPath, options) {
|
|
6794
6966
|
if (options.fromMeta) {
|
|
6795
|
-
const outputDir =
|
|
6967
|
+
const outputDir = join18(dirPath, options.output);
|
|
6796
6968
|
const pipeline = new ImageProcessingPipeline(dirPath, { outputDir });
|
|
6797
6969
|
const result = await pipeline.processDirectory();
|
|
6798
6970
|
console.log("");
|
|
@@ -6828,10 +7000,10 @@ async function processSingleFile(filePath, options) {
|
|
|
6828
7000
|
}
|
|
6829
7001
|
const processor = new ImageProcessor();
|
|
6830
7002
|
const dir = dirname8(filePath);
|
|
6831
|
-
const filename =
|
|
6832
|
-
const outputDir =
|
|
7003
|
+
const filename = basename9(filePath);
|
|
7004
|
+
const outputDir = join18(dir, options.output);
|
|
6833
7005
|
await mkdir8(outputDir, { recursive: true });
|
|
6834
|
-
const outputPath =
|
|
7006
|
+
const outputPath = join18(outputDir, filename);
|
|
6835
7007
|
let success = false;
|
|
6836
7008
|
if (options.crop) {
|
|
6837
7009
|
const edges = parseCropSpec(options.crop);
|
|
@@ -6926,14 +7098,13 @@ function parseBlurSpec(spec) {
|
|
|
6926
7098
|
// src/cli/commands/screenshot.ts
|
|
6927
7099
|
import { Command as Command9 } from "commander";
|
|
6928
7100
|
import { access as access12, mkdir as mkdir9, readdir as readdir7, unlink as unlink3 } from "fs/promises";
|
|
6929
|
-
import { basename as
|
|
6930
|
-
import { execSync as execSync3, execFileSync as execFileSync3 } from "child_process";
|
|
7101
|
+
import { basename as basename10, dirname as dirname9, join as join19 } from "path";
|
|
6931
7102
|
import chalk9 from "chalk";
|
|
6932
7103
|
import ora4 from "ora";
|
|
6933
7104
|
async function filterToSpecificSlide(outputDir, baseName, slideNumber, format) {
|
|
6934
7105
|
const slideStr = slideNumber.toString().padStart(3, "0");
|
|
6935
7106
|
const targetFileName = `${baseName}.${slideStr}.${format}`;
|
|
6936
|
-
const targetPath =
|
|
7107
|
+
const targetPath = join19(outputDir, targetFileName);
|
|
6937
7108
|
try {
|
|
6938
7109
|
await access12(targetPath);
|
|
6939
7110
|
} catch {
|
|
@@ -6948,7 +7119,7 @@ async function filterToSpecificSlide(outputDir, baseName, slideNumber, format) {
|
|
|
6948
7119
|
);
|
|
6949
7120
|
for (const file of slideFiles) {
|
|
6950
7121
|
if (file !== targetFileName) {
|
|
6951
|
-
await unlink3(
|
|
7122
|
+
await unlink3(join19(outputDir, file));
|
|
6952
7123
|
}
|
|
6953
7124
|
}
|
|
6954
7125
|
return {
|
|
@@ -6956,17 +7127,12 @@ async function filterToSpecificSlide(outputDir, baseName, slideNumber, format) {
|
|
|
6956
7127
|
keptFile: targetFileName
|
|
6957
7128
|
};
|
|
6958
7129
|
}
|
|
6959
|
-
function checkMarpCliAvailable2() {
|
|
6960
|
-
|
|
6961
|
-
execSync3("marp --version", { stdio: "ignore", timeout: 5e3 });
|
|
6962
|
-
return true;
|
|
6963
|
-
} catch {
|
|
6964
|
-
return false;
|
|
6965
|
-
}
|
|
7130
|
+
function checkMarpCliAvailable2(projectDir) {
|
|
7131
|
+
return isMarpAvailable(projectDir);
|
|
6966
7132
|
}
|
|
6967
7133
|
function buildMarpCommandArgs(markdownPath, outputDir, options) {
|
|
6968
7134
|
const format = options.format || "png";
|
|
6969
|
-
const args = ["
|
|
7135
|
+
const args = ["--images", format];
|
|
6970
7136
|
if (options.width && options.width !== 1280) {
|
|
6971
7137
|
const scale = options.width / 1280;
|
|
6972
7138
|
args.push("--image-scale", String(scale));
|
|
@@ -7001,9 +7167,9 @@ async function executeScreenshot(inputPath, options) {
|
|
|
7001
7167
|
return { success: false, errors };
|
|
7002
7168
|
}
|
|
7003
7169
|
spinner?.start("Checking for Marp CLI...");
|
|
7004
|
-
if (!checkMarpCliAvailable2()) {
|
|
7170
|
+
if (!checkMarpCliAvailable2(dirname9(inputPath))) {
|
|
7005
7171
|
spinner?.fail("Marp CLI not found");
|
|
7006
|
-
const message = "Marp CLI not found. Install it with: npm install -
|
|
7172
|
+
const message = "Marp CLI not found. Install it with: npm install -D @marp-team/marp-cli";
|
|
7007
7173
|
console.error(chalk9.red(`Error: ${message}`));
|
|
7008
7174
|
errors.push(message);
|
|
7009
7175
|
process.exitCode = ExitCode.GeneralError;
|
|
@@ -7063,10 +7229,13 @@ async function executeScreenshot(inputPath, options) {
|
|
|
7063
7229
|
spinner?.start("Taking screenshots...");
|
|
7064
7230
|
const marpArgs = buildMarpCommandArgs(tempMdPath, outputDir, options);
|
|
7065
7231
|
if (options.verbose) {
|
|
7066
|
-
console.log(`Running:
|
|
7232
|
+
console.log(`Running: marp ${marpArgs.join(" ")}`);
|
|
7067
7233
|
}
|
|
7068
7234
|
try {
|
|
7069
|
-
|
|
7235
|
+
runMarp(marpArgs, {
|
|
7236
|
+
projectDir: dirname9(inputPath),
|
|
7237
|
+
stdio: options.verbose ? "inherit" : "pipe"
|
|
7238
|
+
});
|
|
7070
7239
|
spinner?.succeed(`Screenshots saved to ${outputDir}`);
|
|
7071
7240
|
} catch (error) {
|
|
7072
7241
|
spinner?.fail("Failed to take screenshots");
|
|
@@ -7079,7 +7248,7 @@ async function executeScreenshot(inputPath, options) {
|
|
|
7079
7248
|
}
|
|
7080
7249
|
if (options.slide !== void 0) {
|
|
7081
7250
|
spinner?.start(`Filtering to slide ${options.slide}...`);
|
|
7082
|
-
const mdBaseName =
|
|
7251
|
+
const mdBaseName = basename10(tempMdPath, ".md");
|
|
7083
7252
|
const format = options.format || "png";
|
|
7084
7253
|
const filterResult = await filterToSpecificSlide(
|
|
7085
7254
|
outputDir,
|