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,261 @@
|
|
|
1
|
+
# Theme Management Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how to use the theme management system in your Marp presentation project.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The theme management system provides a simple way to:
|
|
8
|
+
- Add pre-built themes to your project
|
|
9
|
+
- List available and installed themes
|
|
10
|
+
- Switch between themes
|
|
11
|
+
- Create custom themes
|
|
12
|
+
- Integrate with VSCode for live preview
|
|
13
|
+
|
|
14
|
+
## Available Themes
|
|
15
|
+
|
|
16
|
+
The following themes are available in the template:
|
|
17
|
+
|
|
18
|
+
- **beam** - Clean, modern theme with progress bar
|
|
19
|
+
- **default-clean** - Minimal variation of default theme
|
|
20
|
+
- **gaia-dark** - Dark version of the Gaia theme
|
|
21
|
+
- **marpx** - Extended version of Marp's default theme
|
|
22
|
+
- **socrates** - Educational theme with clear typography
|
|
23
|
+
- **uncover-minimal** - Minimal reveal-style theme
|
|
24
|
+
|
|
25
|
+
### System Themes
|
|
26
|
+
|
|
27
|
+
These built-in Marp themes are always available:
|
|
28
|
+
- **default** - Marp's default theme
|
|
29
|
+
- **gaia** - Clean, professional theme
|
|
30
|
+
- **uncover** - Slide-by-slide reveal theme
|
|
31
|
+
|
|
32
|
+
## Commands
|
|
33
|
+
|
|
34
|
+
### List Themes
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm run theme:list
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This shows:
|
|
41
|
+
- Available themes in the theme library
|
|
42
|
+
- Installed themes in your project's `themes/` directory
|
|
43
|
+
- Dependencies for each theme
|
|
44
|
+
|
|
45
|
+
### Add Themes
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm run theme:add
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
You'll be prompted to:
|
|
52
|
+
1. Select themes from the available list
|
|
53
|
+
2. Resolve any conflicts (if themes with the same name exist)
|
|
54
|
+
3. Confirm the selection
|
|
55
|
+
|
|
56
|
+
The command will:
|
|
57
|
+
- Copy theme files to your `themes/` directory
|
|
58
|
+
- Resolve dependencies automatically
|
|
59
|
+
- Update VSCode settings
|
|
60
|
+
- Skip themes that would conflict (unless using `--force`)
|
|
61
|
+
|
|
62
|
+
**Options:**
|
|
63
|
+
```bash
|
|
64
|
+
npm run theme add --force # Overwrite existing themes
|
|
65
|
+
npm run theme add --no-vscode # Skip VSCode settings update
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Set Active Theme
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npm run theme:set <theme-name>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This will:
|
|
75
|
+
- Update the `theme` value in `presentation.md` frontmatter
|
|
76
|
+
- Add the theme to VSCode settings (for custom themes)
|
|
77
|
+
- Warn if the theme is not installed
|
|
78
|
+
|
|
79
|
+
**Examples:**
|
|
80
|
+
```bash
|
|
81
|
+
npm run theme:set beam
|
|
82
|
+
npm run theme:set default
|
|
83
|
+
npm run theme:set gaia
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Create Custom Theme
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm run theme:create <theme-name>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
You'll be prompted to:
|
|
93
|
+
1. Select a parent theme to base your theme on
|
|
94
|
+
2. Choose a directory location (root, subfolder, or new folder)
|
|
95
|
+
|
|
96
|
+
The command will:
|
|
97
|
+
- Create a new CSS file in the appropriate location
|
|
98
|
+
- Add the theme directive and parent import
|
|
99
|
+
- Update VSCode settings if needed
|
|
100
|
+
|
|
101
|
+
**Example:**
|
|
102
|
+
```bash
|
|
103
|
+
npm run theme:create my-brand
|
|
104
|
+
# Select parent: beam
|
|
105
|
+
# Select location: root
|
|
106
|
+
# Creates: themes/my-brand.css
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Theme File Structure
|
|
110
|
+
|
|
111
|
+
Themes are organized in the `themes/` directory:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
my-presentation/
|
|
115
|
+
├── themes/
|
|
116
|
+
│ ├── beam.css
|
|
117
|
+
│ ├── marpx.css
|
|
118
|
+
│ └── custom/
|
|
119
|
+
│ └── my-theme.css
|
|
120
|
+
└── presentation.md
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Theme File Format
|
|
124
|
+
|
|
125
|
+
Each theme CSS file must include:
|
|
126
|
+
1. A theme directive: `/* @theme theme-name */`
|
|
127
|
+
2. Optional parent imports: `@import "parent-theme";`
|
|
128
|
+
|
|
129
|
+
**Example:**
|
|
130
|
+
```css
|
|
131
|
+
/* @theme my-custom */
|
|
132
|
+
@import "beam";
|
|
133
|
+
|
|
134
|
+
:root {
|
|
135
|
+
--color-primary: #3498db;
|
|
136
|
+
--color-secondary: #2ecc71;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
section {
|
|
140
|
+
background: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## VSCode Integration
|
|
145
|
+
|
|
146
|
+
The theme management system automatically updates VSCode settings for live preview support.
|
|
147
|
+
|
|
148
|
+
### Settings Location
|
|
149
|
+
|
|
150
|
+
`.vscode/settings.json`:
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"markdown.marp.themes": [
|
|
154
|
+
"themes/beam/beam.css",
|
|
155
|
+
"themes/marpx/marpx.css"
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### How It Works
|
|
161
|
+
|
|
162
|
+
- When you add themes, they're added to the settings
|
|
163
|
+
- When you set an active theme, it's added to the settings
|
|
164
|
+
- System themes (default, gaia, uncover) are not added (built-in)
|
|
165
|
+
- Use `--no-vscode` to skip this behavior
|
|
166
|
+
|
|
167
|
+
## Manual Theme Management
|
|
168
|
+
|
|
169
|
+
You can also manage themes manually:
|
|
170
|
+
|
|
171
|
+
### Add a Theme Manually
|
|
172
|
+
|
|
173
|
+
1. Copy your theme CSS file to the `themes/` directory (e.g., `themes/your-theme/your-theme.css`)
|
|
174
|
+
2. Add the theme directive: `/* @theme your-theme-name */`
|
|
175
|
+
3. Update `.vscode/settings.json` if needed:
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"markdown.marp.themes": ["themes/your-theme/your-theme.css"]
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Switch Theme Manually
|
|
183
|
+
|
|
184
|
+
Edit `presentation.md`:
|
|
185
|
+
```yaml
|
|
186
|
+
---
|
|
187
|
+
marp: true
|
|
188
|
+
theme: your-theme-name
|
|
189
|
+
---
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Troubleshooting
|
|
193
|
+
|
|
194
|
+
### Theme Not Found
|
|
195
|
+
|
|
196
|
+
If you get a "Theme not found" error:
|
|
197
|
+
1. Check if the theme is installed: `npm run theme:list`
|
|
198
|
+
2. Add the theme if missing: `npm run theme:add`
|
|
199
|
+
3. Verify the theme name matches exactly
|
|
200
|
+
|
|
201
|
+
### Live Preview Not Working
|
|
202
|
+
|
|
203
|
+
If VSCode live preview doesn't show your theme:
|
|
204
|
+
1. Check `.vscode/settings.json` exists
|
|
205
|
+
2. Verify the theme path is correct
|
|
206
|
+
3. Reload the VSCode window
|
|
207
|
+
|
|
208
|
+
### Dependencies Not Found
|
|
209
|
+
|
|
210
|
+
Warning about missing dependencies is expected for system themes (default, gaia, uncover). These are built into Marp CLI and don't need to be in your project.
|
|
211
|
+
|
|
212
|
+
## Best Practices
|
|
213
|
+
|
|
214
|
+
1. **Use Descriptive Names**: Name themes clearly (e.g., `brand-primary`, `presentation-dark`)
|
|
215
|
+
2. **Organize Themes**: Use subfolders for many themes
|
|
216
|
+
3. **Document Dependencies**: Include parent theme imports in comments
|
|
217
|
+
4. **Test Themes**: Always test with `npm run dev` after changing themes
|
|
218
|
+
5. **Version Control**: Commit your custom themes to git
|
|
219
|
+
|
|
220
|
+
## Advanced Usage
|
|
221
|
+
|
|
222
|
+
### Creating Theme Variants
|
|
223
|
+
|
|
224
|
+
Create multiple variants based on the same parent:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
npm run theme:create brand-light # Parent: beam
|
|
228
|
+
npm run theme:create brand-dark # Parent: beam
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Edit the themes to differentiate them:
|
|
232
|
+
|
|
233
|
+
```css
|
|
234
|
+
/* themes/brand-light.css */
|
|
235
|
+
/* @theme brand-light */
|
|
236
|
+
@import "beam";
|
|
237
|
+
:root { --bg-color: #ffffff; }
|
|
238
|
+
|
|
239
|
+
/* themes/brand-dark.css */
|
|
240
|
+
/* @theme brand-dark */
|
|
241
|
+
@import "beam";
|
|
242
|
+
:root { --bg-color: #1a1a1a; }
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Conditional Themes
|
|
246
|
+
|
|
247
|
+
Use different themes for different presentations:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# For external presentations
|
|
251
|
+
npm run theme:set brand-professional
|
|
252
|
+
|
|
253
|
+
# For internal workshops
|
|
254
|
+
npm run theme:set brand-casual
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## References
|
|
258
|
+
|
|
259
|
+
- [Marp Theme Documentation](https://marp.app/docs/theming)
|
|
260
|
+
- [Marp CLI GitHub](https://github.com/marp-team/marp-cli)
|
|
261
|
+
- [CSS Custom Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties)
|
|
@@ -319,7 +319,11 @@ class AddThemesCommand {
|
|
|
319
319
|
if (result === 'overwrite-all') return { overwrite: conflicts };
|
|
320
320
|
if (result === 'cancel') return { overwrite: [] };
|
|
321
321
|
|
|
322
|
-
// Handle
|
|
322
|
+
// Handle single conflict responses
|
|
323
|
+
if (result === 'skip') return { overwrite: [] };
|
|
324
|
+
if (result === 'overwrite') return { overwrite: conflicts };
|
|
325
|
+
|
|
326
|
+
// Handle 'choose-each' - prompt for each conflict individually
|
|
323
327
|
const overwrite = [];
|
|
324
328
|
for (const conflict of conflicts) {
|
|
325
329
|
const choice = await Prompts.promptSingleConflict(conflict);
|
package/lib/prompts.js
CHANGED
|
@@ -17,11 +17,16 @@ class Prompts {
|
|
|
17
17
|
return [];
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const choices = availableThemes.map(theme =>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
const choices = availableThemes.map(theme => {
|
|
21
|
+
const displayName = theme.description
|
|
22
|
+
? `${theme.name} - ${theme.description}`
|
|
23
|
+
: theme.name;
|
|
24
|
+
return {
|
|
25
|
+
name: displayName,
|
|
26
|
+
value: theme.name,
|
|
27
|
+
checked: false
|
|
28
|
+
};
|
|
29
|
+
});
|
|
25
30
|
|
|
26
31
|
return await inquirer.checkbox({
|
|
27
32
|
message: 'Select themes to add:',
|
|
@@ -152,6 +157,18 @@ class Prompts {
|
|
|
152
157
|
});
|
|
153
158
|
}
|
|
154
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Prompt user for new theme description
|
|
162
|
+
*
|
|
163
|
+
* @returns {Promise<string|null>} Theme description or null if skipped
|
|
164
|
+
*/
|
|
165
|
+
static async promptNewThemeDescription() {
|
|
166
|
+
return await inquirer.input({
|
|
167
|
+
message: 'Theme description (optional - press Enter to skip):',
|
|
168
|
+
default: ''
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
155
172
|
/**
|
|
156
173
|
* Prompt user for conflict resolution
|
|
157
174
|
*
|
package/lib/theme-manager.js
CHANGED
|
@@ -4,6 +4,7 @@ const path = require('path');
|
|
|
4
4
|
const { ThemeResolver } = require('./theme-resolver');
|
|
5
5
|
const { VSCodeIntegration } = require('./vscode-integration');
|
|
6
6
|
const { Frontmatter } = require('./frontmatter');
|
|
7
|
+
const { Prompts } = require('./prompts');
|
|
7
8
|
const {
|
|
8
9
|
ThemeNotFoundError,
|
|
9
10
|
ThemeAlreadyExistsError,
|
|
@@ -173,10 +174,11 @@ class ThemeManager {
|
|
|
173
174
|
* @param {string|null} parent - Parent theme name or null
|
|
174
175
|
* @param {string} location - 'root', 'existing' folder name, or 'new'
|
|
175
176
|
* @param {string} newFolderName - Required if location is 'new'
|
|
177
|
+
* @param {string|null} description - Optional theme description
|
|
176
178
|
* @throws {ThemeAlreadyExistsError} If theme with same name already exists
|
|
177
179
|
* @throws {Error} If location is 'new' but newFolderName not provided
|
|
178
180
|
*/
|
|
179
|
-
createTheme(name, parent, location, newFolderName = null) {
|
|
181
|
+
createTheme(name, parent, location, newFolderName = null, description = null) {
|
|
180
182
|
// Check for duplicate
|
|
181
183
|
if (this.getTheme(name)) {
|
|
182
184
|
throw new ThemeAlreadyExistsError(name);
|
|
@@ -198,7 +200,11 @@ class ThemeManager {
|
|
|
198
200
|
}
|
|
199
201
|
|
|
200
202
|
// Generate CSS content
|
|
201
|
-
let css = `/* @theme ${name}
|
|
203
|
+
let css = `/* @theme ${name}`;
|
|
204
|
+
if (description && description.trim()) {
|
|
205
|
+
css += `\n * @description ${description.trim()}`;
|
|
206
|
+
}
|
|
207
|
+
css += ` */\n\n`;
|
|
202
208
|
|
|
203
209
|
if (parent) {
|
|
204
210
|
css += `@import "${parent}";\n\n`;
|
package/lib/theme-resolver.js
CHANGED
|
@@ -7,11 +7,12 @@ const path = require('path');
|
|
|
7
7
|
* Represents a Marp theme
|
|
8
8
|
*/
|
|
9
9
|
class Theme {
|
|
10
|
-
constructor(name, cssPath, css, dependencies = []) {
|
|
10
|
+
constructor(name, cssPath, css, dependencies = [], description = null) {
|
|
11
11
|
this.name = name;
|
|
12
12
|
this.path = cssPath;
|
|
13
13
|
this.css = css;
|
|
14
14
|
this.dependencies = dependencies;
|
|
15
|
+
this.description = description;
|
|
15
16
|
this.isSystem = ['default', 'gaia', 'uncover'].includes(name);
|
|
16
17
|
}
|
|
17
18
|
}
|
|
@@ -81,6 +82,22 @@ class ThemeResolver {
|
|
|
81
82
|
return dependencies;
|
|
82
83
|
}
|
|
83
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Extract @description from CSS comment directive
|
|
87
|
+
* Pattern: /* @description text *\/
|
|
88
|
+
*
|
|
89
|
+
* @param {string} cssContent - CSS file content
|
|
90
|
+
* @returns {string|null} Description text or null if not found
|
|
91
|
+
*/
|
|
92
|
+
static extractDescription(cssContent) {
|
|
93
|
+
// Match /* @description text */ - supports multi-line comments
|
|
94
|
+
// The [\s\S]*? allows matching across newlines (non-greedy)
|
|
95
|
+
const descRegex = /\/\*[\s\S]*?@description\s+([^\r\n*]+)[\s\S]*?\*\//;
|
|
96
|
+
const match = cssContent.match(descRegex);
|
|
97
|
+
|
|
98
|
+
return match ? match[1].trim() : null;
|
|
99
|
+
}
|
|
100
|
+
|
|
84
101
|
/**
|
|
85
102
|
* Resolve theme from a CSS file
|
|
86
103
|
*
|
|
@@ -97,8 +114,9 @@ class ThemeResolver {
|
|
|
97
114
|
const filename = path.basename(cssPath);
|
|
98
115
|
const name = this.extractThemeName(css, filename) || filename;
|
|
99
116
|
const dependencies = this.extractDependencies(css);
|
|
117
|
+
const description = this.extractDescription(css);
|
|
100
118
|
|
|
101
|
-
return new Theme(name, cssPath, css, dependencies);
|
|
119
|
+
return new Theme(name, cssPath, css, dependencies, description);
|
|
102
120
|
}
|
|
103
121
|
|
|
104
122
|
/**
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-marp-presentation",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Create a new Marp presentation project with one command. Manage themes quickly and easily with the CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-marp-presentation": "index.js"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
9
|
"index.js",
|
|
10
|
+
"cli/",
|
|
10
11
|
"lib/",
|
|
12
|
+
"docs/",
|
|
11
13
|
"template/",
|
|
12
14
|
"template-optional/",
|
|
13
15
|
"themes/"
|
package/themes/beam/beam.css
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* @theme beam */
|
|
2
|
+
/* @description Beamer-inspired theme with clean headers and footer bars */
|
|
2
3
|
/* Author: rnd195 https://github.com/rnd195/ */
|
|
3
4
|
/* beam license - GNU GPLv3 https://github.com/rnd195/my-marp-themes/blob/live/licenses/LICENSE_beam */
|
|
4
5
|
/* License of beamer which inspired this theme - GNU GPLv2 https://github.com/rnd195/my-marp-themes/blob/live/licenses/LICENSE_GPLv2 */
|
package/themes/marpx/marpx.css
CHANGED