@mcpher/gas-fakes 1.2.26 → 1.2.27

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 (36) hide show
  1. package/package.json +1 -1
  2. package/src/cli/setup.js +5 -5
  3. package/src/cli/utils.js +2 -4
  4. package/src/services/enums/slidesenums.js +1 -1
  5. package/src/services/formapp/fakechoiceitem.js +1 -1
  6. package/src/services/formapp/fakeform.js +4 -3
  7. package/src/services/formapp/fakeformitem.js +1 -2
  8. package/src/services/formapp/fakeformresponse.js +3 -2
  9. package/src/services/formapp/fakelistitem.js +3 -2
  10. package/src/services/slidesapp/fakeaffinetransform.js +55 -0
  11. package/src/services/slidesapp/fakeaffinetransformbuilder.js +64 -0
  12. package/src/services/slidesapp/fakeautofit.js +49 -0
  13. package/src/services/slidesapp/fakeautotext.js +29 -0
  14. package/src/services/slidesapp/fakeconnectionsite.js +24 -0
  15. package/src/services/slidesapp/fakelayout.js +38 -0
  16. package/src/services/slidesapp/fakeline.js +195 -0
  17. package/src/services/slidesapp/fakelinefill.js +58 -0
  18. package/src/services/slidesapp/fakelink.js +31 -0
  19. package/src/services/slidesapp/fakemaster.js +28 -0
  20. package/src/services/slidesapp/fakenotespage.js +19 -0
  21. package/src/services/slidesapp/fakepagebackground.js +17 -0
  22. package/src/services/slidesapp/fakepageelement.js +395 -0
  23. package/src/services/slidesapp/fakeparagraph.js +46 -0
  24. package/src/services/slidesapp/fakepoint.js +24 -0
  25. package/src/services/slidesapp/fakepresentation.js +61 -3
  26. package/src/services/slidesapp/fakeshape.js +49 -0
  27. package/src/services/slidesapp/fakeslide.js +232 -0
  28. package/src/services/slidesapp/fakeslidesapp.js +5 -0
  29. package/src/services/slidesapp/faketextrange.js +253 -0
  30. package/src/services/slidesapp/pageelementfactory.js +19 -0
  31. package/src/services/stores/gasflex.js +1 -1
  32. package/src/services/urlfetchapp/app.js +17 -1
  33. package/src/support/sxfetch.js +39 -13
  34. package/src/support/sxforms.js +3 -1
  35. package/src/support/syncit.js +7 -2
  36. package/src/support/utils.js +2 -0
package/package.json CHANGED
@@ -34,7 +34,7 @@
34
34
  },
35
35
  "name": "@mcpher/gas-fakes",
36
36
  "author": "bruce mcpherson",
37
- "version": "1.2.26",
37
+ "version": "1.2.27",
38
38
  "license": "MIT",
39
39
  "main": "main.js",
40
40
  "description": "A proof of concept implementation of Apps Script Environment on Node",
package/src/cli/setup.js CHANGED
@@ -302,8 +302,8 @@ export async function initializeConfiguration(options = {}) {
302
302
  existingConfig.LOG_DESTINATION
303
303
  ) > -1
304
304
  ? ["CONSOLE", "CLOUD", "BOTH", "NONE"].indexOf(
305
- existingConfig.LOG_DESTINATION
306
- )
305
+ existingConfig.LOG_DESTINATION
306
+ )
307
307
  : 0,
308
308
  },
309
309
  {
@@ -316,7 +316,7 @@ export async function initializeConfiguration(options = {}) {
316
316
  ],
317
317
  initial:
318
318
  ["FILE", "UPSTASH"].indexOf(existingConfig.STORE_TYPE?.toUpperCase()) >
319
- -1
319
+ -1
320
320
  ? ["FILE", "UPSTASH"].indexOf(existingConfig.STORE_TYPE.toUpperCase())
321
321
  : 0,
322
322
  },
