@masaki39/marp-mcp 0.1.0 → 0.3.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/README.md +31 -318
- package/build/index.js +7 -9
- package/build/layouts/content.js +41 -0
- package/build/layouts/figure.js +62 -0
- package/build/layouts/image-center.js +49 -0
- package/build/layouts/image-right.js +50 -0
- package/build/layouts/image.js +59 -0
- package/build/layouts/index.js +48 -0
- package/build/layouts/list.js +43 -0
- package/build/layouts/multi-column.js +46 -0
- package/build/layouts/section.js +30 -0
- package/build/layouts/table.js +50 -0
- package/build/layouts/title.js +30 -0
- package/build/layouts/two-column.js +69 -0
- package/build/layouts/types.js +4 -0
- package/build/templates/{academic_custom.css → custom_theme.css} +6 -5
- package/build/templates/marp_guide.md +100 -0
- package/build/templates/slides.template.md +3 -20
- package/build/tools/generate.js +293 -3
- package/build/tools/init.js +17 -34
- package/build/tools/list_layouts.js +68 -0
- package/build/tools/manage_slide.js +344 -0
- package/package.json +3 -3
- package/build/layouts/academic.js +0 -258
- package/build/templates/gitignore.template +0 -20
package/README.md
CHANGED
|
@@ -1,45 +1,15 @@
|
|
|
1
1
|
# Marp MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
An MCP server for creating and editing Marp presentations with AI assistance.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Setup
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- 📁 **Project Initialization** - Automatic directory structure setup
|
|
9
|
-
- 🎯 **Structured Slide Generation** - 6 layout templates for consistent design
|
|
10
|
-
- 🔧 **Editor Integration** - Designed for Claude Code and Cursor
|
|
11
|
-
- 📝 **Markdown Output** - Generate slides as markdown strings for easy editing
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
|
|
15
|
-
### Via npx (Recommended)
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npx @masaki39/marp-mcp
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
### Global Installation
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
npm install -g @masaki39/marp-mcp
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### Local Installation
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
npm install @masaki39/marp-mcp
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Configuration
|
|
34
|
-
|
|
35
|
-
### Claude Desktop
|
|
36
|
-
|
|
37
|
-
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
7
|
+
Add to your MCP client configuration:
|
|
38
8
|
|
|
39
9
|
```json
|
|
40
10
|
{
|
|
41
11
|
"mcpServers": {
|
|
42
|
-
"marp": {
|
|
12
|
+
"marp-mcp": {
|
|
43
13
|
"command": "npx",
|
|
44
14
|
"args": ["-y", "@masaki39/marp-mcp"]
|
|
45
15
|
}
|
|
@@ -47,301 +17,44 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
|
47
17
|
}
|
|
48
18
|
```
|
|
49
19
|
|
|
50
|
-
|
|
20
|
+
## Tools
|
|
51
21
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"command": "marp-mcp"
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### Claude Code / Cursor
|
|
63
|
-
|
|
64
|
-
The server works seamlessly with Claude Code and Cursor. The generated markdown can be directly inserted into your editor.
|
|
65
|
-
|
|
66
|
-
## Available Tools
|
|
67
|
-
|
|
68
|
-
### 1. `init_presentation`
|
|
69
|
-
|
|
70
|
-
Initialize a new Marp presentation project with complete directory structure.
|
|
71
|
-
|
|
72
|
-
**Parameters:**
|
|
73
|
-
- `projectPath` (string) - Directory where project will be created
|
|
74
|
-
- `projectName` (string) - Name of the presentation project
|
|
75
|
-
- `presentationTitle` (string) - Title of the presentation
|
|
76
|
-
- `presentationSubtitle` (string, optional) - Subtitle
|
|
77
|
-
- `description` (string, optional) - Brief description
|
|
78
|
-
|
|
79
|
-
**Generated Structure:**
|
|
80
|
-
```
|
|
81
|
-
my-presentation/
|
|
82
|
-
├── slides.md # Main presentation file
|
|
83
|
-
├── themes/
|
|
84
|
-
│ └── academic_custom.css # Academic theme
|
|
85
|
-
├── attachments/
|
|
86
|
-
│ ├── images/ # Image files
|
|
87
|
-
│ ├── videos/ # Video files
|
|
88
|
-
│ └── data/ # Data files
|
|
89
|
-
├── .gitignore
|
|
90
|
-
└── README.md
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
**Example:**
|
|
94
|
-
```javascript
|
|
95
|
-
{
|
|
96
|
-
"projectPath": "/Users/yourname/presentations",
|
|
97
|
-
"projectName": "research-2024",
|
|
98
|
-
"presentationTitle": "Research Findings",
|
|
99
|
-
"presentationSubtitle": "Annual Report 2024",
|
|
100
|
-
"description": "Research results presentation"
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### 2. `generate_slide`
|
|
105
|
-
|
|
106
|
-
Generate a slide using academic theme layouts. Returns markdown string for copy-paste.
|
|
107
|
-
|
|
108
|
-
**Parameters:**
|
|
109
|
-
- `layoutType` (string) - Layout type (title, lead, content, table, multi-column, quote)
|
|
110
|
-
- `params` (object) - Layout-specific parameters
|
|
111
|
-
|
|
112
|
-
**Example:**
|
|
113
|
-
```javascript
|
|
114
|
-
{
|
|
115
|
-
"layoutType": "title",
|
|
116
|
-
"params": {
|
|
117
|
-
"title": "Presentation Title",
|
|
118
|
-
"subtitle": "Subtitle"
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### 3. `list_slide_layouts`
|
|
124
|
-
|
|
125
|
-
List all available slide layouts with their parameters and descriptions.
|
|
126
|
-
|
|
127
|
-
**No parameters required.**
|
|
22
|
+
| Tool | Description |
|
|
23
|
+
|------|-------------|
|
|
24
|
+
| `list_layouts` | List all available slide layouts with parameters and descriptions |
|
|
25
|
+
| `manage_slide` | Insert, replace, or delete slides in a Marp markdown file |
|
|
128
26
|
|
|
129
27
|
## Available Layouts
|
|
130
28
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
# Presentation Title
|
|
141
|
-
## Subtitle
|
|
142
|
-
|
|
143
|
-
<!-- _class: title -->
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
### Lead Slide (`lead`)
|
|
147
|
-
Left-aligned with maroon color headings using `.lead` class.
|
|
148
|
-
|
|
149
|
-
**Parameters:**
|
|
150
|
-
- `heading` (required, max 80 chars)
|
|
151
|
-
- `content` (optional, markdown supported)
|
|
29
|
+
| Layout | Description |
|
|
30
|
+
|--------|-------------|
|
|
31
|
+
| `title` | Title slide with left-aligned heading and metadata |
|
|
32
|
+
| `section` | Section divider with centered title and subtitle |
|
|
33
|
+
| `list` | Content slide with heading and bullet points or text |
|
|
34
|
+
| `table` | Table layout with customizable size and alignment |
|
|
35
|
+
| `two-column` | Two-column layout for side-by-side content |
|
|
36
|
+
| `image-right` | Layout with image on the right side |
|
|
37
|
+
| `image-center` | Centered image layout with adjustable dimensions |
|
|
152
38
|
|
|
153
|
-
|
|
154
|
-
```markdown
|
|
155
|
-
# Main Heading
|
|
39
|
+
## Example
|
|
156
40
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
<!-- _class: lead -->
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
### Content Slide (`content`)
|
|
163
|
-
Standard content slide with optional heading.
|
|
164
|
-
|
|
165
|
-
**Parameters:**
|
|
166
|
-
- `heading` (optional, max 80 chars)
|
|
167
|
-
- `content` (required, markdown supported)
|
|
168
|
-
|
|
169
|
-
**Output:**
|
|
170
|
-
```markdown
|
|
171
|
-
# Heading
|
|
172
|
-
|
|
173
|
-
Content with markdown support
|
|
174
|
-
- List item 1
|
|
175
|
-
- List item 2
|
|
176
|
-
```
|
|
41
|
+
See the [example presentation](./assets/example.html) demonstrating all available layouts.
|
|
177
42
|
|
|
178
|
-
|
|
179
|
-
|
|
43
|
+
The example was created entirely using this MCP server and showcases:
|
|
44
|
+
- Title and section slides
|
|
45
|
+
- List and table layouts
|
|
46
|
+
- Two-column layout
|
|
47
|
+
- Image layouts (center and right)
|
|
180
48
|
|
|
181
|
-
|
|
182
|
-
- `heading` (optional, max 80 chars)
|
|
183
|
-
- `tableMarkdown` (required, markdown table)
|
|
184
|
-
- `tableClass` (optional: "center", "100", "tiny", "small", "large")
|
|
185
|
-
|
|
186
|
-
**Output:**
|
|
187
|
-
```markdown
|
|
188
|
-
# Table Heading
|
|
189
|
-
|
|
190
|
-
| Column 1 | Column 2 |
|
|
191
|
-
|----------|----------|
|
|
192
|
-
| Data 1 | Data 2 |
|
|
193
|
-
|
|
194
|
-
<!-- _class: table-center table-100 -->
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
### Multi-Column Slide (`multi-column`)
|
|
198
|
-
2-3 column layout using double blockquote syntax.
|
|
199
|
-
|
|
200
|
-
**Parameters:**
|
|
201
|
-
- `heading` (optional, max 80 chars)
|
|
202
|
-
- `columns` (required, array of strings)
|
|
203
|
-
|
|
204
|
-
**Output:**
|
|
205
|
-
```markdown
|
|
206
|
-
# Comparison
|
|
207
|
-
|
|
208
|
-
> > Column 1 content
|
|
209
|
-
> > - Point 1
|
|
210
|
-
>
|
|
211
|
-
> > Column 2 content
|
|
212
|
-
> > - Point 2
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Quote Slide (`quote`)
|
|
216
|
-
Quote with citation in footer.
|
|
217
|
-
|
|
218
|
-
**Parameters:**
|
|
219
|
-
- `heading` (optional, max 80 chars)
|
|
220
|
-
- `content` (optional)
|
|
221
|
-
- `quote` (required, max 300 chars)
|
|
222
|
-
- `citation` (optional, max 100 chars)
|
|
223
|
-
|
|
224
|
-
**Output:**
|
|
225
|
-
```markdown
|
|
226
|
-
# Heading
|
|
227
|
-
|
|
228
|
-
Main content
|
|
229
|
-
|
|
230
|
-
> Quote text here — Citation
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
## Academic Theme Features
|
|
234
|
-
|
|
235
|
-
The included `academic_custom.css` theme provides:
|
|
236
|
-
|
|
237
|
-
- **Page numbering** - Automatic slide numbers
|
|
238
|
-
- **Custom fonts** - Noto Sans JP and Source Code Pro
|
|
239
|
-
- **Color scheme** - Maroon highlights (#800000)
|
|
240
|
-
- **Table styles** - Multiple size and alignment options
|
|
241
|
-
- **Multi-column support** - Flexible column layouts
|
|
242
|
-
- **Header support** - Customizable presentation headers
|
|
243
|
-
|
|
244
|
-
### CSS Classes
|
|
245
|
-
|
|
246
|
-
- `.title` - Title slide (centered)
|
|
247
|
-
- `.lead` - Lead slide (left-aligned, maroon)
|
|
248
|
-
- `.table-center` - Centered table
|
|
249
|
-
- `.table-100` - Full-width table
|
|
250
|
-
- `.table-tiny` - Small font table (0.7em)
|
|
251
|
-
- `.table-small` - Small font table (0.8em)
|
|
252
|
-
- `.table-large` - Large font table (1.1em)
|
|
253
|
-
|
|
254
|
-
## Building Presentations
|
|
255
|
-
|
|
256
|
-
### Prerequisites
|
|
257
|
-
|
|
258
|
-
Install Marp CLI:
|
|
259
|
-
|
|
260
|
-
```bash
|
|
261
|
-
npm install -g @marp-team/marp-cli
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
### Build to PDF
|
|
265
|
-
|
|
266
|
-
```bash
|
|
267
|
-
marp slides.md -o slides.pdf
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
### Build to HTML
|
|
271
|
-
|
|
272
|
-
```bash
|
|
273
|
-
marp slides.md -o slides.html
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Build to PowerPoint
|
|
277
|
-
|
|
278
|
-
```bash
|
|
279
|
-
marp slides.md -o slides.pptx
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
### Preview in VS Code
|
|
283
|
-
|
|
284
|
-
Install [Marp for VS Code](https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode) extension for live preview.
|
|
285
|
-
|
|
286
|
-
## Development
|
|
287
|
-
|
|
288
|
-
### Building from Source
|
|
289
|
-
|
|
290
|
-
```bash
|
|
291
|
-
git clone https://github.com/masaki39/marp-mcp.git
|
|
292
|
-
cd marp-mcp
|
|
293
|
-
npm install
|
|
294
|
-
npm run build
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
### Testing Locally
|
|
298
|
-
|
|
299
|
-
```bash
|
|
300
|
-
npm link
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
Then configure Claude Desktop to use the local version.
|
|
304
|
-
|
|
305
|
-
## Troubleshooting
|
|
306
|
-
|
|
307
|
-
### Server Not Starting
|
|
308
|
-
|
|
309
|
-
Check logs in `~/Library/Logs/Claude/`:
|
|
310
|
-
```bash
|
|
311
|
-
tail -f ~/Library/Logs/Claude/mcp*.log
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
### Template Files Not Found
|
|
315
|
-
|
|
316
|
-
Ensure the package was built correctly:
|
|
317
|
-
```bash
|
|
318
|
-
npm run build
|
|
319
|
-
ls build/templates/
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
Should show:
|
|
323
|
-
- `academic_custom.css`
|
|
324
|
-
- `slides.template.md`
|
|
325
|
-
- `README.template.md`
|
|
326
|
-
- `gitignore.template`
|
|
327
|
-
|
|
328
|
-
## Contributing
|
|
329
|
-
|
|
330
|
-
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
49
|
+
Source: [example.md](./assets/example.md)
|
|
331
50
|
|
|
332
51
|
## License
|
|
333
52
|
|
|
334
|
-
MIT License
|
|
335
|
-
|
|
336
|
-
## Credits
|
|
337
|
-
|
|
338
|
-
- Academic theme based on [marp-theme-academic](https://github.com/kaisugi/marp-theme-academic) by kaisugi
|
|
339
|
-
- Built on [Model Context Protocol](https://modelcontextprotocol.io)
|
|
340
|
-
- Powered by [Marp](https://marp.app/)
|
|
53
|
+
MIT License
|
|
341
54
|
|
|
342
55
|
## Links
|
|
343
56
|
|
|
344
|
-
- [GitHub
|
|
345
|
-
- [npm
|
|
346
|
-
- [Marp
|
|
347
|
-
- [
|
|
57
|
+
- [GitHub](https://github.com/masaki39/marp-mcp)
|
|
58
|
+
- [npm](https://www.npmjs.com/package/@masaki39/marp-mcp)
|
|
59
|
+
- [Marp](https://marp.app/)
|
|
60
|
+
- [Model Context Protocol](https://modelcontextprotocol.io)
|
package/build/index.js
CHANGED
|
@@ -7,28 +7,26 @@
|
|
|
7
7
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
8
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9
9
|
// Import tools
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { listLayoutsSchema, listLayouts, } from "./tools/list_layouts.js";
|
|
11
|
+
import { manageSlideSchema, manageSlide, } from "./tools/manage_slide.js";
|
|
12
12
|
// Create server instance
|
|
13
13
|
const server = new McpServer({
|
|
14
14
|
name: "marp-mcp",
|
|
15
|
-
version: "
|
|
15
|
+
version: "0.3.0",
|
|
16
16
|
capabilities: {
|
|
17
17
|
resources: {},
|
|
18
18
|
tools: {},
|
|
19
19
|
},
|
|
20
20
|
});
|
|
21
21
|
// Register tools
|
|
22
|
-
server.tool("
|
|
23
|
-
server.tool("
|
|
24
|
-
server.tool("list_slide_layouts", "List all available slide layouts with their parameters and descriptions", listSlideLayoutsSchema.shape, listSlideLayouts);
|
|
22
|
+
server.tool("list_layouts", "ALWAYS read this first before creating Marp slides - lists all available layouts with parameters and descriptions", listLayoutsSchema.shape, listLayouts);
|
|
23
|
+
server.tool("manage_slide", "Create slides using this tool with appropriate layouts, then fine-tune by direct editing if needed", manageSlideSchema.shape, manageSlide);
|
|
25
24
|
// Start the server
|
|
26
25
|
async function main() {
|
|
27
26
|
const transport = new StdioServerTransport();
|
|
28
27
|
await server.connect(transport);
|
|
29
|
-
console.error("Marp MCP Server
|
|
30
|
-
console.error("
|
|
31
|
-
console.error("Tools: init_presentation, generate_slide, list_slide_layouts");
|
|
28
|
+
console.error("Marp MCP Server v0.3.0 running on stdio");
|
|
29
|
+
console.error("Tools: list_layouts, manage_slide");
|
|
32
30
|
}
|
|
33
31
|
main().catch((error) => {
|
|
34
32
|
console.error("Fatal error in main():", error);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default content slide
|
|
3
|
+
*/
|
|
4
|
+
export const contentLayout = {
|
|
5
|
+
name: "content",
|
|
6
|
+
description: "Standard content slide with optional h2 heading",
|
|
7
|
+
params: {
|
|
8
|
+
heading: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Slide heading (max 80 chars, displays as h2)",
|
|
11
|
+
required: false,
|
|
12
|
+
maxLength: 80,
|
|
13
|
+
},
|
|
14
|
+
content: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Content (markdown supported, keep concise - max 800 chars recommended)",
|
|
17
|
+
required: true,
|
|
18
|
+
maxLength: 1500,
|
|
19
|
+
},
|
|
20
|
+
citations: {
|
|
21
|
+
type: "array",
|
|
22
|
+
description: "Citations/references (array of strings)",
|
|
23
|
+
required: false,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
template: (params) => {
|
|
27
|
+
let slide = "";
|
|
28
|
+
if (params.heading) {
|
|
29
|
+
slide += `## ${params.heading}\n\n`;
|
|
30
|
+
}
|
|
31
|
+
slide += params.content;
|
|
32
|
+
// Add citations
|
|
33
|
+
if (params.citations && params.citations.length > 0) {
|
|
34
|
+
slide += '\n\n';
|
|
35
|
+
params.citations.forEach((citation) => {
|
|
36
|
+
slide += `> ${citation}\n`;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return slide;
|
|
40
|
+
},
|
|
41
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Figure layout - content with background image
|
|
3
|
+
*/
|
|
4
|
+
export const figureLayout = {
|
|
5
|
+
name: "figure",
|
|
6
|
+
description: "Slide with background image and content overlay",
|
|
7
|
+
params: {
|
|
8
|
+
heading: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Slide heading (max 50 chars, displays as h2)",
|
|
11
|
+
required: false,
|
|
12
|
+
maxLength: 50,
|
|
13
|
+
},
|
|
14
|
+
content: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Content text (max 300 chars recommended, markdown supported)",
|
|
17
|
+
required: false,
|
|
18
|
+
maxLength: 500,
|
|
19
|
+
},
|
|
20
|
+
imagePath: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "Image file path (local paths supported, e.g., ./attachments/image.png)",
|
|
23
|
+
required: true,
|
|
24
|
+
},
|
|
25
|
+
imagePosition: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Image position: 'right' or 'left' (default: 'right')",
|
|
28
|
+
required: false,
|
|
29
|
+
},
|
|
30
|
+
imageSize: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "Image size: 'cover' or 'contain' (default: 'contain')",
|
|
33
|
+
required: false,
|
|
34
|
+
},
|
|
35
|
+
citations: {
|
|
36
|
+
type: "array",
|
|
37
|
+
description: "Citations/references (array of strings)",
|
|
38
|
+
required: false,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
template: (params) => {
|
|
42
|
+
let slide = "";
|
|
43
|
+
if (params.heading) {
|
|
44
|
+
slide += `## ${params.heading}\n\n`;
|
|
45
|
+
}
|
|
46
|
+
if (params.content) {
|
|
47
|
+
slide += `${params.content}\n\n`;
|
|
48
|
+
}
|
|
49
|
+
// Build background image directive
|
|
50
|
+
const position = params.imagePosition || 'right';
|
|
51
|
+
const size = params.imageSize || 'contain';
|
|
52
|
+
slide += ``;
|
|
53
|
+
// Add citations
|
|
54
|
+
if (params.citations && params.citations.length > 0) {
|
|
55
|
+
slide += '\n\n';
|
|
56
|
+
params.citations.forEach((citation) => {
|
|
57
|
+
slide += `> ${citation}\n`;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return slide;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image layout - centered image display
|
|
3
|
+
*/
|
|
4
|
+
export const imageLayout = {
|
|
5
|
+
name: "image-center",
|
|
6
|
+
description: "Slide with centered image (fixed h:350)",
|
|
7
|
+
params: {
|
|
8
|
+
heading: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Slide heading (max 40 chars, ~22 chars for Japanese)",
|
|
11
|
+
required: true,
|
|
12
|
+
maxLength: 40,
|
|
13
|
+
},
|
|
14
|
+
imagePath: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Image file path (local paths supported, e.g., ./attachments/image.png)",
|
|
17
|
+
required: true,
|
|
18
|
+
},
|
|
19
|
+
description: {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "Image description below image (max 55 chars, ~33 chars for Japanese)",
|
|
22
|
+
required: false,
|
|
23
|
+
maxLength: 55,
|
|
24
|
+
},
|
|
25
|
+
citations: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Citation (max 50 chars, ~30 chars for Japanese, no line break)",
|
|
28
|
+
required: false,
|
|
29
|
+
maxLength: 50,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
template: (params) => {
|
|
33
|
+
let slide = "";
|
|
34
|
+
if (params.heading) {
|
|
35
|
+
slide += `## ${params.heading}\n\n`;
|
|
36
|
+
}
|
|
37
|
+
// Fixed image directive: center h:350
|
|
38
|
+
slide += ``;
|
|
39
|
+
// Image description (optional)
|
|
40
|
+
if (params.description) {
|
|
41
|
+
slide += `\n\n${params.description}`;
|
|
42
|
+
}
|
|
43
|
+
// Citation (single, no line break)
|
|
44
|
+
if (params.citations) {
|
|
45
|
+
slide += `\n\n> ${params.citations}`;
|
|
46
|
+
}
|
|
47
|
+
return slide;
|
|
48
|
+
},
|
|
49
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image-right layout - content list with background image on right
|
|
3
|
+
*/
|
|
4
|
+
export const imageRightLayout = {
|
|
5
|
+
name: "image-right",
|
|
6
|
+
description: "Slide with image on right and content list (allows more explanation than image-center)",
|
|
7
|
+
params: {
|
|
8
|
+
heading: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Slide heading (max 17 chars, ~10 chars for Japanese)",
|
|
11
|
+
required: true,
|
|
12
|
+
maxLength: 17,
|
|
13
|
+
},
|
|
14
|
+
list: {
|
|
15
|
+
type: "array",
|
|
16
|
+
description: "List items (max 8 items, each max 23 chars, ~14 chars for Japanese)",
|
|
17
|
+
required: true,
|
|
18
|
+
maxItems: 8,
|
|
19
|
+
maxLength: 23,
|
|
20
|
+
},
|
|
21
|
+
imagePath: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "Image file path (local paths supported, e.g., ./attachments/image.png)",
|
|
24
|
+
required: true,
|
|
25
|
+
},
|
|
26
|
+
citations: {
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "Citation (max 50 chars, ~30 chars for Japanese, no line break)",
|
|
29
|
+
required: false,
|
|
30
|
+
maxLength: 50,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
template: (params) => {
|
|
34
|
+
let slide = "";
|
|
35
|
+
if (params.heading) {
|
|
36
|
+
slide += `## ${params.heading}\n\n`;
|
|
37
|
+
}
|
|
38
|
+
// List items
|
|
39
|
+
params.list.forEach((item) => {
|
|
40
|
+
slide += `- ${item}\n`;
|
|
41
|
+
});
|
|
42
|
+
// Fixed background image: bg right:50% contain
|
|
43
|
+
slide += `\n`;
|
|
44
|
+
// Citation (single, no line break)
|
|
45
|
+
if (params.citations) {
|
|
46
|
+
slide += `\n\n> ${params.citations}`;
|
|
47
|
+
}
|
|
48
|
+
return slide;
|
|
49
|
+
},
|
|
50
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image layout - centered image display
|
|
3
|
+
*/
|
|
4
|
+
export const imageLayout = {
|
|
5
|
+
name: "image",
|
|
6
|
+
description: "Slide with centered image",
|
|
7
|
+
params: {
|
|
8
|
+
heading: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Slide heading (max 50 chars, displays as h2)",
|
|
11
|
+
required: false,
|
|
12
|
+
maxLength: 50,
|
|
13
|
+
},
|
|
14
|
+
imagePath: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Image file path (local paths supported, e.g., ./attachments/image.png)",
|
|
17
|
+
required: true,
|
|
18
|
+
},
|
|
19
|
+
height: {
|
|
20
|
+
type: "number",
|
|
21
|
+
description: "Image height in pixels (e.g., 330)",
|
|
22
|
+
required: false,
|
|
23
|
+
},
|
|
24
|
+
width: {
|
|
25
|
+
type: "string",
|
|
26
|
+
description: "Image width (e.g., '80%', '500px')",
|
|
27
|
+
required: false,
|
|
28
|
+
},
|
|
29
|
+
citations: {
|
|
30
|
+
type: "array",
|
|
31
|
+
description: "Citations/references (array of strings)",
|
|
32
|
+
required: false,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
template: (params) => {
|
|
36
|
+
let slide = "";
|
|
37
|
+
if (params.heading) {
|
|
38
|
+
slide += `## ${params.heading}\n\n`;
|
|
39
|
+
}
|
|
40
|
+
// Build image directive
|
|
41
|
+
let imageDirective = "`;
|
|
49
|
+
slide += imageDirective;
|
|
50
|
+
// Add citations
|
|
51
|
+
if (params.citations && params.citations.length > 0) {
|
|
52
|
+
slide += '\n\n';
|
|
53
|
+
params.citations.forEach((citation) => {
|
|
54
|
+
slide += `> ${citation}\n`;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return slide;
|
|
58
|
+
},
|
|
59
|
+
};
|