@pipedream/google_slides 0.5.0 → 0.6.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/actions/create-image/create-image.mjs +1 -1
- package/actions/create-page-element/create-page-element.mjs +1 -1
- package/actions/create-presentation/create-presentation.mjs +1 -1
- package/actions/create-slide/create-slide.mjs +1 -1
- package/actions/create-table/create-table.mjs +1 -1
- package/actions/delete-page-element/delete-page-element.mjs +1 -1
- package/actions/delete-slide/delete-slide.mjs +1 -1
- package/actions/delete-table-column/delete-table-column.mjs +1 -1
- package/actions/delete-table-row/delete-table-row.mjs +1 -1
- package/actions/find-presentation/find-presentation.mjs +1 -1
- package/actions/format-paragraph/format-paragraph.mjs +236 -0
- package/actions/format-shape/format-shape.mjs +193 -0
- package/actions/format-slide-background/format-slide-background.mjs +74 -0
- package/actions/format-table-cell/format-table-cell.mjs +162 -0
- package/actions/format-text/format-text.mjs +248 -0
- package/actions/get-presentation/get-presentation.mjs +1 -1
- package/actions/insert-table-columns/insert-table-columns.mjs +1 -1
- package/actions/insert-table-rows/insert-table-rows.mjs +1 -1
- package/actions/insert-text/insert-text.mjs +1 -1
- package/actions/insert-text-into-table/insert-text-into-table.mjs +1 -1
- package/actions/merge-data/merge-data.mjs +1 -1
- package/actions/position-element/position-element.mjs +219 -0
- package/actions/refresh-chart/refresh-chart.mjs +1 -1
- package/actions/replace-all-text/replace-all-text.mjs +1 -1
- package/common/constants.mjs +110 -0
- package/common/utils.mjs +115 -0
- package/google_slides.app.mjs +101 -0
- package/package.json +1 -1
- package/sources/new-presentation/new-presentation.mjs +1 -1
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { ConfigurationError } from "@pipedream/platform";
|
|
2
|
+
import googleSlides from "../../google_slides.app.mjs";
|
|
3
|
+
import utils from "../../common/utils.mjs";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
key: "google_slides-format-table-cell",
|
|
7
|
+
name: "Format Table Cell",
|
|
8
|
+
description: "Set the background fill or content alignment of table cells in a Google Slides presentation. Applies to a single cell, or to a block of cells via **Row Span** and **Column Span**. Omit the cell location to format the whole table. Use **Get Presentation** to find the table's object ID. [See the documentation](https://developers.google.com/workspace/slides/api/reference/rest/v1/presentations/request#UpdateTableCellPropertiesRequest)",
|
|
9
|
+
version: "0.0.1",
|
|
10
|
+
annotations: {
|
|
11
|
+
destructiveHint: false,
|
|
12
|
+
openWorldHint: true,
|
|
13
|
+
readOnlyHint: false,
|
|
14
|
+
},
|
|
15
|
+
type: "action",
|
|
16
|
+
props: {
|
|
17
|
+
googleSlides,
|
|
18
|
+
presentationId: {
|
|
19
|
+
propDefinition: [
|
|
20
|
+
googleSlides,
|
|
21
|
+
"staticPresentationId",
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
objectId: {
|
|
25
|
+
propDefinition: [
|
|
26
|
+
googleSlides,
|
|
27
|
+
"pageElementId",
|
|
28
|
+
],
|
|
29
|
+
description: "The object ID of the table to format. Use **Get Presentation** and read `slides[].pageElements[].objectId` for an element with a `table` field.",
|
|
30
|
+
},
|
|
31
|
+
rowIndex: {
|
|
32
|
+
propDefinition: [
|
|
33
|
+
googleSlides,
|
|
34
|
+
"rowIndex",
|
|
35
|
+
],
|
|
36
|
+
description: "0-based row of the first cell to format. Omit (with **Column Index**) to format every cell in the table.",
|
|
37
|
+
},
|
|
38
|
+
columnIndex: {
|
|
39
|
+
propDefinition: [
|
|
40
|
+
googleSlides,
|
|
41
|
+
"columnIndex",
|
|
42
|
+
],
|
|
43
|
+
description: "0-based column of the first cell to format. Omit (with **Row Index**) to format every cell in the table.",
|
|
44
|
+
},
|
|
45
|
+
rowSpan: {
|
|
46
|
+
type: "integer",
|
|
47
|
+
label: "Row Span",
|
|
48
|
+
description: "Number of rows to cover, starting at **Row Index**. Defaults to 1.",
|
|
49
|
+
min: 1,
|
|
50
|
+
optional: true,
|
|
51
|
+
},
|
|
52
|
+
columnSpan: {
|
|
53
|
+
type: "integer",
|
|
54
|
+
label: "Column Span",
|
|
55
|
+
description: "Number of columns to cover, starting at **Column Index**. Defaults to 1.",
|
|
56
|
+
min: 1,
|
|
57
|
+
optional: true,
|
|
58
|
+
},
|
|
59
|
+
backgroundColor: {
|
|
60
|
+
propDefinition: [
|
|
61
|
+
googleSlides,
|
|
62
|
+
"backgroundColor",
|
|
63
|
+
],
|
|
64
|
+
description: "Cell fill as a hex code (e.g. `#EEEEEE`) or a theme color name (e.g. `ACCENT1`).",
|
|
65
|
+
},
|
|
66
|
+
backgroundOpacity: {
|
|
67
|
+
propDefinition: [
|
|
68
|
+
googleSlides,
|
|
69
|
+
"backgroundOpacity",
|
|
70
|
+
],
|
|
71
|
+
description: "Opacity of the cell fill as a whole percentage, from `0` (fully transparent) to `100` (fully opaque). Can be set on its own to change an existing fill's opacity without restating its color.",
|
|
72
|
+
},
|
|
73
|
+
contentAlignment: {
|
|
74
|
+
propDefinition: [
|
|
75
|
+
googleSlides,
|
|
76
|
+
"contentAlignment",
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
async run({ $ }) {
|
|
81
|
+
const {
|
|
82
|
+
googleSlides,
|
|
83
|
+
presentationId,
|
|
84
|
+
objectId,
|
|
85
|
+
rowIndex,
|
|
86
|
+
columnIndex,
|
|
87
|
+
rowSpan,
|
|
88
|
+
columnSpan,
|
|
89
|
+
backgroundColor,
|
|
90
|
+
backgroundOpacity,
|
|
91
|
+
contentAlignment,
|
|
92
|
+
} = this;
|
|
93
|
+
|
|
94
|
+
const tableCellProperties = {};
|
|
95
|
+
const fields = [];
|
|
96
|
+
|
|
97
|
+
if (backgroundColor || backgroundOpacity != null) {
|
|
98
|
+
const solidFill = utils.toSolidFill(backgroundColor, backgroundOpacity);
|
|
99
|
+
if (!solidFill) {
|
|
100
|
+
throw new ConfigurationError(`Background Color "${backgroundColor}" is not a valid hex color or theme color name. Use a 6-digit hex code such as \`#EEEEEE\`, or a theme color such as \`ACCENT1\`.`);
|
|
101
|
+
}
|
|
102
|
+
tableCellProperties.tableCellBackgroundFill = {
|
|
103
|
+
solidFill,
|
|
104
|
+
};
|
|
105
|
+
// Colour and opacity are masked separately so either can be set alone.
|
|
106
|
+
if (solidFill.color) {
|
|
107
|
+
fields.push("tableCellBackgroundFill.solidFill.color");
|
|
108
|
+
}
|
|
109
|
+
if (solidFill.alpha != null) {
|
|
110
|
+
fields.push("tableCellBackgroundFill.solidFill.alpha");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (contentAlignment) {
|
|
114
|
+
tableCellProperties.contentAlignment = contentAlignment;
|
|
115
|
+
fields.push("contentAlignment");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (!fields.length) {
|
|
119
|
+
throw new ConfigurationError("Provide at least one formatting option (Background Color, Background Opacity, or Content Alignment).");
|
|
120
|
+
}
|
|
121
|
+
if ((rowIndex == null) !== (columnIndex == null)) {
|
|
122
|
+
throw new ConfigurationError("Row Index and Column Index must be provided together.");
|
|
123
|
+
}
|
|
124
|
+
if (rowIndex == null && (rowSpan != null || columnSpan != null)) {
|
|
125
|
+
throw new ConfigurationError("Row Span and Column Span need a starting cell. Provide Row Index and Column Index, or omit all four to format the whole table.");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Omitting tableRange entirely is what the API treats as "every cell".
|
|
129
|
+
const tableRange = rowIndex == null
|
|
130
|
+
? {}
|
|
131
|
+
: {
|
|
132
|
+
tableRange: {
|
|
133
|
+
location: {
|
|
134
|
+
rowIndex,
|
|
135
|
+
columnIndex,
|
|
136
|
+
},
|
|
137
|
+
rowSpan: rowSpan ?? 1,
|
|
138
|
+
columnSpan: columnSpan ?? 1,
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
await googleSlides.batchUpdate(googleSlides.getPresentationId(presentationId), [
|
|
143
|
+
{
|
|
144
|
+
updateTableCellProperties: {
|
|
145
|
+
objectId,
|
|
146
|
+
tableCellProperties,
|
|
147
|
+
fields: fields.join(","),
|
|
148
|
+
...tableRange,
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
]);
|
|
152
|
+
|
|
153
|
+
$.export("$summary", `Formatted table cells on ${objectId}`);
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
presentationId,
|
|
157
|
+
objectId,
|
|
158
|
+
fieldsUpdated: fields,
|
|
159
|
+
...tableRange,
|
|
160
|
+
};
|
|
161
|
+
},
|
|
162
|
+
};
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { ConfigurationError } from "@pipedream/platform";
|
|
2
|
+
import googleSlides from "../../google_slides.app.mjs";
|
|
3
|
+
import utils from "../../common/utils.mjs";
|
|
4
|
+
import {
|
|
5
|
+
BASELINE_OFFSETS, POINTS,
|
|
6
|
+
} from "../../common/constants.mjs";
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
key: "google_slides-format-text",
|
|
10
|
+
name: "Format Text",
|
|
11
|
+
description: "Apply character formatting (bold, italic, underline, strikethrough, font, size, color, link) to the text of a shape or table cell in a Google Slides presentation. Use **Get Presentation** to find the page element's object ID. [See the documentation](https://developers.google.com/workspace/slides/api/reference/rest/v1/presentations/request#UpdateTextStyleRequest)",
|
|
12
|
+
version: "0.0.1",
|
|
13
|
+
annotations: {
|
|
14
|
+
destructiveHint: false,
|
|
15
|
+
openWorldHint: true,
|
|
16
|
+
readOnlyHint: false,
|
|
17
|
+
},
|
|
18
|
+
type: "action",
|
|
19
|
+
props: {
|
|
20
|
+
googleSlides,
|
|
21
|
+
presentationId: {
|
|
22
|
+
propDefinition: [
|
|
23
|
+
googleSlides,
|
|
24
|
+
"staticPresentationId",
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
objectId: {
|
|
28
|
+
propDefinition: [
|
|
29
|
+
googleSlides,
|
|
30
|
+
"pageElementId",
|
|
31
|
+
],
|
|
32
|
+
description: "The object ID of the shape or table whose text should be styled. Use **Get Presentation** and read `slides[].pageElements[].objectId`.",
|
|
33
|
+
},
|
|
34
|
+
rowIndex: {
|
|
35
|
+
propDefinition: [
|
|
36
|
+
googleSlides,
|
|
37
|
+
"rowIndex",
|
|
38
|
+
],
|
|
39
|
+
label: "Table Row Index",
|
|
40
|
+
description: "Required only when **Page Element ID** refers to a table: the 0-based row of the cell to style.",
|
|
41
|
+
},
|
|
42
|
+
columnIndex: {
|
|
43
|
+
propDefinition: [
|
|
44
|
+
googleSlides,
|
|
45
|
+
"columnIndex",
|
|
46
|
+
],
|
|
47
|
+
label: "Table Column Index",
|
|
48
|
+
description: "Required only when **Page Element ID** refers to a table: the 0-based column of the cell to style.",
|
|
49
|
+
},
|
|
50
|
+
startIndex: {
|
|
51
|
+
propDefinition: [
|
|
52
|
+
googleSlides,
|
|
53
|
+
"startIndex",
|
|
54
|
+
],
|
|
55
|
+
description: "Character index to style from, inclusive. On its own, styles from here to the end of the text. Omit both indices to style all of it.",
|
|
56
|
+
},
|
|
57
|
+
endIndex: {
|
|
58
|
+
propDefinition: [
|
|
59
|
+
googleSlides,
|
|
60
|
+
"endIndex",
|
|
61
|
+
],
|
|
62
|
+
description: "Character index to style up to, exclusive. Requires **Start Index**, and must be greater than it.",
|
|
63
|
+
},
|
|
64
|
+
bold: {
|
|
65
|
+
type: "boolean",
|
|
66
|
+
label: "Bold",
|
|
67
|
+
description: "Set `true` to bold the text, `false` to remove bold. Leave unset to keep it unchanged.",
|
|
68
|
+
optional: true,
|
|
69
|
+
},
|
|
70
|
+
italic: {
|
|
71
|
+
type: "boolean",
|
|
72
|
+
label: "Italic",
|
|
73
|
+
description: "Set `true` to italicize the text, `false` to remove italics. Leave unset to keep it unchanged.",
|
|
74
|
+
optional: true,
|
|
75
|
+
},
|
|
76
|
+
underline: {
|
|
77
|
+
type: "boolean",
|
|
78
|
+
label: "Underline",
|
|
79
|
+
description: "Set `true` to underline the text, `false` to remove the underline. Leave unset to keep it unchanged.",
|
|
80
|
+
optional: true,
|
|
81
|
+
},
|
|
82
|
+
strikethrough: {
|
|
83
|
+
type: "boolean",
|
|
84
|
+
label: "Strikethrough",
|
|
85
|
+
description: "Set `true` to strike through the text, `false` to remove it. Leave unset to keep it unchanged.",
|
|
86
|
+
optional: true,
|
|
87
|
+
},
|
|
88
|
+
smallCaps: {
|
|
89
|
+
type: "boolean",
|
|
90
|
+
label: "Small Caps",
|
|
91
|
+
description: "Set `true` to render the text in small capitals, `false` to return it to normal casing. Leave unset to keep it unchanged.",
|
|
92
|
+
optional: true,
|
|
93
|
+
},
|
|
94
|
+
baselineOffset: {
|
|
95
|
+
type: "string",
|
|
96
|
+
label: "Baseline Offset",
|
|
97
|
+
description: "Vertical offset from the normal baseline. `SUPERSCRIPT` and `SUBSCRIPT` are also rendered in a smaller font, computed from the current size.",
|
|
98
|
+
options: BASELINE_OFFSETS,
|
|
99
|
+
optional: true,
|
|
100
|
+
},
|
|
101
|
+
fontSize: {
|
|
102
|
+
type: "integer",
|
|
103
|
+
label: "Font Size",
|
|
104
|
+
description: "Font size in points (1-400).",
|
|
105
|
+
min: 1,
|
|
106
|
+
max: 400,
|
|
107
|
+
optional: true,
|
|
108
|
+
},
|
|
109
|
+
fontFamily: {
|
|
110
|
+
type: "string",
|
|
111
|
+
label: "Font Family",
|
|
112
|
+
description: "Font family name as it appears in the Slides font menu, e.g. `Roboto`.",
|
|
113
|
+
optional: true,
|
|
114
|
+
},
|
|
115
|
+
foregroundColor: {
|
|
116
|
+
type: "string",
|
|
117
|
+
label: "Text Color",
|
|
118
|
+
description: "Hex code (e.g. `#FF0000`) or one of the deck's theme colors (e.g. `ACCENT1`, `DARK1`).",
|
|
119
|
+
optional: true,
|
|
120
|
+
},
|
|
121
|
+
backgroundColor: {
|
|
122
|
+
propDefinition: [
|
|
123
|
+
googleSlides,
|
|
124
|
+
"backgroundColor",
|
|
125
|
+
],
|
|
126
|
+
label: "Highlight Color",
|
|
127
|
+
description: "Hex code (e.g. `#FFFF00`) or one of the deck's theme colors (e.g. `ACCENT2`).",
|
|
128
|
+
},
|
|
129
|
+
link: {
|
|
130
|
+
type: "string",
|
|
131
|
+
label: "Link URL",
|
|
132
|
+
description: "Turn the text into a hyperlink pointing at this URL.",
|
|
133
|
+
optional: true,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
async run({ $ }) {
|
|
137
|
+
const {
|
|
138
|
+
googleSlides,
|
|
139
|
+
presentationId,
|
|
140
|
+
objectId,
|
|
141
|
+
rowIndex,
|
|
142
|
+
columnIndex,
|
|
143
|
+
startIndex,
|
|
144
|
+
endIndex,
|
|
145
|
+
bold,
|
|
146
|
+
italic,
|
|
147
|
+
underline,
|
|
148
|
+
strikethrough,
|
|
149
|
+
smallCaps,
|
|
150
|
+
baselineOffset,
|
|
151
|
+
fontSize,
|
|
152
|
+
fontFamily,
|
|
153
|
+
foregroundColor,
|
|
154
|
+
backgroundColor,
|
|
155
|
+
link,
|
|
156
|
+
} = this;
|
|
157
|
+
|
|
158
|
+
const builder = utils.styleBuilder();
|
|
159
|
+
|
|
160
|
+
builder.set("bold", bold);
|
|
161
|
+
builder.set("italic", italic);
|
|
162
|
+
builder.set("underline", underline);
|
|
163
|
+
builder.set("strikethrough", strikethrough);
|
|
164
|
+
builder.set("smallCaps", smallCaps);
|
|
165
|
+
builder.set("baselineOffset", baselineOffset);
|
|
166
|
+
|
|
167
|
+
if (fontSize != null) {
|
|
168
|
+
builder.set("fontSize", {
|
|
169
|
+
magnitude: fontSize,
|
|
170
|
+
unit: POINTS,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (fontFamily) {
|
|
174
|
+
builder.set("fontFamily", fontFamily);
|
|
175
|
+
}
|
|
176
|
+
if (link) {
|
|
177
|
+
builder.set("link", {
|
|
178
|
+
url: link,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
[
|
|
183
|
+
[
|
|
184
|
+
"foregroundColor",
|
|
185
|
+
foregroundColor,
|
|
186
|
+
"Text Color",
|
|
187
|
+
],
|
|
188
|
+
[
|
|
189
|
+
"backgroundColor",
|
|
190
|
+
backgroundColor,
|
|
191
|
+
"Highlight Color",
|
|
192
|
+
],
|
|
193
|
+
].forEach(([
|
|
194
|
+
name,
|
|
195
|
+
value,
|
|
196
|
+
label,
|
|
197
|
+
]) => {
|
|
198
|
+
if (!value) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const solidFill = utils.toSolidFill(value);
|
|
202
|
+
if (!solidFill) {
|
|
203
|
+
throw new ConfigurationError(`${label} "${value}" is not a valid hex color or theme color name. Use a 6-digit hex code such as \`#FF0000\`, or a theme color such as \`ACCENT1\`.`);
|
|
204
|
+
}
|
|
205
|
+
builder.set(name, {
|
|
206
|
+
opaqueColor: solidFill.color,
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
if (builder.isEmpty) {
|
|
211
|
+
throw new ConfigurationError("Provide at least one formatting option (for example Bold, Font Size, or Text Color).");
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if ((rowIndex == null) !== (columnIndex == null)) {
|
|
215
|
+
throw new ConfigurationError("Table Row Index and Table Column Index must be provided together.");
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const textRange = utils.buildTextRange(startIndex, endIndex);
|
|
219
|
+
|
|
220
|
+
const request = {
|
|
221
|
+
objectId,
|
|
222
|
+
style: builder.style,
|
|
223
|
+
textRange,
|
|
224
|
+
fields: builder.mask,
|
|
225
|
+
...(rowIndex != null && {
|
|
226
|
+
cellLocation: {
|
|
227
|
+
rowIndex,
|
|
228
|
+
columnIndex,
|
|
229
|
+
},
|
|
230
|
+
}),
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
await googleSlides.batchUpdate(googleSlides.getPresentationId(presentationId), [
|
|
234
|
+
{
|
|
235
|
+
updateTextStyle: request,
|
|
236
|
+
},
|
|
237
|
+
]);
|
|
238
|
+
|
|
239
|
+
$.export("$summary", `Formatted text on element ${objectId}`);
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
presentationId,
|
|
243
|
+
objectId,
|
|
244
|
+
fieldsUpdated: builder.fields,
|
|
245
|
+
textRange,
|
|
246
|
+
};
|
|
247
|
+
},
|
|
248
|
+
};
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "google_slides-get-presentation",
|
|
5
5
|
name: "Get Presentation",
|
|
6
6
|
description: "Get a Google Slides presentation by its ID. Returns the presentation's metadata and structure (title, slides, masters, layouts, page size, etc.) according to requested `fields`. Use **Find a Presentation** first to resolve a presentation's name to its ID. [See the documentation](https://developers.google.com/slides/api/reference/rest/v1/presentations/get)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.2",
|
|
8
8
|
annotations: {
|
|
9
9
|
destructiveHint: false,
|
|
10
10
|
openWorldHint: true,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "google_slides-insert-table-columns",
|
|
5
5
|
name: "Insert Table Columns",
|
|
6
6
|
description: "Insert new columns into a table. [See the documentation](https://developers.google.com/workspace/slides/api/reference/rest/v1/presentations/request#InsertTableColumnsRequest)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.5",
|
|
8
8
|
annotations: {
|
|
9
9
|
destructiveHint: false,
|
|
10
10
|
openWorldHint: true,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "google_slides-insert-table-rows",
|
|
5
5
|
name: "Insert Table Rows",
|
|
6
6
|
description: "Insert new rows into a table. [See the documentation](https://developers.google.com/workspace/slides/api/reference/rest/v1/presentations/request#InsertTableRowsRequest)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.5",
|
|
8
8
|
annotations: {
|
|
9
9
|
destructiveHint: false,
|
|
10
10
|
openWorldHint: true,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "google_slides-insert-text",
|
|
5
5
|
name: "Insert Text",
|
|
6
6
|
description: "Insert text into a shape. [See the documentation](https://developers.google.com/workspace/slides/api/reference/rest/v1/presentations/request#InsertTextRequest)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.6",
|
|
8
8
|
annotations: {
|
|
9
9
|
destructiveHint: false,
|
|
10
10
|
openWorldHint: true,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "google_slides-insert-text-into-table",
|
|
5
5
|
name: "Insert Text into Table",
|
|
6
6
|
description: "Insert text into a table cell. [See the documentation](https://developers.google.com/workspace/slides/api/reference/rest/v1/presentations/request#InsertTextRequest)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.5",
|
|
8
8
|
annotations: {
|
|
9
9
|
destructiveHint: false,
|
|
10
10
|
openWorldHint: true,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "google_slides-merge-data",
|
|
5
5
|
name: "Merge Data",
|
|
6
6
|
description: "Merge data into a presentation. [See the docs here](https://developers.google.com/slides/api/guides/merge)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.8",
|
|
8
8
|
annotations: {
|
|
9
9
|
destructiveHint: false,
|
|
10
10
|
openWorldHint: true,
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { ConfigurationError } from "@pipedream/platform";
|
|
2
|
+
import googleSlides from "../../google_slides.app.mjs";
|
|
3
|
+
import {
|
|
4
|
+
EMU, EMU_PER_POINT, POINTS, Z_ORDER_OPERATIONS,
|
|
5
|
+
} from "../../common/constants.mjs";
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
key: "google_slides-position-element",
|
|
9
|
+
name: "Position Element",
|
|
10
|
+
description: "Move, scale, rotate, or restack a page element in a Google Slides presentation. Unspecified properties keep their current values. Use **Get Presentation** to find the element's object ID. [See the documentation](https://developers.google.com/workspace/slides/api/reference/rest/v1/presentations/request#UpdatePageElementTransformRequest)",
|
|
11
|
+
version: "0.0.1",
|
|
12
|
+
annotations: {
|
|
13
|
+
destructiveHint: false,
|
|
14
|
+
openWorldHint: true,
|
|
15
|
+
readOnlyHint: false,
|
|
16
|
+
},
|
|
17
|
+
type: "action",
|
|
18
|
+
props: {
|
|
19
|
+
googleSlides,
|
|
20
|
+
presentationId: {
|
|
21
|
+
propDefinition: [
|
|
22
|
+
googleSlides,
|
|
23
|
+
"staticPresentationId",
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
objectId: {
|
|
27
|
+
propDefinition: [
|
|
28
|
+
googleSlides,
|
|
29
|
+
"pageElementId",
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
translateX: {
|
|
33
|
+
type: "integer",
|
|
34
|
+
label: "X Position",
|
|
35
|
+
description: "Horizontal position in points, measured from the top-left of the slide.",
|
|
36
|
+
optional: true,
|
|
37
|
+
},
|
|
38
|
+
translateY: {
|
|
39
|
+
type: "integer",
|
|
40
|
+
label: "Y Position",
|
|
41
|
+
description: "Vertical position in points, measured from the top-left of the slide.",
|
|
42
|
+
optional: true,
|
|
43
|
+
},
|
|
44
|
+
scaleXPercent: {
|
|
45
|
+
type: "integer",
|
|
46
|
+
label: "Horizontal Scale",
|
|
47
|
+
description: "Horizontal scale as a percentage of the element's intrinsic size (100 = unscaled). Range 1-1000.",
|
|
48
|
+
min: 1,
|
|
49
|
+
max: 1000,
|
|
50
|
+
optional: true,
|
|
51
|
+
},
|
|
52
|
+
scaleYPercent: {
|
|
53
|
+
type: "integer",
|
|
54
|
+
label: "Vertical Scale",
|
|
55
|
+
description: "Vertical scale as a percentage of the element's intrinsic size (100 = unscaled). Range 1-1000.",
|
|
56
|
+
min: 1,
|
|
57
|
+
max: 1000,
|
|
58
|
+
optional: true,
|
|
59
|
+
},
|
|
60
|
+
rotation: {
|
|
61
|
+
type: "integer",
|
|
62
|
+
label: "Rotation",
|
|
63
|
+
description: "Clockwise rotation in degrees (-360 to 360).",
|
|
64
|
+
min: -360,
|
|
65
|
+
max: 360,
|
|
66
|
+
optional: true,
|
|
67
|
+
},
|
|
68
|
+
zOrderOperation: {
|
|
69
|
+
type: "string",
|
|
70
|
+
label: "Z-Order",
|
|
71
|
+
description: "Restack the element relative to the other elements on its slide.",
|
|
72
|
+
options: Z_ORDER_OPERATIONS,
|
|
73
|
+
optional: true,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
async run({ $ }) {
|
|
77
|
+
const {
|
|
78
|
+
googleSlides,
|
|
79
|
+
presentationId,
|
|
80
|
+
objectId,
|
|
81
|
+
translateX,
|
|
82
|
+
translateY,
|
|
83
|
+
scaleXPercent,
|
|
84
|
+
scaleYPercent,
|
|
85
|
+
rotation,
|
|
86
|
+
zOrderOperation,
|
|
87
|
+
} = this;
|
|
88
|
+
|
|
89
|
+
const movesElement = [
|
|
90
|
+
translateX,
|
|
91
|
+
translateY,
|
|
92
|
+
scaleXPercent,
|
|
93
|
+
scaleYPercent,
|
|
94
|
+
rotation,
|
|
95
|
+
].some((value) => value != null);
|
|
96
|
+
|
|
97
|
+
if (!movesElement && !zOrderOperation) {
|
|
98
|
+
throw new ConfigurationError("Provide at least one of X Position, Y Position, Horizontal Scale, Vertical Scale, Rotation, or Z-Order.");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const id = googleSlides.getPresentationId(presentationId);
|
|
102
|
+
const requests = [];
|
|
103
|
+
|
|
104
|
+
const {
|
|
105
|
+
element, groupId,
|
|
106
|
+
} = await googleSlides.getPageElement(id, objectId);
|
|
107
|
+
|
|
108
|
+
// A grouped child's transform is relative to its group, so the slide-space
|
|
109
|
+
// X/Y props would not mean what they say, and the API rejects grouped IDs
|
|
110
|
+
// for z-order outright.
|
|
111
|
+
if (groupId) {
|
|
112
|
+
throw new ConfigurationError(`Page element "${objectId}" is inside group "${groupId}". Its position is relative to that group, and z-order cannot target a grouped element. Target the group itself, or ungroup it first.`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (movesElement) {
|
|
116
|
+
const current = element.transform || {};
|
|
117
|
+
const unit = current.unit || POINTS;
|
|
118
|
+
const toUnit = (points) => (unit === EMU
|
|
119
|
+
? points * EMU_PER_POINT
|
|
120
|
+
: points);
|
|
121
|
+
|
|
122
|
+
// A move alone leaves the matrix untouched. When scale or rotation is
|
|
123
|
+
// set, the matrix is decomposed so that reflection (carried by the signed
|
|
124
|
+
// scaleY) and shear survive the rebuild.
|
|
125
|
+
let matrix = {
|
|
126
|
+
scaleX: current.scaleX ?? 1,
|
|
127
|
+
scaleY: current.scaleY ?? 1,
|
|
128
|
+
shearX: current.shearX ?? 0,
|
|
129
|
+
shearY: current.shearY ?? 0,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
if (scaleXPercent != null || scaleYPercent != null || rotation != null) {
|
|
133
|
+
// Factor any reflection onto the axis that already carries it before
|
|
134
|
+
// decomposing, so changing the rotation cannot move a horizontal flip
|
|
135
|
+
// onto the vertical axis and leave the element 180 degrees out.
|
|
136
|
+
const determinant = (matrix.scaleX * matrix.scaleY) - (matrix.shearY * matrix.shearX);
|
|
137
|
+
const flipX = determinant < 0 && matrix.scaleX < 0
|
|
138
|
+
? -1
|
|
139
|
+
: 1;
|
|
140
|
+
const flipY = determinant < 0 && flipX === 1
|
|
141
|
+
? -1
|
|
142
|
+
: 1;
|
|
143
|
+
|
|
144
|
+
const columnX = matrix.scaleX * flipX;
|
|
145
|
+
const columnXShear = matrix.shearY * flipX;
|
|
146
|
+
const columnY = matrix.shearX * flipY;
|
|
147
|
+
const columnYScale = matrix.scaleY * flipY;
|
|
148
|
+
|
|
149
|
+
const currentAngle = Math.atan2(columnXShear, columnX);
|
|
150
|
+
const cos = Math.cos(currentAngle);
|
|
151
|
+
const sin = Math.sin(currentAngle);
|
|
152
|
+
|
|
153
|
+
const currentScaleX = Math.hypot(columnX, columnXShear) || 1;
|
|
154
|
+
const shear = (columnY * cos) + (columnYScale * sin);
|
|
155
|
+
const currentScaleY = (columnYScale * cos) - (columnY * sin);
|
|
156
|
+
|
|
157
|
+
const scaleX = scaleXPercent != null
|
|
158
|
+
? scaleXPercent / 100
|
|
159
|
+
: currentScaleX;
|
|
160
|
+
const scaleY = scaleYPercent != null
|
|
161
|
+
? (scaleYPercent / 100) * (currentScaleY < 0
|
|
162
|
+
? -1
|
|
163
|
+
: 1)
|
|
164
|
+
: currentScaleY;
|
|
165
|
+
const angle = rotation != null
|
|
166
|
+
? rotation * Math.PI / 180
|
|
167
|
+
: currentAngle;
|
|
168
|
+
|
|
169
|
+
const newCos = Math.cos(angle);
|
|
170
|
+
const newSin = Math.sin(angle);
|
|
171
|
+
|
|
172
|
+
matrix = {
|
|
173
|
+
scaleX: scaleX * newCos * flipX,
|
|
174
|
+
shearY: scaleX * newSin * flipX,
|
|
175
|
+
shearX: ((shear * newCos) - (scaleY * newSin)) * flipY,
|
|
176
|
+
scaleY: ((shear * newSin) + (scaleY * newCos)) * flipY,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
requests.push({
|
|
181
|
+
updatePageElementTransform: {
|
|
182
|
+
objectId,
|
|
183
|
+
applyMode: "ABSOLUTE",
|
|
184
|
+
transform: {
|
|
185
|
+
...matrix,
|
|
186
|
+
translateX: translateX != null
|
|
187
|
+
? toUnit(translateX)
|
|
188
|
+
: current.translateX ?? 0,
|
|
189
|
+
translateY: translateY != null
|
|
190
|
+
? toUnit(translateY)
|
|
191
|
+
: current.translateY ?? 0,
|
|
192
|
+
unit,
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (zOrderOperation) {
|
|
199
|
+
requests.push({
|
|
200
|
+
updatePageElementsZOrder: {
|
|
201
|
+
pageElementObjectIds: [
|
|
202
|
+
objectId,
|
|
203
|
+
],
|
|
204
|
+
operation: zOrderOperation,
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
await googleSlides.batchUpdate(id, requests);
|
|
210
|
+
|
|
211
|
+
$.export("$summary", `Repositioned element ${objectId}`);
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
presentationId,
|
|
215
|
+
objectId,
|
|
216
|
+
requestsApplied: requests.map((request) => Object.keys(request)[0]),
|
|
217
|
+
};
|
|
218
|
+
},
|
|
219
|
+
};
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "google_slides-refresh-chart",
|
|
5
5
|
name: "Refresh a chart",
|
|
6
6
|
description: "Refresh a chart from Sheets. [See the docs here](https://developers.google.com/slides/api/samples/elements#refresh_a_chart_from_sheets)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.9",
|
|
8
8
|
annotations: {
|
|
9
9
|
destructiveHint: false,
|
|
10
10
|
openWorldHint: true,
|