@honeydeck/honeydeck 0.1.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/AGENTS.md +25 -0
- package/DEVELOPMENT.md +522 -0
- package/LICENSE +21 -0
- package/Readme.md +49 -0
- package/SPEC.md +88 -0
- package/docs/components.md +63 -0
- package/docs/configuration.md +91 -0
- package/docs/getting-started.md +116 -0
- package/docs/kit-authoring.md +207 -0
- package/docs/kits.md +387 -0
- package/docs/local-development.md +95 -0
- package/docs/mermaid.md +198 -0
- package/docs/mobile.md +108 -0
- package/docs/navigation.md +93 -0
- package/docs/next-steps.md +377 -0
- package/docs/pdf-export.md +91 -0
- package/docs/presenter-mode.md +104 -0
- package/docs/slides.md +130 -0
- package/docs/slidev-migration.md +42 -0
- package/docs/steps-and-reveals.md +171 -0
- package/package.json +134 -0
- package/skills/SPEC.md +21 -0
- package/skills/honeydeck/SKILL.md +65 -0
- package/skills/presentation-writing/SKILL.md +75 -0
- package/skills/slidev-migration/SKILL.md +153 -0
- package/src/SPEC.md +89 -0
- package/src/assets.d.ts +30 -0
- package/src/cli/SPEC.md +230 -0
- package/src/cli/args.ts +3 -0
- package/src/cli/banner.ts +9 -0
- package/src/cli/bin.js +5 -0
- package/src/cli/build.ts +229 -0
- package/src/cli/deck-path.ts +32 -0
- package/src/cli/dev.ts +263 -0
- package/src/cli/index.ts +126 -0
- package/src/cli/init.ts +369 -0
- package/src/cli/pdf.ts +923 -0
- package/src/cli/skill.ts +75 -0
- package/src/cli/templates/SPEC.md +70 -0
- package/src/cli/templates/deck-mdx.ts +15 -0
- package/src/cli/templates/package-json.ts +36 -0
- package/src/cli/templates/sparkle-button.ts +15 -0
- package/src/cli/templates/starter/components/SparkleButton.tsx +84 -0
- package/src/cli/templates/starter/deck.mdx +153 -0
- package/src/cli/templates/starter/styles.css +14 -0
- package/src/cli/templates/styles-css.ts +14 -0
- package/src/defaults.ts +1 -0
- package/src/layouts/ColorModeImage.tsx +55 -0
- package/src/layouts/SPEC.md +393 -0
- package/src/layouts/SlideFrame.tsx +48 -0
- package/src/layouts/bee/Blank.tsx +12 -0
- package/src/layouts/bee/Cover.tsx +70 -0
- package/src/layouts/bee/Default.tsx +42 -0
- package/src/layouts/bee/Image/Image.tsx +151 -0
- package/src/layouts/bee/Image/placeholder-dark.webp +0 -0
- package/src/layouts/bee/Image/placeholder-vertical-dark.webp +0 -0
- package/src/layouts/bee/Image/placeholder-vertical.webp +0 -0
- package/src/layouts/bee/Image/placeholder.webp +0 -0
- package/src/layouts/bee/ImageLeft.tsx +27 -0
- package/src/layouts/bee/ImageRight.tsx +27 -0
- package/src/layouts/bee/ImageSide.tsx +107 -0
- package/src/layouts/bee/Section.tsx +40 -0
- package/src/layouts/bee/TwoCol.tsx +108 -0
- package/src/layouts/bee/index.ts +40 -0
- package/src/layouts/clean/Blank.tsx +12 -0
- package/src/layouts/clean/Cover.tsx +58 -0
- package/src/layouts/clean/Default.tsx +33 -0
- package/src/layouts/clean/Image/Image.tsx +103 -0
- package/src/layouts/clean/ImageLeft.tsx +27 -0
- package/src/layouts/clean/ImageRight.tsx +27 -0
- package/src/layouts/clean/ImageSide.tsx +113 -0
- package/src/layouts/clean/Section.tsx +35 -0
- package/src/layouts/clean/TwoCol.tsx +63 -0
- package/src/layouts/clean/index.ts +40 -0
- package/src/layouts/index.ts +60 -0
- package/src/layouts/placeholders.ts +9 -0
- package/src/layouts/utils.ts +13 -0
- package/src/remark/SPEC.md +49 -0
- package/src/remark/h1-extract.ts +124 -0
- package/src/remark/index.ts +4 -0
- package/src/remark/shiki-code-blocks.ts +325 -0
- package/src/remark/step-numbering.ts +412 -0
- package/src/runtime/Deck.tsx +533 -0
- package/src/runtime/SPEC.md +256 -0
- package/src/runtime/SlideCanvas.tsx +95 -0
- package/src/runtime/TimelineContext.tsx +122 -0
- package/src/runtime/app-shell/index.html +31 -0
- package/src/runtime/app-shell/main.tsx +42 -0
- package/src/runtime/aspectRatio.ts +34 -0
- package/src/runtime/colorMode.ts +23 -0
- package/src/runtime/components/BrowserFrame.tsx +233 -0
- package/src/runtime/components/Button.tsx +57 -0
- package/src/runtime/components/CodeBlock.tsx +210 -0
- package/src/runtime/components/ColorModeCycleButton.tsx +59 -0
- package/src/runtime/components/ErrorBoundary.tsx +125 -0
- package/src/runtime/components/Keyboard.tsx +87 -0
- package/src/runtime/components/ListStyle.tsx +203 -0
- package/src/runtime/components/NavBar.tsx +223 -0
- package/src/runtime/components/NavBarButton.tsx +47 -0
- package/src/runtime/components/NavBarDivider.tsx +3 -0
- package/src/runtime/components/Notes.tsx +171 -0
- package/src/runtime/components/Reveal.tsx +82 -0
- package/src/runtime/components/RevealGroup.tsx +193 -0
- package/src/runtime/components/SPEC.md +263 -0
- package/src/runtime/components/SlideNumberBadge.tsx +11 -0
- package/src/runtime/components/TimelineSteps.tsx +115 -0
- package/src/runtime/components/index.ts +55 -0
- package/src/runtime/index.ts +42 -0
- package/src/runtime/inputOwnership.ts +68 -0
- package/src/runtime/keyboardTarget.ts +7 -0
- package/src/runtime/lastSlideRoute.ts +56 -0
- package/src/runtime/navigation.ts +211 -0
- package/src/runtime/router.ts +157 -0
- package/src/runtime/slideData.ts +137 -0
- package/src/runtime/sync.ts +267 -0
- package/src/runtime/types.ts +182 -0
- package/src/runtime/useKeyboardNav.ts +138 -0
- package/src/runtime/useSwipeNav.ts +257 -0
- package/src/runtime/views/DocsView.tsx +74 -0
- package/src/runtime/views/OverviewView.tsx +386 -0
- package/src/runtime/views/PresenterNotesPanel.tsx +76 -0
- package/src/runtime/views/PresenterView.tsx +340 -0
- package/src/runtime/views/SPEC.md +152 -0
- package/src/runtime/views/docs/ComponentsTab.tsx +178 -0
- package/src/runtime/views/docs/DocsHeader.tsx +101 -0
- package/src/runtime/views/docs/Intro.tsx +20 -0
- package/src/runtime/views/docs/LayoutsTab.tsx +324 -0
- package/src/runtime/views/docs/ThemeTab.tsx +110 -0
- package/src/runtime/views/index.ts +7 -0
- package/src/runtime/views/overviewGrid.ts +106 -0
- package/src/runtime/views/presenterPreview.ts +27 -0
- package/src/runtime/virtual-modules.d.ts +98 -0
- package/src/theme/SPEC.md +179 -0
- package/src/theme/base.css +623 -0
- package/src/theme/bee.css +35 -0
- package/src/theme/clean.css +38 -0
- package/src/vite-plugin/SPEC.md +114 -0
- package/src/vite-plugin/component-doc-crawler.ts +350 -0
- package/src/vite-plugin/deck-loader.ts +148 -0
- package/src/vite-plugin/index.ts +373 -0
- package/src/vite-plugin/layout-demo-crawler.ts +802 -0
- package/src/vite-plugin/splitter.ts +353 -0
- package/src/vite-plugin/token-manifest.ts +163 -0
- package/src/vite-plugin/virtual-modules.ts +587 -0
package/src/cli/init.ts
ADDED
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `honeydeck init` — scaffold a new Honeydeck presentation project.
|
|
3
|
+
*
|
|
4
|
+
* ### Flow
|
|
5
|
+
*
|
|
6
|
+
* 1. Parse CLI flags (`--name`, `--skip-install`, skill options).
|
|
7
|
+
* 2. intro() — greeting banner.
|
|
8
|
+
* 3. Prompt for project name (skipped with --name flag).
|
|
9
|
+
* 4. Create project directory + subdirectories.
|
|
10
|
+
* 5. Write all template files.
|
|
11
|
+
* 6. Install dependencies with npm (skipped with --skip-install flag).
|
|
12
|
+
* 7. Optionally install Honeydeck agent skills.
|
|
13
|
+
* 8. outro() — success message with next steps.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { execSync } from "node:child_process";
|
|
17
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
18
|
+
import { dirname, join, resolve } from "node:path";
|
|
19
|
+
import * as p from "@clack/prompts";
|
|
20
|
+
import { DEFAULT_DECK_ENTRY } from "../defaults.ts";
|
|
21
|
+
import { hasHelpFlag } from "./args.ts";
|
|
22
|
+
import { openHoneydeckAgentSkillsInstaller } from "./skill.ts";
|
|
23
|
+
import { generateDeckMdx } from "./templates/deck-mdx.ts";
|
|
24
|
+
import { generatePackageJson } from "./templates/package-json.ts";
|
|
25
|
+
import { generateSparkleButton } from "./templates/sparkle-button.ts";
|
|
26
|
+
import { generateStylesCss } from "./templates/styles-css.ts";
|
|
27
|
+
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Arg parsing
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
export type InitOptions = {
|
|
33
|
+
/** Explicit project name — skips the interactive prompt. */
|
|
34
|
+
name: string | null;
|
|
35
|
+
/** Skip running npm install. */
|
|
36
|
+
skipInstall: boolean;
|
|
37
|
+
/** Open the Honeydeck agent skills installer; null means ask first. */
|
|
38
|
+
installSkill: boolean | null;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export function printInitHelp(): void {
|
|
42
|
+
console.log(`
|
|
43
|
+
✨ honeydeck init — scaffold a new presentation project
|
|
44
|
+
|
|
45
|
+
Usage:
|
|
46
|
+
honeydeck init [options]
|
|
47
|
+
|
|
48
|
+
Options:
|
|
49
|
+
--name <name> Project name (skips interactive prompt)
|
|
50
|
+
--skip-install Skip running npm install
|
|
51
|
+
--skip-skill Skip the Honeydeck agent skills installer
|
|
52
|
+
--install-skill Open the Honeydeck agent skills installer via npx skills add
|
|
53
|
+
-h, --help Show this help page
|
|
54
|
+
|
|
55
|
+
Examples:
|
|
56
|
+
honeydeck init
|
|
57
|
+
honeydeck init --name my-talk
|
|
58
|
+
honeydeck init --name my-talk --skip-install --install-skill
|
|
59
|
+
`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function readOptionValue(
|
|
63
|
+
args: string[],
|
|
64
|
+
index: number,
|
|
65
|
+
option: string,
|
|
66
|
+
): string {
|
|
67
|
+
const value = args[index + 1];
|
|
68
|
+
if (!value || value.startsWith("-")) {
|
|
69
|
+
console.error(`❌ Missing value for ${option}`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
return value;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function parseInitArgs(args: string[]): InitOptions {
|
|
76
|
+
let name: string | null = null;
|
|
77
|
+
let skipInstall = false;
|
|
78
|
+
let installSkill: boolean | null = null;
|
|
79
|
+
|
|
80
|
+
for (let i = 0; i < args.length; i++) {
|
|
81
|
+
const arg = args[i];
|
|
82
|
+
if (arg === "--name") {
|
|
83
|
+
const value = readOptionValue(args, i, arg);
|
|
84
|
+
name = value;
|
|
85
|
+
i++;
|
|
86
|
+
} else if (arg === "--skip-install") {
|
|
87
|
+
skipInstall = true;
|
|
88
|
+
} else if (arg === "--install-skill") {
|
|
89
|
+
installSkill = true;
|
|
90
|
+
} else if (arg === "--skip-skill") {
|
|
91
|
+
installSkill = false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { name, skipInstall, installSkill };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// Package manager commands
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
|
|
102
|
+
const INSTALL_COMMAND = "npm install";
|
|
103
|
+
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
// Validation
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Validate a project name.
|
|
110
|
+
* Returns an error message string if invalid, undefined if valid.
|
|
111
|
+
*/
|
|
112
|
+
function validateProjectName(value: string | undefined): string | undefined {
|
|
113
|
+
const name = (value ?? "").trim();
|
|
114
|
+
if (name.length === 0) {
|
|
115
|
+
return "Project name cannot be empty.";
|
|
116
|
+
}
|
|
117
|
+
if (!/^[a-z0-9][a-z0-9._-]*$/.test(name)) {
|
|
118
|
+
return "Use lowercase letters, numbers, hyphens, underscores, or dots. Must start with a letter or digit.";
|
|
119
|
+
}
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// File writing helpers
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Write a file to disk, creating parent directories as needed.
|
|
129
|
+
* Logs the relative path for visibility.
|
|
130
|
+
*/
|
|
131
|
+
export function resolveParentDir(
|
|
132
|
+
abs: string,
|
|
133
|
+
dirnameFn: (path: string) => string = dirname,
|
|
134
|
+
): string {
|
|
135
|
+
return dirnameFn(abs);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function writeFile(
|
|
139
|
+
projectDir: string,
|
|
140
|
+
relativePath: string,
|
|
141
|
+
content: string,
|
|
142
|
+
): void {
|
|
143
|
+
const abs = join(projectDir, relativePath);
|
|
144
|
+
// Ensure parent directory exists.
|
|
145
|
+
const parentDir = resolveParentDir(abs);
|
|
146
|
+
mkdirSync(parentDir, { recursive: true });
|
|
147
|
+
writeFileSync(abs, content, "utf-8");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function cleanupGeneratedProject(
|
|
151
|
+
projectDir: string,
|
|
152
|
+
canRemoveProjectDir: boolean,
|
|
153
|
+
): void {
|
|
154
|
+
if (!canRemoveProjectDir) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
rmSync(projectDir, { recursive: true, force: true });
|
|
160
|
+
p.log.info("Cleaned up generated project files.");
|
|
161
|
+
} catch (err) {
|
|
162
|
+
p.log.warn(
|
|
163
|
+
`Could not clean up generated project files: ${err instanceof Error ? err.message : String(err)}`,
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function isInterruptError(err: unknown): boolean {
|
|
169
|
+
if (!err || typeof err !== "object") {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const processError = err as { signal?: unknown; status?: unknown };
|
|
174
|
+
return processError.signal === "SIGINT" || processError.status === 130;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// Public API
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
|
|
181
|
+
export async function runInit(args: string[]): Promise<void> {
|
|
182
|
+
if (hasHelpFlag(args)) {
|
|
183
|
+
printInitHelp();
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const opts = parseInitArgs(args);
|
|
188
|
+
|
|
189
|
+
p.intro(" ✨ honeydeck init — Create a new presentation");
|
|
190
|
+
|
|
191
|
+
// ── Step 1: Determine project name ─────────────────────────────────────────
|
|
192
|
+
let projectName: string;
|
|
193
|
+
|
|
194
|
+
if (opts.name) {
|
|
195
|
+
const err = validateProjectName(opts.name ?? undefined);
|
|
196
|
+
if (err) {
|
|
197
|
+
p.cancel(`❌ Invalid project name: ${err}`);
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
projectName = opts.name.trim();
|
|
201
|
+
p.log.info(`Project name: ${projectName}`);
|
|
202
|
+
} else {
|
|
203
|
+
const answer = await p.text({
|
|
204
|
+
message: "What is your project name?",
|
|
205
|
+
placeholder: "my-awesome-talk",
|
|
206
|
+
validate: validateProjectName,
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
if (p.isCancel(answer)) {
|
|
210
|
+
p.cancel("Setup cancelled.");
|
|
211
|
+
process.exit(0);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
projectName = answer.trim();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ── Step 2: Check target directory ─────────────────────────────────────────
|
|
218
|
+
const projectDir = resolve(process.cwd(), projectName);
|
|
219
|
+
const targetExistedBeforeInit = existsSync(projectDir);
|
|
220
|
+
|
|
221
|
+
if (targetExistedBeforeInit) {
|
|
222
|
+
const overwrite = await p.confirm({
|
|
223
|
+
message: `Directory "${projectName}" already exists. Continue anyway?`,
|
|
224
|
+
initialValue: false,
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
if (p.isCancel(overwrite) || !overwrite) {
|
|
228
|
+
p.cancel("Setup cancelled.");
|
|
229
|
+
process.exit(0);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const cleanupProjectOnCancel = () =>
|
|
234
|
+
cleanupGeneratedProject(projectDir, !targetExistedBeforeInit);
|
|
235
|
+
const abortInit = (exitCode: number) => {
|
|
236
|
+
cleanupProjectOnCancel();
|
|
237
|
+
p.cancel("Setup cancelled.");
|
|
238
|
+
process.exit(exitCode);
|
|
239
|
+
};
|
|
240
|
+
const handleInterrupt = () => abortInit(130);
|
|
241
|
+
process.once("SIGINT", handleInterrupt);
|
|
242
|
+
|
|
243
|
+
// ── Step 3: Package manager ────────────────────────────────────────────────
|
|
244
|
+
p.log.step("Using npm");
|
|
245
|
+
|
|
246
|
+
// ── Step 4: Create project files ───────────────────────────────────────────
|
|
247
|
+
const spinner = p.spinner();
|
|
248
|
+
spinner.start("Creating project files…");
|
|
249
|
+
|
|
250
|
+
try {
|
|
251
|
+
// Root directories
|
|
252
|
+
mkdirSync(join(projectDir, "components"), { recursive: true });
|
|
253
|
+
mkdirSync(join(projectDir, "public"), { recursive: true });
|
|
254
|
+
|
|
255
|
+
// package.json
|
|
256
|
+
writeFile(projectDir, "package.json", generatePackageJson(projectName));
|
|
257
|
+
|
|
258
|
+
// deck.mdx
|
|
259
|
+
writeFile(projectDir, DEFAULT_DECK_ENTRY, generateDeckMdx(projectName));
|
|
260
|
+
|
|
261
|
+
// styles.css
|
|
262
|
+
writeFile(projectDir, "styles.css", generateStylesCss());
|
|
263
|
+
|
|
264
|
+
// components/SparkleButton.tsx
|
|
265
|
+
writeFile(
|
|
266
|
+
projectDir,
|
|
267
|
+
"components/SparkleButton.tsx",
|
|
268
|
+
generateSparkleButton(),
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
// .gitignore
|
|
272
|
+
writeFile(projectDir, ".gitignore", GITIGNORE_CONTENT);
|
|
273
|
+
|
|
274
|
+
spinner.stop("Project files created ✅");
|
|
275
|
+
} catch (err) {
|
|
276
|
+
spinner.stop("Failed to create files ❌");
|
|
277
|
+
cleanupProjectOnCancel();
|
|
278
|
+
p.cancel(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
279
|
+
process.exit(1);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// ── Step 5: Install dependencies ───────────────────────────────────────────
|
|
283
|
+
if (!opts.skipInstall) {
|
|
284
|
+
const installSpinner = p.spinner();
|
|
285
|
+
installSpinner.start("Installing dependencies with npm…");
|
|
286
|
+
|
|
287
|
+
try {
|
|
288
|
+
execSync(INSTALL_COMMAND, {
|
|
289
|
+
cwd: projectDir,
|
|
290
|
+
stdio: "pipe",
|
|
291
|
+
});
|
|
292
|
+
installSpinner.stop("Dependencies installed ✅");
|
|
293
|
+
} catch (_err) {
|
|
294
|
+
installSpinner.stop("Dependency installation failed ⚠️");
|
|
295
|
+
p.log.warn(
|
|
296
|
+
"Could not install dependencies automatically. Run the install command manually.",
|
|
297
|
+
);
|
|
298
|
+
p.log.info(` cd ${projectName} && ${INSTALL_COMMAND}`);
|
|
299
|
+
}
|
|
300
|
+
} else {
|
|
301
|
+
p.log.info(
|
|
302
|
+
`Skipping install. Run \`${INSTALL_COMMAND}\` in the project directory.`,
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ── Step 6: Optional agent skills ──────────────────────────────────────────
|
|
307
|
+
let shouldOpenSkillsInstaller = opts.installSkill;
|
|
308
|
+
|
|
309
|
+
if (shouldOpenSkillsInstaller === null) {
|
|
310
|
+
const answer = await p.confirm({
|
|
311
|
+
message:
|
|
312
|
+
"Open the Honeydeck agent skills installer? This runs `npx skills add`.",
|
|
313
|
+
initialValue: true,
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
if (p.isCancel(answer)) {
|
|
317
|
+
abortInit(0);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
shouldOpenSkillsInstaller = !!answer;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (shouldOpenSkillsInstaller) {
|
|
324
|
+
p.log.info(
|
|
325
|
+
"Opening `npx skills add` so you can choose skill, scope, and agents.",
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
try {
|
|
329
|
+
openHoneydeckAgentSkillsInstaller(projectDir);
|
|
330
|
+
} catch (err) {
|
|
331
|
+
if (isInterruptError(err)) {
|
|
332
|
+
abortInit(130);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
p.log.warn("Could not install skills automatically.");
|
|
336
|
+
p.log.info("Install them later with: honeydeck skill");
|
|
337
|
+
}
|
|
338
|
+
} else {
|
|
339
|
+
p.log.info("Skipping agent skills. Install later with: honeydeck skill");
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
process.off("SIGINT", handleInterrupt);
|
|
343
|
+
|
|
344
|
+
// ── Step 7: Outro ──────────────────────────────────────────────────────────
|
|
345
|
+
p.outro(
|
|
346
|
+
[
|
|
347
|
+
"",
|
|
348
|
+
` 🎉 Project "${projectName}" is ready!`,
|
|
349
|
+
"",
|
|
350
|
+
" Next steps:",
|
|
351
|
+
"",
|
|
352
|
+
` cd ${projectName}`,
|
|
353
|
+
" npm run dev",
|
|
354
|
+
"",
|
|
355
|
+
" Happy presenting! 🎞",
|
|
356
|
+
"",
|
|
357
|
+
].join("\n"),
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// ---------------------------------------------------------------------------
|
|
362
|
+
// Static template content
|
|
363
|
+
// ---------------------------------------------------------------------------
|
|
364
|
+
|
|
365
|
+
const GITIGNORE_CONTENT = `node_modules/
|
|
366
|
+
dist/
|
|
367
|
+
.DS_Store
|
|
368
|
+
*.pdf
|
|
369
|
+
`;
|