@mcpher/gas-fakes 2.5.2 → 2.5.3

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.
Files changed (50) hide show
  1. package/README.md +8 -1
  2. package/package.json +1 -1
  3. package/pngs/srv.jpg +0 -0
  4. package/src/cli/app.js +1 -0
  5. package/src/cli/togas.js +23 -14
  6. package/src/index.js +1 -0
  7. package/src/services/advslides/fakeadvslides.js +11 -5
  8. package/src/services/base/app.js +9 -0
  9. package/src/services/base/fakebase.js +28 -0
  10. package/src/services/common/fakeadvresource.js +3 -2
  11. package/src/services/enums/baseenums.js +47 -0
  12. package/src/services/enums/slidesenums.js +3 -1
  13. package/src/services/html/serverworker.js +1 -1
  14. package/src/services/slidesapp/app.js +5 -0
  15. package/src/services/slidesapp/fakeautofit.js +1 -1
  16. package/src/services/slidesapp/fakeborder.js +106 -0
  17. package/src/services/slidesapp/fakecolorscheme.js +1 -1
  18. package/src/services/slidesapp/fakefill.js +216 -0
  19. package/src/services/slidesapp/fakegroup.js +35 -0
  20. package/src/services/slidesapp/fakeimage.js +118 -0
  21. package/src/services/slidesapp/fakelayout.js +351 -0
  22. package/src/services/slidesapp/fakeline.js +2 -2
  23. package/src/services/slidesapp/fakelinefill.js +15 -16
  24. package/src/services/slidesapp/fakelink.js +20 -3
  25. package/src/services/slidesapp/fakelist.js +36 -0
  26. package/src/services/slidesapp/fakeliststyle.js +105 -0
  27. package/src/services/slidesapp/fakemaster.js +358 -0
  28. package/src/services/slidesapp/fakenotesmaster.js +125 -0
  29. package/src/services/slidesapp/fakenotespage.js +102 -2
  30. package/src/services/slidesapp/fakepagebackground.js +109 -1
  31. package/src/services/slidesapp/fakepageelement.js +157 -18
  32. package/src/services/slidesapp/fakepageelementrange.js +28 -0
  33. package/src/services/slidesapp/fakepagerange.js +28 -0
  34. package/src/services/slidesapp/fakeparagraphstyle.js +139 -0
  35. package/src/services/slidesapp/fakepicturefill.js +32 -0
  36. package/src/services/slidesapp/fakepresentation.js +126 -2
  37. package/src/services/slidesapp/fakeshape.js +9 -0
  38. package/src/services/slidesapp/fakeslide.js +216 -24
  39. package/src/services/slidesapp/fakesolidfill.js +45 -0
  40. package/src/services/slidesapp/fakespeakerspotlight.js +18 -0
  41. package/src/services/slidesapp/faketable.js +55 -9
  42. package/src/services/slidesapp/faketablecell.js +141 -12
  43. package/src/services/slidesapp/faketablecellrange.js +28 -0
  44. package/src/services/slidesapp/faketablecolumn.js +72 -0
  45. package/src/services/slidesapp/faketablerow.js +31 -0
  46. package/src/services/slidesapp/faketextrange.js +179 -135
  47. package/src/services/slidesapp/faketextstyle.js +158 -0
  48. package/src/services/slidesapp/fakevideo.js +35 -0
  49. package/src/services/slidesapp/fakewordart.js +22 -0
  50. package/src/services/slidesapp/pageelementfactory.js +24 -1
