@mcpher/gas-fakes 2.3.10 → 2.3.11
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/package.json
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"name": "@mcpher/gas-fakes",
|
|
42
42
|
"author": "bruce mcpherson",
|
|
43
|
-
"version": "2.3.
|
|
43
|
+
"version": "2.3.11",
|
|
44
44
|
"license": "MIT",
|
|
45
45
|
"main": "main.js",
|
|
46
46
|
"description": "An implementation of the Google Workspace Apps Script runtime: Run native App Script Code on Node and Cloud Run",
|
|
@@ -286,3 +286,30 @@ export const updateParagraphStyle = (element, paragraphStyle, fields) => {
|
|
|
286
286
|
shadow.refresh();
|
|
287
287
|
return element;
|
|
288
288
|
};
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Updates the text style for a given element or range within it.
|
|
292
|
+
* @param {import('./fakeelement.js').FakeElement} element The element whose text style to update.
|
|
293
|
+
* @param {GoogleAppsScript.Document.TextStyle} textStyle The style object to apply.
|
|
294
|
+
* @param {string} fields The comma-separated string of field names to update.
|
|
295
|
+
* @param {object} [range] Optional specific range. Defaults to the element's range.
|
|
296
|
+
* @returns {import('./fakeelement.js').FakeElement} The element, for chaining.
|
|
297
|
+
*/
|
|
298
|
+
export const updateTextStyle = (element, textStyle, fields, range = null) => {
|
|
299
|
+
const shadow = element.shadowDocument;
|
|
300
|
+
const item = element.__elementMapItem;
|
|
301
|
+
const updateRange = range || {
|
|
302
|
+
startIndex: item.startIndex,
|
|
303
|
+
endIndex: item.endIndex,
|
|
304
|
+
segmentId: shadow.__segmentId,
|
|
305
|
+
tabId: shadow.__tabId,
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
const requests = [{
|
|
309
|
+
updateTextStyle: { range: updateRange, textStyle, fields },
|
|
310
|
+
}];
|
|
311
|
+
|
|
312
|
+
Docs.Documents.batchUpdate({ requests }, shadow.getId());
|
|
313
|
+
shadow.refresh();
|
|
314
|
+
return element;
|
|
315
|
+
};
|
|
@@ -96,6 +96,14 @@ export class FakeElement {
|
|
|
96
96
|
});
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Gets the shadow document manager associated with this element's structure.
|
|
101
|
+
* @type {import('./shadowdocument.js').ShadowDocument | null}
|
|
102
|
+
*/
|
|
103
|
+
get shadowDocument() {
|
|
104
|
+
return this.__shadowDocument;
|
|
105
|
+
}
|
|
106
|
+
|
|
99
107
|
get __structure() {
|
|
100
108
|
if (this.__isDetached) return null;
|
|
101
109
|
return this.__shadowDocument.structure;
|
|
@@ -4,6 +4,7 @@ import { Utils } from '../../support/utils.js';
|
|
|
4
4
|
import { imageOptions } from './elementoptions.js';
|
|
5
5
|
import { FakeContainerElement } from './fakecontainerelement.js';
|
|
6
6
|
import { registerElement } from './elementRegistry.js';
|
|
7
|
+
import { newFakeText } from './faketext.js';
|
|
7
8
|
import { appendText, addPositionedImage, appendImage, insertImage } from './appenderhelpers.js';
|
|
8
9
|
import { getText as getTextHelper, getAttributes as getAttributesHelper, updateParagraphStyle } from './elementhelpers.js';
|
|
9
10
|
|
|
@@ -32,6 +33,19 @@ export class FakeParagraph extends FakeContainerElement {
|
|
|
32
33
|
return getTextHelper(this);
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Returns the contents of the paragraph as a Text element.
|
|
38
|
+
* @returns {GoogleAppsScript.Document.Text} The text element.
|
|
39
|
+
*/
|
|
40
|
+
editAsText() {
|
|
41
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Paragraph.editAsText');
|
|
42
|
+
if (nargs !== 0) matchThrow();
|
|
43
|
+
// In gas-fakes, we can return a FakeText that points to the same underlying item.
|
|
44
|
+
// The getText and updateTextStyle methods will work correctly because they
|
|
45
|
+
// handle both PARAGRAPH and TEXT items or ranges.
|
|
46
|
+
return newFakeText(this.__shadowDocument, this.__name);
|
|
47
|
+
}
|
|
48
|
+
|
|
35
49
|
appendText(text) {
|
|
36
50
|
const { nargs, matchThrow } = signatureArgs(arguments, 'Paragraph.appendText');
|
|
37
51
|
if (nargs !== 1) matchThrow();
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { Proxies } from '../../support/proxies.js';
|
|
2
|
+
import { signatureArgs } from '../../support/helpers.js';
|
|
3
|
+
import { Utils } from '../../support/utils.js';
|
|
2
4
|
import { FakeElement } from './fakeelement.js';
|
|
3
5
|
import { registerElement } from './elementRegistry.js';
|
|
6
|
+
import { getAttributes as getAttributesHelper, updateTextStyle, getText as getTextHelper } from './elementhelpers.js';
|
|
7
|
+
|
|
8
|
+
const { is } = Utils;
|
|
4
9
|
|
|
5
10
|
/**
|
|
6
11
|
* A fake implementation of the Text class for DocumentApp.
|
|
12
|
+
* @implements {GoogleAppsScript.Document.Text}
|
|
7
13
|
* @see https://developers.google.com/apps-script/reference/document/text
|
|
8
14
|
*/
|
|
9
15
|
class FakeText extends FakeElement {
|
|
@@ -16,9 +22,173 @@ class FakeText extends FakeElement {
|
|
|
16
22
|
* @returns {string} The text contents.
|
|
17
23
|
*/
|
|
18
24
|
getText() {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
return
|
|
25
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.getText');
|
|
26
|
+
if (nargs !== 0) matchThrow();
|
|
27
|
+
return getTextHelper(this);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getAttributes() {
|
|
31
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.getAttributes');
|
|
32
|
+
if (nargs !== 0) matchThrow();
|
|
33
|
+
return getAttributesHelper(this);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
setAttributes(attributes) {
|
|
37
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.setAttributes');
|
|
38
|
+
if (nargs !== 1 || !is.object(attributes)) matchThrow();
|
|
39
|
+
|
|
40
|
+
const textStyle = {};
|
|
41
|
+
const textFields = [];
|
|
42
|
+
const Attribute = DocumentApp.Attribute;
|
|
43
|
+
|
|
44
|
+
const colorToRgb = (hex) => {
|
|
45
|
+
if (!hex || !hex.startsWith('#') || hex.length !== 7) return null;
|
|
46
|
+
const r = parseInt(hex.slice(1, 3), 16) / 255;
|
|
47
|
+
const g = parseInt(hex.slice(3, 5), 16) / 255;
|
|
48
|
+
const b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
49
|
+
return { red: r, green: g, blue: b };
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
for (const key in attributes) {
|
|
53
|
+
const value = attributes[key];
|
|
54
|
+
// Note: GAS allows null to clear some attributes, but let's handle the basics first.
|
|
55
|
+
switch (String(key)) {
|
|
56
|
+
case String(Attribute.BACKGROUND_COLOR): textStyle.backgroundColor = { color: { rgbColor: colorToRgb(value) } }; textFields.push('backgroundColor'); break;
|
|
57
|
+
case String(Attribute.BOLD): textStyle.bold = value; textFields.push('bold'); break;
|
|
58
|
+
case String(Attribute.FONT_FAMILY): textStyle.weightedFontFamily = { fontFamily: value }; textFields.push('weightedFontFamily'); break;
|
|
59
|
+
case String(Attribute.FONT_SIZE): textStyle.fontSize = { magnitude: value, unit: 'PT' }; textFields.push('fontSize'); break;
|
|
60
|
+
case String(Attribute.FOREGROUND_COLOR): textStyle.foregroundColor = { color: { rgbColor: colorToRgb(value) } }; textFields.push('foregroundColor'); break;
|
|
61
|
+
case String(Attribute.ITALIC): textStyle.italic = value; textFields.push('italic'); break;
|
|
62
|
+
case String(Attribute.LINK_URL): textStyle.link = { url: value }; textFields.push('link'); break;
|
|
63
|
+
case String(Attribute.STRIKETHROUGH): textStyle.strikethrough = value; textFields.push('strikethrough'); break;
|
|
64
|
+
case String(Attribute.UNDERLINE): textStyle.underline = value; textFields.push('underline'); break;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (textFields.length === 0) return this;
|
|
69
|
+
return updateTextStyle(this, textStyle, textFields.join(','));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
setBold(bold) {
|
|
73
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.setBold');
|
|
74
|
+
if (nargs !== 1 || !is.boolean(bold)) matchThrow();
|
|
75
|
+
return updateTextStyle(this, { bold }, 'bold');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
isBold() {
|
|
79
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.isBold');
|
|
80
|
+
if (nargs !== 0) matchThrow();
|
|
81
|
+
return !!this.getAttributes()[DocumentApp.Attribute.BOLD];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
setItalic(italic) {
|
|
85
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.setItalic');
|
|
86
|
+
if (nargs !== 1 || !is.boolean(italic)) matchThrow();
|
|
87
|
+
return updateTextStyle(this, { italic }, 'italic');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
isItalic() {
|
|
91
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.isItalic');
|
|
92
|
+
if (nargs !== 0) matchThrow();
|
|
93
|
+
return !!this.getAttributes()[DocumentApp.Attribute.ITALIC];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
setUnderline(underline) {
|
|
97
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.setUnderline');
|
|
98
|
+
if (nargs !== 1 || !is.boolean(underline)) matchThrow();
|
|
99
|
+
return updateTextStyle(this, { underline }, 'underline');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
isUnderline() {
|
|
103
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.isUnderline');
|
|
104
|
+
if (nargs !== 0) matchThrow();
|
|
105
|
+
return !!this.getAttributes()[DocumentApp.Attribute.UNDERLINE];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
setFontFamily(fontFamily) {
|
|
109
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.setFontFamily');
|
|
110
|
+
if (nargs !== 1 || !is.string(fontFamily)) matchThrow();
|
|
111
|
+
return updateTextStyle(this, { weightedFontFamily: { fontFamily } }, 'weightedFontFamily');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
getFontFamily() {
|
|
115
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.getFontFamily');
|
|
116
|
+
if (nargs !== 0) matchThrow();
|
|
117
|
+
return this.getAttributes()[DocumentApp.Attribute.FONT_FAMILY];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
setFontSize(fontSize) {
|
|
121
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.setFontSize');
|
|
122
|
+
if (nargs !== 1 || !is.number(fontSize)) matchThrow();
|
|
123
|
+
return updateTextStyle(this, { fontSize: { magnitude: fontSize, unit: 'PT' } }, 'fontSize');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
getFontSize() {
|
|
127
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.getFontSize');
|
|
128
|
+
if (nargs !== 0) matchThrow();
|
|
129
|
+
return this.getAttributes()[DocumentApp.Attribute.FONT_SIZE];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
setForegroundColor(color) {
|
|
133
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.setForegroundColor');
|
|
134
|
+
if (nargs !== 1 || !is.string(color)) matchThrow();
|
|
135
|
+
const colorToRgb = (hex) => {
|
|
136
|
+
if (!hex || !hex.startsWith('#') || hex.length !== 7) return null;
|
|
137
|
+
const r = parseInt(hex.slice(1, 3), 16) / 255;
|
|
138
|
+
const g = parseInt(hex.slice(3, 5), 16) / 255;
|
|
139
|
+
const b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
140
|
+
return { red: r, green: g, blue: b };
|
|
141
|
+
};
|
|
142
|
+
return updateTextStyle(this, { foregroundColor: { color: { rgbColor: colorToRgb(color) } } }, 'foregroundColor');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
getForegroundColor() {
|
|
146
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.getForegroundColor');
|
|
147
|
+
if (nargs !== 0) matchThrow();
|
|
148
|
+
return this.getAttributes()[DocumentApp.Attribute.FOREGROUND_COLOR];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
setBackgroundColor(color) {
|
|
152
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.setBackgroundColor');
|
|
153
|
+
if (nargs !== 1 || !is.string(color)) matchThrow();
|
|
154
|
+
const colorToRgb = (hex) => {
|
|
155
|
+
if (!hex || !hex.startsWith('#') || hex.length !== 7) return null;
|
|
156
|
+
const r = parseInt(hex.slice(1, 3), 16) / 255;
|
|
157
|
+
const g = parseInt(hex.slice(3, 5), 16) / 255;
|
|
158
|
+
const b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
159
|
+
return { red: r, green: g, blue: b };
|
|
160
|
+
};
|
|
161
|
+
return updateTextStyle(this, { backgroundColor: { color: { rgbColor: colorToRgb(color) } } }, 'backgroundColor');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
getBackgroundColor() {
|
|
165
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.getBackgroundColor');
|
|
166
|
+
if (nargs !== 0) matchThrow();
|
|
167
|
+
return this.getAttributes()[DocumentApp.Attribute.BACKGROUND_COLOR];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
setLinkUrl(url) {
|
|
171
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.setLinkUrl');
|
|
172
|
+
if (nargs !== 1 || (!is.string(url) && !is.null(url))) matchThrow();
|
|
173
|
+
return updateTextStyle(this, { link: { url: url } }, 'link');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
getLinkUrl() {
|
|
177
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.getLinkUrl');
|
|
178
|
+
if (nargs !== 0) matchThrow();
|
|
179
|
+
return this.getAttributes()[DocumentApp.Attribute.LINK_URL];
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
setStrikethrough(strikethrough) {
|
|
183
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.setStrikethrough');
|
|
184
|
+
if (nargs !== 1 || !is.boolean(strikethrough)) matchThrow();
|
|
185
|
+
return updateTextStyle(this, { strikethrough }, 'strikethrough');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
isStrikethrough() {
|
|
189
|
+
const { nargs, matchThrow } = signatureArgs(arguments, 'Text.isStrikethrough');
|
|
190
|
+
if (nargs !== 0) matchThrow();
|
|
191
|
+
return !!this.getAttributes()[DocumentApp.Attribute.STRIKETHROUGH];
|
|
22
192
|
}
|
|
23
193
|
|
|
24
194
|
toString() {
|
|
@@ -28,4 +198,4 @@ class FakeText extends FakeElement {
|
|
|
28
198
|
|
|
29
199
|
export const newFakeText = (...args) => Proxies.guard(new FakeText(...args));
|
|
30
200
|
|
|
31
|
-
registerElement('TEXT', newFakeText);
|
|
201
|
+
registerElement('TEXT', newFakeText);
|