@mcpher/gas-fakes 2.3.10 → 2.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/gas-fakes.js +1 -0
- package/gf_agent/scripts/builder.js +26 -1
- package/package.json +1 -1
- package/src/cli/lib-manager.js +14 -4
- package/src/cli/setup.js +17 -4
- package/src/services/chartsapp/fakechartsapp.js +6 -1
- package/src/services/documentapp/elementhelpers.js +27 -0
- package/src/services/documentapp/fakeelement.js +8 -0
- package/src/services/documentapp/fakeparagraph.js +14 -0
- package/src/services/documentapp/faketext.js +174 -4
- package/src/services/driveapp/driveiterators.js +53 -8
- package/src/services/driveapp/fakedriveapp.js +49 -15
- package/src/services/driveapp/fakedrivefile.js +105 -0
- package/src/services/driveapp/fakedrivefolder.js +8 -0
- package/src/services/driveapp/fakedrivemeta.js +68 -16
- package/src/services/driveapp/fakefolderapp.js +19 -6
- package/src/services/enums/chartsenums.js +53 -20
- package/src/services/enums/driveenums.js +1 -0
- package/src/services/slidesapp/fakeautofit.js +23 -15
- package/src/services/slidesapp/fakecolorscheme.js +160 -0
- package/src/services/slidesapp/fakelayout.js +11 -1
- package/src/services/slidesapp/fakemaster.js +10 -0
- package/src/services/slidesapp/fakepresentation.js +27 -0
- package/src/services/slidesapp/fakeslide.js +9 -0
- package/src/services/slidesapp/faketextrange.js +6 -11
- package/src/services/spreadsheetapp/chartenummapping.js +15 -0
- package/src/services/spreadsheetapp/fakebooleancondition.js +119 -0
- package/src/services/spreadsheetapp/fakecellimage.js +42 -0
- package/src/services/spreadsheetapp/fakecellimagebuilder.js +59 -0
- package/src/services/spreadsheetapp/fakeconditionalformatrule.js +55 -0
- package/src/services/spreadsheetapp/fakeconditionalformatrulebuilder.js +330 -0
- package/src/services/spreadsheetapp/fakedevelopermetadata.js +32 -4
- package/src/services/spreadsheetapp/fakedevelopermetadatalocation.js +27 -5
- package/src/services/spreadsheetapp/fakeembeddedchartbuilder.js +155 -21
- package/src/services/spreadsheetapp/fakegradientcondition.js +71 -0
- package/src/services/spreadsheetapp/fakesheet.js +63 -0
- package/src/services/spreadsheetapp/fakesheetrange.js +12 -1
- package/src/services/spreadsheetapp/fakespreadsheet.js +30 -11
- package/src/services/spreadsheetapp/fakespreadsheetapp.js +21 -3
- package/src/services/urlfetchapp/app.js +33 -1
- package/src/support/fileiterators.js +3 -1
- package/src/support/filesharers.js +7 -3
- package/src/support/peeker.js +8 -2
- package/src/support/sheetutils.js +1 -0
- package/src/support/sxdrive.js +26 -15
- package/src/support/syncit.js +4 -6
- package/src/support/workersync/synchronizer.js +24 -4
- package/src/support/workersync/worker.js +13 -2
- package/summarize_advanced.js +0 -69
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Proxies } from '../../support/proxies.js';
|
|
2
|
+
import { newFakeColor } from '../common/fakecolor.js';
|
|
3
|
+
import { newFakeColorBuilder } from '../common/fakecolorbuilder.js';
|
|
4
|
+
import { ThemeColorType } from '../enums/slidesenums.js';
|
|
5
|
+
import { signatureArgs } from '../../support/helpers.js';
|
|
6
|
+
|
|
7
|
+
export const newFakeColorScheme = (...args) => {
|
|
8
|
+
return Proxies.guard(new FakeColorScheme(...args));
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @class FakeColorScheme
|
|
13
|
+
*/
|
|
14
|
+
export class FakeColorScheme {
|
|
15
|
+
constructor(parent) {
|
|
16
|
+
this.__parent = parent;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get __masterPage() {
|
|
20
|
+
const parent = this.__parent;
|
|
21
|
+
const type = parent.toString();
|
|
22
|
+
|
|
23
|
+
if (type === 'Master') return parent;
|
|
24
|
+
if (type === 'Slide' || type === 'Layout') {
|
|
25
|
+
// Find the master for this slide/layout
|
|
26
|
+
if (type === 'Slide') {
|
|
27
|
+
const layout = parent.getLayout();
|
|
28
|
+
return layout ? layout.getMaster() : null;
|
|
29
|
+
} else {
|
|
30
|
+
return parent.getMaster();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (type === 'Presentation') {
|
|
34
|
+
// Use the first master of the presentation
|
|
35
|
+
const masters = parent.getMasters();
|
|
36
|
+
if (masters.length > 0) {
|
|
37
|
+
return masters[0];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get __resource() {
|
|
44
|
+
const master = this.__masterPage;
|
|
45
|
+
return master?.__resource?.pageProperties?.colorScheme || { colors: [] };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* getConcreteColor(themeColorType) https://developers.google.com/apps-script/reference/slides/color-scheme#getconcretecolorthemecolortype
|
|
50
|
+
* @param {ThemeColorType} themeColorType
|
|
51
|
+
* @returns {FakeColor}
|
|
52
|
+
*/
|
|
53
|
+
getConcreteColor(themeColorType) {
|
|
54
|
+
const { nargs, matchThrow } = signatureArgs(arguments, "ColorScheme.getConcreteColor");
|
|
55
|
+
if (nargs !== 1) matchThrow();
|
|
56
|
+
|
|
57
|
+
const colors = this.__resource.colors || [];
|
|
58
|
+
const typeStr = themeColorType.toString();
|
|
59
|
+
const pair = colors.find(c => c.type === typeStr);
|
|
60
|
+
|
|
61
|
+
if (pair && pair.color) {
|
|
62
|
+
return makeColorFromApiForSlides(pair.color);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* getThemeColors() https://developers.google.com/apps-script/reference/slides/color-scheme#getthemecolors
|
|
70
|
+
* @returns {ThemeColorType[]}
|
|
71
|
+
*/
|
|
72
|
+
getThemeColors() {
|
|
73
|
+
return Object.keys(ThemeColorType)
|
|
74
|
+
.filter(k => k !== 'UNSUPPORTED')
|
|
75
|
+
.map(k => ThemeColorType[k]);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* setConcreteColor(themeColorType, color) https://developers.google.com/apps-script/reference/slides/color-scheme#setconcretecolorthemecolortype,color
|
|
80
|
+
* @param {ThemeColorType} themeColorType
|
|
81
|
+
* @param {FakeColor} color
|
|
82
|
+
* @returns {FakeColorScheme} self
|
|
83
|
+
*/
|
|
84
|
+
setConcreteColor(themeColorType, color) {
|
|
85
|
+
const { nargs, matchThrow } = signatureArgs(arguments, "ColorScheme.setConcreteColor");
|
|
86
|
+
if (nargs !== 2) matchThrow();
|
|
87
|
+
|
|
88
|
+
const master = this.__masterPage;
|
|
89
|
+
if (!master) throw new Error('Could not find master page for color scheme');
|
|
90
|
+
|
|
91
|
+
const presentationId = master.__presentation.getId();
|
|
92
|
+
const typeStr = themeColorType.toString();
|
|
93
|
+
|
|
94
|
+
// The API requires ALL theme colors to be present when updating the color scheme.
|
|
95
|
+
// So we fetch the current colors, update the one we want, and send them all back.
|
|
96
|
+
const currentResource = this.__resource;
|
|
97
|
+
const colors = [...(currentResource.colors || [])];
|
|
98
|
+
|
|
99
|
+
// Convert the new Color to API format
|
|
100
|
+
const apiColor = {};
|
|
101
|
+
if (color.getColorType().toString() === 'RGB') {
|
|
102
|
+
const rgb = color.asRgbColor();
|
|
103
|
+
apiColor.red = rgb.getRed() / 255;
|
|
104
|
+
apiColor.green = rgb.getGreen() / 255;
|
|
105
|
+
apiColor.blue = rgb.getBlue() / 255;
|
|
106
|
+
} else if (color.getColorType().toString() === 'THEME') {
|
|
107
|
+
apiColor.themeColor = color.asThemeColor().getThemeColorType().toString();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Find and update or add the color pair
|
|
111
|
+
const index = colors.findIndex(c => c.type === typeStr);
|
|
112
|
+
if (index !== -1) {
|
|
113
|
+
colors[index] = { type: typeStr, color: apiColor };
|
|
114
|
+
} else {
|
|
115
|
+
colors.push({ type: typeStr, color: apiColor });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Ensure we have exactly the right set of colors if possible?
|
|
119
|
+
// The API error said "must have 12 theme colors pairs".
|
|
120
|
+
// Usually these are the standard 12 types.
|
|
121
|
+
|
|
122
|
+
const requests = [{
|
|
123
|
+
updatePageProperties: {
|
|
124
|
+
objectId: master.getObjectId(),
|
|
125
|
+
pageProperties: {
|
|
126
|
+
colorScheme: {
|
|
127
|
+
colors: colors
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
fields: 'colorScheme'
|
|
131
|
+
}
|
|
132
|
+
}];
|
|
133
|
+
|
|
134
|
+
Slides.Presentations.batchUpdate(requests, presentationId);
|
|
135
|
+
return this;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
toString() {
|
|
139
|
+
return 'ColorScheme';
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Helper to avoid circular dependency or reusing the spreadsheet-specific one if it differs
|
|
144
|
+
const makeColorFromApiForSlides = (apiColor) => {
|
|
145
|
+
const builder = newFakeColorBuilder();
|
|
146
|
+
const rgb = apiColor.rgbColor || (apiColor.red !== undefined ? apiColor : null);
|
|
147
|
+
|
|
148
|
+
if (rgb) {
|
|
149
|
+
const hex = '#' + [rgb.red, rgb.green, rgb.blue].map(v => {
|
|
150
|
+
const val = Math.round((v || 0) * 255);
|
|
151
|
+
const hex = val.toString(16);
|
|
152
|
+
return hex.length === 1 ? '0' + hex : hex;
|
|
153
|
+
}).join('');
|
|
154
|
+
builder.setRgbColor(hex);
|
|
155
|
+
} else if (apiColor.themeColor) {
|
|
156
|
+
const tc = apiColor.themeColor;
|
|
157
|
+
builder.setThemeColor(ThemeColorType[tc]);
|
|
158
|
+
}
|
|
159
|
+
return builder.build();
|
|
160
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Proxies } from '../../support/proxies.js';
|
|
2
2
|
import { newFakeMaster } from './fakemaster.js';
|
|
3
|
+
import { newFakeColorScheme } from './fakecolorscheme.js';
|
|
3
4
|
|
|
4
5
|
export const newFakeLayout = (...args) => {
|
|
5
6
|
return Proxies.guard(new FakeLayout(...args));
|
|
@@ -21,7 +22,7 @@ export class FakeLayout {
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
getMaster() {
|
|
24
|
-
const masterId = this.__resource.masterObjectId;
|
|
25
|
+
const masterId = this.__resource.layoutProperties?.masterObjectId;
|
|
25
26
|
if (!masterId) return null;
|
|
26
27
|
|
|
27
28
|
const presentationResource = this.__presentation.__resource;
|
|
@@ -32,6 +33,15 @@ export class FakeLayout {
|
|
|
32
33
|
getObjectId() {
|
|
33
34
|
return this.__id;
|
|
34
35
|
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Gets the color scheme of the layout.
|
|
39
|
+
* @returns {FakeColorScheme} The color scheme.
|
|
40
|
+
*/
|
|
41
|
+
getColorScheme() {
|
|
42
|
+
return newFakeColorScheme(this);
|
|
43
|
+
}
|
|
44
|
+
|
|
35
45
|
toString() {
|
|
36
46
|
return 'Layout';
|
|
37
47
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Proxies } from '../../support/proxies.js';
|
|
2
|
+
import { newFakeColorScheme } from './fakecolorscheme.js';
|
|
2
3
|
|
|
3
4
|
export const newFakeMaster = (...args) => {
|
|
4
5
|
return Proxies.guard(new FakeMaster(...args));
|
|
@@ -22,6 +23,15 @@ export class FakeMaster {
|
|
|
22
23
|
getObjectId() {
|
|
23
24
|
return this.__id;
|
|
24
25
|
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Gets the color scheme of the master.
|
|
29
|
+
* @returns {FakeColorScheme} The color scheme.
|
|
30
|
+
*/
|
|
31
|
+
getColorScheme() {
|
|
32
|
+
return newFakeColorScheme(this);
|
|
33
|
+
}
|
|
34
|
+
|
|
25
35
|
toString() {
|
|
26
36
|
return 'Master';
|
|
27
37
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Proxies } from '../../support/proxies.js';
|
|
2
2
|
import { newFakeSlide } from './fakeslide.js';
|
|
3
|
+
import { newFakeMaster } from './fakemaster.js';
|
|
4
|
+
import { newFakeColorScheme } from './fakecolorscheme.js';
|
|
3
5
|
|
|
4
6
|
export const newFakePresentation = (...args) => {
|
|
5
7
|
return Proxies.guard(new FakePresentation(...args));
|
|
@@ -50,6 +52,31 @@ export class FakePresentation {
|
|
|
50
52
|
return `https://docs.google.com/presentation/d/${this.getId()}/edit`;
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Gets the color scheme of the presentation.
|
|
57
|
+
* @returns {FakeColorScheme} The color scheme.
|
|
58
|
+
*/
|
|
59
|
+
getColorScheme() {
|
|
60
|
+
return newFakeColorScheme(this);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Gets the masters in the presentation.
|
|
65
|
+
* @returns {FakeMaster[]} The masters.
|
|
66
|
+
*/
|
|
67
|
+
getMasters() {
|
|
68
|
+
return (this.__resource.masters || []).map(m => newFakeMaster(m, this));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Gets a master by its ID.
|
|
73
|
+
* @param {string} id The master ID.
|
|
74
|
+
* @returns {FakeMaster | null} The master, or null if not found.
|
|
75
|
+
*/
|
|
76
|
+
getMasterById(id) {
|
|
77
|
+
return this.getMasters().find(m => m.getObjectId() === id) || null;
|
|
78
|
+
}
|
|
79
|
+
|
|
53
80
|
/**
|
|
54
81
|
* Gets the slides in the presentation.
|
|
55
82
|
* @returns {FakeSlide[]} The slides.
|
|
@@ -4,6 +4,7 @@ import { newFakeLayout } from './fakelayout.js';
|
|
|
4
4
|
import { newFakeMaster } from './fakemaster.js';
|
|
5
5
|
import { newFakePageElement } from './fakepageelement.js';
|
|
6
6
|
import { newFakePageBackground } from './fakepagebackground.js';
|
|
7
|
+
import { newFakeColorScheme } from './fakecolorscheme.js';
|
|
7
8
|
import { asSpecificPageElement } from './pageelementfactory.js';
|
|
8
9
|
|
|
9
10
|
export const newFakeSlide = (...args) => {
|
|
@@ -86,6 +87,14 @@ export class FakeSlide {
|
|
|
86
87
|
return background ? newFakePageBackground(this) : null;
|
|
87
88
|
}
|
|
88
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Gets the color scheme of the slide.
|
|
92
|
+
* @returns {FakeColorScheme} The color scheme.
|
|
93
|
+
*/
|
|
94
|
+
getColorScheme() {
|
|
95
|
+
return newFakeColorScheme(this);
|
|
96
|
+
}
|
|
97
|
+
|
|
89
98
|
/**
|
|
90
99
|
* Gets the list of tables on the slide.
|
|
91
100
|
* @returns {FakeTable[]} The tables.
|
|
@@ -17,10 +17,11 @@ export class FakeTextRange {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
get __resource() {
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
const shapeResource = this.__shape.__resource;
|
|
21
|
+
if (shapeResource && shapeResource.shape && shapeResource.shape.text) {
|
|
22
|
+
return shapeResource.shape.text;
|
|
22
23
|
}
|
|
23
|
-
return
|
|
24
|
+
return {};
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
getStartIndex() {
|
|
@@ -42,7 +43,7 @@ export class FakeTextRange {
|
|
|
42
43
|
* @returns {string} The text.
|
|
43
44
|
*/
|
|
44
45
|
asString() {
|
|
45
|
-
const textElements = this.__resource
|
|
46
|
+
const textElements = this.__resource?.textElements || [];
|
|
46
47
|
let fullText = textElements.map(te => {
|
|
47
48
|
if (te.textRun) return te.textRun.content;
|
|
48
49
|
if (te.autoText) return te.autoText.content || '[AutoText]'; // Use placeholder
|
|
@@ -114,12 +115,6 @@ export class FakeTextRange {
|
|
|
114
115
|
|
|
115
116
|
if (requests.length > 0) {
|
|
116
117
|
Slides.Presentations.batchUpdate(requests, presentationId);
|
|
117
|
-
|
|
118
|
-
// REST API documentation: "The field is automatically set to NONE if a request is made that might affect text fitting within its bounding text box."
|
|
119
|
-
if (!this.__resource.autoFit) {
|
|
120
|
-
this.__resource.autoFit = {};
|
|
121
|
-
}
|
|
122
|
-
this.__resource.autoFit.autofitType = AutofitType.NONE;
|
|
123
118
|
}
|
|
124
119
|
|
|
125
120
|
return this;
|
|
@@ -176,7 +171,7 @@ export class FakeTextRange {
|
|
|
176
171
|
* @returns {FakeAutoText[]} The auto texts.
|
|
177
172
|
*/
|
|
178
173
|
getAutoTexts() {
|
|
179
|
-
const textElements = this.__resource
|
|
174
|
+
const textElements = this.__resource?.textElements || [];
|
|
180
175
|
const autoTexts = [];
|
|
181
176
|
let charIndex = 0;
|
|
182
177
|
let autoTextIndex = 0;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const ChartEnumMapping = {
|
|
2
|
+
Position: {
|
|
3
|
+
BOTTOM: "BOTTOM_LEGEND",
|
|
4
|
+
TOP: "TOP_LEGEND",
|
|
5
|
+
LEFT: "LEFT_LEGEND",
|
|
6
|
+
RIGHT: "RIGHT_LEGEND",
|
|
7
|
+
NONE: "NO_LEGEND",
|
|
8
|
+
},
|
|
9
|
+
ChartHiddenDimensionStrategy: {
|
|
10
|
+
IGNORE_BOTH: "SKIP_HIDDEN_ROWS_AND_COLUMNS",
|
|
11
|
+
IGNORE_ROWS: "SKIP_HIDDEN_ROWS",
|
|
12
|
+
IGNORE_COLUMNS: "SKIP_HIDDEN_COLUMNS",
|
|
13
|
+
SHOW_BOTH: "SHOW_ALL",
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Proxies } from '../../support/proxies.js';
|
|
2
|
+
import { BooleanCriteria } from '../enums/sheetsenums.js';
|
|
3
|
+
import { newFakeColor } from '../common/fakecolor.js';
|
|
4
|
+
import { makeColorFromApi } from '../common/fakecolorbuilder.js';
|
|
5
|
+
|
|
6
|
+
export const newFakeBooleanCondition = (...args) => {
|
|
7
|
+
return Proxies.guard(new FakeBooleanCondition(...args));
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export class FakeBooleanCondition {
|
|
11
|
+
constructor(apiCondition, format) {
|
|
12
|
+
this.__apiCondition = apiCondition;
|
|
13
|
+
this.__format = format || {};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getBackgroundObject() {
|
|
17
|
+
if (this.__format.backgroundColorStyle) {
|
|
18
|
+
return makeColorFromApi(this.__format.backgroundColorStyle);
|
|
19
|
+
}
|
|
20
|
+
if (this.__format.backgroundColor) {
|
|
21
|
+
return makeColorFromApi({ rgbColor: this.__format.backgroundColor });
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getBold() {
|
|
27
|
+
return this.__format.textFormat?.bold ?? null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getCriteriaType() {
|
|
31
|
+
// The API uses slightly different strings than the GAS enum for many rules
|
|
32
|
+
const map = {
|
|
33
|
+
'BLANK': 'CELL_EMPTY',
|
|
34
|
+
'NOT_BLANK': 'CELL_NOT_EMPTY',
|
|
35
|
+
'DATE_AFTER': 'DATE_AFTER',
|
|
36
|
+
'DATE_BEFORE': 'DATE_BEFORE',
|
|
37
|
+
'DATE_EQ': 'DATE_EQUAL_TO',
|
|
38
|
+
'DATE_NOT_EQ': 'DATE_NOT_EQUAL_TO',
|
|
39
|
+
'DATE_AFTER_RELATIVE': 'DATE_AFTER_RELATIVE',
|
|
40
|
+
'DATE_BEFORE_RELATIVE': 'DATE_BEFORE_RELATIVE',
|
|
41
|
+
'DATE_EQUAL_TO_RELATIVE': 'DATE_EQUAL_TO_RELATIVE',
|
|
42
|
+
'DATE_EQ_RELATIVE': 'DATE_EQUAL_TO_RELATIVE',
|
|
43
|
+
'NUMBER_BETWEEN': 'NUMBER_BETWEEN',
|
|
44
|
+
'NUMBER_NOT_BETWEEN': 'NUMBER_NOT_BETWEEN',
|
|
45
|
+
'NUMBER_EQ': 'NUMBER_EQUAL_TO',
|
|
46
|
+
'NUMBER_NOT_EQ': 'NUMBER_NOT_EQUAL_TO',
|
|
47
|
+
'NUMBER_GREATER': 'NUMBER_GREATER_THAN',
|
|
48
|
+
'NUMBER_GREATER_THAN_EQ': 'NUMBER_GREATER_THAN_OR_EQUAL_TO',
|
|
49
|
+
'NUMBER_LESS': 'NUMBER_LESS_THAN',
|
|
50
|
+
'NUMBER_LESS_THAN_EQ': 'NUMBER_LESS_THAN_OR_EQUAL_TO',
|
|
51
|
+
'TEXT_CONTAINS': 'TEXT_CONTAINS',
|
|
52
|
+
'TEXT_NOT_CONTAINS': 'TEXT_DOES_NOT_CONTAIN',
|
|
53
|
+
'TEXT_EQ': 'TEXT_EQUAL_TO',
|
|
54
|
+
'TEXT_NOT_EQ': 'TEXT_NOT_EQUAL_TO',
|
|
55
|
+
'TEXT_STARTS_WITH': 'TEXT_STARTS_WITH',
|
|
56
|
+
'TEXT_ENDS_WITH': 'TEXT_ENDS_WITH',
|
|
57
|
+
'CUSTOM_FORMULA': 'CUSTOM_FORMULA'
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// If the API value contains RELATIVE properties it should probably be resolved to the _RELATIVE equivalents
|
|
61
|
+
// However the API 'type' doesn't usually distinguish between DATE_EQ and DATE_EQUAL_TO_RELATIVE at the root level,
|
|
62
|
+
// they are often just DATE_EQ and the value object specifies if it's relative.
|
|
63
|
+
// Let's infer if it's relative.
|
|
64
|
+
let type = this.__apiCondition.type;
|
|
65
|
+
if (type && type.startsWith('DATE_')) {
|
|
66
|
+
const isRelative = this.__apiCondition.values && this.__apiCondition.values.some(v => v.relativeDate !== undefined);
|
|
67
|
+
if (isRelative && !type.endsWith('_RELATIVE')) {
|
|
68
|
+
type += '_RELATIVE';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const enumKey = map[type] || type;
|
|
73
|
+
|
|
74
|
+
// Return the Enum if available
|
|
75
|
+
if (BooleanCriteria[enumKey]) {
|
|
76
|
+
return BooleanCriteria[enumKey];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return enumKey || null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getCriteriaValues() {
|
|
83
|
+
if (!this.__apiCondition.values) return [];
|
|
84
|
+
|
|
85
|
+
// API condition values are typically { userEnteredValue: 'string' } or { relativeDate: 'TODAY' }
|
|
86
|
+
return this.__apiCondition.values.map(v => {
|
|
87
|
+
if (v.userEnteredValue !== undefined) return v.userEnteredValue;
|
|
88
|
+
// In Apps Script, RelativeDate enum values are typically returned as strings matching the enum
|
|
89
|
+
if (v.relativeDate !== undefined) return SpreadsheetApp.RelativeDate[v.relativeDate] || v.relativeDate;
|
|
90
|
+
return null;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
getFontColorObject() {
|
|
95
|
+
if (this.__format.textFormat?.foregroundColorStyle) {
|
|
96
|
+
return makeColorFromApi(this.__format.textFormat.foregroundColorStyle);
|
|
97
|
+
}
|
|
98
|
+
if (this.__format.textFormat?.foregroundColor) {
|
|
99
|
+
return makeColorFromApi({ rgbColor: this.__format.textFormat.foregroundColor });
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
getItalic() {
|
|
105
|
+
return this.__format.textFormat?.italic ?? null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
getStrikethrough() {
|
|
109
|
+
return this.__format.textFormat?.strikethrough ?? null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
getUnderline() {
|
|
113
|
+
return this.__format.textFormat?.underline ?? null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
toString() {
|
|
117
|
+
return 'BooleanCondition';
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Proxies } from "../../support/proxies.js";
|
|
2
|
+
import { newFakeCellImageBuilder } from "./fakecellimagebuilder.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fake CellImage
|
|
6
|
+
* @class FakeCellImage
|
|
7
|
+
*/
|
|
8
|
+
export class FakeCellImage {
|
|
9
|
+
constructor(properties) {
|
|
10
|
+
this._properties = properties || {};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
getAltTextDescription() {
|
|
14
|
+
return this._properties.altTextDescription || null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
getAltTextTitle() {
|
|
18
|
+
return this._properties.altTextTitle || null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
getContentUrl() {
|
|
22
|
+
const url = this._properties.sourceUrl || null;
|
|
23
|
+
if (url && !url.includes('googleusercontent.com')) {
|
|
24
|
+
throw new Error('Unexpected error while getting the method or property getContentUrl on object SpreadsheetApp.CellImage.');
|
|
25
|
+
}
|
|
26
|
+
return url;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
toBuilder() {
|
|
30
|
+
const builder = newFakeCellImageBuilder();
|
|
31
|
+
if (this._properties.sourceUrl) builder.setSourceUrl(this._properties.sourceUrl);
|
|
32
|
+
if (this._properties.altTextTitle) builder.setAltTextTitle(this._properties.altTextTitle);
|
|
33
|
+
if (this._properties.altTextDescription) builder.setAltTextDescription(this._properties.altTextDescription);
|
|
34
|
+
return builder;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
toString() {
|
|
38
|
+
return 'CellImage';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const newFakeCellImage = (...args) => Proxies.guard(new FakeCellImage(...args));
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Proxies } from "../../support/proxies.js";
|
|
2
|
+
import { newFakeCellImage } from "./fakecellimage.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fake CellImageBuilder
|
|
6
|
+
* @class FakeCellImageBuilder
|
|
7
|
+
*/
|
|
8
|
+
export class FakeCellImageBuilder {
|
|
9
|
+
constructor() {
|
|
10
|
+
this._properties = {};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
build() {
|
|
14
|
+
return newFakeCellImage(this._properties);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
getAltTextDescription() {
|
|
18
|
+
return this._properties.altTextDescription || null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
getAltTextTitle() {
|
|
22
|
+
return this._properties.altTextTitle || null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getContentUrl() {
|
|
26
|
+
const url = this._properties.sourceUrl || null;
|
|
27
|
+
if (url && !url.includes('googleusercontent.com')) {
|
|
28
|
+
throw new Error('Unexpected error while getting the method or property getContentUrl on object SpreadsheetApp.CellImageBuilder.');
|
|
29
|
+
}
|
|
30
|
+
return url;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
setAltTextDescription(description) {
|
|
34
|
+
this._properties.altTextDescription = description;
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
setAltTextTitle(title) {
|
|
39
|
+
this._properties.altTextTitle = title;
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
setSourceUrl(url) {
|
|
44
|
+
this._properties.sourceUrl = url;
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
toBuilder() {
|
|
49
|
+
const builder = newFakeCellImageBuilder();
|
|
50
|
+
builder._properties = { ...this._properties };
|
|
51
|
+
return builder;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
toString() {
|
|
55
|
+
return 'CellImageBuilder';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const newFakeCellImageBuilder = (...args) => Proxies.guard(new FakeCellImageBuilder(...args));
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Proxies } from '../../support/proxies.js';
|
|
2
|
+
import { newFakeBooleanCondition } from './fakebooleancondition.js';
|
|
3
|
+
import { newFakeGradientCondition } from './fakegradientcondition.js';
|
|
4
|
+
import { newFakeSheetRange } from './fakesheetrange.js';
|
|
5
|
+
import { newFakeConditionalFormatRuleBuilder } from './fakeconditionalformatrulebuilder.js';
|
|
6
|
+
|
|
7
|
+
export const newFakeConditionalFormatRule = (...args) => {
|
|
8
|
+
return Proxies.guard(new FakeConditionalFormatRule(...args));
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export class FakeConditionalFormatRule {
|
|
12
|
+
constructor(apiRule, sheet) {
|
|
13
|
+
this.__apiRule = apiRule;
|
|
14
|
+
this.__sheet = sheet;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
copy() {
|
|
18
|
+
// Builder takes spreadsheet. Sheet gives us spreadsheet via getParent()
|
|
19
|
+
return newFakeConditionalFormatRuleBuilder(this.__apiRule, this.__sheet.getParent());
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getBooleanCondition() {
|
|
23
|
+
if (!this.__apiRule.booleanRule) return null;
|
|
24
|
+
return newFakeBooleanCondition(
|
|
25
|
+
this.__apiRule.booleanRule.condition,
|
|
26
|
+
this.__apiRule.booleanRule.format
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getGradientCondition() {
|
|
31
|
+
if (!this.__apiRule.gradientRule) return null;
|
|
32
|
+
return newFakeGradientCondition(this.__apiRule.gradientRule);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getRanges() {
|
|
36
|
+
if (!this.__apiRule.ranges) return [];
|
|
37
|
+
return this.__apiRule.ranges.map(gridRange => {
|
|
38
|
+
const sheetId = gridRange.sheetId;
|
|
39
|
+
let sheet = this.__sheet; // Default to the sheet this rule was fetched from
|
|
40
|
+
if (sheetId !== undefined && sheet.getSheetId() !== sheetId) {
|
|
41
|
+
sheet = this.__sheet.getParent().getSheets().find(s => s.getSheetId() === sheetId);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!sheet) return null;
|
|
45
|
+
return newFakeSheetRange(
|
|
46
|
+
gridRange,
|
|
47
|
+
sheet
|
|
48
|
+
);
|
|
49
|
+
}).filter(Boolean);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
toString() {
|
|
53
|
+
return 'ConditionalFormatRule';
|
|
54
|
+
}
|
|
55
|
+
}
|