@@ -408,9 +408,9 @@ export async function initializeConfiguration(options = {}) {
408
408
  /**
409
409
  * Handles the 'auth' command to authenticate with Google Cloud.
410
410
  */
411
- export function authenticateUser() {
411
+ export async function authenticateUser() {
412
412
  // First, check if gcloud CLI is available.
413
- checkForGcloudCli();
413
+ await checkForGcloudCli();
414
414
 
415
415
  const rootDirectory = process.cwd();
416
416
  const envPath = path.join(rootDirectory, ".env");
package/src/cli/utils.js CHANGED
@@ -1,6 +1,5 @@
1
- import { spawn } from "child_process";
1
+ import { spawn, execSync } from "child_process";
2
2
  import { createRequire } from "node:module";
3
-
4
3
  const require = createRequire(import.meta.url);
5
4
  const pjson = require("../../package.json");
6
5
 
@@ -73,8 +72,7 @@ export async function checkForGcloudCli() {
73
72
  /**
74
73
  * Helper function to run a shell command sync (used in setup).
75
74
  */
76
- export async function runCommandSync(command) {
77
- const { execSync } = await import("child_process");
75
+ export function runCommandSync(command) {
78
76
  try {
79
77
  execSync(command, { stdio: "inherit" });
80
78
  } catch (error) {
@@ -1,4 +1,4 @@
1
- import { newFakeGasenum} from "@mcpher/fake-gasenum";
1
+ import { newFakeGasenum } from "@mcpher/fake-gasenum";
2
2
 
3
3
  export const AlignmentPosition = newFakeGasenum([
4
4
  "CENTER",
@@ -45,7 +45,7 @@ export class FakeChoiceItem extends newFakeFormItem().constructor {
45
45
 
46
46
  const updateRequest = Forms.newRequest().setUpdateItem({
47
47
  item: {
48
- itemId: this.getId(),
48
+ itemId: this.__itemId,
49
49
  questionItem: {
50
50
  question: {
51
51
  choiceQuestion: choiceQuestion,
@@ -13,7 +13,7 @@ import { newFakeListItem } from './fakelistitem.js';
13
13
  import { newFakePageBreakItem } from './fakepagebreakitem.js';
14
14
  import { newFakeTextItem } from './faketextitem.js';
15
15
  import { signatureArgs } from '../../support/helpers.js';
16
- import {Utils} from '../../support/utils.js';
16
+ import { Utils } from '../../support/utils.js';
17
17
  const { is } = Utils
18
18
  export const newFakeForm = (...args) => {
19
19
  return Proxies.guard(new FakeForm(...args));
@@ -53,7 +53,7 @@ export class FakeForm {
53
53
  return this;
54
54
  }
55
55
 
56
-
56
+
57
57
  saveAndClose() {
58
58
  // this is a no-op in fake environment since it is stateless
59
59
  }
@@ -298,6 +298,7 @@ export class FakeForm {
298
298
  if (!this.__resource.items) {
299
299
  return null;
300
300
  }
301
+ const hexId = Utils.toHex(id);
301
302
  const isKnownItem = (id, item) => {
302
303
  if (item.itemId === id) return true;
303
304
  if (item.questionItem?.question?.questionId === id) return true;
@@ -307,7 +308,7 @@ export class FakeForm {
307
308
  return found
308
309
  }
309
310
 
310
- const itemResource = this.__resource.items.find((item) => isKnownItem(id, item));
311
+ const itemResource = this.__resource.items.find((item) => isKnownItem(hexId, item));
311
312
 
312
313
  if (!itemResource) {
313
314
  return null;
@@ -114,8 +114,7 @@ export class FakeFormItem {
114
114
  }
115
115
 
116
116
  getId() {
117
- // Live Apps Script returns IDs as decimal numbers, not the hex strings from the API.
118
- return parseInt(this.__itemId, 16); // Convert to decimal
117
+ return Utils.fromHex(this.__itemId);
119
118
  }
120
119
 
121
120
  getIndex() {
@@ -1,5 +1,6 @@
1
1
  import { Proxies } from '../../support/proxies.js';
2
2
  import { newFakeItemResponse } from './fakeitemresponse.js';
3
+ import { Utils } from '../../support/utils.js';
3
4
 
4
5
  export const newFakeFormResponse = (...args) => {
5
6
  return Proxies.guard(new FakeFormResponse(...args));
@@ -33,7 +34,7 @@ export class FakeFormResponse {
33
34
  * @returns {number} the unique hex ID converted to a decimal number
34
35
  */
35
36
  getId() {
36
- return parseInt(this.__resource.responseId, 16);
37
+ return Utils.fromHex(this.__resource.responseId);
37
38
  }
38
39
 
39
40
  /**
@@ -59,7 +60,7 @@ export class FakeFormResponse {
59
60
  const groupedAnswers = new Map();
60
61
 
61
62
  for (const [questionId, answer] of Object.entries(this.__resource.answers)) {
62
- const item = this.__form.getItemById(questionId);
63
+ const item = this.__form.getItemById(Utils.fromHex(questionId));
63
64
 
64
65
  if (item) {
65
66
  const itemId = item.getId(); // Use the unique item ID as the key.
@@ -3,6 +3,7 @@ import { FakeFormItem } from './fakeformitem.js';
3
3
  import { newFakeChoice } from './fakechoice.js';
4
4
  import { registerFormItem } from './formitemregistry.js';
5
5
  import { ItemType } from '../enums/formsenums.js';
6
+ import { Utils } from '../../support/utils.js';
6
7
 
7
8
  export const newFakeListItem = (...args) => {
8
9
  return Proxies.guard(new FakeListItem(...args));
@@ -56,7 +57,7 @@ export class FakeListItem extends FakeFormItem {
56
57
  // Translate from API format back to Apps Script format.
57
58
  if (option.goToSectionId) {
58
59
  navType = 'GO_TO_PAGE';
59
- pageId = option.goToSectionId;
60
+ pageId = Utils.fromHex(option.goToSectionId);
60
61
  } else if (option.goToAction) {
61
62
  switch (option.goToAction) {
62
63
  case 'NEXT_SECTION': navType = 'CONTINUE'; break;
@@ -85,7 +86,7 @@ export class FakeListItem extends FakeFormItem {
85
86
  case 'GO_TO_PAGE':
86
87
  // For navigating to a specific page, you ONLY set the goToSectionId.
87
88
  // The pageId is the itemId of the PageBreakItem.
88
- option.goToSectionId = choice.__pageId;
89
+ option.goToSectionId = Utils.toHex(choice.__pageId);
89
90
  break;
90
91
  case 'CONTINUE':
91
92
  option.goToAction = 'NEXT_SECTION';
@@ -0,0 +1,55 @@
1
+ import { Proxies } from '../../support/proxies.js';
2
+ import { newFakeAffineTransformBuilder } from './fakeaffinetransformbuilder.js';
3
+
4
+ export const newFakeAffineTransform = (...args) => {
5
+ return Proxies.guard(new FakeAffineTransform(...args));
6
+ };
7
+
8
+ export class FakeAffineTransform {
9
+ constructor(scaleX, shearY, shearX, scaleY, translateX, translateY) {
10
+ this.__scaleX = scaleX;
11
+ this.__shearY = shearY;
12
+ this.__shearX = shearX;
13
+ this.__scaleY = scaleY;
14
+ this.__translateX = translateX;
15
+ this.__translateY = translateY;
16
+ }
17
+
18
+ getScaleX() {
19
+ return this.__scaleX;
20
+ }
21
+
22
+ getScaleY() {
23
+ return this.__scaleY;
24
+ }
25
+
26
+ getShearX() {
27
+ return this.__shearX;
28
+ }
29
+
30
+ getShearY() {
31
+ return this.__shearY;
32
+ }
33
+
34
+ getTranslateX() {
35
+ return this.__translateX;
36
+ }
37
+
38
+ getTranslateY() {
39
+ return this.__translateY;
40
+ }
41
+
42
+ toBuilder() {
43
+ return newFakeAffineTransformBuilder()
44
+ .setScaleX(this.__scaleX)
45
+ .setShearY(this.__shearY)
46
+ .setShearX(this.__shearX)
47
+ .setScaleY(this.__scaleY)
48
+ .setTranslateX(this.__translateX)
49
+ .setTranslateY(this.__translateY);
50
+ }
51
+
52
+ toString() {
53
+ return 'AffineTransform';
54
+ }
55
+ }
@@ -0,0 +1,64 @@
1
+ import { Proxies } from '../../support/proxies.js';
2
+ import { newFakeAffineTransform } from './fakeaffinetransform.js';
3
+
4
+ export const newFakeAffineTransformBuilder = (...args) => {
5
+ return Proxies.guard(new FakeAffineTransformBuilder(...args));
6
+ };
7
+
8
+ export class FakeAffineTransformBuilder {
9
+ constructor() {
10
+ // Defaults? Documentation doesn't explicitly specify, but identity matrix is reasonable.
11
+ // scaleX=1, scaleY=1, others 0.
12
+ this.__scaleX = 1;
13
+ this.__shearY = 0;
14
+ this.__shearX = 0;
15
+ this.__scaleY = 1;
16
+ this.__translateX = 0;
17
+ this.__translateY = 0;
18
+ }
19
+
20
+ build() {
21
+ return newFakeAffineTransform(
22
+ this.__scaleX,
23
+ this.__shearY,
24
+ this.__shearX,
25
+ this.__scaleY,
26
+ this.__translateX,
27
+ this.__translateY
28
+ );
29
+ }
30
+
31
+ setScaleX(scaleX) {
32
+ this.__scaleX = scaleX;
33
+ return this;
34
+ }
35
+
36
+ setScaleY(scaleY) {
37
+ this.__scaleY = scaleY;
38
+ return this;
39
+ }
40
+
41
+ setShearX(shearX) {
42
+ this.__shearX = shearX;
43
+ return this;
44
+ }
45
+
46
+ setShearY(shearY) {
47
+ this.__shearY = shearY;
48
+ return this;
49
+ }
50
+
51
+ setTranslateX(translateX) {
52
+ this.__translateX = translateX;
53
+ return this;
54
+ }
55
+
56
+ setTranslateY(translateY) {
57
+ this.__translateY = translateY;
58
+ return this;
59
+ }
60
+
61
+ toString() {
62
+ return 'AffineTransformBuilder';
63
+ }
64
+ }
@@ -0,0 +1,49 @@
1
+ import { Proxies } from '../../support/proxies.js';
2
+ import { AutofitType } from '../enums/slidesenums.js';
3
+
4
+ export const newFakeAutofit = (...args) => {
5
+ return Proxies.guard(new FakeAutofit(...args));
6
+ };
7
+
8
+ export class FakeAutofit {
9
+ constructor(shape) {
10
+ this.__shape = shape;
11
+ // Store autofit type on the shape resource or locally?
12
+ // Ideally on the resource so it persists if we reload the shape.
13
+ // But for now, let's look at the shape's property if meaningful or just a local property default.
14
+ // The resource might have 'text.autoFit'.
15
+ }
16
+
17
+ get __resource() {
18
+ // Ensure shape.text exists
19
+ if (!this.__shape.__resource.shape.text) {
20
+ this.__shape.__resource.shape.text = {};
21
+ }
22
+ return this.__shape.__resource.shape.text;
23
+ }
24
+
25
+ getAutofitType() {
26
+ const type = (this.__resource.autoFit && this.__resource.autoFit.autofitType) || 'NONE';
27
+ return AutofitType[type] || AutofitType.NONE;
28
+ }
29
+
30
+ disableAutofit() {
31
+ if (!this.__resource.autoFit) {
32
+ this.__resource.autoFit = {};
33
+ }
34
+ this.__resource.autoFit.autofitType = AutofitType.NONE.toString();
35
+ return this;
36
+ }
37
+
38
+ getFontScale() {
39
+ return (this.__resource.autoFit && this.__resource.autoFit.fontScale) !== undefined ? this.__resource.autoFit.fontScale : 1;
40
+ }
41
+
42
+ getLineSpacingReduction() {
43
+ return (this.__resource.autoFit && this.__resource.autoFit.lineSpacingReduction) !== undefined ? this.__resource.autoFit.lineSpacingReduction : 0;
44
+ }
45
+
46
+ toString() {
47
+ return 'Autofit';
48
+ }
49
+ }
@@ -0,0 +1,29 @@
1
+ import { Proxies } from '../../support/proxies.js';
2
+
3
+ export const newFakeAutoText = (...args) => {
4
+ return Proxies.guard(new FakeAutoText(...args));
5
+ };
6
+
7
+ export class FakeAutoText {
8
+ constructor(range, type, index) {
9
+ this.__range = range;
10
+ this.__type = type;
11
+ this.__index = index;
12
+ }
13
+
14
+ getIndex() {
15
+ return this.__index;
16
+ }
17
+
18
+ getRange() {
19
+ return this.__range;
20
+ }
21
+
22
+ getAutoTextType() {
23
+ return this.__type;
24
+ }
25
+
26
+ toString() {
27
+ return 'AutoText';
28
+ }
29
+ }
@@ -0,0 +1,24 @@
1
+ import { Proxies } from '../../support/proxies.js';
2
+
3
+ export const newFakeConnectionSite = (...args) => {
4
+ return Proxies.guard(new FakeConnectionSite(...args));
5
+ };
6
+
7
+ export class FakeConnectionSite {
8
+ constructor(pageElement, index) {
9
+ this.__pageElement = pageElement;
10
+ this.__index = index;
11
+ }
12
+
13
+ getIndex() {
14
+ return this.__index;
15
+ }
16
+
17
+ getPageElement() {
18
+ return this.__pageElement;
19
+ }
20
+
21
+ toString() {
22
+ return 'ConnectionSite';
23
+ }
24
+ }
@@ -0,0 +1,38 @@
1
+ import { Proxies } from '../../support/proxies.js';
2
+ import { newFakeMaster } from './fakemaster.js';
3
+
4
+ export const newFakeLayout = (...args) => {
5
+ return Proxies.guard(new FakeLayout(...args));
6
+ };
7
+
8
+ export class FakeLayout {
9
+ constructor(resource, presentation) {
10
+ this.__id = resource.objectId;
11
+ this.__presentation = presentation;
12
+ }
13
+
14
+ get __resource() {
15
+ const presentationResource = this.__presentation.__resource;
16
+ const layout = (presentationResource.layouts || []).find(l => l.objectId === this.__id);
17
+ if (!layout) {
18
+ throw new Error(`Layout with ID ${this.__id} not found`);
19
+ }
20
+ return layout;
21
+ }
22
+
23
+ getMaster() {
24
+ const masterId = this.__resource.masterObjectId;
25
+ if (!masterId) return null;
26
+
27
+ const presentationResource = this.__presentation.__resource;
28
+ const master = (presentationResource.masters || []).find(m => m.objectId === masterId);
29
+ return master ? newFakeMaster(master, this.__presentation) : null;
30
+ }
31
+
32
+ getObjectId() {
33
+ return this.__id;
34
+ }
35
+ toString() {
36
+ return 'Layout';
37
+ }
38
+ }
@@ -0,0 +1,195 @@
1
+ import { Proxies } from '../../support/proxies.js';
2
+ import { FakePageElement, PageElementRegistry } from './fakepageelement.js';
3
+ import { newFakeLineFill } from './fakelinefill.js';
4
+ import { newFakePoint } from './fakepoint.js';
5
+
6
+ export const newFakeLine = (...args) => {
7
+ const line = Proxies.guard(new FakeLine(...args));
8
+ return line;
9
+ };
10
+
11
+ PageElementRegistry.newFakeLine = newFakeLine;
12
+
13
+ export class FakeLine extends FakePageElement {
14
+ constructor(resource, page) {
15
+ super(resource, page);
16
+ }
17
+
18
+ get __line() {
19
+ return this.__resource.line;
20
+ }
21
+
22
+ getLineCategory() {
23
+ return this.__line.lineCategory;
24
+ }
25
+
26
+ getLineType() {
27
+ return this.__line.lineType;
28
+ }
29
+
30
+ isConnector() {
31
+ return this.getLineCategory() !== 'NON_CONNECTOR';
32
+ }
33
+
34
+ getLineFill() {
35
+ return newFakeLineFill(this);
36
+ }
37
+
38
+ getWeight() {
39
+ return this.__normalize(this.__line.lineProperties?.weight);
40
+ }
41
+
42
+ setWeight(weight) {
43
+ this.__updateLineProps({ weight: { magnitude: weight, unit: 'PT' } }, 'weight');
44
+ return this;
45
+ }
46
+
47
+ getDashStyle() {
48
+ const style = this.__line.lineProperties?.dashStyle || 'SOLID';
49
+ return SlidesApp.DashStyle[style] || SlidesApp.DashStyle.SOLID;
50
+ }
51
+
52
+ setDashStyle(dashStyle) {
53
+ this.__updateLineProps({ dashStyle: dashStyle }, 'dashStyle');
54
+ return this;
55
+ }
56
+
57
+ getStartArrow() {
58
+ const style = this.__line.lineProperties?.startArrow || 'NONE';
59
+ return SlidesApp.ArrowStyle[style] || SlidesApp.ArrowStyle.NONE;
60
+ }
61
+
62
+ setStartArrow(arrowStyle) {
63
+ this.__updateLineProps({ startArrow: arrowStyle }, 'startArrow');
64
+ return this;
65
+ }
66
+
67
+ getEndArrow() {
68
+ const style = this.__line.lineProperties?.endArrow || 'NONE';
69
+ return SlidesApp.ArrowStyle[style] || SlidesApp.ArrowStyle.NONE;
70
+ }
71
+
72
+ setEndArrow(arrowStyle) {
73
+ this.__updateLineProps({ endArrow: arrowStyle }, 'endArrow');
74
+ return this;
75
+ }
76
+
77
+ getStart() {
78
+ // Start point of the line.
79
+ // Usually lines are defined by transform and size.
80
+ // For now, let's just return normalized coordinates
81
+ return newFakePoint(this.getLeft(), this.getTop());
82
+ }
83
+
84
+ setStart(xOrPoint, y) {
85
+ let xValue, yValue;
86
+ if (typeof xOrPoint === 'object') {
87
+ xValue = xOrPoint.getX();
88
+ yValue = xOrPoint.getY();
89
+ } else {
90
+ xValue = xOrPoint;
91
+ yValue = y;
92
+ }
93
+ this.__updateLineProps({
94
+ startPoint: {
95
+ x: { magnitude: xValue, unit: 'PT' },
96
+ y: { magnitude: yValue, unit: 'PT' }
97
+ }
98
+ }, 'startPoint');
99
+ return this;
100
+ }
101
+
102
+ getEnd() {
103
+ return newFakePoint(this.getLeft() + this.getWidth(), this.getTop() + this.getHeight());
104
+ }
105
+
106
+ setEnd(xOrPoint, y) {
107
+ let xValue, yValue;
108
+ if (typeof xOrPoint === 'object') {
109
+ xValue = xOrPoint.getX();
110
+ yValue = xOrPoint.getY();
111
+ } else {
112
+ xValue = xOrPoint;
113
+ yValue = y;
114
+ }
115
+ // We update size/transform to match endpoints for straight lines?
116
+ // Simplified: just set width/height
117
+ const dx = xValue - this.getLeft();
118
+ const dy = yValue - this.getTop();
119
+ this.setWidth(Math.abs(dx));
120
+ this.setHeight(Math.abs(dy));
121
+ return this;
122
+ }
123
+
124
+ reroute() {
125
+ // In API, there's no reroute directly in batchUpdate for lines?
126
+ // Wait, the documentation says reroute is available.
127
+ // It might be a specific request type.
128
+ // Actually, I don't see 'rerouteLine' in Slides API reference.
129
+ // It might be an Apps Script specific implementation that uses other methods.
130
+ return this;
131
+ }
132
+
133
+ getStartConnection() {
134
+ const conn = this.__line.lineProperties?.startConnection;
135
+ if (!conn) return null;
136
+
137
+ // We need to find the connected element
138
+ const element = this.__page.getPageElements().find(e => e.getObjectId() === conn.connectedObjectId);
139
+ if (!element) return null;
140
+
141
+ // And the connection site
142
+ const sites = element.getConnectionSites();
143
+ const site = sites.find(s => s.getIndex() === conn.connectionSiteIndex);
144
+
145
+ return site || null;
146
+ }
147
+
148
+ getEndConnection() {
149
+ const conn = this.__line.lineProperties?.endConnection;
150
+ if (!conn) return null;
151
+
152
+ const element = this.__page.getPageElements().find(e => e.getObjectId() === conn.connectedObjectId);
153
+ if (!element) return null;
154
+
155
+ const sites = element.getConnectionSites();
156
+ const site = sites.find(s => s.getIndex() === conn.connectionSiteIndex);
157
+
158
+ return site || null;
159
+ }
160
+
161
+ setStartConnection(connectionSite) {
162
+ this.__updateLineProps({
163
+ startConnection: {
164
+ connectedObjectId: connectionSite.getPageElement().getObjectId(),
165
+ connectionSiteIndex: connectionSite.getIndex()
166
+ }
167
+ }, 'startConnection');
168
+ return this;
169
+ }
170
+
171
+ setEndConnection(connectionSite) {
172
+ this.__updateLineProps({
173
+ endConnection: {
174
+ connectedObjectId: connectionSite.getPageElement().getObjectId(),
175
+ connectionSiteIndex: connectionSite.getIndex()
176
+ }
177
+ }, 'endConnection');
178
+ return this;
179
+ }
180
+
181
+ __updateLineProps(lineProperties, fields) {
182
+ const presentationId = this.__page.__presentation?.getId() || this.__page.__slide?.__presentation.getId();
183
+ Slides.Presentations.batchUpdate([{
184
+ updateLineProperties: {
185
+ objectId: this.getObjectId(),
186
+ lineProperties: lineProperties,
187
+ fields: fields
188
+ }
189
+ }], presentationId);
190
+ }
191
+
192
+ toString() {
193
+ return 'Line';
194
+ }
195
+ }
@@ -0,0 +1,58 @@
1
+ import { Proxies } from '../../support/proxies.js';
2
+
3
+ export const newFakeLineFill = (...args) => {
4
+ return Proxies.guard(new FakeLineFill(...args));
5
+ };
6
+
7
+ export class FakeLineFill {
8
+ constructor(line) {
9
+ this.__line = line;
10
+ }
11
+
12
+ getFillType() {
13
+ return this.__line.__line.lineFill?.solidFill ? 'SOLID' : 'NONE';
14
+ }
15
+
16
+ getSolidFill() {
17
+ // This should return a SolidFill object
18
+ // For now we might need a FakeSolidFill or just return something simple
19
+ return null;
20
+ }
21
+
22
+ setSolidFill(color) {
23
+ // Implementing this requires updateLineProperties with solidFill
24
+ const presentationId = this.__line.__page.__presentation?.getId() || this.__line.__page.__slide?.__presentation.getId();
25
+
26
+ let solidFill = {};
27
+ if (typeof color === 'string') {
28
+ solidFill = { color: { rgbColor: this.__hexToRgb(color) } };
29
+ }
30
+ // Handle other color types if needed
31
+
32
+ Slides.Presentations.batchUpdate([{
33
+ updateLineProperties: {
34
+ objectId: this.__line.getObjectId(),
35
+ lineProperties: {
36
+ lineFill: {
37
+ solidFill: solidFill
38
+ }
39
+ },
40
+ fields: 'lineFill.solidFill'
41
+ }
42
+ }], presentationId);
43
+ return this;
44
+ }
45
+
46
+ __hexToRgb(hex) {
47
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
48
+ return result ? {
49
+ red: parseInt(result[1], 16) / 255.0,
50
+ green: parseInt(result[2], 16) / 255.0,
51
+ blue: parseInt(result[3], 16) / 255.0
52
+ } : null;
53
+ }
54
+
55
+ toString() {
56
+ return 'LineFill';
57
+ }
58
+ }