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.
@@ -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 'choose-each' or individual conflicts
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
- name: theme.name,
22
- value: theme.name,
23
- checked: false
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
  *
@@ -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} */\n\n`;
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`;
@@ -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.0",
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/"
@@ -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 */
@@ -1,5 +1,5 @@
1
1
  /* @theme default-clean */
2
- /* A clean, minimal theme based on default */
2
+ /* @description A clean, minimal theme based on default */
3
3
 
4
4
  @import "default";
5
5
 
@@ -1,5 +1,5 @@
1
1
  /* @theme gaia-dark */
2
- /* A dark variant of the gaia theme */
2
+ /* @description A dark variant of the gaia theme */
3
3
 
4
4
  @import "gaia";
5
5
 
@@ -31,8 +31,9 @@
31
31
  *
32
32
  * ================================================================================ */
33
33
 
34
- /*
34
+ /*
35
35
  * @theme marpx
36
+ * @description Modern multi-format theme with auto-scaling support
36
37
  *
37
38
  * @auto-scaling true
38
39
  * @size 16:9 1280px 720px
@@ -1,4 +1,5 @@
1
1
  /* @theme socrates */
2
+ /* @description A classic teaching theme based on marpx */
2
3
 
3
4
  @import "marpx";
4
5
 
@@ -1,5 +1,5 @@
1
1
  /* @theme uncover-minimal */
2
- /* A minimal variant of the uncover theme */
2
+ /* @description A minimal variant of the uncover theme */
3
3
 
4
4
  @import "uncover";
5
5