@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.
- package/package.json +1 -1
- package/src/cli/setup.js +5 -5
- package/src/cli/utils.js +2 -4
- package/src/services/enums/slidesenums.js +1 -1
- package/src/services/formapp/fakechoiceitem.js +1 -1
- package/src/services/formapp/fakeform.js +4 -3
- package/src/services/formapp/fakeformitem.js +1 -2
- package/src/services/formapp/fakeformresponse.js +3 -2
- package/src/services/formapp/fakelistitem.js +3 -2
- package/src/services/slidesapp/fakeaffinetransform.js +55 -0
- package/src/services/slidesapp/fakeaffinetransformbuilder.js +64 -0
- package/src/services/slidesapp/fakeautofit.js +49 -0
- package/src/services/slidesapp/fakeautotext.js +29 -0
- package/src/services/slidesapp/fakeconnectionsite.js +24 -0
- package/src/services/slidesapp/fakelayout.js +38 -0
- package/src/services/slidesapp/fakeline.js +195 -0
- package/src/services/slidesapp/fakelinefill.js +58 -0
- package/src/services/slidesapp/fakelink.js +31 -0
- package/src/services/slidesapp/fakemaster.js +28 -0
- package/src/services/slidesapp/fakenotespage.js +19 -0
- package/src/services/slidesapp/fakepagebackground.js +17 -0
- package/src/services/slidesapp/fakepageelement.js +395 -0
- package/src/services/slidesapp/fakeparagraph.js +46 -0
- package/src/services/slidesapp/fakepoint.js +24 -0
- package/src/services/slidesapp/fakepresentation.js +61 -3
- package/src/services/slidesapp/fakeshape.js +49 -0
- package/src/services/slidesapp/fakeslide.js +232 -0
- package/src/services/slidesapp/fakeslidesapp.js +5 -0
- package/src/services/slidesapp/faketextrange.js +253 -0
- package/src/services/slidesapp/pageelementfactory.js +19 -0
- package/src/services/stores/gasflex.js +1 -1
- package/src/services/urlfetchapp/app.js +17 -1
- package/src/support/sxfetch.js +39 -13
- package/src/support/sxforms.js +3 -1
- package/src/support/syncit.js +7 -2
- package/src/support/utils.js +2 -0
package/package.json
CHANGED
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
|
-
|
|
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
|
-
|
|
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
|
|
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) {
|
|
@@ -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.
|
|
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(
|
|
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
|
-
|
|
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
|
|
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
|
+
}
|