runline 0.11.2 → 0.11.4
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/dist/plugin/loader.js +5 -0
- package/dist/plugins/googleDocs/src/documents.js +91 -0
- package/dist/plugins/googleDocs/src/formatting.js +126 -0
- package/dist/plugins/googleDocs/src/images.js +66 -0
- package/dist/plugins/googleDocs/src/index.js +45 -1008
- package/dist/plugins/googleDocs/src/shared.js +110 -0
- package/dist/plugins/googleDocs/src/structure.js +392 -0
- package/dist/plugins/googleDocs/src/tables.js +390 -0
- package/dist/plugins/googleDocs/src/tabs.js +77 -0
- package/dist/plugins/googleDocs/src/text.js +313 -0
- package/dist/plugins/linear/src/attachments.js +36 -12
- package/dist/plugins/linear/src/comments.js +20 -8
- package/dist/plugins/linear/src/cycles.js +22 -8
- package/dist/plugins/linear/src/initiatives.js +59 -19
- package/dist/plugins/linear/src/issues.js +123 -41
- package/dist/plugins/linear/src/labels.js +31 -11
- package/dist/plugins/linear/src/organization.js +1 -1
- package/dist/plugins/linear/src/projects.js +171 -57
- package/dist/plugins/linear/src/shared.js +16 -5
- package/dist/plugins/linear/src/states.js +14 -6
- package/dist/plugins/linear/src/teams.js +35 -12
- package/dist/plugins/linear/src/users.js +7 -3
- package/dist/plugins/linear/src/views.js +29 -10
- package/dist/plugins/linear/src/webhooks.js +39 -13
- package/dist/plugins/salesforce/src/index.js +33 -219
- package/dist/plugins/salesforce/src/metadata.js +50 -0
- package/dist/plugins/salesforce/src/query.js +52 -0
- package/dist/plugins/salesforce/src/queryResult.js +4 -0
- package/dist/plugins/salesforce/src/shared.js +122 -0
- package/dist/plugins/salesforce/src/sobjects.js +152 -0
- package/package.json +1 -1
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { googleAccessToken } from "../../_shared/googleAuth.js";
|
|
2
|
+
export const SCOPES = [
|
|
3
|
+
"https://www.googleapis.com/auth/documents",
|
|
4
|
+
"https://www.googleapis.com/auth/drive.file",
|
|
5
|
+
];
|
|
6
|
+
export const DOCS_BASE = "https://docs.googleapis.com/v1";
|
|
7
|
+
export const DRIVE_BASE = "https://www.googleapis.com/drive/v3";
|
|
8
|
+
export async function accessToken(ctx) {
|
|
9
|
+
return googleAccessToken(ctx, "googleDocs", SCOPES);
|
|
10
|
+
}
|
|
11
|
+
export async function docsRequest(ctx, method, path, body, qs, baseOverride) {
|
|
12
|
+
const token = await accessToken(ctx);
|
|
13
|
+
const url = new URL(`${baseOverride ?? DOCS_BASE}${path}`);
|
|
14
|
+
if (qs) {
|
|
15
|
+
for (const [k, v] of Object.entries(qs)) {
|
|
16
|
+
if (v === undefined || v === null)
|
|
17
|
+
continue;
|
|
18
|
+
url.searchParams.set(k, String(v));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const init = {
|
|
22
|
+
method,
|
|
23
|
+
headers: { Authorization: `Bearer ${token}`, Accept: "application/json" },
|
|
24
|
+
};
|
|
25
|
+
if (body && Object.keys(body).length > 0) {
|
|
26
|
+
init.headers["Content-Type"] =
|
|
27
|
+
"application/json";
|
|
28
|
+
init.body = JSON.stringify(body);
|
|
29
|
+
}
|
|
30
|
+
const res = await fetch(url.toString(), init);
|
|
31
|
+
if (res.status === 204)
|
|
32
|
+
return { success: true };
|
|
33
|
+
const text = await res.text();
|
|
34
|
+
if (!res.ok) {
|
|
35
|
+
throw new Error(`googleDocs: ${method} ${path} → ${res.status} ${text}`);
|
|
36
|
+
}
|
|
37
|
+
return text ? JSON.parse(text) : { success: true };
|
|
38
|
+
}
|
|
39
|
+
const DOC_URL_REGEX = /https:\/\/docs\.google\.com\/document\/d\/([a-zA-Z0-9-_]+)/;
|
|
40
|
+
export function extractDocumentId(input) {
|
|
41
|
+
if (!input)
|
|
42
|
+
throw new Error("googleDocs: documentId or URL is required");
|
|
43
|
+
const m = input.match(DOC_URL_REGEX);
|
|
44
|
+
return m ? m[1] : input;
|
|
45
|
+
}
|
|
46
|
+
export function buildLocation(kind, segmentId, index, tabId) {
|
|
47
|
+
const seg = segmentId && segmentId !== "body" ? segmentId : "";
|
|
48
|
+
if (kind === "endOfSegmentLocation") {
|
|
49
|
+
return { endOfSegmentLocation: compact({ segmentId: seg, tabId }) };
|
|
50
|
+
}
|
|
51
|
+
if (index === undefined || index === null) {
|
|
52
|
+
throw new Error("googleDocs: `index` is required when location kind is 'location'");
|
|
53
|
+
}
|
|
54
|
+
return { location: location(index, segmentId, tabId) };
|
|
55
|
+
}
|
|
56
|
+
export function location(index, segmentId, tabId) {
|
|
57
|
+
const seg = segmentId && segmentId !== "body" ? segmentId : "";
|
|
58
|
+
return compact({ segmentId: seg, index, tabId });
|
|
59
|
+
}
|
|
60
|
+
export function compact(obj) {
|
|
61
|
+
for (const key of Object.keys(obj)) {
|
|
62
|
+
if (obj[key] === undefined || obj[key] === null)
|
|
63
|
+
delete obj[key];
|
|
64
|
+
}
|
|
65
|
+
return obj;
|
|
66
|
+
}
|
|
67
|
+
export async function runBatchUpdate(ctx, documentId, requestOrRequests, writeControl) {
|
|
68
|
+
const requests = Array.isArray(requestOrRequests)
|
|
69
|
+
? requestOrRequests
|
|
70
|
+
: [requestOrRequests];
|
|
71
|
+
const body = { requests };
|
|
72
|
+
if (writeControl)
|
|
73
|
+
body.writeControl = writeControl;
|
|
74
|
+
const res = (await docsRequest(ctx, "POST", `/documents/${documentId}:batchUpdate`, body));
|
|
75
|
+
if (requests.length !== 1)
|
|
76
|
+
return { documentId, replies: res.replies ?? [] };
|
|
77
|
+
const reply = res.replies?.[0] ?? {};
|
|
78
|
+
const key = Object.keys(reply)[0];
|
|
79
|
+
return { documentId, ...(key ? { [key]: reply[key] } : {}) };
|
|
80
|
+
}
|
|
81
|
+
export function flattenBodyText(body) {
|
|
82
|
+
const parts = [];
|
|
83
|
+
const content = body?.content ?? [];
|
|
84
|
+
for (const item of content) {
|
|
85
|
+
const para = item.paragraph;
|
|
86
|
+
if (!para?.elements)
|
|
87
|
+
continue;
|
|
88
|
+
for (const el of para.elements) {
|
|
89
|
+
const tr = el.textRun;
|
|
90
|
+
if (tr?.content)
|
|
91
|
+
parts.push(tr.content);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return parts.join("");
|
|
95
|
+
}
|
|
96
|
+
export function hexToRgbF(hex) {
|
|
97
|
+
const h = hex.replace(/^#/, "");
|
|
98
|
+
const full = h.length === 3
|
|
99
|
+
? h
|
|
100
|
+
.split("")
|
|
101
|
+
.map((c) => c + c)
|
|
102
|
+
.join("")
|
|
103
|
+
: h;
|
|
104
|
+
const n = parseInt(full, 16);
|
|
105
|
+
return {
|
|
106
|
+
red: ((n >> 16) & 0xff) / 255,
|
|
107
|
+
green: ((n >> 8) & 0xff) / 255,
|
|
108
|
+
blue: (n & 0xff) / 255,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { buildLocation, compact, extractDocumentId, location, runBatchUpdate, } from "./shared.js";
|
|
2
|
+
function range(p) {
|
|
3
|
+
return compact({
|
|
4
|
+
segmentId: p.segmentId && p.segmentId !== "body" ? p.segmentId : "",
|
|
5
|
+
startIndex: p.startIndex,
|
|
6
|
+
endIndex: p.endIndex,
|
|
7
|
+
tabId: p.tabId,
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
function point(value) {
|
|
11
|
+
return { magnitude: value, unit: "PT" };
|
|
12
|
+
}
|
|
13
|
+
export function registerStructureActions(rl) {
|
|
14
|
+
rl.registerAction("document.insertPageBreak", {
|
|
15
|
+
description: "Insert a page break at an index or at the end of a segment.",
|
|
16
|
+
inputSchema: {
|
|
17
|
+
document: { type: "string", required: true },
|
|
18
|
+
locationKind: { type: "string", required: false },
|
|
19
|
+
index: { type: "number", required: false },
|
|
20
|
+
segmentId: { type: "string", required: false },
|
|
21
|
+
tabId: { type: "string", required: false },
|
|
22
|
+
},
|
|
23
|
+
async execute(input, ctx) {
|
|
24
|
+
const p = (input ?? {});
|
|
25
|
+
const documentId = extractDocumentId(p.document);
|
|
26
|
+
const kind = p.locationKind ?? "location";
|
|
27
|
+
return runBatchUpdate(ctx, documentId, {
|
|
28
|
+
insertPageBreak: buildLocation(kind, p.segmentId, p.index, p.tabId),
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
rl.registerAction("document.createNamedRange", {
|
|
33
|
+
description: "Create a named range over a span of text (useful for later programmatic edits).",
|
|
34
|
+
inputSchema: {
|
|
35
|
+
document: { type: "string", required: true },
|
|
36
|
+
name: { type: "string", required: true },
|
|
37
|
+
startIndex: { type: "number", required: true },
|
|
38
|
+
endIndex: { type: "number", required: true },
|
|
39
|
+
segmentId: { type: "string", required: false },
|
|
40
|
+
tabId: { type: "string", required: false },
|
|
41
|
+
},
|
|
42
|
+
async execute(input, ctx) {
|
|
43
|
+
const p = (input ?? {});
|
|
44
|
+
const documentId = extractDocumentId(p.document);
|
|
45
|
+
return runBatchUpdate(ctx, documentId, {
|
|
46
|
+
createNamedRange: {
|
|
47
|
+
name: p.name,
|
|
48
|
+
range: range(p),
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
rl.registerAction("document.deleteNamedRange", {
|
|
54
|
+
description: "Delete named range(s). Pass one of `namedRangeId` or `name`; the latter deletes every range sharing that name.",
|
|
55
|
+
inputSchema: {
|
|
56
|
+
document: { type: "string", required: true },
|
|
57
|
+
namedRangeId: { type: "string", required: false },
|
|
58
|
+
name: { type: "string", required: false },
|
|
59
|
+
tabIds: {
|
|
60
|
+
type: "array",
|
|
61
|
+
required: false,
|
|
62
|
+
description: "Optional tab IDs for tabsCriteria.",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
async execute(input, ctx) {
|
|
66
|
+
const p = (input ?? {});
|
|
67
|
+
const documentId = extractDocumentId(p.document);
|
|
68
|
+
if (!p.namedRangeId && !p.name) {
|
|
69
|
+
throw new Error("googleDocs: provide namedRangeId or name");
|
|
70
|
+
}
|
|
71
|
+
const req = p.namedRangeId
|
|
72
|
+
? { namedRangeId: p.namedRangeId }
|
|
73
|
+
: { name: p.name };
|
|
74
|
+
if (Array.isArray(p.tabIds))
|
|
75
|
+
req.tabsCriteria = { tabIds: p.tabIds };
|
|
76
|
+
return runBatchUpdate(ctx, documentId, { deleteNamedRange: req });
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
rl.registerAction("document.createHeader", {
|
|
80
|
+
description: "Create a DEFAULT header attached to a SectionBreak.",
|
|
81
|
+
inputSchema: {
|
|
82
|
+
document: { type: "string", required: true },
|
|
83
|
+
locationKind: { type: "string", required: false },
|
|
84
|
+
index: { type: "number", required: false },
|
|
85
|
+
segmentId: { type: "string", required: false },
|
|
86
|
+
tabId: { type: "string", required: false },
|
|
87
|
+
},
|
|
88
|
+
async execute(input, ctx) {
|
|
89
|
+
const p = (input ?? {});
|
|
90
|
+
const documentId = extractDocumentId(p.document);
|
|
91
|
+
const kind = p.locationKind ?? "location";
|
|
92
|
+
const seg = p.segmentId && p.segmentId !== "body" ? p.segmentId : "";
|
|
93
|
+
const sectionBreakLocation = compact({
|
|
94
|
+
segmentId: seg,
|
|
95
|
+
tabId: p.tabId,
|
|
96
|
+
});
|
|
97
|
+
if (kind === "location") {
|
|
98
|
+
if (p.index === undefined) {
|
|
99
|
+
throw new Error("googleDocs: `index` is required when locationKind=location");
|
|
100
|
+
}
|
|
101
|
+
sectionBreakLocation.index = p.index;
|
|
102
|
+
}
|
|
103
|
+
return runBatchUpdate(ctx, documentId, {
|
|
104
|
+
createHeader: { type: "DEFAULT", sectionBreakLocation },
|
|
105
|
+
});
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
rl.registerAction("document.deleteHeader", {
|
|
109
|
+
description: "Delete a header by ID.",
|
|
110
|
+
inputSchema: {
|
|
111
|
+
document: { type: "string", required: true },
|
|
112
|
+
headerId: { type: "string", required: true },
|
|
113
|
+
},
|
|
114
|
+
async execute(input, ctx) {
|
|
115
|
+
const p = (input ?? {});
|
|
116
|
+
const documentId = extractDocumentId(p.document);
|
|
117
|
+
return runBatchUpdate(ctx, documentId, {
|
|
118
|
+
deleteHeader: compact({ headerId: p.headerId, tabId: p.tabId }),
|
|
119
|
+
});
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
rl.registerAction("document.createFooter", {
|
|
123
|
+
description: "Create a DEFAULT footer attached to a SectionBreak.",
|
|
124
|
+
inputSchema: {
|
|
125
|
+
document: { type: "string", required: true },
|
|
126
|
+
locationKind: { type: "string", required: false },
|
|
127
|
+
index: { type: "number", required: false },
|
|
128
|
+
segmentId: { type: "string", required: false },
|
|
129
|
+
tabId: { type: "string", required: false },
|
|
130
|
+
},
|
|
131
|
+
async execute(input, ctx) {
|
|
132
|
+
const p = (input ?? {});
|
|
133
|
+
const documentId = extractDocumentId(p.document);
|
|
134
|
+
const kind = p.locationKind ?? "location";
|
|
135
|
+
const seg = p.segmentId && p.segmentId !== "body" ? p.segmentId : "";
|
|
136
|
+
const sectionBreakLocation = compact({
|
|
137
|
+
segmentId: seg,
|
|
138
|
+
tabId: p.tabId,
|
|
139
|
+
});
|
|
140
|
+
if (kind === "location") {
|
|
141
|
+
if (p.index === undefined) {
|
|
142
|
+
throw new Error("googleDocs: `index` is required when locationKind=location");
|
|
143
|
+
}
|
|
144
|
+
sectionBreakLocation.index = p.index;
|
|
145
|
+
}
|
|
146
|
+
return runBatchUpdate(ctx, documentId, {
|
|
147
|
+
createFooter: { type: "DEFAULT", sectionBreakLocation },
|
|
148
|
+
});
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
rl.registerAction("document.deleteFooter", {
|
|
152
|
+
description: "Delete a footer by ID.",
|
|
153
|
+
inputSchema: {
|
|
154
|
+
document: { type: "string", required: true },
|
|
155
|
+
footerId: { type: "string", required: true },
|
|
156
|
+
},
|
|
157
|
+
async execute(input, ctx) {
|
|
158
|
+
const p = (input ?? {});
|
|
159
|
+
const documentId = extractDocumentId(p.document);
|
|
160
|
+
return runBatchUpdate(ctx, documentId, {
|
|
161
|
+
deleteFooter: compact({ footerId: p.footerId, tabId: p.tabId }),
|
|
162
|
+
});
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
rl.registerAction("document.deletePositionedObject", {
|
|
166
|
+
description: "Delete a positioned object (inline image, floating image, etc.) by its objectId.",
|
|
167
|
+
inputSchema: {
|
|
168
|
+
document: { type: "string", required: true },
|
|
169
|
+
objectId: { type: "string", required: true },
|
|
170
|
+
tabId: { type: "string", required: false },
|
|
171
|
+
},
|
|
172
|
+
async execute(input, ctx) {
|
|
173
|
+
const p = (input ?? {});
|
|
174
|
+
const documentId = extractDocumentId(p.document);
|
|
175
|
+
return runBatchUpdate(ctx, documentId, {
|
|
176
|
+
deletePositionedObject: compact({
|
|
177
|
+
objectId: p.objectId,
|
|
178
|
+
tabId: p.tabId,
|
|
179
|
+
}),
|
|
180
|
+
});
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
rl.registerAction("document.createFootnote", {
|
|
184
|
+
description: "Create a footnote reference at a location or at the end of the document body.",
|
|
185
|
+
inputSchema: {
|
|
186
|
+
document: { type: "string", required: true },
|
|
187
|
+
locationKind: {
|
|
188
|
+
type: "string",
|
|
189
|
+
required: false,
|
|
190
|
+
description: "location (default; requires index) | endOfSegmentLocation",
|
|
191
|
+
},
|
|
192
|
+
index: { type: "number", required: false },
|
|
193
|
+
segmentId: { type: "string", required: false },
|
|
194
|
+
tabId: { type: "string", required: false },
|
|
195
|
+
},
|
|
196
|
+
async execute(input, ctx) {
|
|
197
|
+
const p = (input ?? {});
|
|
198
|
+
const documentId = extractDocumentId(p.document);
|
|
199
|
+
const kind = p.locationKind ?? "location";
|
|
200
|
+
return runBatchUpdate(ctx, documentId, {
|
|
201
|
+
createFootnote: buildLocation(kind, p.segmentId, p.index, p.tabId),
|
|
202
|
+
});
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
rl.registerAction("document.replaceNamedRangeContent", {
|
|
206
|
+
description: "Replace the content of a named range by ID or name with text.",
|
|
207
|
+
inputSchema: {
|
|
208
|
+
document: { type: "string", required: true },
|
|
209
|
+
text: { type: "string", required: true },
|
|
210
|
+
namedRangeId: { type: "string", required: false },
|
|
211
|
+
namedRangeName: { type: "string", required: false },
|
|
212
|
+
tabIds: {
|
|
213
|
+
type: "array",
|
|
214
|
+
required: false,
|
|
215
|
+
description: "Optional tab IDs for tabsCriteria.",
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
async execute(input, ctx) {
|
|
219
|
+
const p = (input ?? {});
|
|
220
|
+
const documentId = extractDocumentId(p.document);
|
|
221
|
+
if (!p.namedRangeId && !p.namedRangeName) {
|
|
222
|
+
throw new Error("googleDocs: provide namedRangeId or namedRangeName");
|
|
223
|
+
}
|
|
224
|
+
return runBatchUpdate(ctx, documentId, {
|
|
225
|
+
replaceNamedRangeContent: compact({
|
|
226
|
+
text: p.text,
|
|
227
|
+
namedRangeId: p.namedRangeId,
|
|
228
|
+
namedRangeName: p.namedRangeName,
|
|
229
|
+
tabsCriteria: Array.isArray(p.tabIds)
|
|
230
|
+
? { tabIds: p.tabIds }
|
|
231
|
+
: undefined,
|
|
232
|
+
}),
|
|
233
|
+
});
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
rl.registerAction("document.updateSectionStyle", {
|
|
237
|
+
description: "Update section style over a range, such as margins or column properties.",
|
|
238
|
+
inputSchema: {
|
|
239
|
+
document: { type: "string", required: true },
|
|
240
|
+
startIndex: { type: "number", required: true },
|
|
241
|
+
endIndex: { type: "number", required: true },
|
|
242
|
+
marginTopPt: { type: "number", required: false },
|
|
243
|
+
marginBottomPt: { type: "number", required: false },
|
|
244
|
+
marginLeftPt: { type: "number", required: false },
|
|
245
|
+
marginRightPt: { type: "number", required: false },
|
|
246
|
+
columnSeparatorStyle: {
|
|
247
|
+
type: "string",
|
|
248
|
+
required: false,
|
|
249
|
+
description: "NONE | BETWEEN_EACH_COLUMN",
|
|
250
|
+
},
|
|
251
|
+
contentDirection: {
|
|
252
|
+
type: "string",
|
|
253
|
+
required: false,
|
|
254
|
+
description: "LEFT_TO_RIGHT | RIGHT_TO_LEFT",
|
|
255
|
+
},
|
|
256
|
+
fields: {
|
|
257
|
+
type: "string",
|
|
258
|
+
required: false,
|
|
259
|
+
description: "Field mask. Defaults to fields implied by supplied properties.",
|
|
260
|
+
},
|
|
261
|
+
segmentId: { type: "string", required: false },
|
|
262
|
+
tabId: { type: "string", required: false },
|
|
263
|
+
},
|
|
264
|
+
async execute(input, ctx) {
|
|
265
|
+
const p = (input ?? {});
|
|
266
|
+
const documentId = extractDocumentId(p.document);
|
|
267
|
+
const sectionStyle = {};
|
|
268
|
+
const fields = [];
|
|
269
|
+
if (p.marginTopPt !== undefined) {
|
|
270
|
+
sectionStyle.marginTop = point(p.marginTopPt);
|
|
271
|
+
fields.push("marginTop");
|
|
272
|
+
}
|
|
273
|
+
if (p.marginBottomPt !== undefined) {
|
|
274
|
+
sectionStyle.marginBottom = point(p.marginBottomPt);
|
|
275
|
+
fields.push("marginBottom");
|
|
276
|
+
}
|
|
277
|
+
if (p.marginLeftPt !== undefined) {
|
|
278
|
+
sectionStyle.marginLeft = point(p.marginLeftPt);
|
|
279
|
+
fields.push("marginLeft");
|
|
280
|
+
}
|
|
281
|
+
if (p.marginRightPt !== undefined) {
|
|
282
|
+
sectionStyle.marginRight = point(p.marginRightPt);
|
|
283
|
+
fields.push("marginRight");
|
|
284
|
+
}
|
|
285
|
+
if (p.columnSeparatorStyle) {
|
|
286
|
+
sectionStyle.columnSeparatorStyle = p.columnSeparatorStyle;
|
|
287
|
+
fields.push("columnSeparatorStyle");
|
|
288
|
+
}
|
|
289
|
+
if (p.contentDirection) {
|
|
290
|
+
sectionStyle.contentDirection = p.contentDirection;
|
|
291
|
+
fields.push("contentDirection");
|
|
292
|
+
}
|
|
293
|
+
const mask = p.fields ?? fields.join(",");
|
|
294
|
+
if (!mask)
|
|
295
|
+
throw new Error("googleDocs.document.updateSectionStyle: fields or section style property required");
|
|
296
|
+
return runBatchUpdate(ctx, documentId, {
|
|
297
|
+
updateSectionStyle: {
|
|
298
|
+
range: range(p),
|
|
299
|
+
sectionStyle,
|
|
300
|
+
fields: mask,
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
rl.registerAction("document.insertSectionBreak", {
|
|
306
|
+
description: "Insert a section break at the given location.",
|
|
307
|
+
inputSchema: {
|
|
308
|
+
document: { type: "string", required: true },
|
|
309
|
+
index: { type: "number", required: true },
|
|
310
|
+
sectionType: {
|
|
311
|
+
type: "string",
|
|
312
|
+
required: false,
|
|
313
|
+
description: "CONTINUOUS | NEXT_PAGE. Default CONTINUOUS.",
|
|
314
|
+
},
|
|
315
|
+
segmentId: { type: "string", required: false },
|
|
316
|
+
tabId: { type: "string", required: false },
|
|
317
|
+
},
|
|
318
|
+
async execute(input, ctx) {
|
|
319
|
+
const p = (input ?? {});
|
|
320
|
+
const documentId = extractDocumentId(p.document);
|
|
321
|
+
return runBatchUpdate(ctx, documentId, [
|
|
322
|
+
{
|
|
323
|
+
insertSectionBreak: {
|
|
324
|
+
location: location(p.index, p.segmentId, p.tabId),
|
|
325
|
+
sectionType: p.sectionType ?? "CONTINUOUS",
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
]);
|
|
329
|
+
},
|
|
330
|
+
});
|
|
331
|
+
rl.registerAction("document.updateDocumentStyle", {
|
|
332
|
+
description: "Update document-level style (page size, margins, page numbers, default direction).",
|
|
333
|
+
inputSchema: {
|
|
334
|
+
document: { type: "string", required: true },
|
|
335
|
+
pageMarginTopPt: { type: "number", required: false },
|
|
336
|
+
pageMarginBottomPt: { type: "number", required: false },
|
|
337
|
+
pageMarginLeftPt: { type: "number", required: false },
|
|
338
|
+
pageMarginRightPt: { type: "number", required: false },
|
|
339
|
+
pageSizeWidthPt: { type: "number", required: false },
|
|
340
|
+
pageSizeHeightPt: { type: "number", required: false },
|
|
341
|
+
useCustomHeaderFooterMargins: { type: "boolean", required: false },
|
|
342
|
+
tabId: { type: "string", required: false },
|
|
343
|
+
},
|
|
344
|
+
async execute(input, ctx) {
|
|
345
|
+
const p = (input ?? {});
|
|
346
|
+
const documentId = extractDocumentId(p.document);
|
|
347
|
+
const ds = {};
|
|
348
|
+
const fields = [];
|
|
349
|
+
const pt = (n) => ({ magnitude: n, unit: "PT" });
|
|
350
|
+
if (p.pageMarginTopPt !== undefined) {
|
|
351
|
+
ds.marginTop = pt(p.pageMarginTopPt);
|
|
352
|
+
fields.push("marginTop");
|
|
353
|
+
}
|
|
354
|
+
if (p.pageMarginBottomPt !== undefined) {
|
|
355
|
+
ds.marginBottom = pt(p.pageMarginBottomPt);
|
|
356
|
+
fields.push("marginBottom");
|
|
357
|
+
}
|
|
358
|
+
if (p.pageMarginLeftPt !== undefined) {
|
|
359
|
+
ds.marginLeft = pt(p.pageMarginLeftPt);
|
|
360
|
+
fields.push("marginLeft");
|
|
361
|
+
}
|
|
362
|
+
if (p.pageMarginRightPt !== undefined) {
|
|
363
|
+
ds.marginRight = pt(p.pageMarginRightPt);
|
|
364
|
+
fields.push("marginRight");
|
|
365
|
+
}
|
|
366
|
+
if (p.pageSizeWidthPt !== undefined || p.pageSizeHeightPt !== undefined) {
|
|
367
|
+
ds.pageSize = {};
|
|
368
|
+
if (p.pageSizeWidthPt !== undefined)
|
|
369
|
+
ds.pageSize.width = pt(p.pageSizeWidthPt);
|
|
370
|
+
if (p.pageSizeHeightPt !== undefined)
|
|
371
|
+
ds.pageSize.height = pt(p.pageSizeHeightPt);
|
|
372
|
+
fields.push("pageSize");
|
|
373
|
+
}
|
|
374
|
+
if (p.useCustomHeaderFooterMargins !== undefined) {
|
|
375
|
+
ds.useCustomHeaderFooterMargins = p.useCustomHeaderFooterMargins;
|
|
376
|
+
fields.push("useCustomHeaderFooterMargins");
|
|
377
|
+
}
|
|
378
|
+
if (fields.length === 0) {
|
|
379
|
+
throw new Error("googleDocs.document.updateDocumentStyle: pass at least one property");
|
|
380
|
+
}
|
|
381
|
+
return runBatchUpdate(ctx, documentId, [
|
|
382
|
+
{
|
|
383
|
+
updateDocumentStyle: compact({
|
|
384
|
+
documentStyle: ds,
|
|
385
|
+
fields: fields.join(","),
|
|
386
|
+
tabId: p.tabId,
|
|
387
|
+
}),
|
|
388
|
+
},
|
|
389
|
+
]);
|
|
390
|
+
},
|
|
391
|
+
});
|
|
392
|
+
}
|