gogcli-mcp-slides 2.0.4 → 2.0.6
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/.claude-plugin/marketplace.json +4 -4
- package/.claude-plugin/plugin.json +2 -2
- package/dist/index.js +58 -57
- package/manifest.json +1 -1
- package/package.json +1 -1
- package/server.json +3 -3
- package/src/tools/slides-extra.ts +110 -2
- package/tests/tools/slides-extra.test.ts +216 -6
|
@@ -6,16 +6,16 @@
|
|
|
6
6
|
"email": "chris.c.hall@gmail.com"
|
|
7
7
|
},
|
|
8
8
|
"metadata": {
|
|
9
|
-
"description": "Extended Google Slides for Claude via gogcli
|
|
10
|
-
"version": "2.0.
|
|
9
|
+
"description": "Extended Google Slides for Claude via gogcli \u2014 auth + full Slides support (create, edit, export, templates, markdown)",
|
|
10
|
+
"version": "2.0.3"
|
|
11
11
|
},
|
|
12
12
|
"plugins": [
|
|
13
13
|
{
|
|
14
14
|
"name": "gogcli-mcp-slides",
|
|
15
15
|
"displayName": "gogcli (Slides)",
|
|
16
16
|
"source": "./",
|
|
17
|
-
"description": "Extended Google Slides for Claude via gogcli
|
|
18
|
-
"version": "2.0.
|
|
17
|
+
"description": "Extended Google Slides for Claude via gogcli \u2014 auth + full Slides support (create, edit, export, templates, markdown)",
|
|
18
|
+
"version": "2.0.3",
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "Chris Hall"
|
|
21
21
|
},
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gogcli-mcp-slides",
|
|
3
3
|
"displayName": "gogcli (Slides)",
|
|
4
|
-
"version": "2.0.
|
|
5
|
-
"description": "Extended Google Slides for Claude via gogcli
|
|
4
|
+
"version": "2.0.3",
|
|
5
|
+
"description": "Extended Google Slides for Claude via gogcli \u2014 auth + full Slides support (create, edit, export, templates, markdown)",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Chris Hall",
|
|
8
8
|
"email": "chris.c.hall@gmail.com"
|
package/dist/index.js
CHANGED
|
@@ -31068,6 +31068,64 @@ function registerSlidesTools(server2) {
|
|
|
31068
31068
|
if (template) args.push(`--template=${template}`);
|
|
31069
31069
|
return runOrDiagnose(args, { account });
|
|
31070
31070
|
});
|
|
31071
|
+
server2.registerTool("gog_slides_copy", {
|
|
31072
|
+
description: "Copy a Google Slides presentation to a new presentation with the given title.",
|
|
31073
|
+
inputSchema: {
|
|
31074
|
+
presentationId: external_exports.string().describe("Presentation ID to copy"),
|
|
31075
|
+
title: external_exports.string().describe("Title for the new copy"),
|
|
31076
|
+
parent: external_exports.string().optional().describe("Destination folder ID"),
|
|
31077
|
+
account: accountParam
|
|
31078
|
+
}
|
|
31079
|
+
}, async ({ presentationId, title, parent, account }) => {
|
|
31080
|
+
const args = ["slides", "copy", presentationId, title];
|
|
31081
|
+
if (parent) args.push(`--parent=${parent}`);
|
|
31082
|
+
return runOrDiagnose(args, { account });
|
|
31083
|
+
});
|
|
31084
|
+
server2.registerTool("gog_slides_list_slides", {
|
|
31085
|
+
description: "List slides in a Google Slides presentation.",
|
|
31086
|
+
annotations: { readOnlyHint: true },
|
|
31087
|
+
inputSchema: {
|
|
31088
|
+
presentationId: external_exports.string().describe("Presentation ID"),
|
|
31089
|
+
account: accountParam
|
|
31090
|
+
}
|
|
31091
|
+
}, async ({ presentationId, account }) => {
|
|
31092
|
+
return runOrDiagnose(["slides", "list-slides", presentationId], { account });
|
|
31093
|
+
});
|
|
31094
|
+
server2.registerTool("gog_slides_read_slide", {
|
|
31095
|
+
description: "Read the content of a slide (text, shapes, speaker notes).",
|
|
31096
|
+
annotations: { readOnlyHint: true },
|
|
31097
|
+
inputSchema: {
|
|
31098
|
+
presentationId: external_exports.string().describe("Presentation ID"),
|
|
31099
|
+
slideId: external_exports.string().describe("Slide ID to read"),
|
|
31100
|
+
account: accountParam
|
|
31101
|
+
}
|
|
31102
|
+
}, async ({ presentationId, slideId, account }) => {
|
|
31103
|
+
return runOrDiagnose(["slides", "read-slide", presentationId, slideId], { account });
|
|
31104
|
+
});
|
|
31105
|
+
server2.registerTool("gog_slides_run", {
|
|
31106
|
+
description: "Run any gog slides subcommand not covered by the other tools. Run `gog slides --help` for the full list of subcommands, or `gog slides <subcommand> --help` for flags on a specific subcommand.",
|
|
31107
|
+
annotations: { destructiveHint: true },
|
|
31108
|
+
inputSchema: {
|
|
31109
|
+
subcommand: external_exports.string().describe("The gog slides subcommand to run"),
|
|
31110
|
+
args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
|
|
31111
|
+
account: accountParam
|
|
31112
|
+
}
|
|
31113
|
+
}, async ({ subcommand, args, account }) => {
|
|
31114
|
+
return runOrDiagnose(["slides", subcommand, ...args], { account });
|
|
31115
|
+
});
|
|
31116
|
+
}
|
|
31117
|
+
|
|
31118
|
+
// ../gogcli-mcp/src/server.ts
|
|
31119
|
+
var VERSION = true ? "2.0.5" : "0.0.0";
|
|
31120
|
+
function createServer(options) {
|
|
31121
|
+
return new McpServer({
|
|
31122
|
+
name: options?.name ?? "gogcli",
|
|
31123
|
+
version: options?.version ?? VERSION
|
|
31124
|
+
});
|
|
31125
|
+
}
|
|
31126
|
+
|
|
31127
|
+
// src/tools/slides-extra.ts
|
|
31128
|
+
function registerExtraSlidesTools(server2) {
|
|
31071
31129
|
server2.registerTool("gog_slides_create_from_markdown", {
|
|
31072
31130
|
description: "Create a new Google Slides presentation from markdown content (inline or from a file).",
|
|
31073
31131
|
inputSchema: {
|
|
@@ -31109,19 +31167,6 @@ function registerSlidesTools(server2) {
|
|
|
31109
31167
|
if (exact) args.push("--exact");
|
|
31110
31168
|
return runOrDiagnose(args, { account });
|
|
31111
31169
|
});
|
|
31112
|
-
server2.registerTool("gog_slides_copy", {
|
|
31113
|
-
description: "Copy a Google Slides presentation to a new presentation with the given title.",
|
|
31114
|
-
inputSchema: {
|
|
31115
|
-
presentationId: external_exports.string().describe("Presentation ID to copy"),
|
|
31116
|
-
title: external_exports.string().describe("Title for the new copy"),
|
|
31117
|
-
parent: external_exports.string().optional().describe("Destination folder ID"),
|
|
31118
|
-
account: accountParam
|
|
31119
|
-
}
|
|
31120
|
-
}, async ({ presentationId, title, parent, account }) => {
|
|
31121
|
-
const args = ["slides", "copy", presentationId, title];
|
|
31122
|
-
if (parent) args.push(`--parent=${parent}`);
|
|
31123
|
-
return runOrDiagnose(args, { account });
|
|
31124
|
-
});
|
|
31125
31170
|
server2.registerTool("gog_slides_add_slide", {
|
|
31126
31171
|
description: "Add a new slide to a presentation from a local image, with optional speaker notes.",
|
|
31127
31172
|
inputSchema: {
|
|
@@ -31139,16 +31184,6 @@ function registerSlidesTools(server2) {
|
|
|
31139
31184
|
if (before) args.push(`--before=${before}`);
|
|
31140
31185
|
return runOrDiagnose(args, { account });
|
|
31141
31186
|
});
|
|
31142
|
-
server2.registerTool("gog_slides_list_slides", {
|
|
31143
|
-
description: "List slides in a Google Slides presentation.",
|
|
31144
|
-
annotations: { readOnlyHint: true },
|
|
31145
|
-
inputSchema: {
|
|
31146
|
-
presentationId: external_exports.string().describe("Presentation ID"),
|
|
31147
|
-
account: accountParam
|
|
31148
|
-
}
|
|
31149
|
-
}, async ({ presentationId, account }) => {
|
|
31150
|
-
return runOrDiagnose(["slides", "list-slides", presentationId], { account });
|
|
31151
|
-
});
|
|
31152
31187
|
server2.registerTool("gog_slides_delete_slide", {
|
|
31153
31188
|
description: "Delete a slide from a Google Slides presentation.",
|
|
31154
31189
|
annotations: { destructiveHint: true },
|
|
@@ -31160,17 +31195,6 @@ function registerSlidesTools(server2) {
|
|
|
31160
31195
|
}, async ({ presentationId, slideId, account }) => {
|
|
31161
31196
|
return runOrDiagnose(["slides", "delete-slide", presentationId, slideId], { account });
|
|
31162
31197
|
});
|
|
31163
|
-
server2.registerTool("gog_slides_read_slide", {
|
|
31164
|
-
description: "Read the content of a slide (text, shapes, speaker notes).",
|
|
31165
|
-
annotations: { readOnlyHint: true },
|
|
31166
|
-
inputSchema: {
|
|
31167
|
-
presentationId: external_exports.string().describe("Presentation ID"),
|
|
31168
|
-
slideId: external_exports.string().describe("Slide ID to read"),
|
|
31169
|
-
account: accountParam
|
|
31170
|
-
}
|
|
31171
|
-
}, async ({ presentationId, slideId, account }) => {
|
|
31172
|
-
return runOrDiagnose(["slides", "read-slide", presentationId, slideId], { account });
|
|
31173
|
-
});
|
|
31174
31198
|
server2.registerTool("gog_slides_update_notes", {
|
|
31175
31199
|
description: "Update the speaker notes on a slide (inline text or from a file).",
|
|
31176
31200
|
annotations: { destructiveHint: true },
|
|
@@ -31204,29 +31228,6 @@ function registerSlidesTools(server2) {
|
|
|
31204
31228
|
if (notesFile) args.push(`--notes-file=${notesFile}`);
|
|
31205
31229
|
return runOrDiagnose(args, { account });
|
|
31206
31230
|
});
|
|
31207
|
-
server2.registerTool("gog_slides_run", {
|
|
31208
|
-
description: "Run any gog slides subcommand not covered by the other tools. Run `gog slides --help` for the full list of subcommands, or `gog slides <subcommand> --help` for flags on a specific subcommand.",
|
|
31209
|
-
inputSchema: {
|
|
31210
|
-
subcommand: external_exports.string().describe("The gog slides subcommand to run"),
|
|
31211
|
-
args: external_exports.array(external_exports.string()).describe("Additional positional args and flags"),
|
|
31212
|
-
account: accountParam
|
|
31213
|
-
}
|
|
31214
|
-
}, async ({ subcommand, args, account }) => {
|
|
31215
|
-
return runOrDiagnose(["slides", subcommand, ...args], { account });
|
|
31216
|
-
});
|
|
31217
|
-
}
|
|
31218
|
-
|
|
31219
|
-
// ../gogcli-mcp/src/server.ts
|
|
31220
|
-
var VERSION = true ? "2.0.4" : "0.0.0";
|
|
31221
|
-
function createServer(options) {
|
|
31222
|
-
return new McpServer({
|
|
31223
|
-
name: options?.name ?? "gogcli",
|
|
31224
|
-
version: options?.version ?? VERSION
|
|
31225
|
-
});
|
|
31226
|
-
}
|
|
31227
|
-
|
|
31228
|
-
// src/tools/slides-extra.ts
|
|
31229
|
-
function registerExtraSlidesTools(_server) {
|
|
31230
31231
|
}
|
|
31231
31232
|
|
|
31232
31233
|
// src/index.ts
|
package/manifest.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"manifest_version": "0.3",
|
|
4
4
|
"name": "gogcli-mcp-slides",
|
|
5
5
|
"display_name": "gogcli (Slides)",
|
|
6
|
-
"version": "2.0.
|
|
6
|
+
"version": "2.0.6",
|
|
7
7
|
"description": "Extended Google Slides for Claude via gogcli — auth + full Slides support (create, edit, export, templates, markdown)",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "Chris Hall",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gogcli-mcp-slides",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.6",
|
|
4
4
|
"mcpName": "io.github.chrischall/gogcli-mcp-slides",
|
|
5
5
|
"description": "Extended Google Slides MCP server via gogcli — auth + full Slides support",
|
|
6
6
|
"author": "Claude Code (AI) <https://www.anthropic.com/claude>",
|
package/server.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.chrischall/gogcli-mcp-slides",
|
|
4
|
-
"description": "Google Slides via gogcli for Claude
|
|
4
|
+
"description": "Google Slides via gogcli for Claude \u2014 deck and slide authoring",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/chrischall/gogcli-mcp",
|
|
7
7
|
"source": "github",
|
|
8
8
|
"subfolder": "packages/gogcli-mcp-slides"
|
|
9
9
|
},
|
|
10
|
-
"version": "2.0.
|
|
10
|
+
"version": "2.0.3",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "gogcli-mcp-slides",
|
|
15
|
-
"version": "2.0.
|
|
15
|
+
"version": "2.0.3",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
},
|
|
@@ -1,5 +1,113 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { accountParam, runOrDiagnose } from '../../../gogcli-mcp/src/lib.js';
|
|
2
4
|
|
|
3
|
-
export function registerExtraSlidesTools(
|
|
4
|
-
|
|
5
|
+
export function registerExtraSlidesTools(server: McpServer): void {
|
|
6
|
+
server.registerTool('gog_slides_create_from_markdown', {
|
|
7
|
+
description: 'Create a new Google Slides presentation from markdown content (inline or from a file).',
|
|
8
|
+
inputSchema: {
|
|
9
|
+
title: z.string().describe('Presentation title'),
|
|
10
|
+
content: z.string().optional().describe('Inline markdown content'),
|
|
11
|
+
contentFile: z.string().optional().describe('Path to a markdown file'),
|
|
12
|
+
parent: z.string().optional().describe('Destination folder ID'),
|
|
13
|
+
debug: z.boolean().optional().describe('Enable debug output'),
|
|
14
|
+
account: accountParam,
|
|
15
|
+
},
|
|
16
|
+
}, async ({ title, content, contentFile, parent, debug, account }) => {
|
|
17
|
+
const args = ['slides', 'create-from-markdown', title];
|
|
18
|
+
if (content) args.push(`--content=${content}`);
|
|
19
|
+
if (contentFile) args.push(`--content-file=${contentFile}`);
|
|
20
|
+
if (parent) args.push(`--parent=${parent}`);
|
|
21
|
+
if (debug) args.push('--debug');
|
|
22
|
+
return runOrDiagnose(args, { account });
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
server.registerTool('gog_slides_create_from_template', {
|
|
26
|
+
description: 'Create a new Google Slides presentation from a template, with optional placeholder replacements.',
|
|
27
|
+
inputSchema: {
|
|
28
|
+
templateId: z.string().describe('Template presentation ID'),
|
|
29
|
+
title: z.string().describe('New presentation title'),
|
|
30
|
+
replacements: z.record(z.string(), z.string()).optional().describe('Placeholder replacements as a key/value object (emitted as --replace=k=v for each entry)'),
|
|
31
|
+
replacementsFile: z.string().optional().describe('Path to a JSON file containing replacements'),
|
|
32
|
+
parent: z.string().optional().describe('Destination folder ID'),
|
|
33
|
+
exact: z.boolean().optional().describe('Require exact placeholder matches'),
|
|
34
|
+
account: accountParam,
|
|
35
|
+
},
|
|
36
|
+
}, async ({ templateId, title, replacements, replacementsFile, parent, exact, account }) => {
|
|
37
|
+
const args = ['slides', 'create-from-template', templateId, title];
|
|
38
|
+
if (replacements) {
|
|
39
|
+
for (const [k, v] of Object.entries(replacements)) {
|
|
40
|
+
args.push(`--replace=${k}=${v}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (replacementsFile) args.push(`--replacements=${replacementsFile}`);
|
|
44
|
+
if (parent) args.push(`--parent=${parent}`);
|
|
45
|
+
if (exact) args.push('--exact');
|
|
46
|
+
return runOrDiagnose(args, { account });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
server.registerTool('gog_slides_add_slide', {
|
|
50
|
+
description: 'Add a new slide to a presentation from a local image, with optional speaker notes.',
|
|
51
|
+
inputSchema: {
|
|
52
|
+
presentationId: z.string().describe('Presentation ID'),
|
|
53
|
+
image: z.string().describe('Path to the local image file'),
|
|
54
|
+
notes: z.string().optional().describe('Speaker notes text'),
|
|
55
|
+
notesFile: z.string().optional().describe('Path to a file containing speaker notes'),
|
|
56
|
+
before: z.string().optional().describe('Insert before this slide ID (default: append at end)'),
|
|
57
|
+
account: accountParam,
|
|
58
|
+
},
|
|
59
|
+
}, async ({ presentationId, image, notes, notesFile, before, account }) => {
|
|
60
|
+
const args = ['slides', 'add-slide', presentationId, image];
|
|
61
|
+
if (notes) args.push(`--notes=${notes}`);
|
|
62
|
+
if (notesFile) args.push(`--notes-file=${notesFile}`);
|
|
63
|
+
if (before) args.push(`--before=${before}`);
|
|
64
|
+
return runOrDiagnose(args, { account });
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
server.registerTool('gog_slides_delete_slide', {
|
|
68
|
+
description: 'Delete a slide from a Google Slides presentation.',
|
|
69
|
+
annotations: { destructiveHint: true },
|
|
70
|
+
inputSchema: {
|
|
71
|
+
presentationId: z.string().describe('Presentation ID'),
|
|
72
|
+
slideId: z.string().describe('Slide ID to delete'),
|
|
73
|
+
account: accountParam,
|
|
74
|
+
},
|
|
75
|
+
}, async ({ presentationId, slideId, account }) => {
|
|
76
|
+
return runOrDiagnose(['slides', 'delete-slide', presentationId, slideId], { account });
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
server.registerTool('gog_slides_update_notes', {
|
|
80
|
+
description: 'Update the speaker notes on a slide (inline text or from a file).',
|
|
81
|
+
annotations: { destructiveHint: true },
|
|
82
|
+
inputSchema: {
|
|
83
|
+
presentationId: z.string().describe('Presentation ID'),
|
|
84
|
+
slideId: z.string().describe('Slide ID'),
|
|
85
|
+
notes: z.string().optional().describe('New speaker notes text'),
|
|
86
|
+
notesFile: z.string().optional().describe('Path to a file containing new speaker notes'),
|
|
87
|
+
account: accountParam,
|
|
88
|
+
},
|
|
89
|
+
}, async ({ presentationId, slideId, notes, notesFile, account }) => {
|
|
90
|
+
const args = ['slides', 'update-notes', presentationId, slideId];
|
|
91
|
+
if (notes) args.push(`--notes=${notes}`);
|
|
92
|
+
if (notesFile) args.push(`--notes-file=${notesFile}`);
|
|
93
|
+
return runOrDiagnose(args, { account });
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
server.registerTool('gog_slides_replace_slide', {
|
|
97
|
+
description: 'Replace the image content of an existing slide, with optional speaker notes.',
|
|
98
|
+
annotations: { destructiveHint: true },
|
|
99
|
+
inputSchema: {
|
|
100
|
+
presentationId: z.string().describe('Presentation ID'),
|
|
101
|
+
slideId: z.string().describe('Slide ID to replace'),
|
|
102
|
+
image: z.string().describe('Path to the new local image file'),
|
|
103
|
+
notes: z.string().optional().describe('Speaker notes text'),
|
|
104
|
+
notesFile: z.string().optional().describe('Path to a file containing speaker notes'),
|
|
105
|
+
account: accountParam,
|
|
106
|
+
},
|
|
107
|
+
}, async ({ presentationId, slideId, image, notes, notesFile, account }) => {
|
|
108
|
+
const args = ['slides', 'replace-slide', presentationId, slideId, image];
|
|
109
|
+
if (notes) args.push(`--notes=${notes}`);
|
|
110
|
+
if (notesFile) args.push(`--notes-file=${notesFile}`);
|
|
111
|
+
return runOrDiagnose(args, { account });
|
|
112
|
+
});
|
|
5
113
|
}
|
|
@@ -1,10 +1,220 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
3
2
|
import { registerExtraSlidesTools } from '../../src/tools/slides-extra.js';
|
|
3
|
+
import * as lib from '../../../gogcli-mcp/src/lib.js';
|
|
4
|
+
import { setupExtrasHandlers, toText, type ToolHandler } from '../../../gogcli-mcp/tests/helpers/extras-harness.js';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
vi.mock('../../../gogcli-mcp/src/lib.js', async (importOriginal) => {
|
|
7
|
+
const actual = await importOriginal<typeof lib>();
|
|
8
|
+
return {
|
|
9
|
+
...actual,
|
|
10
|
+
runOrDiagnose: vi.fn(),
|
|
11
|
+
};
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
let handlers: Map<string, ToolHandler>;
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
vi.clearAllMocks();
|
|
18
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
19
|
+
handlers = setupExtrasHandlers(registerExtraSlidesTools);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('gog_slides_create_from_markdown', () => {
|
|
23
|
+
it('calls runOrDiagnose with title only', async () => {
|
|
24
|
+
await handlers.get('gog_slides_create_from_markdown')!({ title: 'Deck' });
|
|
25
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
26
|
+
['slides', 'create-from-markdown', 'Deck'],
|
|
27
|
+
{ account: undefined },
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('passes all optional flags', async () => {
|
|
32
|
+
await handlers.get('gog_slides_create_from_markdown')!({
|
|
33
|
+
title: 'Deck',
|
|
34
|
+
content: '# Slide 1',
|
|
35
|
+
contentFile: '/tmp/deck.md',
|
|
36
|
+
parent: 'folder1',
|
|
37
|
+
debug: true,
|
|
38
|
+
});
|
|
39
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
40
|
+
[
|
|
41
|
+
'slides', 'create-from-markdown', 'Deck',
|
|
42
|
+
'--content=# Slide 1',
|
|
43
|
+
'--content-file=/tmp/deck.md',
|
|
44
|
+
'--parent=folder1',
|
|
45
|
+
'--debug',
|
|
46
|
+
],
|
|
47
|
+
{ account: undefined },
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('omits --debug when false', async () => {
|
|
52
|
+
await handlers.get('gog_slides_create_from_markdown')!({ title: 'Deck', debug: false });
|
|
53
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
54
|
+
['slides', 'create-from-markdown', 'Deck'],
|
|
55
|
+
{ account: undefined },
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe('gog_slides_create_from_template', () => {
|
|
61
|
+
it('calls runOrDiagnose with templateId and title only', async () => {
|
|
62
|
+
await handlers.get('gog_slides_create_from_template')!({ templateId: 'tpl1', title: 'Deck' });
|
|
63
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
64
|
+
['slides', 'create-from-template', 'tpl1', 'Deck'],
|
|
65
|
+
{ account: undefined },
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('passes --replace for a single replacement entry', async () => {
|
|
70
|
+
await handlers.get('gog_slides_create_from_template')!({
|
|
71
|
+
templateId: 'tpl1',
|
|
72
|
+
title: 'Deck',
|
|
73
|
+
replacements: { name: 'Alice' },
|
|
74
|
+
});
|
|
75
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
76
|
+
['slides', 'create-from-template', 'tpl1', 'Deck', '--replace=name=Alice'],
|
|
77
|
+
{ account: undefined },
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('passes --replace for each entry in replacements', async () => {
|
|
82
|
+
await handlers.get('gog_slides_create_from_template')!({
|
|
83
|
+
templateId: 'tpl1',
|
|
84
|
+
title: 'Deck',
|
|
85
|
+
replacements: { name: 'Alice', company: 'Acme' },
|
|
86
|
+
});
|
|
87
|
+
const call = vi.mocked(lib.runOrDiagnose).mock.calls[0]!;
|
|
88
|
+
expect(call[0]).toEqual(expect.arrayContaining(['--replace=name=Alice', '--replace=company=Acme']));
|
|
89
|
+
expect(call[1]).toEqual({ account: undefined });
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('passes --replacements, --parent, and --exact', async () => {
|
|
93
|
+
await handlers.get('gog_slides_create_from_template')!({
|
|
94
|
+
templateId: 'tpl1',
|
|
95
|
+
title: 'Deck',
|
|
96
|
+
replacementsFile: '/tmp/r.json',
|
|
97
|
+
parent: 'folder1',
|
|
98
|
+
exact: true,
|
|
99
|
+
});
|
|
100
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
101
|
+
[
|
|
102
|
+
'slides', 'create-from-template', 'tpl1', 'Deck',
|
|
103
|
+
'--replacements=/tmp/r.json',
|
|
104
|
+
'--parent=folder1',
|
|
105
|
+
'--exact',
|
|
106
|
+
],
|
|
107
|
+
{ account: undefined },
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('omits --exact when false', async () => {
|
|
112
|
+
await handlers.get('gog_slides_create_from_template')!({
|
|
113
|
+
templateId: 'tpl1',
|
|
114
|
+
title: 'Deck',
|
|
115
|
+
exact: false,
|
|
116
|
+
});
|
|
117
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
118
|
+
['slides', 'create-from-template', 'tpl1', 'Deck'],
|
|
119
|
+
{ account: undefined },
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('gog_slides_add_slide', () => {
|
|
125
|
+
it('calls runOrDiagnose with presentationId and image', async () => {
|
|
126
|
+
await handlers.get('gog_slides_add_slide')!({ presentationId: 'p1', image: '/tmp/img.png' });
|
|
127
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
128
|
+
['slides', 'add-slide', 'p1', '/tmp/img.png'],
|
|
129
|
+
{ account: undefined },
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('passes --notes, --notes-file, and --before', async () => {
|
|
134
|
+
await handlers.get('gog_slides_add_slide')!({
|
|
135
|
+
presentationId: 'p1',
|
|
136
|
+
image: '/tmp/img.png',
|
|
137
|
+
notes: 'Speaker note',
|
|
138
|
+
notesFile: '/tmp/notes.txt',
|
|
139
|
+
before: 'slide5',
|
|
140
|
+
});
|
|
141
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
142
|
+
[
|
|
143
|
+
'slides', 'add-slide', 'p1', '/tmp/img.png',
|
|
144
|
+
'--notes=Speaker note',
|
|
145
|
+
'--notes-file=/tmp/notes.txt',
|
|
146
|
+
'--before=slide5',
|
|
147
|
+
],
|
|
148
|
+
{ account: undefined },
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe('gog_slides_delete_slide', () => {
|
|
154
|
+
it('calls runOrDiagnose with presentationId and slideId', async () => {
|
|
155
|
+
await handlers.get('gog_slides_delete_slide')!({ presentationId: 'p1', slideId: 's1' });
|
|
156
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
157
|
+
['slides', 'delete-slide', 'p1', 's1'],
|
|
158
|
+
{ account: undefined },
|
|
159
|
+
);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe('gog_slides_update_notes', () => {
|
|
164
|
+
it('calls runOrDiagnose with presentationId and slideId', async () => {
|
|
165
|
+
await handlers.get('gog_slides_update_notes')!({ presentationId: 'p1', slideId: 's1' });
|
|
166
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
167
|
+
['slides', 'update-notes', 'p1', 's1'],
|
|
168
|
+
{ account: undefined },
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('passes --notes and --notes-file when provided', async () => {
|
|
173
|
+
await handlers.get('gog_slides_update_notes')!({
|
|
174
|
+
presentationId: 'p1',
|
|
175
|
+
slideId: 's1',
|
|
176
|
+
notes: 'speak clearly',
|
|
177
|
+
notesFile: '/tmp/n.txt',
|
|
178
|
+
});
|
|
179
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
180
|
+
[
|
|
181
|
+
'slides', 'update-notes', 'p1', 's1',
|
|
182
|
+
'--notes=speak clearly',
|
|
183
|
+
'--notes-file=/tmp/n.txt',
|
|
184
|
+
],
|
|
185
|
+
{ account: undefined },
|
|
186
|
+
);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
describe('gog_slides_replace_slide', () => {
|
|
191
|
+
it('calls runOrDiagnose with presentationId, slideId, and image', async () => {
|
|
192
|
+
await handlers.get('gog_slides_replace_slide')!({
|
|
193
|
+
presentationId: 'p1',
|
|
194
|
+
slideId: 's1',
|
|
195
|
+
image: '/tmp/img.png',
|
|
196
|
+
});
|
|
197
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
198
|
+
['slides', 'replace-slide', 'p1', 's1', '/tmp/img.png'],
|
|
199
|
+
{ account: undefined },
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('passes --notes and --notes-file when provided', async () => {
|
|
204
|
+
await handlers.get('gog_slides_replace_slide')!({
|
|
205
|
+
presentationId: 'p1',
|
|
206
|
+
slideId: 's1',
|
|
207
|
+
image: '/tmp/img.png',
|
|
208
|
+
notes: 'updated',
|
|
209
|
+
notesFile: '/tmp/n.txt',
|
|
210
|
+
});
|
|
211
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
212
|
+
[
|
|
213
|
+
'slides', 'replace-slide', 'p1', 's1', '/tmp/img.png',
|
|
214
|
+
'--notes=updated',
|
|
215
|
+
'--notes-file=/tmp/n.txt',
|
|
216
|
+
],
|
|
217
|
+
{ account: undefined },
|
|
218
|
+
);
|
|
9
219
|
});
|
|
10
220
|
});
|