create-marp-presentation 1.2.0 → 1.2.2
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/cli/commands/add-themes-cli.js +85 -0
- package/cli/commands/create-project.js +199 -0
- package/cli/utils/file-utils.js +106 -0
- package/cli/utils/prompt-utils.js +89 -0
- package/docs/plans/2025-02-19-marp-template-design.md +207 -0
- package/docs/plans/2025-02-19-marp-template-implementation.md +848 -0
- package/docs/plans/2026-02-20-example-slides-design.md +179 -0
- package/docs/plans/2026-02-20-example-slides-implementation.md +811 -0
- package/docs/plans/2026-02-23-theme-management-design.md +836 -0
- package/docs/plans/2026-02-23-theme-management-implementation.md +3585 -0
- package/docs/plans/2026-02-26-theme-addition-refactoring-design.md +172 -0
- package/docs/plans/2026-02-26-theme-addition-refactoring.md +456 -0
- package/docs/plans/2026-02-27-theme-add-fix-design.md +136 -0
- package/docs/plans/2026-02-27-theme-add-fix.md +353 -0
- package/docs/plans/2026-02-28-conflict-resolution-fix.md +62 -0
- package/docs/plans/TODO.md +5 -0
- package/docs/reqs/themes-requirements.md +49 -0
- package/docs/theme-management.md +261 -0
- package/lib/add-themes-command.js +5 -1
- package/lib/prompts.js +22 -5
- package/lib/theme-manager.js +8 -2
- package/lib/theme-resolver.js +20 -2
- package/package.json +3 -1
- package/themes/beam/beam.css +1 -0
- package/themes/default-clean/default-clean.css +1 -1
- package/themes/gaia-dark/gaia-dark.css +1 -1
- package/themes/marpx/marpx.css +2 -1
- package/themes/marpx/socrates.css +1 -0
- package/themes/uncover-minimal/uncover-minimal.css +1 -1
|
@@ -0,0 +1,811 @@
|
|
|
1
|
+
# Optional Example Slides Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
4
|
+
|
|
5
|
+
**Goal:** Add optional example slides demonstrating all Marp capabilities with interactive CLI prompt.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Separate `template-optional/` folder contains example files that are conditionally copied when user accepts the prompt. CLI uses built-in `readline` for interactive input with non-interactive mode fallback.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Node.js built-in modules (fs, path, readline), Jest for testing
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Task 1: Create template-optional directory structure
|
|
14
|
+
|
|
15
|
+
**Files:**
|
|
16
|
+
- Create: `template-optional/.gitkeep`
|
|
17
|
+
- Create: `template-optional/static/.gitkeep`
|
|
18
|
+
|
|
19
|
+
**Step 1: Create template-optional directory**
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
mkdir -p template-optional/static
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Step 2: Create .gitkeep files**
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
touch template-optional/.gitkeep template-optional/static/.gitkeep
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Step 3: Verify structure**
|
|
32
|
+
|
|
33
|
+
Run: `ls -la template-optional/ && ls -la template-optional/static/`
|
|
34
|
+
Expected: Both directories exist with .gitkeep files
|
|
35
|
+
|
|
36
|
+
**Step 4: Commit**
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
git add template-optional/
|
|
40
|
+
git commit -m "feat: create template-optional directory structure"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Task 2: Create demo image for examples
|
|
46
|
+
|
|
47
|
+
**Files:**
|
|
48
|
+
- Create: `template-optional/static/demo-image.png`
|
|
49
|
+
|
|
50
|
+
**Step 1: Generate minimal SVG**
|
|
51
|
+
|
|
52
|
+
Create a temporary SVG file with minimalist geometric design:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
cat > /tmp/demo-image.svg << 'EOF'
|
|
56
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
|
|
57
|
+
<rect width="800" height="400" fill="#f8f9fa"/>
|
|
58
|
+
<circle cx="200" cy="200" r="80" fill="#4a90d9" opacity="0.8"/>
|
|
59
|
+
<rect x="350" y="100" width="150" height="150" fill="#6c5ce7" opacity="0.7"/>
|
|
60
|
+
<polygon points="600,320 700,120 800,320" fill="#00b894" opacity="0.75"/>
|
|
61
|
+
<circle cx="500" cy="280" r="40" fill="#fd79a8" opacity="0.6"/>
|
|
62
|
+
<rect x="100" y="280" width="100" height="60" fill="#ffeaa7" opacity="0.8"/>
|
|
63
|
+
</svg>
|
|
64
|
+
EOF
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Step 2: Convert SVG to PNG (requires ImageMagick or similar)**
|
|
68
|
+
|
|
69
|
+
If ImageMagick is available:
|
|
70
|
+
```bash
|
|
71
|
+
convert /tmp/demo-image.svg template-optional/static/demo-image.png
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Alternative: Create a placeholder PNG using base64:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Create a minimal 100x50 PNG placeholder
|
|
78
|
+
echo "iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAYAAADDhn8LAAAACXBIWXMAAAsTAAALEwEAmpwYAAAF" | base64 -d > template-optional/static/demo-image.png 2>/dev/null || \
|
|
79
|
+
echo "Note: Demo image will be created manually or use online tool"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
If no image tool available, note in the file that a real image should be added:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
echo "Demo image placeholder - replace with actual 800x400 PNG" > template-optional/static/README.txt
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Step 3: Verify image exists**
|
|
89
|
+
|
|
90
|
+
Run: `ls -la template-optional/static/`
|
|
91
|
+
Expected: demo-image.png exists (or README.txt as fallback)
|
|
92
|
+
|
|
93
|
+
**Step 4: Commit**
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
git add template-optional/static/
|
|
97
|
+
git commit -m "feat: add demo image for example slides"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Task 3: Create examples.md with all slide types
|
|
103
|
+
|
|
104
|
+
**Files:**
|
|
105
|
+
- Create: `template-optional/examples.md`
|
|
106
|
+
|
|
107
|
+
**Step 1: Write examples.md**
|
|
108
|
+
|
|
109
|
+
```markdown
|
|
110
|
+
---
|
|
111
|
+
marp: true
|
|
112
|
+
theme: default
|
|
113
|
+
paginate: true
|
|
114
|
+
math: katex
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
# Marp Examples
|
|
118
|
+
|
|
119
|
+
Complete demonstration of Marp presentation capabilities
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Table of Contents
|
|
124
|
+
|
|
125
|
+
<!-- This auto-generates a table of contents -->
|
|
126
|
+
1. [Basic Formatting](#basic-formatting)
|
|
127
|
+
2. [Lists](#lists)
|
|
128
|
+
3. [Quotes and Footnotes](#quotes-and-footnotes)
|
|
129
|
+
4. [Code](#code)
|
|
130
|
+
5. [Tables](#tables)
|
|
131
|
+
6. [LaTeX Formulas](#latex-formulas)
|
|
132
|
+
7. [Images](#images)
|
|
133
|
+
8. [Multi-column Layouts](#multi-column-layouts)
|
|
134
|
+
9. [Backgrounds and Styling](#backgrounds-and-styling)
|
|
135
|
+
10. [Fragments (Animations)](#fragments-animations)
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Basic Formatting
|
|
140
|
+
|
|
141
|
+
### Headings work like regular Markdown
|
|
142
|
+
|
|
143
|
+
This is **bold text** and this is *italic text*.
|
|
144
|
+
|
|
145
|
+
You can also use ~~strikethrough~~ and `inline code`.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Lists
|
|
150
|
+
|
|
151
|
+
### Unordered Lists
|
|
152
|
+
|
|
153
|
+
- First item
|
|
154
|
+
- Second item
|
|
155
|
+
- Nested item
|
|
156
|
+
- Another nested item
|
|
157
|
+
- Third item
|
|
158
|
+
|
|
159
|
+
### Ordered Lists
|
|
160
|
+
|
|
161
|
+
1. First step
|
|
162
|
+
2. Second step
|
|
163
|
+
3. Third step
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Quotes and Footnotes
|
|
168
|
+
|
|
169
|
+
> This is a blockquote.
|
|
170
|
+
> It can span multiple lines.
|
|
171
|
+
>
|
|
172
|
+
> — Author Name
|
|
173
|
+
|
|
174
|
+
Here's a sentence with a footnote[^1].
|
|
175
|
+
|
|
176
|
+
[^1]: This is the footnote content that appears at the bottom.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Code
|
|
181
|
+
|
|
182
|
+
### JavaScript
|
|
183
|
+
|
|
184
|
+
```javascript
|
|
185
|
+
function greet(name) {
|
|
186
|
+
console.log(`Hello, ${name}!`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
greet('Marp');
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Python
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
def fibonacci(n):
|
|
196
|
+
if n <= 1:
|
|
197
|
+
return n
|
|
198
|
+
return fibonacci(n-1) + fibonacci(n-2)
|
|
199
|
+
|
|
200
|
+
print(fibonacci(10))
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Bash
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
#!/bin/bash
|
|
207
|
+
echo "Building presentation..."
|
|
208
|
+
npx @marp-team/marp-cli presentation.md -o output.html
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Tables
|
|
214
|
+
|
|
215
|
+
### Simple Table
|
|
216
|
+
|
|
217
|
+
| Feature | Status | Notes |
|
|
218
|
+
|---------|--------|-------|
|
|
219
|
+
| Markdown | ✅ | Full support |
|
|
220
|
+
| Code blocks | ✅ | Syntax highlighting |
|
|
221
|
+
| Images | ✅ | Local and remote |
|
|
222
|
+
| Math | ✅ | KaTeX support |
|
|
223
|
+
|
|
224
|
+
### Aligned Columns
|
|
225
|
+
|
|
226
|
+
| Left | Center | Right |
|
|
227
|
+
|:-----|:------:|------:|
|
|
228
|
+
| Default | Centered | Numbers |
|
|
229
|
+
| Text | Text | 1,234 |
|
|
230
|
+
| More | Data | 5,678 |
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## LaTeX Formulas
|
|
235
|
+
|
|
236
|
+
### Inline and Block Math
|
|
237
|
+
|
|
238
|
+
Inline formula: $E = mc^2$
|
|
239
|
+
|
|
240
|
+
Block formula:
|
|
241
|
+
|
|
242
|
+
$$
|
|
243
|
+
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
|
|
244
|
+
$$
|
|
245
|
+
|
|
246
|
+
### More Examples
|
|
247
|
+
|
|
248
|
+
Quadratic formula:
|
|
249
|
+
|
|
250
|
+
$$
|
|
251
|
+
x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
|
|
252
|
+
$$
|
|
253
|
+
|
|
254
|
+
Matrix:
|
|
255
|
+
|
|
256
|
+
$$
|
|
257
|
+
\begin{pmatrix}
|
|
258
|
+
a & b \\
|
|
259
|
+
c & d
|
|
260
|
+
\end{pmatrix}
|
|
261
|
+
$$
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Images
|
|
266
|
+
|
|
267
|
+
### Basic Image
|
|
268
|
+
|
|
269
|
+

|
|
270
|
+
|
|
271
|
+
### Sized Image
|
|
272
|
+
|
|
273
|
+
{ width=300px }
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Multi-column Layouts
|
|
278
|
+
|
|
279
|
+
### Using HTML Tables
|
|
280
|
+
|
|
281
|
+
<table>
|
|
282
|
+
<tr>
|
|
283
|
+
<td>
|
|
284
|
+
|
|
285
|
+
**Left Column**
|
|
286
|
+
|
|
287
|
+
- Point one
|
|
288
|
+
- Point two
|
|
289
|
+
- Point three
|
|
290
|
+
|
|
291
|
+
</td>
|
|
292
|
+
<td>
|
|
293
|
+
|
|
294
|
+
**Right Column**
|
|
295
|
+
|
|
296
|
+
- Another point
|
|
297
|
+
- More content
|
|
298
|
+
- Final item
|
|
299
|
+
|
|
300
|
+
</td>
|
|
301
|
+
</tr>
|
|
302
|
+
</table>
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Backgrounds and Styling
|
|
307
|
+
|
|
308
|
+
<!-- _backgroundColor: #1a1a2e -->
|
|
309
|
+
<!-- _color: #eaeaea -->
|
|
310
|
+
|
|
311
|
+
### Dark Slide
|
|
312
|
+
|
|
313
|
+
This slide has a custom dark background and light text color.
|
|
314
|
+
|
|
315
|
+
You can use HTML color codes or named colors.
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
<!-- _backgroundImage: url('static/demo-image.png') -->
|
|
320
|
+
<!-- _backgroundOpacity: 0.3 -->
|
|
321
|
+
|
|
322
|
+
### Image Background
|
|
323
|
+
|
|
324
|
+
This slide has an image background with reduced opacity.
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Fragments (Animations)
|
|
329
|
+
|
|
330
|
+
Use asterisk `*` for incremental reveal:
|
|
331
|
+
|
|
332
|
+
- *This appears first
|
|
333
|
+
- *This appears second
|
|
334
|
+
- *This appears third
|
|
335
|
+
- *This appears last
|
|
336
|
+
|
|
337
|
+
Press space to reveal each item!
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
<!-- _paginate: false -->
|
|
342
|
+
|
|
343
|
+
# Thank You!
|
|
344
|
+
|
|
345
|
+
## Questions?
|
|
346
|
+
|
|
347
|
+
- GitHub: https://github.com/marp-team/marp
|
|
348
|
+
- Docs: https://marp.app/
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
Contact: your-email@example.com
|
|
352
|
+
```
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Write this content to `template-optional/examples.md`.
|
|
356
|
+
|
|
357
|
+
**Step 2: Verify file created**
|
|
358
|
+
|
|
359
|
+
Run: `wc -l template-optional/examples.md`
|
|
360
|
+
Expected: ~200+ lines
|
|
361
|
+
|
|
362
|
+
**Step 3: Commit**
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
git add template-optional/examples.md
|
|
366
|
+
git commit -m "feat: add examples.md with 13 slide types demonstrating Marp capabilities"
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Task 4: Add askCreateExamples function to CLI
|
|
372
|
+
|
|
373
|
+
**Files:**
|
|
374
|
+
- Modify: `index.js`
|
|
375
|
+
|
|
376
|
+
**Step 1: Add readline import at top of index.js**
|
|
377
|
+
|
|
378
|
+
After line 5 (`const { spawnSync } = require('child_process');`), add:
|
|
379
|
+
|
|
380
|
+
```javascript
|
|
381
|
+
const readline = require('readline');
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**Step 2: Add askCreateExamples function**
|
|
385
|
+
|
|
386
|
+
After the `projectPath` variable (around line 23), add:
|
|
387
|
+
|
|
388
|
+
```javascript
|
|
389
|
+
// Запрос на создание примеров слайдов
|
|
390
|
+
async function askCreateExamples() {
|
|
391
|
+
// Неинтерактивный режим — по умолчанию создаём примеры
|
|
392
|
+
if (!process.stdin.isTTY) {
|
|
393
|
+
return true;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return new Promise((resolve) => {
|
|
397
|
+
const rl = readline.createInterface({
|
|
398
|
+
input: process.stdin,
|
|
399
|
+
output: process.stdout
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
rl.question('Create example slides file? (Y/n) ', (answer) => {
|
|
403
|
+
rl.close();
|
|
404
|
+
const normalized = answer.toLowerCase().trim();
|
|
405
|
+
resolve(normalized !== 'n' && normalized !== 'no');
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
**Step 3: Verify syntax**
|
|
412
|
+
|
|
413
|
+
Run: `node -c index.js`
|
|
414
|
+
Expected: No syntax errors
|
|
415
|
+
|
|
416
|
+
**Step 4: Commit**
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
git add index.js
|
|
420
|
+
git commit -m "feat: add askCreateExamples function for interactive prompt"
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## Task 5: Add optional files copying logic to CLI
|
|
426
|
+
|
|
427
|
+
**Files:**
|
|
428
|
+
- Modify: `index.js`
|
|
429
|
+
|
|
430
|
+
**Step 1: Add copyOptionalFiles function**
|
|
431
|
+
|
|
432
|
+
After `copyDir` function (around line 63), add:
|
|
433
|
+
|
|
434
|
+
```javascript
|
|
435
|
+
// Копирование опциональных файлов
|
|
436
|
+
const copyOptionalFiles = (destPath) => {
|
|
437
|
+
const optionalPath = path.join(__dirname, 'template-optional');
|
|
438
|
+
|
|
439
|
+
// Копируем examples.md
|
|
440
|
+
const examplesSrc = path.join(optionalPath, 'examples.md');
|
|
441
|
+
const examplesDest = path.join(destPath, 'examples.md');
|
|
442
|
+
if (fs.existsSync(examplesSrc)) {
|
|
443
|
+
fs.copyFileSync(examplesSrc, examplesDest);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Копируем демо-изображение
|
|
447
|
+
const demoImageSrc = path.join(optionalPath, 'static', 'demo-image.png');
|
|
448
|
+
const demoImageDest = path.join(destPath, 'static', 'demo-image.png');
|
|
449
|
+
if (fs.existsSync(demoImageSrc)) {
|
|
450
|
+
fs.copyFileSync(demoImageSrc, demoImageDest);
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
**Step 2: Verify syntax**
|
|
456
|
+
|
|
457
|
+
Run: `node -c index.js`
|
|
458
|
+
Expected: No syntax errors
|
|
459
|
+
|
|
460
|
+
**Step 3: Commit**
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
git add index.js
|
|
464
|
+
git commit -m "feat: add copyOptionalFiles function"
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## Task 6: Integrate async flow into main CLI
|
|
470
|
+
|
|
471
|
+
**Files:**
|
|
472
|
+
- Modify: `index.js`
|
|
473
|
+
|
|
474
|
+
**Step 1: Wrap main logic in async IIFE**
|
|
475
|
+
|
|
476
|
+
Replace the main try block (lines 44-92) with async flow:
|
|
477
|
+
|
|
478
|
+
```javascript
|
|
479
|
+
// Получаем путь к template
|
|
480
|
+
const templatePath = path.join(__dirname, 'template');
|
|
481
|
+
|
|
482
|
+
console.log(`Creating Marp presentation: ${projectName}`);
|
|
483
|
+
console.log();
|
|
484
|
+
|
|
485
|
+
// Основной async flow
|
|
486
|
+
(async () => {
|
|
487
|
+
try {
|
|
488
|
+
// Запрашиваем создание примеров
|
|
489
|
+
const createExamples = await askCreateExamples();
|
|
490
|
+
|
|
491
|
+
// Создаём папку проекта
|
|
492
|
+
fs.mkdirSync(projectPath, { recursive: true });
|
|
493
|
+
|
|
494
|
+
// Рекурсивно копируем template
|
|
495
|
+
copyDir(templatePath, projectPath);
|
|
496
|
+
|
|
497
|
+
console.log('✓ Project created');
|
|
498
|
+
|
|
499
|
+
// Копируем опциональные файлы
|
|
500
|
+
if (createExamples) {
|
|
501
|
+
copyOptionalFiles(projectPath);
|
|
502
|
+
console.log('✓ Example slides added');
|
|
503
|
+
console.log('✓ Demo image added to static/');
|
|
504
|
+
}
|
|
505
|
+
console.log();
|
|
506
|
+
|
|
507
|
+
// Запускаем npm install
|
|
508
|
+
console.log('Installing dependencies...');
|
|
509
|
+
const installResult = spawnSync('npm', ['install'], {
|
|
510
|
+
cwd: projectPath,
|
|
511
|
+
stdio: 'inherit',
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
if (installResult.status !== 0) {
|
|
515
|
+
console.error();
|
|
516
|
+
console.error('Failed to install dependencies.');
|
|
517
|
+
console.error('Please run "cd ' + projectName + ' && npm install" manually.');
|
|
518
|
+
process.exit(1);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
console.log();
|
|
522
|
+
console.log('✓ Dependencies installed');
|
|
523
|
+
console.log();
|
|
524
|
+
console.log('Next steps:');
|
|
525
|
+
console.log(` cd ${projectName}`);
|
|
526
|
+
console.log(' npm run dev # Start live preview');
|
|
527
|
+
if (createExamples) {
|
|
528
|
+
console.log(' marp examples.md # Preview example slides');
|
|
529
|
+
}
|
|
530
|
+
console.log(' npm run build:all # Build all formats');
|
|
531
|
+
console.log();
|
|
532
|
+
|
|
533
|
+
} catch (err) {
|
|
534
|
+
console.error('Error creating project:', err.message);
|
|
535
|
+
process.exit(1);
|
|
536
|
+
}
|
|
537
|
+
})();
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
**Step 2: Verify syntax**
|
|
541
|
+
|
|
542
|
+
Run: `node -c index.js`
|
|
543
|
+
Expected: No syntax errors
|
|
544
|
+
|
|
545
|
+
**Step 3: Commit**
|
|
546
|
+
|
|
547
|
+
```bash
|
|
548
|
+
git add index.js
|
|
549
|
+
git commit -m "feat: integrate interactive prompt and optional files into CLI flow"
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## Task 7: Update package.json files field
|
|
555
|
+
|
|
556
|
+
**Files:**
|
|
557
|
+
- Modify: `package.json`
|
|
558
|
+
|
|
559
|
+
**Step 1: Update files array**
|
|
560
|
+
|
|
561
|
+
Change the `files` field from:
|
|
562
|
+
|
|
563
|
+
```json
|
|
564
|
+
"files": [
|
|
565
|
+
"index.js",
|
|
566
|
+
"template/"
|
|
567
|
+
],
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
To:
|
|
571
|
+
|
|
572
|
+
```json
|
|
573
|
+
"files": [
|
|
574
|
+
"index.js",
|
|
575
|
+
"template/",
|
|
576
|
+
"template-optional/"
|
|
577
|
+
],
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
**Step 2: Verify package.json is valid**
|
|
581
|
+
|
|
582
|
+
Run: `node -e "console.log(JSON.parse(require('fs').readFileSync('package.json')).files)"`
|
|
583
|
+
Expected: `['index.js', 'template/', 'template-optional/']`
|
|
584
|
+
|
|
585
|
+
**Step 3: Commit**
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
git add package.json
|
|
589
|
+
git commit -m "feat: add template-optional to npm package files"
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
## Task 8: Write tests for new CLI functionality
|
|
595
|
+
|
|
596
|
+
**Files:**
|
|
597
|
+
- Modify: `tests/cli.test.js`
|
|
598
|
+
|
|
599
|
+
**Step 1: Add test for examples.md creation**
|
|
600
|
+
|
|
601
|
+
Add this test to the existing test file:
|
|
602
|
+
|
|
603
|
+
```javascript
|
|
604
|
+
describe('CLI with examples', () => {
|
|
605
|
+
const projectRoot = path.resolve(__dirname, '..');
|
|
606
|
+
const testProjects = [];
|
|
607
|
+
|
|
608
|
+
afterEach(() => {
|
|
609
|
+
for (const project of testProjects) {
|
|
610
|
+
if (fs.existsSync(project)) {
|
|
611
|
+
fs.rmSync(project, { recursive: true, force: true });
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
test('should create examples.md in non-interactive mode', () => {
|
|
617
|
+
const projectName = 'test-examples-auto';
|
|
618
|
+
const projectPath = path.join(projectRoot, projectName);
|
|
619
|
+
testProjects.push(projectPath);
|
|
620
|
+
|
|
621
|
+
// stdin is not a TTY in test environment, so examples should be created
|
|
622
|
+
const result = spawnSync('node', ['index.js', projectName], {
|
|
623
|
+
cwd: projectRoot,
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
expect(result.status).toBe(0);
|
|
627
|
+
expect(fs.existsSync(path.join(projectPath, 'examples.md'))).toBe(true);
|
|
628
|
+
expect(fs.existsSync(path.join(projectPath, 'static', 'demo-image.png'))).toBe(true);
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
test('should not create examples.md when user declines', () => {
|
|
632
|
+
const projectName = 'test-no-examples';
|
|
633
|
+
const projectPath = path.join(projectRoot, projectName);
|
|
634
|
+
testProjects.push(projectPath);
|
|
635
|
+
|
|
636
|
+
const result = spawnSync('node', ['index.js', projectName], {
|
|
637
|
+
cwd: projectRoot,
|
|
638
|
+
input: 'n\n',
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
expect(result.status).toBe(0);
|
|
642
|
+
expect(fs.existsSync(path.join(projectPath, 'examples.md'))).toBe(false);
|
|
643
|
+
});
|
|
644
|
+
});
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
**Step 2: Run tests**
|
|
648
|
+
|
|
649
|
+
Run: `npm test`
|
|
650
|
+
Expected: All tests pass
|
|
651
|
+
|
|
652
|
+
**Step 3: Commit**
|
|
653
|
+
|
|
654
|
+
```bash
|
|
655
|
+
git add tests/cli.test.js
|
|
656
|
+
git commit -m "test: add tests for optional examples feature"
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
---
|
|
660
|
+
|
|
661
|
+
## Task 9: Manual integration testing
|
|
662
|
+
|
|
663
|
+
**Files:**
|
|
664
|
+
- None (manual testing)
|
|
665
|
+
|
|
666
|
+
**Step 1: Test interactive mode with examples**
|
|
667
|
+
|
|
668
|
+
```bash
|
|
669
|
+
node index.js test-manual-with-examples
|
|
670
|
+
# When prompted: Press Enter or type 'y'
|
|
671
|
+
cd test-manual-with-examples
|
|
672
|
+
ls -la
|
|
673
|
+
# Verify: examples.md exists, static/demo-image.png exists
|
|
674
|
+
npm run dev
|
|
675
|
+
# Verify: presentation.md loads in browser
|
|
676
|
+
# Then: marp examples.md
|
|
677
|
+
# Verify: examples.md renders correctly
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
**Step 2: Test interactive mode without examples**
|
|
681
|
+
|
|
682
|
+
```bash
|
|
683
|
+
cd ..
|
|
684
|
+
node index.js test-manual-no-examples
|
|
685
|
+
# When prompted: type 'n'
|
|
686
|
+
cd test-manual-no-examples
|
|
687
|
+
ls -la
|
|
688
|
+
# Verify: examples.md does NOT exist, static/ exists but no demo-image.png
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
**Step 3: Test non-interactive mode**
|
|
692
|
+
|
|
693
|
+
```bash
|
|
694
|
+
cd ..
|
|
695
|
+
echo "" | node index.js test-piped-input
|
|
696
|
+
cd test-piped-input
|
|
697
|
+
ls -la
|
|
698
|
+
# Verify: examples.md exists (piped empty input = default yes)
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
**Step 4: Clean up test projects**
|
|
702
|
+
|
|
703
|
+
```bash
|
|
704
|
+
cd ..
|
|
705
|
+
rm -rf test-manual-with-examples test-manual-no-examples test-piped-input
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
---
|
|
709
|
+
|
|
710
|
+
## Task 10: Update CLAUDE.md documentation
|
|
711
|
+
|
|
712
|
+
**Files:**
|
|
713
|
+
- Modify: `CLAUDE.md`
|
|
714
|
+
|
|
715
|
+
**Step 1: Add documentation for template-optional**
|
|
716
|
+
|
|
717
|
+
Add this section after "## Architecture":
|
|
718
|
+
|
|
719
|
+
```markdown
|
|
720
|
+
### Optional Template Files
|
|
721
|
+
|
|
722
|
+
The `template-optional/` folder contains files that are conditionally copied based on user preference:
|
|
723
|
+
|
|
724
|
+
- `examples.md` - Comprehensive demonstration of Marp capabilities (13 slides)
|
|
725
|
+
- `static/demo-image.png` - Demo image for image insertion examples
|
|
726
|
+
|
|
727
|
+
When users run `npx create-marp-presentation <name>`, they are prompted:
|
|
728
|
+
```
|
|
729
|
+
Create example slides file? (Y/n)
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
- Yes (default): Both `presentation.md` and `examples.md` are created
|
|
733
|
+
- No: Only `presentation.md` is created
|
|
734
|
+
|
|
735
|
+
In non-interactive mode (CI/CD), examples are created by default.
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
**Step 2: Update Key Files table**
|
|
739
|
+
|
|
740
|
+
Add to the Key Files table:
|
|
741
|
+
|
|
742
|
+
```markdown
|
|
743
|
+
| `template-optional/examples.md` | Comprehensive Marp capabilities demo (13 slide types) |
|
|
744
|
+
| `template-optional/static/demo-image.png` | Demo image for image insertion examples |
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
**Step 3: Commit**
|
|
748
|
+
|
|
749
|
+
```bash
|
|
750
|
+
git add CLAUDE.md
|
|
751
|
+
git commit -m "docs: update CLAUDE.md with template-optional documentation"
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
## Task 11: Final verification and version bump
|
|
757
|
+
|
|
758
|
+
**Files:**
|
|
759
|
+
- Modify: `package.json`
|
|
760
|
+
|
|
761
|
+
**Step 1: Run all tests**
|
|
762
|
+
|
|
763
|
+
```bash
|
|
764
|
+
npm test
|
|
765
|
+
```
|
|
766
|
+
Expected: All tests pass
|
|
767
|
+
|
|
768
|
+
**Step 2: Test dry-run publish**
|
|
769
|
+
|
|
770
|
+
```bash
|
|
771
|
+
npm publish --dry-run
|
|
772
|
+
```
|
|
773
|
+
Expected: Package includes template-optional/ files
|
|
774
|
+
|
|
775
|
+
**Step 3: Bump version**
|
|
776
|
+
|
|
777
|
+
```bash
|
|
778
|
+
# Update version in package.json from 1.0.1 to 1.1.0
|
|
779
|
+
npm version minor --no-git-tag-version
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
**Step 4: Final commit**
|
|
783
|
+
|
|
784
|
+
```bash
|
|
785
|
+
git add package.json
|
|
786
|
+
git commit -m "chore: bump version to 1.1.0 for optional examples feature"
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
**Step 5: Push to remote**
|
|
790
|
+
|
|
791
|
+
```bash
|
|
792
|
+
git push origin template-slides
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
---
|
|
796
|
+
|
|
797
|
+
## Summary
|
|
798
|
+
|
|
799
|
+
| Task | Description | Files Changed |
|
|
800
|
+
|------|-------------|---------------|
|
|
801
|
+
| 1 | Create template-optional structure | `template-optional/.gitkeep`, `template-optional/static/.gitkeep` |
|
|
802
|
+
| 2 | Create demo image | `template-optional/static/demo-image.png` |
|
|
803
|
+
| 3 | Create examples.md | `template-optional/examples.md` |
|
|
804
|
+
| 4 | Add askCreateExamples function | `index.js` |
|
|
805
|
+
| 5 | Add copyOptionalFiles function | `index.js` |
|
|
806
|
+
| 6 | Integrate async flow | `index.js` |
|
|
807
|
+
| 7 | Update package.json files | `package.json` |
|
|
808
|
+
| 8 | Add tests | `tests/cli.test.js` |
|
|
809
|
+
| 9 | Manual testing | - |
|
|
810
|
+
| 10 | Update docs | `CLAUDE.md` |
|
|
811
|
+
| 11 | Final verification | `package.json` |
|