@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.
- package/README.md +8 -1
- package/package.json +1 -1
- package/pngs/srv.jpg +0 -0
- package/src/cli/app.js +1 -0
- package/src/cli/togas.js +23 -14
- package/src/index.js +1 -0
- package/src/services/advslides/fakeadvslides.js +11 -5
- package/src/services/base/app.js +9 -0
- package/src/services/base/fakebase.js +28 -0
- package/src/services/common/fakeadvresource.js +3 -2
- package/src/services/enums/baseenums.js +47 -0
- package/src/services/enums/slidesenums.js +3 -1
- package/src/services/html/serverworker.js +1 -1
- package/src/services/slidesapp/app.js +5 -0
- package/src/services/slidesapp/fakeautofit.js +1 -1
- package/src/services/slidesapp/fakeborder.js +106 -0
- package/src/services/slidesapp/fakecolorscheme.js +1 -1
- package/src/services/slidesapp/fakefill.js +216 -0
- package/src/services/slidesapp/fakegroup.js +35 -0
- package/src/services/slidesapp/fakeimage.js +118 -0
- package/src/services/slidesapp/fakelayout.js +351 -0
- package/src/services/slidesapp/fakeline.js +2 -2
- package/src/services/slidesapp/fakelinefill.js +15 -16
- package/src/services/slidesapp/fakelink.js +20 -3
- package/src/services/slidesapp/fakelist.js +36 -0
- package/src/services/slidesapp/fakeliststyle.js +105 -0
- package/src/services/slidesapp/fakemaster.js +358 -0
- package/src/services/slidesapp/fakenotesmaster.js +125 -0
- package/src/services/slidesapp/fakenotespage.js +102 -2
- package/src/services/slidesapp/fakepagebackground.js +109 -1
- package/src/services/slidesapp/fakepageelement.js +157 -18
- package/src/services/slidesapp/fakepageelementrange.js +28 -0
- package/src/services/slidesapp/fakepagerange.js +28 -0
- package/src/services/slidesapp/fakeparagraphstyle.js +139 -0
- package/src/services/slidesapp/fakepicturefill.js +32 -0
- package/src/services/slidesapp/fakepresentation.js +126 -2
- package/src/services/slidesapp/fakeshape.js +9 -0
- package/src/services/slidesapp/fakeslide.js +216 -24
- package/src/services/slidesapp/fakesolidfill.js +45 -0
- package/src/services/slidesapp/fakespeakerspotlight.js +18 -0
- package/src/services/slidesapp/faketable.js +55 -9
- package/src/services/slidesapp/faketablecell.js +141 -12
- package/src/services/slidesapp/faketablecellrange.js +28 -0
- package/src/services/slidesapp/faketablecolumn.js +72 -0
- package/src/services/slidesapp/faketablerow.js +31 -0
- package/src/services/slidesapp/faketextrange.js +179 -135
- package/src/services/slidesapp/faketextstyle.js +158 -0
- package/src/services/slidesapp/fakevideo.js +35 -0
- package/src/services/slidesapp/fakewordart.js +22 -0
- package/src/services/slidesapp/pageelementfactory.js +24 -1
package/README.md
CHANGED
|
@@ -167,17 +167,24 @@ As I mentioned earlier, to take this further, I'm going to need a lot of help to
|
|
|
167
167
|
|
|
168
168
|
[](https://youtu.be/lujByoX71HU)
|
|
169
169
|
|
|
170
|
+
## Watch the local webapps and addons development video
|
|
171
|
+
|
|
172
|
+
[](https://youtu.be/vH9wl7QloZ4)
|
|
173
|
+
|
|
170
174
|
## Read more docs
|
|
171
175
|
|
|
172
176
|
- [release notes](versionnotes/)
|
|
173
177
|
- [gas fakes intro video](https://youtu.be/oEjpIrkYpEM)
|
|
174
178
|
- [getting started](GETTING_STARTED.md) - how to handle authentication for Workspace scopes.
|
|
175
179
|
- [readme](README.md)
|
|
180
|
+
- [apps script parity](notes/parity.md)
|
|
176
181
|
- [Natural Language Automation with Gemini Skills & MCP Server](notes/gemini-skills-mcp.md) - new skills-based agent approach.
|
|
177
182
|
- [Add agent skills to gf_agent](https://ramblings.mcpher.com/add-skills-gf_agent/)
|
|
178
183
|
- [gf_agent documentation](../gf_agent/README.md) - instructions for the Gemini CLI automation agent and MCP server.
|
|
179
184
|
- [gas fakes cli](notes/gas-fakes-cli.md)
|
|
180
|
-
-[local add-on and webapp development with gas-fakes](notes/local-web-development.md)
|
|
185
|
+
- [local add-on and webapp development with gas-fakes](notes/local-web-development.md)
|
|
186
|
+
- [Bringing the webapp home](https://ramblings.mcpher.com/local-apps-script-webapp-and-ui-emulation/)
|
|
187
|
+
- [Local development example code](https://github.com/brucemcpherson/gf-serve)
|
|
181
188
|
- [github actions using adc](https://github.com/brucemcpherson/gas-fakes-actions-adc)
|
|
182
189
|
- [github actions using dwd and wif](https://github.com/brucemcpherson/gas-fakes-actions-dwd)
|
|
183
190
|
- [ksuite as a back end](notes/ksuite_poc.md)
|
package/package.json
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"name": "@mcpher/gas-fakes",
|
|
41
41
|
"author": "bruce mcpherson",
|
|
42
|
-
"version": "2.5.
|
|
42
|
+
"version": "2.5.3",
|
|
43
43
|
"license": "MIT",
|
|
44
44
|
"main": "main.js",
|
|
45
45
|
"description": "An implementation of the Google Workspace Apps Script runtime: Run native App Script Code on Node and Cloud Run",
|
package/pngs/srv.jpg
ADDED
|
Binary file
|
package/src/cli/app.js
CHANGED
|
@@ -219,6 +219,7 @@ export async function main() {
|
|
|
219
219
|
.option("-s, --source <string>", "Source directory (default: ./ )")
|
|
220
220
|
.option("-e, --env <path>", "Path to a custom .env file.", "./.env")
|
|
221
221
|
.option("--scriptId <string>", "Script ID for the target clasp project.")
|
|
222
|
+
.option("-q, --quiet", "Automatically accept all prompts.")
|
|
222
223
|
.action(togas);
|
|
223
224
|
|
|
224
225
|
program.showHelpAfterError("(add --help for additional information)");
|
package/src/cli/togas.js
CHANGED
|
@@ -20,6 +20,7 @@ export async function togas(options) {
|
|
|
20
20
|
const scriptId = options.scriptId || process.env.TOGAS_SCRIPT_ID || process.env.GF_SCRIPT_ID;
|
|
21
21
|
const pattern = options.pattern || process.env.TOGAS_PATTERN || "*";
|
|
22
22
|
const source = options.source || "./";
|
|
23
|
+
const autoAccept = !!options.quiet;
|
|
23
24
|
|
|
24
25
|
if (!target) {
|
|
25
26
|
console.error("Error: TOGAS_TARGET is not set. Please run 'gas-fakes init' or provide --target.");
|
|
@@ -41,14 +42,18 @@ export async function togas(options) {
|
|
|
41
42
|
|
|
42
43
|
const claspJsonPath = path.join(absoluteTarget, ".clasp.json");
|
|
43
44
|
if (!fs.existsSync(claspJsonPath)) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
let create = autoAccept;
|
|
46
|
+
if (!create) {
|
|
47
|
+
const response = await prompts({
|
|
48
|
+
type: "confirm",
|
|
49
|
+
name: "create",
|
|
50
|
+
message: `No .clasp.json found in ${target}. Create one?`,
|
|
51
|
+
initial: true
|
|
52
|
+
});
|
|
53
|
+
create = response.create;
|
|
54
|
+
}
|
|
50
55
|
|
|
51
|
-
if (
|
|
56
|
+
if (create) {
|
|
52
57
|
if (!scriptId) {
|
|
53
58
|
console.error("Error: No Script ID found. Please provide one with --scriptId or in .env.");
|
|
54
59
|
process.exit(1);
|
|
@@ -157,14 +162,18 @@ export async function togas(options) {
|
|
|
157
162
|
console.log(`Ready for clasp push in ${target}.`);
|
|
158
163
|
|
|
159
164
|
// 5. Clasp push
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
let push = autoAccept;
|
|
166
|
+
if (!push) {
|
|
167
|
+
const response = await prompts({
|
|
168
|
+
type: "confirm",
|
|
169
|
+
name: "push",
|
|
170
|
+
message: "Push to Apps Script using clasp now?",
|
|
171
|
+
initial: true
|
|
172
|
+
});
|
|
173
|
+
push = response.push;
|
|
174
|
+
}
|
|
166
175
|
|
|
167
|
-
if (
|
|
176
|
+
if (push) {
|
|
168
177
|
console.log("Running clasp push...");
|
|
169
178
|
try {
|
|
170
179
|
execSync("clasp push", { cwd: absoluteTarget, stdio: "inherit" });
|
package/src/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import './services/gmailapp/app.js'
|
|
|
11
11
|
import './services/calendarapp/app.js'
|
|
12
12
|
import './services/chartsapp/app.js'
|
|
13
13
|
import './services/session/app.js'
|
|
14
|
+
import './services/base/app.js'
|
|
14
15
|
import './services/advdrive/app.js'
|
|
15
16
|
import './services/advsheets/app.js'
|
|
16
17
|
import './services/advdocs/app.js'
|
|
@@ -16,15 +16,15 @@ class FakeAdvSlidesPresentations extends FakeAdvResource {
|
|
|
16
16
|
// Override 'get' to use the caching-enabled function fxSlidesGet.
|
|
17
17
|
get(presentationId, options) {
|
|
18
18
|
ScriptApp.__behavior.isAccessible(presentationId, 'Slides', 'read');
|
|
19
|
-
const { response, data } = this._call('get', { presentationId, ...options }, Syncit.fxSlidesGet);
|
|
19
|
+
const { response, data } = this._call('get', { presentationId, ...options }, {}, null, Syncit.fxSlidesGet);
|
|
20
20
|
gError(response, 'slides.presentations', 'get');
|
|
21
21
|
return data;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
// Signature matches Apps Script advanced service.
|
|
25
25
|
create(presentation) {
|
|
26
|
-
// The underlying API wants the resource in a '
|
|
27
|
-
const result = this._call('create', {
|
|
26
|
+
// The underlying API wants the resource in a 'requestBody' property for Node.js.
|
|
27
|
+
const result = this._call('create', { requestBody: presentation });
|
|
28
28
|
if (result.data) {
|
|
29
29
|
this.slides.__addAllowed(result.data.presentationId);
|
|
30
30
|
}
|
|
@@ -32,12 +32,18 @@ class FakeAdvSlidesPresentations extends FakeAdvResource {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// Signature matches Apps Script advanced service.
|
|
35
|
-
|
|
35
|
+
// Robustly handle both resource object and raw requests array.
|
|
36
|
+
batchUpdate(resource, presentationId) {
|
|
36
37
|
// for slides, any batch update is a write
|
|
37
38
|
ScriptApp.__behavior.isAccessible(presentationId, 'Slides', 'write');
|
|
39
|
+
|
|
40
|
+
const requestBody = Array.isArray(resource)
|
|
41
|
+
? { requests: resource }
|
|
42
|
+
: resource;
|
|
43
|
+
|
|
38
44
|
const result = this._call('batchUpdate', {
|
|
39
45
|
presentationId,
|
|
40
|
-
|
|
46
|
+
requestBody,
|
|
41
47
|
});
|
|
42
48
|
gError(result.response, 'slides.presentations', 'batchUpdate');
|
|
43
49
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* the idea here is to create an empty global entry for the singleton
|
|
3
|
+
* but only load it when it is actually used.
|
|
4
|
+
*/
|
|
5
|
+
import { lazyLoaderApp } from '../common/lazyloader.js'
|
|
6
|
+
import { newFakeBase as maker } from './fakebase.js';
|
|
7
|
+
|
|
8
|
+
let _app = null;
|
|
9
|
+
_app = lazyLoaderApp(_app, 'Base', maker);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Proxies } from '../../support/proxies.js';
|
|
2
|
+
import * as BaseEnums from '../enums/baseenums.js';
|
|
3
|
+
import { newFakeMimeType } from '../mimetype/fakemimetype.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @class FakeBase
|
|
7
|
+
* @description The Base service in Google Apps Script.
|
|
8
|
+
* @see https://developers.google.com/apps-script/reference/base
|
|
9
|
+
*/
|
|
10
|
+
export class FakeBase {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.Button = BaseEnums.Button;
|
|
13
|
+
this.ButtonSet = BaseEnums.ButtonSet;
|
|
14
|
+
this.ColorType = BaseEnums.ColorType;
|
|
15
|
+
this.MimeType = newFakeMimeType();
|
|
16
|
+
this.Month = BaseEnums.Month;
|
|
17
|
+
this.Weekday = BaseEnums.Weekday;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
toString() {
|
|
21
|
+
return 'Base';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @returns {FakeBase}
|
|
27
|
+
*/
|
|
28
|
+
export const newFakeBase = () => Proxies.guard(new FakeBase());
|
|
@@ -14,7 +14,7 @@ export class FakeAdvResource {
|
|
|
14
14
|
this.__syncitMethod = syncitMethod; // e.g., Syncit.fxDocs or Syncit.fxSheets
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
_call(method, params, options, subProp = null) {
|
|
17
|
+
_call(method, params, options, subProp = null, syncMethodOverride = null) {
|
|
18
18
|
const pack = {
|
|
19
19
|
prop: this.__serviceName,
|
|
20
20
|
subProp,
|
|
@@ -22,7 +22,8 @@ export class FakeAdvResource {
|
|
|
22
22
|
params,
|
|
23
23
|
options
|
|
24
24
|
};
|
|
25
|
-
const
|
|
25
|
+
const syncMethod = syncMethodOverride || this.__syncitMethod;
|
|
26
|
+
const result = syncMethod(pack);
|
|
26
27
|
if (!result || !result.response) {
|
|
27
28
|
// Simulate an error response if the worker didn't provide one.
|
|
28
29
|
return {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { newFakeGasenum } from "@mcpher/fake-gasenum";
|
|
2
|
+
|
|
3
|
+
export const Button = newFakeGasenum([
|
|
4
|
+
"CANCEL",
|
|
5
|
+
"CLOSE",
|
|
6
|
+
"NO",
|
|
7
|
+
"OK",
|
|
8
|
+
"YES"
|
|
9
|
+
])
|
|
10
|
+
|
|
11
|
+
export const ButtonSet = newFakeGasenum([
|
|
12
|
+
"OK",
|
|
13
|
+
"OK_CANCEL",
|
|
14
|
+
"YES_NO",
|
|
15
|
+
"YES_NO_CANCEL"
|
|
16
|
+
])
|
|
17
|
+
|
|
18
|
+
export const ColorType = newFakeGasenum([
|
|
19
|
+
"RGB",
|
|
20
|
+
"THEME",
|
|
21
|
+
"UNSUPPORTED"
|
|
22
|
+
])
|
|
23
|
+
|
|
24
|
+
export const Month = newFakeGasenum([
|
|
25
|
+
"JANUARY",
|
|
26
|
+
"FEBRUARY",
|
|
27
|
+
"MARCH",
|
|
28
|
+
"APRIL",
|
|
29
|
+
"MAY",
|
|
30
|
+
"JUNE",
|
|
31
|
+
"JULY",
|
|
32
|
+
"AUGUST",
|
|
33
|
+
"SEPTEMBER",
|
|
34
|
+
"OCTOBER",
|
|
35
|
+
"NOVEMBER",
|
|
36
|
+
"DECEMBER"
|
|
37
|
+
])
|
|
38
|
+
|
|
39
|
+
export const Weekday = newFakeGasenum([
|
|
40
|
+
"SUNDAY",
|
|
41
|
+
"MONDAY",
|
|
42
|
+
"TUESDAY",
|
|
43
|
+
"WEDNESDAY",
|
|
44
|
+
"THURSDAY",
|
|
45
|
+
"FRIDAY",
|
|
46
|
+
"SATURDAY"
|
|
47
|
+
])
|
|
@@ -60,7 +60,7 @@ export class ServerWorkerContext {
|
|
|
60
60
|
mainScriptPath: globalThis.__gasFakesMainScriptPath || this._mainScriptPath,
|
|
61
61
|
controlBuf: this._controlBuf,
|
|
62
62
|
dataBuf: this._dataBuf,
|
|
63
|
-
env: process.env // Pass current environment
|
|
63
|
+
env: { ...process.env, GAS_FAKES_WORKER: 'true' } // Pass current environment and mark as worker
|
|
64
64
|
},
|
|
65
65
|
stdout: true,
|
|
66
66
|
stderr: true
|
|
@@ -5,5 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
import { lazyLoaderApp } from '../common/lazyloader.js'
|
|
7
7
|
import { newFakeSlidesApp as maker} from './fakeslidesapp.js';
|
|
8
|
+
import './pageelementfactory.js';
|
|
9
|
+
export { newFakePageElementRange } from './fakepageelementrange.js';
|
|
10
|
+
export { newFakePageRange } from './fakepagerange.js';
|
|
11
|
+
export { newFakeTableCellRange } from './faketablecellrange.js';
|
|
12
|
+
export { newFakeTableColumn } from './faketablecolumn.js';
|
|
8
13
|
let _app = null;
|
|
9
14
|
_app = lazyLoaderApp(_app, 'SlidesApp', maker)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Proxies } from '../../support/proxies.js';
|
|
2
|
+
import { newFakeLineFill } from './fakelinefill.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Represents the Border properties of a Slides element.
|
|
6
|
+
* Emulates the Slides API resource structure.
|
|
7
|
+
*/
|
|
8
|
+
export const newFakeBorder = (...args) => {
|
|
9
|
+
return Proxies.guard(new FakeBorder(...args));
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export class FakeBorder {
|
|
13
|
+
/**
|
|
14
|
+
* @param {FakePageElement} parent - The element this border belongs to.
|
|
15
|
+
*/
|
|
16
|
+
constructor(parent) {
|
|
17
|
+
this._parent = parent;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get __resource() {
|
|
21
|
+
// Border properties are typically in imageProperties.outline or shapeProperties.outline
|
|
22
|
+
const res = this._parent.__resource;
|
|
23
|
+
return res.image?.imageProperties?.outline || res.shape?.shapeProperties?.outline;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getLineFill() {
|
|
27
|
+
return newFakeLineFill(this._parent);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
isVisible() {
|
|
31
|
+
const weight = this.getWeight();
|
|
32
|
+
return weight !== null && weight > 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setDashStyle(style) {
|
|
36
|
+
this.__update({ dashStyle: style.toString() }, 'dashStyle');
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
setTransparent() {
|
|
41
|
+
this.__update({ propertyState: 'NOT_RENDERED' }, 'propertyState');
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setWeight(weight) {
|
|
46
|
+
this.__update({ weight: { magnitude: weight, unit: 'PT' }, propertyState: 'RENDERED' }, 'weight,propertyState');
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
__update(props, fields) {
|
|
51
|
+
const presentationId = this._parent.__presentation?.getId() || this._parent.__page?.__presentation?.getId();
|
|
52
|
+
const type = this._parent.getPageElementType().toString();
|
|
53
|
+
const objectId = this._parent.getObjectId();
|
|
54
|
+
|
|
55
|
+
let request = null;
|
|
56
|
+
if (type === 'SHAPE') {
|
|
57
|
+
request = {
|
|
58
|
+
updateShapeProperties: {
|
|
59
|
+
objectId,
|
|
60
|
+
shapeProperties: { outline: props },
|
|
61
|
+
fields: fields ? fields.split(',').map(f => `outline.${f}`).join(',') : 'outline'
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
} else if (type === 'IMAGE') {
|
|
65
|
+
request = {
|
|
66
|
+
updateImageProperties: {
|
|
67
|
+
objectId,
|
|
68
|
+
imageProperties: { outline: props },
|
|
69
|
+
fields: fields ? fields.split(',').map(f => `outline.${f}`).join(',') : 'outline'
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (request) {
|
|
75
|
+
Slides.Presentations.batchUpdate({ requests: [request] }, presentationId);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Retrieves the weight of the border in Points (PT).
|
|
81
|
+
* @returns {number | null} The border weight in PT, or null if not defined/rendered.
|
|
82
|
+
*/
|
|
83
|
+
getWeight() {
|
|
84
|
+
const outline = this.__resource;
|
|
85
|
+
if (!outline || outline.propertyState === 'NOT_RENDERED' || outline.weight === undefined) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
return this._parent.__normalize(outline.weight);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Gets the DashStyle of the border.
|
|
93
|
+
* @returns {string} The dash style.
|
|
94
|
+
*/
|
|
95
|
+
getDashStyle() {
|
|
96
|
+
const outline = this.__resource;
|
|
97
|
+
if (!outline || outline.propertyState === 'NOT_RENDERED' || !outline.dashStyle) {
|
|
98
|
+
return 'SOLID';
|
|
99
|
+
}
|
|
100
|
+
return outline.dashStyle;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
toString() {
|
|
104
|
+
return 'Border';
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { Proxies } from '../../support/proxies.js';
|
|
2
|
+
import { newFakeSolidFill } from './fakesolidfill.js';
|
|
3
|
+
import { FillType } from '../enums/slidesenums.js';
|
|
4
|
+
|
|
5
|
+
export const newFakeFill = (...args) => {
|
|
6
|
+
return Proxies.guard(new FakeFill(...args));
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export class FakeFill {
|
|
10
|
+
constructor(element) {
|
|
11
|
+
this.__element = element;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get __fill() {
|
|
15
|
+
if (this.__element.__resource.shape) {
|
|
16
|
+
return this.__element.__resource.shape.shapeProperties?.shapeBackgroundFill || {};
|
|
17
|
+
}
|
|
18
|
+
if (this.__element.__resource.tableCellProperties) {
|
|
19
|
+
return this.__element.__resource.tableCellProperties.tableCellBackgroundFill || {};
|
|
20
|
+
}
|
|
21
|
+
return this.__element.__resource.pageProperties?.pageBackgroundFill || {};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getType() {
|
|
25
|
+
const fill = this.__fill;
|
|
26
|
+
if (fill.solidFill && fill.propertyState !== 'NOT_RENDERED') {
|
|
27
|
+
return FillType.SOLID;
|
|
28
|
+
}
|
|
29
|
+
return FillType.NONE;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
isVisible() {
|
|
33
|
+
return this.getType().toString() !== 'NONE';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getSolidFill() {
|
|
37
|
+
if (this.getType().toString() !== 'SOLID') {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
return newFakeSolidFill(this);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
setSolidFill(...args) {
|
|
44
|
+
let rgbColor = null;
|
|
45
|
+
let themeColor = null;
|
|
46
|
+
let alpha = 1.0;
|
|
47
|
+
|
|
48
|
+
if (args.length >= 3) {
|
|
49
|
+
const r = args[0] / 255;
|
|
50
|
+
const g = args[1] / 255;
|
|
51
|
+
const b = args[2] / 255;
|
|
52
|
+
rgbColor = { red: r, green: g, blue: b };
|
|
53
|
+
if (args.length === 4) {
|
|
54
|
+
alpha = args[3];
|
|
55
|
+
}
|
|
56
|
+
} else if (args.length > 0) {
|
|
57
|
+
const colorArg = args[0];
|
|
58
|
+
if (args.length === 2) {
|
|
59
|
+
alpha = args[1];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (typeof colorArg === 'string') {
|
|
63
|
+
if (colorArg.startsWith('#') || colorArg.length === 6 || colorArg.length === 3) {
|
|
64
|
+
const hex = colorArg.startsWith('#') ? colorArg : '#' + colorArg;
|
|
65
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
66
|
+
if (result) {
|
|
67
|
+
rgbColor = {
|
|
68
|
+
red: parseInt(result[1], 16) / 255.0,
|
|
69
|
+
green: parseInt(result[2], 16) / 255.0,
|
|
70
|
+
blue: parseInt(result[3], 16) / 255.0
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
themeColor = colorArg.toString();
|
|
75
|
+
}
|
|
76
|
+
} else if (colorArg && typeof colorArg.getColorType === 'function') {
|
|
77
|
+
if (colorArg.getColorType().toString() === 'RGB') {
|
|
78
|
+
const rgb = colorArg.asRgbColor();
|
|
79
|
+
rgbColor = {
|
|
80
|
+
red: rgb.getRed() / 255,
|
|
81
|
+
green: rgb.getGreen() / 255,
|
|
82
|
+
blue: rgb.getBlue() / 255
|
|
83
|
+
};
|
|
84
|
+
} else if (colorArg.getColorType().toString() === 'THEME') {
|
|
85
|
+
themeColor = colorArg.asThemeColor().getThemeColorType().toString();
|
|
86
|
+
}
|
|
87
|
+
} else if (colorArg && colorArg.toString) {
|
|
88
|
+
themeColor = colorArg.toString();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const solidFill = {
|
|
93
|
+
color: {}
|
|
94
|
+
};
|
|
95
|
+
if (rgbColor) {
|
|
96
|
+
solidFill.color.rgbColor = rgbColor;
|
|
97
|
+
} else if (themeColor) {
|
|
98
|
+
solidFill.color.themeColor = themeColor;
|
|
99
|
+
}
|
|
100
|
+
if (alpha !== 1.0) {
|
|
101
|
+
solidFill.alpha = alpha;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const presentationId = this.__element.__presentation?.getId() || this.__element.__page?.__presentation?.getId() || this.__element.__table?.__presentation?.getId();
|
|
105
|
+
if (this.__element.__resource.shape) {
|
|
106
|
+
Slides.Presentations.batchUpdate({ requests: [{
|
|
107
|
+
updateShapeProperties: {
|
|
108
|
+
objectId: this.__element.getObjectId(),
|
|
109
|
+
shapeProperties: {
|
|
110
|
+
shapeBackgroundFill: {
|
|
111
|
+
propertyState: 'RENDERED',
|
|
112
|
+
solidFill: solidFill
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
fields: 'shapeBackgroundFill'
|
|
116
|
+
}
|
|
117
|
+
}] }, presentationId);
|
|
118
|
+
|
|
119
|
+
} else if (this.__element.__resource.tableCellProperties) {
|
|
120
|
+
Slides.Presentations.batchUpdate({ requests: [{
|
|
121
|
+
updateTableCellProperties: {
|
|
122
|
+
objectId: this.__element.getObjectId(),
|
|
123
|
+
tableCellProperties: {
|
|
124
|
+
tableCellBackgroundFill: {
|
|
125
|
+
propertyState: 'RENDERED',
|
|
126
|
+
solidFill: solidFill
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
fields: 'tableCellBackgroundFill',
|
|
130
|
+
tableRange: {
|
|
131
|
+
location: {
|
|
132
|
+
rowIndex: this.__element.getRowIndex(),
|
|
133
|
+
columnIndex: this.__element.getColumnIndex()
|
|
134
|
+
},
|
|
135
|
+
rowSpan: 1,
|
|
136
|
+
columnSpan: 1
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}] }, presentationId);
|
|
140
|
+
|
|
141
|
+
} else {
|
|
142
|
+
Slides.Presentations.batchUpdate({ requests: [{
|
|
143
|
+
updatePageProperties: {
|
|
144
|
+
objectId: this.__element.getObjectId(),
|
|
145
|
+
pageProperties: {
|
|
146
|
+
pageBackgroundFill: {
|
|
147
|
+
propertyState: 'RENDERED',
|
|
148
|
+
solidFill: solidFill
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
fields: 'pageBackgroundFill'
|
|
152
|
+
}
|
|
153
|
+
}] }, presentationId);
|
|
154
|
+
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return this;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
setTransparent() {
|
|
161
|
+
const presentationId = this.__element.__presentation?.getId() || this.__element.__page?.__presentation?.getId() || this.__element.__table?.__presentation?.getId();
|
|
162
|
+
if (this.__element.__resource.shape) {
|
|
163
|
+
Slides.Presentations.batchUpdate({ requests: [{
|
|
164
|
+
updateShapeProperties: {
|
|
165
|
+
objectId: this.__element.getObjectId(),
|
|
166
|
+
shapeProperties: {
|
|
167
|
+
shapeBackgroundFill: {
|
|
168
|
+
propertyState: 'NOT_RENDERED'
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
fields: 'shapeBackgroundFill'
|
|
172
|
+
}
|
|
173
|
+
}] }, presentationId);
|
|
174
|
+
|
|
175
|
+
} else if (this.__element.__resource.tableCellProperties) {
|
|
176
|
+
Slides.Presentations.batchUpdate({ requests: [{
|
|
177
|
+
updateTableCellProperties: {
|
|
178
|
+
objectId: this.__element.getObjectId(),
|
|
179
|
+
tableCellProperties: {
|
|
180
|
+
tableCellBackgroundFill: {
|
|
181
|
+
propertyState: 'NOT_RENDERED'
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
fields: 'tableCellBackgroundFill',
|
|
185
|
+
tableRange: {
|
|
186
|
+
location: {
|
|
187
|
+
rowIndex: this.__element.getRowIndex(),
|
|
188
|
+
columnIndex: this.__element.getColumnIndex()
|
|
189
|
+
},
|
|
190
|
+
rowSpan: 1,
|
|
191
|
+
columnSpan: 1
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}] }, presentationId);
|
|
195
|
+
|
|
196
|
+
} else {
|
|
197
|
+
Slides.Presentations.batchUpdate({ requests: [{
|
|
198
|
+
updatePageProperties: {
|
|
199
|
+
objectId: this.__element.getObjectId(),
|
|
200
|
+
pageProperties: {
|
|
201
|
+
pageBackgroundFill: {
|
|
202
|
+
propertyState: 'NOT_RENDERED'
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
fields: 'pageBackgroundFill'
|
|
206
|
+
}
|
|
207
|
+
}] }, presentationId);
|
|
208
|
+
|
|
209
|
+
}
|
|
210
|
+
return this;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
toString() {
|
|
214
|
+
return 'Fill';
|
|
215
|
+
}
|
|
216
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Proxies } from '../../support/proxies.js';
|
|
2
|
+
import { FakePageElement, PageElementRegistry } from './fakepageelement.js';
|
|
3
|
+
|
|
4
|
+
export const newFakeGroup = (...args) => {
|
|
5
|
+
return Proxies.guard(new FakeGroup(...args));
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
PageElementRegistry.newFakeGroup = newFakeGroup;
|
|
9
|
+
|
|
10
|
+
export class FakeGroup extends FakePageElement {
|
|
11
|
+
constructor(resource, page) {
|
|
12
|
+
super(resource, page);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
getChildren() {
|
|
16
|
+
const children = this.__resource.elementGroup?.children || this.__resource.group?.children || [];
|
|
17
|
+
const { newFakePageElement } = PageElementRegistry;
|
|
18
|
+
return children.map(childResource => {
|
|
19
|
+
return newFakePageElement(childResource, this.__page);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
ungroup() {
|
|
24
|
+
const presentationId = this.__page.__presentation?.getId() || this.__page.__slide?.__presentation.getId();
|
|
25
|
+
Slides.Presentations.batchUpdate({ requests: [{
|
|
26
|
+
ungroupObjects: {
|
|
27
|
+
objectIds: [this.getObjectId()]
|
|
28
|
+
}
|
|
29
|
+
}] }, presentationId);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
toString() {
|
|
33
|
+
return 'Group';
|
|
34
|
+
}
|
|
35
|
+
}
|