@@ -0,0 +1,139 @@
1
+ import { Proxies } from '../../support/proxies.js';
2
+ import { ParagraphAlignment, SpacingMode, TextDirection } from '../enums/slidesenums.js';
3
+
4
+ /**
5
+ * create a new FakeParagraphStyle instance
6
+ * @param {...any} args
7
+ * @returns {FakeParagraphStyle}
8
+ */
9
+ export const newFakeParagraphStyle = (...args) => {
10
+ return Proxies.guard(new FakeParagraphStyle(...args));
11
+ };
12
+
13
+ export class FakeParagraphStyle {
14
+ constructor(textRange) {
15
+ this.__textRange = textRange;
16
+ }
17
+
18
+ get __style() {
19
+ // Similar to TextStyle, find first paragraph marker in range
20
+ const resource = this.__textRange.__resource;
21
+ const elements = resource?.textElements || [];
22
+ const start = this.__textRange.getStartIndex();
23
+
24
+ let currentIndex = 0;
25
+ for (const element of elements) {
26
+ const length = element.textRun?.content?.length || (element.autoText ? 1 : 0);
27
+ if (currentIndex >= start && element.paragraphMarker) {
28
+ return element.paragraphMarker.style || {};
29
+ }
30
+ currentIndex += length;
31
+ }
32
+ return {};
33
+ }
34
+
35
+ getIndentEnd() {
36
+ return this.__textRange.__shape.__normalize(this.__style.indentEnd) || 0;
37
+ }
38
+
39
+ getIndentFirstLine() {
40
+ return this.__textRange.__shape.__normalize(this.__style.indentFirstLine) || 0;
41
+ }
42
+
43
+ getIndentStart() {
44
+ return this.__textRange.__shape.__normalize(this.__style.indentStart) || 0;
45
+ }
46
+
47
+ getLineSpacing() {
48
+ return this.__style.lineSpacing || 100;
49
+ }
50
+
51
+ getParagraphAlignment() {
52
+ return ParagraphAlignment[this.__style.alignment || 'START'];
53
+ }
54
+
55
+ getSpaceAbove() {
56
+ return this.__textRange.__shape.__normalize(this.__style.spaceAbove) || 0;
57
+ }
58
+
59
+ getSpaceBelow() {
60
+ return this.__textRange.__shape.__normalize(this.__style.spaceBelow) || 0;
61
+ }
62
+
63
+ getSpacingMode() {
64
+ return SpacingMode[this.__style.spacingMode || 'NEVER_COLLAPSE'];
65
+ }
66
+
67
+ getTextDirection() {
68
+ return TextDirection[this.__style.direction || 'LEFT_TO_RIGHT'];
69
+ }
70
+
71
+ __update(props, fields) {
72
+ const presentationId = this.__textRange.__shape.__presentation.getId();
73
+ const objectId = this.__textRange.__shape.getObjectId();
74
+ const cellLocation = this.__textRange.__shape.__cellLocation;
75
+
76
+ Slides.Presentations.batchUpdate({ requests: [{
77
+ updateParagraphStyle: {
78
+ objectId,
79
+ cellLocation,
80
+ style: props,
81
+ fields: fields || Object.keys(props).join(','),
82
+ textRange: {
83
+ type: 'FIXED_RANGE',
84
+ startIndex: this.__textRange.getStartIndex(),
85
+ endIndex: this.__textRange.getEndIndex()
86
+ }
87
+ }
88
+ }] }, presentationId);
89
+ }
90
+
91
+ setIndentEnd(indent) {
92
+ this.__update({ indentEnd: { magnitude: indent, unit: 'PT' } }, 'indentEnd');
93
+ return this;
94
+ }
95
+
96
+ setIndentFirstLine(indent) {
97
+ this.__update({ indentFirstLine: { magnitude: indent, unit: 'PT' } }, 'indentFirstLine');
98
+ return this;
99
+ }
100
+
101
+ setIndentStart(indent) {
102
+ this.__update({ indentStart: { magnitude: indent, unit: 'PT' } }, 'indentStart');
103
+ return this;
104
+ }
105
+
106
+ setLineSpacing(spacing) {
107
+ this.__update({ lineSpacing: spacing }, 'lineSpacing');
108
+ return this;
109
+ }
110
+
111
+ setParagraphAlignment(alignment) {
112
+ this.__update({ alignment: alignment.toString() }, 'alignment');
113
+ return this;
114
+ }
115
+
116
+ setSpaceAbove(space) {
117
+ this.__update({ spaceAbove: { magnitude: space, unit: 'PT' } }, 'spaceAbove');
118
+ return this;
119
+ }
120
+
121
+ setSpaceBelow(space) {
122
+ this.__update({ spaceBelow: { magnitude: space, unit: 'PT' } }, 'spaceBelow');
123
+ return this;
124
+ }
125
+
126
+ setSpacingMode(mode) {
127
+ this.__update({ spacingMode: mode.toString() }, 'spacingMode');
128
+ return this;
129
+ }
130
+
131
+ setTextDirection(direction) {
132
+ this.__update({ direction: direction.toString() }, 'direction');
133
+ return this;
134
+ }
135
+
136
+ toString() {
137
+ return 'ParagraphStyle';
138
+ }
139
+ }
@@ -0,0 +1,32 @@
1
+ import { Proxies } from '../../support/proxies.js';
2
+
3
+ export const newFakePictureFill = (...args) => {
4
+ return Proxies.guard(new FakePictureFill(...args));
5
+ };
6
+
7
+ export class FakePictureFill {
8
+ constructor(resource, page) {
9
+ this.__resource = resource;
10
+ this.__page = page;
11
+ }
12
+
13
+ getAs(contentType) {
14
+ return this.getBlob().getAs(contentType);
15
+ }
16
+
17
+ getBlob() {
18
+ return UrlFetchApp.fetch(this.getContentUrl()).getBlob();
19
+ }
20
+
21
+ getContentUrl() {
22
+ return this.__resource.contentUrl || '';
23
+ }
24
+
25
+ getSourceUrl() {
26
+ return this.__resource.sourceUrl || '';
27
+ }
28
+
29
+ toString() {
30
+ return 'PictureFill';
31
+ }
32
+ }
@@ -1,6 +1,8 @@
1
1
  import { Proxies } from '../../support/proxies.js';
2
2
  import { newFakeSlide } from './fakeslide.js';
3
3
  import { newFakeMaster } from './fakemaster.js';
4
+ import { newFakeNotesMaster } from './fakenotesmaster.js';
5
+ import { newFakeLayout } from './fakelayout.js';
4
6
  import { newFakeColorScheme } from './fakecolorscheme.js';
5
7
 
6
8
  export const newFakePresentation = (...args) => {
@@ -28,6 +30,45 @@ export class FakePresentation {
28
30
  saveAndClose() {
29
31
  // this is a no-op in fake environment since it is stateless
30
32
  }
33
+
34
+ addEditor(emailAddress) {
35
+ this.__file.addEditor(emailAddress);
36
+ return this;
37
+ }
38
+
39
+ addEditors(emailAddresses) {
40
+ this.__file.addEditors(emailAddresses);
41
+ return this;
42
+ }
43
+
44
+ addViewer(emailAddress) {
45
+ this.__file.addViewer(emailAddress);
46
+ return this;
47
+ }
48
+
49
+ addViewers(emailAddresses) {
50
+ this.__file.addViewers(emailAddresses);
51
+ return this;
52
+ }
53
+
54
+ getEditors() {
55
+ return this.__file.getEditors();
56
+ }
57
+
58
+ getViewers() {
59
+ return this.__file.getViewers();
60
+ }
61
+
62
+ removeEditor(emailAddress) {
63
+ this.__file.removeEditor(emailAddress);
64
+ return this;
65
+ }
66
+
67
+ removeViewer(emailAddress) {
68
+ this.__file.removeViewer(emailAddress);
69
+ return this;
70
+ }
71
+
31
72
  /**
32
73
  * Gets the ID of the presentation.
33
74
  * @returns {string} The presentation ID.
@@ -44,6 +85,10 @@ export class FakePresentation {
44
85
  return this.__resource.title;
45
86
  }
46
87
 
88
+ setName(name) {
89
+ this.__file.setName(name);
90
+ }
91
+
47
92
  /**
48
93
  * Gets the URL of the presentation.
49
94
  * @returns {string} The presentation URL.
@@ -52,6 +97,38 @@ export class FakePresentation {
52
97
  return `https://docs.google.com/presentation/d/${this.getId()}/edit`;
53
98
  }
54
99
 
100
+ getPageHeight() {
101
+ const size = this.__resource.pageSize;
102
+ return this.__normalize(size?.height);
103
+ }
104
+
105
+ getPageWidth() {
106
+ const size = this.__resource.pageSize;
107
+ return this.__normalize(size?.width);
108
+ }
109
+
110
+ getNotesPageHeight() {
111
+ const size = this.__resource.notesMaster?.notesVisualProperties?.pageSize || this.__resource.pageSize;
112
+ return this.__normalize(size?.height);
113
+ }
114
+
115
+ getNotesPageWidth() {
116
+ const size = this.__resource.notesMaster?.notesVisualProperties?.pageSize || this.__resource.pageSize;
117
+ return this.__normalize(size?.width);
118
+ }
119
+
120
+ __normalize(val) {
121
+ if (!val) return 0;
122
+ if (typeof val === 'number') {
123
+ return val > 5000 ? val / 12700 : val;
124
+ }
125
+ if (typeof val.magnitude === 'number') {
126
+ const isEMU = val.unit === 'EMU' || val.magnitude > 5000;
127
+ return isEMU ? val.magnitude / 12700 : val.magnitude;
128
+ }
129
+ return val || 0;
130
+ }
131
+
55
132
  /**
56
133
  * Gets the masters in the presentation.
57
134
  * @returns {FakeMaster[]} The masters.
@@ -60,6 +137,14 @@ export class FakePresentation {
60
137
  return (this.__resource.masters || []).map(m => newFakeMaster(m, this));
61
138
  }
62
139
 
140
+ /**
141
+ * Gets the layouts in the presentation.
142
+ * @returns {FakeLayout[]} The layouts.
143
+ */
144
+ getLayouts() {
145
+ return (this.__resource.layouts || []).map(l => newFakeLayout(l, this));
146
+ }
147
+
63
148
  /**
64
149
  * Gets a master by its ID.
65
150
  * @param {string} id The master ID.
@@ -69,6 +154,15 @@ export class FakePresentation {
69
154
  return this.getMasters().find(m => m.getObjectId() === id) || null;
70
155
  }
71
156
 
157
+ /**
158
+ * Gets the notes master in the presentation.
159
+ * @returns {FakeNotesMaster | null} The notes master.
160
+ */
161
+ getNotesMaster() {
162
+ const notesMaster = this.__resource.notesMaster;
163
+ return notesMaster ? newFakeNotesMaster(notesMaster, this) : null;
164
+ }
165
+
72
166
  /**
73
167
  * Gets the slides in the presentation.
74
168
  * @returns {FakeSlide[]} The slides.
@@ -86,6 +180,36 @@ export class FakePresentation {
86
180
  return this.getSlides().find(s => s.getObjectId() === id) || null;
87
181
  }
88
182
 
183
+ getPageElementById(id) {
184
+ const pages = [...this.getSlides(), ...this.getLayouts(), ...this.getMasters()];
185
+ const nm = this.getNotesMaster();
186
+ if (nm) pages.push(nm);
187
+
188
+ for (const page of pages) {
189
+ const el = page.getPageElementById(id);
190
+ if (el) return el;
191
+ }
192
+ return null;
193
+ }
194
+
195
+ getSelection() {
196
+ return null; // Mock
197
+ }
198
+
199
+ replaceAllText(findText, replaceText, matchCase = false) {
200
+ const requests = [{
201
+ replaceAllText: {
202
+ replaceText,
203
+ containsText: {
204
+ text: findText,
205
+ matchCase
206
+ }
207
+ }
208
+ }];
209
+ const response = Slides.Presentations.batchUpdate({ requests }, this.getId());
210
+ return response.replies[0].replaceAllText.occurrencesChanged || 0;
211
+ }
212
+
89
213
  /**
90
214
  * Appends a new slide to the presentation.
91
215
  * @param {string} [layout] The layout to use (optional).
@@ -100,7 +224,7 @@ export class FakePresentation {
100
224
  }
101
225
  }];
102
226
  try {
103
- Slides.Presentations.batchUpdate(requests, this.getId());
227
+ Slides.Presentations.batchUpdate({ requests }, this.getId());
104
228
  } catch (err) {
105
229
  // If it already exists, it means a previous attempt succeeded but timed out
106
230
  if (!err?.message?.includes('already exists')) throw err;
@@ -124,7 +248,7 @@ export class FakePresentation {
124
248
  }
125
249
  }];
126
250
  try {
127
- Slides.Presentations.batchUpdate(requests, this.getId());
251
+ Slides.Presentations.batchUpdate({ requests }, this.getId());
128
252
  } catch (err) {
129
253
  if (!err?.message?.includes('already exists')) throw err;
130
254
  }
@@ -3,6 +3,7 @@ import { newFakeTextRange } from './faketextrange.js';
3
3
  import { newFakeAutofit } from './fakeautofit.js';
4
4
  import { newFakeConnectionSite } from './fakeconnectionsite.js';
5
5
  import { FakePageElement, PageElementRegistry } from './fakepageelement.js';
6
+ import { newFakeFill } from './fakefill.js';
6
7
 
7
8
  export const newFakeShape = (...args) => {
8
9
  const shape = Proxies.guard(new FakeShape(...args));
@@ -33,6 +34,14 @@ export class FakeShape extends FakePageElement {
33
34
  return newFakeAutofit(this);
34
35
  }
35
36
 
37
+ /**
38
+ * Gets the fill of the shape.
39
+ * @returns {FakeFill} The fill object.
40
+ */
41
+ getFill() {
42
+ return newFakeFill(this);
43
+ }
44
+
36
45
  /**
37
46
  * Gets the connection sites on the shape.
38
47
  * @returns {FakeConnectionSite[]} The connection sites.