@mcpher/gas-fakes 2.3.18 → 2.5.2
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 +15 -32
- package/package.json +1 -2
- package/src/cli/app.js +30 -2
- package/src/cli/server.js +32 -0
- package/src/cli/setup.js +24 -0
- package/src/cli/togas.js +176 -0
- package/src/index.js +2 -0
- package/src/services/common/fakeui.js +45 -0
- package/src/services/content/app.js +3 -0
- package/src/services/content/contentservice.js +14 -0
- package/src/services/content/textoutput.js +45 -0
- package/src/services/documentapp/fakedocumentapp.js +1 -1
- package/src/services/enums/contentenums.js +15 -0
- package/src/services/enums/htmlenums.js +13 -0
- package/src/services/enums/scriptenums.js +6 -0
- package/src/services/formapp/fakeformapp.js +5 -0
- package/src/services/html/app.js +9 -0
- package/src/services/html/consumerworker.js +129 -0
- package/src/services/html/googlescriptrun.js +91 -0
- package/src/services/html/htmloutput.js +127 -0
- package/src/services/html/htmloutputmetatag.js +14 -0
- package/src/services/html/htmlservice.js +94 -0
- package/src/services/html/htmltemplate.js +63 -0
- package/src/services/html/serverworker.js +135 -0
- package/src/services/html/webapp.js +266 -0
- package/src/services/html/worker.js +63 -0
- package/src/services/libhandlerapp/fakelibrary.js +2 -2
- package/src/services/scriptapp/app.js +44 -0
- package/src/services/scriptapp/fakeauthorizationinfo.js +22 -0
- package/src/services/slidesapp/fakeslidesapp.js +5 -0
- package/src/services/spreadsheetapp/fakebooleancondition.js +14 -2
- package/src/services/spreadsheetapp/fakegradientcondition.js +1 -1
- package/src/services/spreadsheetapp/fakeovergridimage.js +25 -0
- package/src/services/spreadsheetapp/fakesheet.js +23 -1
- package/src/services/spreadsheetapp/fakespreadsheet.js +68 -11
- package/src/services/spreadsheetapp/fakespreadsheetapp.js +70 -9
- package/src/services/stores/fakestores.js +7 -0
- package/src/support/auth.js +2 -0
- package/src/support/proxies.js +1 -1
- package/src/support/sxauth.js +20 -12
- package/src/support/utils.js +480 -200
- package/src/support/workersync/sxhtml.js +8 -0
- package/src/support/workersync/synchronizer.js +8 -1
- package/src/support/workersync/worker.js +5 -0
- package/api-docs/kdrive_api.json +0 -69958
- package/appsscript.json +0 -102
- package/gf_agent/README.md +0 -101
- package/gf_agent/SKILL.md +0 -484
- package/gf_agent/documentation.md +0 -105
- package/gf_agent/gf-agent-contributor/SKILL.md +0 -56
- package/gf_agent/index.md +0 -21
- package/gf_agent/knowledge/00-execution-context.md +0 -5
- package/gf_agent/knowledge/01-drive.md +0 -12
- package/gf_agent/knowledge/02-syntax.md +0 -14
- package/gf_agent/knowledge/03-auth.md +0 -15
- package/gf_agent/knowledge/04-advanced.md +0 -46
- package/gf_agent/knowledge/05-sheets-forms.md +0 -27
- package/gf_agent/knowledge/06-jdbc-cloudsql.md +0 -21
- package/gf_agent/knowledge/07-jdbc-auth-details.md +0 -30
- package/gf_agent/knowledge/08-docs-limitations.md +0 -4
- package/gf_agent/knowledge/09-orchestrator-pattern.md +0 -55
- package/gf_agent/knowledge/10-sandbox-security.md +0 -62
- package/gf_agent/knowledge/11-chart-builder-limitations.md +0 -15
- package/gf_agent/knowledge/12-gmail-eventual-consistency.md +0 -13
- package/gf_agent/knowledge/13-advanced-services-discovery.md +0 -29
- package/gf_agent/knowledge/14-utilities-parity.md +0 -13
- package/gf_agent/knowledge/15-logging-efficiency.md +0 -15
- package/gf_agent/knowledge/README.md +0 -16
- package/gf_agent/scripts/SKILL.template.md +0 -63
- package/gf_agent/scripts/builder.js +0 -118
- package/gf_agent/skills/base.md +0 -156
- package/gf_agent/skills/cache.md +0 -20
- package/gf_agent/skills/calendar.md +0 -780
- package/gf_agent/skills/charts.md +0 -127
- package/gf_agent/skills/document.md +0 -6752
- package/gf_agent/skills/drive.md +0 -423
- package/gf_agent/skills/forms.md +0 -4036
- package/gf_agent/skills/gmail.md +0 -576
- package/gf_agent/skills/jdbc.md +0 -3101
- package/gf_agent/skills/lock.md +0 -20
- package/gf_agent/skills/properties.md +0 -19
- package/gf_agent/skills/script.md +0 -50
- package/gf_agent/skills/slides.md +0 -5054
- package/gf_agent/skills/spreadsheet.md +0 -56075
- package/gf_agent/skills/urlfetch.md +0 -28
- package/gf_agent/skills/utilities.md +0 -50
- package/gf_agent/skills/xml.md +0 -270
- package/skills-lock.json +0 -10
- package/src/services/documentapp/fakeui.js +0 -27
package/src/support/utils.js
CHANGED
|
@@ -1,87 +1,83 @@
|
|
|
1
|
+
import is, { isNonEmptyString } from "@sindresorhus/is";
|
|
2
|
+
import { assert } from "@sindresorhus/is";
|
|
3
|
+
import { slogger } from "./slogger.js";
|
|
1
4
|
|
|
5
|
+
const isNU = (item) => is.null(item) || is.undefined(item);
|
|
2
6
|
|
|
3
|
-
|
|
4
|
-
import { assert } from '@sindresorhus/is'
|
|
5
|
-
import { slogger } from './slogger.js'
|
|
6
|
-
|
|
7
|
-
const isNU = (item) => is.null(item) || is.undefined(item)
|
|
8
|
-
|
|
9
|
-
const arrify = (item) => is.array(item)
|
|
10
|
-
? item
|
|
11
|
-
: (isNU(item) ? item : [item])
|
|
7
|
+
const arrify = (item) => (is.array(item) ? item : isNU(item) ? item : [item]);
|
|
12
8
|
|
|
13
9
|
const fromJson = (text, failOnError = false) => {
|
|
14
10
|
try {
|
|
15
|
-
return JSON.parse(text)
|
|
11
|
+
return JSON.parse(text);
|
|
16
12
|
} catch (err) {
|
|
17
|
-
slogger.warn(text)
|
|
13
|
+
slogger.warn(text);
|
|
18
14
|
if (failOnError) {
|
|
19
|
-
throw err
|
|
15
|
+
throw err;
|
|
20
16
|
}
|
|
21
|
-
return null
|
|
17
|
+
return null;
|
|
22
18
|
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
};
|
|
26
20
|
|
|
27
|
-
const isBlob = (item) =>
|
|
21
|
+
const isBlob = (item) =>
|
|
22
|
+
is.object(item) &&
|
|
23
|
+
Reflect.has(item, "copyBlob") &&
|
|
24
|
+
is.function(item.copyBlob);
|
|
28
25
|
|
|
29
26
|
/**
|
|
30
|
-
* merge a series of url params
|
|
31
|
-
* @param {object|object[]} pob an object eg [{pa:a,pb:b},{pc:c}]
|
|
27
|
+
* merge a series of url params
|
|
28
|
+
* @param {object|object[]} pob an object eg [{pa:a,pb:b},{pc:c}]
|
|
32
29
|
* @returns {string} would return pa=a&pb=pb&pc=c and encoded URI
|
|
33
30
|
*/
|
|
34
31
|
const makeUrlParams = (pob) => {
|
|
35
|
-
return makeParams(pob)
|
|
36
|
-
}
|
|
32
|
+
return makeParams(pob)
|
|
33
|
+
.map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
|
|
34
|
+
.join("&");
|
|
35
|
+
};
|
|
37
36
|
/**
|
|
38
|
-
* merge a series of url params
|
|
39
|
-
* @param {object|object[]} pob an object eg [{pa:a,pb:b},{pc:c}]
|
|
37
|
+
* merge a series of url params
|
|
38
|
+
* @param {object|object[]} pob an object eg [{pa:a,pb:b},{pc:c}]
|
|
40
39
|
* @returns {object} merged and dedupped paramaters reduced
|
|
41
40
|
*/
|
|
42
41
|
const makeParamOb = (pob) => {
|
|
43
|
-
const a = makeParams(pob)
|
|
42
|
+
const a = makeParams(pob);
|
|
44
43
|
return a.reduce((p, [k, v]) => {
|
|
45
|
-
p[k] = v
|
|
46
|
-
return p
|
|
47
|
-
}, {})
|
|
48
|
-
}
|
|
44
|
+
p[k] = v;
|
|
45
|
+
return p;
|
|
46
|
+
}, {});
|
|
47
|
+
};
|
|
49
48
|
/**
|
|
50
|
-
* merge a series of url params
|
|
51
|
-
* @param {object|object[]} pob an object eg [{pa:a,pb:b},{pc:c}]
|
|
49
|
+
* merge a series of url params
|
|
50
|
+
* @param {object|object[]} pob an object eg [{pa:a,pb:b},{pc:c}]
|
|
52
51
|
* @returns {object[]} merged and dedupped paramaters
|
|
53
52
|
*/
|
|
54
53
|
const makeParams = (pob = []) => {
|
|
55
54
|
// dups will be removed
|
|
56
55
|
const mapob = arrify(pob).reduce((p, c) => {
|
|
57
|
-
Reflect.ownKeys(c).forEach(k => p.set(k, c[k]))
|
|
58
|
-
return p
|
|
59
|
-
}, new Map())
|
|
60
|
-
return Array.from(mapob.entries())
|
|
61
|
-
}
|
|
62
|
-
|
|
56
|
+
Reflect.ownKeys(c).forEach((k) => p.set(k, c[k]));
|
|
57
|
+
return p;
|
|
58
|
+
}, new Map());
|
|
59
|
+
return Array.from(mapob.entries());
|
|
60
|
+
};
|
|
63
61
|
|
|
64
62
|
const settleAsString = (data, charset) => {
|
|
65
63
|
if (is.buffer(data)) {
|
|
66
|
-
return bytesToString(Array.from(data), charset)
|
|
64
|
+
return bytesToString(Array.from(data), charset);
|
|
67
65
|
} else if (is.array(data)) {
|
|
68
|
-
return bytesToString(data, charset)
|
|
66
|
+
return bytesToString(data, charset);
|
|
69
67
|
} else {
|
|
70
|
-
assert.string(data)
|
|
71
|
-
return data
|
|
68
|
+
assert.string(data);
|
|
69
|
+
return data;
|
|
72
70
|
}
|
|
73
|
-
|
|
74
|
-
}
|
|
71
|
+
};
|
|
75
72
|
|
|
76
73
|
const settleAsBytes = (data, charset) => {
|
|
77
|
-
|
|
78
74
|
if (is.string(data)) {
|
|
79
|
-
return stringToBytes(data, charset)
|
|
75
|
+
return stringToBytes(data, charset);
|
|
80
76
|
} else if (is.buffer(data)) {
|
|
81
|
-
return Array.from(data)
|
|
77
|
+
return Array.from(data);
|
|
82
78
|
} else {
|
|
83
79
|
// Handle JSON representation of a Buffer
|
|
84
|
-
if (is.object(data) && data.type ===
|
|
80
|
+
if (is.object(data) && data.type === "Buffer" && is.array(data.data)) {
|
|
85
81
|
return data.data;
|
|
86
82
|
}
|
|
87
83
|
// Workaround for an issue where an array of bytes passed from a worker
|
|
@@ -91,105 +87,112 @@ const settleAsBytes = (data, charset) => {
|
|
|
91
87
|
// Check if the object's values look like a valid byte array.
|
|
92
88
|
if (isByteArray(values)) return values;
|
|
93
89
|
}
|
|
94
|
-
if (!is.array(data))
|
|
90
|
+
if (!is.array(data))
|
|
91
|
+
slogger.log(
|
|
92
|
+
`settleAsBytes: data is NOT an array. type: ${typeof data}, keys: ${Object.keys(data)}`,
|
|
93
|
+
);
|
|
95
94
|
assert.array(data);
|
|
96
95
|
return data;
|
|
97
96
|
}
|
|
97
|
+
};
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
const bytesToString = (data, charset) => Buffer.from(data).toString(charset)
|
|
99
|
+
const stringToBytes = (string, charset) =>
|
|
100
|
+
Array.from(Buffer.from(string, charset));
|
|
101
|
+
const bytesToString = (data, charset) => Buffer.from(data).toString(charset);
|
|
103
102
|
|
|
104
103
|
const isByteArray = (arr) => {
|
|
105
|
-
return
|
|
106
|
-
|
|
104
|
+
return (
|
|
105
|
+
Array.isArray(arr) &&
|
|
106
|
+
arr.every((n) => Number.isInteger(n) && n >= 0 && n <= 255)
|
|
107
|
+
);
|
|
108
|
+
};
|
|
107
109
|
|
|
108
110
|
/**
|
|
109
111
|
* merge something like
|
|
110
112
|
* sa = "a,b,f(x,y),g(a,b),h(h)"
|
|
111
113
|
* sb = "c,b,f(x,z),h(h,i)"
|
|
112
|
-
* into "a,b,f(x,y,z),g(a,b),h(h,i)
|
|
113
|
-
* @param {...string} any number of other strings to merge
|
|
114
|
+
* into "a,b,f(x,y,z),g(a,b),h(h,i)
|
|
115
|
+
* @param {...string} any number of other strings to merge
|
|
114
116
|
* @returns {string}
|
|
115
117
|
*/
|
|
116
118
|
export const mergeParamStrings = (...args) => {
|
|
117
|
-
|
|
118
119
|
const enhanceMap = (str, itemMap = new Map()) => {
|
|
119
120
|
// extract all the items with subfields
|
|
120
|
-
const rxSubs = /([^,(]*)(?=\()\(([^)]*)\)/g
|
|
121
|
+
const rxSubs = /([^,(]*)(?=\()\(([^)]*)\)/g;
|
|
121
122
|
/**
|
|
122
123
|
* [ [ 'f(x,y)', 'f', 'x,y' ],
|
|
123
124
|
[ 'g(a,b)', 'g', 'a,b' ],
|
|
124
125
|
[ 'h(h)', 'h', 'h' ] ]
|
|
125
126
|
*/
|
|
126
|
-
const subs = Array.from(str.matchAll(rxSubs))
|
|
127
|
+
const subs = Array.from(str.matchAll(rxSubs));
|
|
127
128
|
|
|
128
129
|
// there should be 3 groups for each member
|
|
129
130
|
// for example fields(a,b) fields a,b - we want to set up an map that looks like fields, "a,b"
|
|
130
131
|
|
|
131
|
-
subs.forEach(match => {
|
|
132
|
+
subs.forEach((match) => {
|
|
132
133
|
if (match.length !== 3) {
|
|
133
|
-
throw new Error(`Invalid format for subfield ${JSON.stringify(match)}`)
|
|
134
|
+
throw new Error(`Invalid format for subfield ${JSON.stringify(match)}`);
|
|
134
135
|
}
|
|
135
|
-
const [_, key, items] = match
|
|
136
|
-
if (!itemMap.has(key)) itemMap.set(key, new Set())
|
|
137
|
-
const item = itemMap.get(key)
|
|
138
|
-
assert.set(item)
|
|
139
|
-
items.split(",").forEach(f => itemMap.get(key).add(f))
|
|
140
|
-
})
|
|
136
|
+
const [_, key, items] = match;
|
|
137
|
+
if (!itemMap.has(key)) itemMap.set(key, new Set());
|
|
138
|
+
const item = itemMap.get(key);
|
|
139
|
+
assert.set(item);
|
|
140
|
+
items.split(",").forEach((f) => itemMap.get(key).add(f));
|
|
141
|
+
});
|
|
141
142
|
|
|
142
143
|
// there should be 2 groups for each member
|
|
143
144
|
// for example foo - we want a map item with key foo and value null
|
|
144
145
|
const rxPlains = /(?<!\([^)]*),?([^,(]+)(?=(?:,|$)(?![^(]*\)))/g;
|
|
145
|
-
const plains = Array.from(str.matchAll(rxPlains))
|
|
146
|
+
const plains = Array.from(str.matchAll(rxPlains));
|
|
146
147
|
|
|
147
|
-
plains.forEach(match => {
|
|
148
|
+
plains.forEach((match) => {
|
|
148
149
|
if (match.length !== 2) {
|
|
149
|
-
throw new Error(`Invalid format for field ${JSON.stringify(match)}`)
|
|
150
|
+
throw new Error(`Invalid format for field ${JSON.stringify(match)}`);
|
|
150
151
|
}
|
|
151
|
-
const [_, key] = match
|
|
152
|
-
const item = itemMap.get(key)
|
|
152
|
+
const [_, key] = match;
|
|
153
|
+
const item = itemMap.get(key);
|
|
153
154
|
// because whether it exists or not it should be null otherwise its a conflict a set
|
|
154
155
|
if (itemMap.has(key)) {
|
|
155
|
-
assert.null(item)
|
|
156
|
+
assert.null(item);
|
|
156
157
|
} else {
|
|
157
|
-
itemMap.set(key, null)
|
|
158
|
+
itemMap.set(key, null);
|
|
158
159
|
}
|
|
159
|
-
})
|
|
160
|
+
});
|
|
160
161
|
|
|
161
|
-
return itemMap
|
|
162
|
-
}
|
|
162
|
+
return itemMap;
|
|
163
|
+
};
|
|
163
164
|
|
|
164
|
-
const itemMap = new Map()
|
|
165
|
-
args.forEach(f => {
|
|
166
|
-
assert.string(f)
|
|
167
|
-
return enhanceMap(f.replace(/\s/g, ""), itemMap)
|
|
168
|
-
})
|
|
165
|
+
const itemMap = new Map();
|
|
166
|
+
args.forEach((f) => {
|
|
167
|
+
assert.string(f);
|
|
168
|
+
return enhanceMap(f.replace(/\s/g, ""), itemMap);
|
|
169
|
+
});
|
|
169
170
|
|
|
170
171
|
// now just convert that into a string
|
|
171
|
-
return Array.from(itemMap.entries())
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
172
|
+
return Array.from(itemMap.entries())
|
|
173
|
+
.map(([key, value]) => {
|
|
174
|
+
return is.null(value)
|
|
175
|
+
? key
|
|
176
|
+
: `${key}(${Array.from(value.keys()).sort().join(",")})`;
|
|
177
|
+
})
|
|
178
|
+
.sort()
|
|
179
|
+
.join(",");
|
|
180
|
+
};
|
|
178
181
|
|
|
179
182
|
/**
|
|
180
183
|
* translated field names from v3 to v2
|
|
181
|
-
* @param {string} fields a comma separated fields string
|
|
184
|
+
* @param {string} fields a comma separated fields string
|
|
182
185
|
* @returns {string} the modified string
|
|
183
186
|
*/
|
|
184
187
|
export const translateFieldsToV2 = (fields) => {
|
|
185
|
-
if (!is.string(fields)) return fields
|
|
188
|
+
if (!is.string(fields)) return fields;
|
|
186
189
|
return fields
|
|
187
|
-
.replace(/\bcreatedTime\b/g,
|
|
188
|
-
.replace(/\bmodifiedTime\b/g,
|
|
189
|
-
}
|
|
190
|
+
.replace(/\bcreatedTime\b/g, "createdDate")
|
|
191
|
+
.replace(/\bmodifiedTime\b/g, "modifiedDate");
|
|
192
|
+
};
|
|
190
193
|
|
|
191
|
-
const capital = (str) => str.substring(0, 1).toUpperCase() + str.substring(1)
|
|
192
|
-
const unCapital = (str) => str.substring(0, 1).toLowerCase() + str.substring(1)
|
|
194
|
+
const capital = (str) => str.substring(0, 1).toUpperCase() + str.substring(1);
|
|
195
|
+
const unCapital = (str) => str.substring(0, 1).toLowerCase() + str.substring(1);
|
|
193
196
|
|
|
194
197
|
const validateHex = (cssString) => {
|
|
195
198
|
const hex = normalizeColorStringToHex(cssString);
|
|
@@ -203,71 +206,75 @@ const validateHex = (cssString) => {
|
|
|
203
206
|
hexValue,
|
|
204
207
|
hex,
|
|
205
208
|
...rgb,
|
|
206
|
-
r: Math.round(rgb.red * 255),
|
|
209
|
+
r: Math.round(rgb.red * 255),
|
|
210
|
+
g: Math.round(rgb.green * 255),
|
|
211
|
+
b: Math.round(rgb.blue * 255),
|
|
207
212
|
};
|
|
208
213
|
};
|
|
209
214
|
|
|
210
|
-
const robToHex = ({ red, green, blue }) => rgbToHex(red, green, blue)
|
|
211
|
-
|
|
215
|
+
const robToHex = ({ red, green, blue }) => rgbToHex(red, green, blue);
|
|
212
216
|
|
|
213
217
|
const rgbToHex = (r, g, b) => {
|
|
214
218
|
const toHex = (c) => {
|
|
215
|
-
if (is.nullOrUndefined(c) || Number.isNaN(c)) return
|
|
219
|
+
if (is.nullOrUndefined(c) || Number.isNaN(c)) return "00";
|
|
216
220
|
const val = Math.round(c * 255);
|
|
217
221
|
const hex = val.toString(16);
|
|
218
|
-
return hex.length === 1 ?
|
|
222
|
+
return hex.length === 1 ? "0" + hex : hex;
|
|
219
223
|
};
|
|
220
224
|
const red = toHex(r);
|
|
221
225
|
const green = toHex(g);
|
|
222
226
|
const blue = toHex(b);
|
|
223
227
|
return `#${red}${green}${blue}`;
|
|
224
|
-
}
|
|
228
|
+
};
|
|
225
229
|
|
|
226
230
|
/**
|
|
227
231
|
* normally we'll have ".x.y.z" and we need to dig in to extract the value for x.y.z of the passed value
|
|
228
232
|
* however we may also have x(y,z) in which case we just need to extract up to x - since the stuff after the brackets was for the benfit of the api
|
|
229
233
|
*/
|
|
230
234
|
const getPlucker = (props, defaultValue) => {
|
|
231
|
-
|
|
232
235
|
// get any bracketed values
|
|
233
236
|
// clean the props
|
|
234
|
-
props = props
|
|
235
|
-
|
|
236
|
-
|
|
237
|
+
props = props
|
|
238
|
+
.trim()
|
|
239
|
+
.replace(/\s/g, "")
|
|
240
|
+
.split(".")
|
|
241
|
+
.filter((f) => f)
|
|
242
|
+
.join(".");
|
|
243
|
+
|
|
244
|
+
// now extract all the bracketed stuff - this will turn x.y(a,b)
|
|
237
245
|
// into G1 - x.y G2 a,b
|
|
238
246
|
// and x.y into just x.y
|
|
239
|
-
const regex = /([^(]*)(.*)
|
|
247
|
+
const regex = /([^(]*)(.*)/;
|
|
240
248
|
const match = regex.exec(props);
|
|
241
249
|
if (!match) {
|
|
242
|
-
throw `undeciperable props ${props} for plucker
|
|
250
|
+
throw `undeciperable props ${props} for plucker`;
|
|
243
251
|
}
|
|
244
252
|
// so this would be a.b(c,d) main [a,b] sub [c,d]
|
|
245
253
|
// right now only supporting single depth
|
|
246
|
-
const main = match[1] && match[1].split(".")
|
|
247
|
-
const subs =
|
|
254
|
+
const main = match[1] && match[1].split(".");
|
|
255
|
+
const subs =
|
|
256
|
+
match[2] && match[2].replace(/\(/, "").replace(/\)/, "").split(",");
|
|
248
257
|
|
|
249
258
|
const pluckSub = (v) => {
|
|
250
|
-
if (!subs) return v
|
|
259
|
+
if (!subs) return v;
|
|
251
260
|
return subs.reduce((p, c) => {
|
|
252
|
-
p[c] = v && is.nonEmptyObject(v) && !isNU(v[c]) ? v[c] : defaultValue
|
|
253
|
-
return p
|
|
254
|
-
}, {})
|
|
255
|
-
}
|
|
261
|
+
p[c] = v && is.nonEmptyObject(v) && !isNU(v[c]) ? v[c] : defaultValue;
|
|
262
|
+
return p;
|
|
263
|
+
}, {});
|
|
264
|
+
};
|
|
256
265
|
|
|
257
266
|
// now we need a function that will extract fields to match these
|
|
258
267
|
return (v) => {
|
|
259
268
|
// if there are no main then we just return the plucked values from the sub
|
|
260
|
-
if (!main) return pluckSub(v)
|
|
269
|
+
if (!main) return pluckSub(v);
|
|
261
270
|
|
|
262
271
|
const px = main.reduce((p, c) => {
|
|
263
|
-
const t = p && p[c]
|
|
264
|
-
return isNU(t) ? defaultValue : t
|
|
265
|
-
}, v)
|
|
266
|
-
return pluckSub(px)
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
|
|
272
|
+
const t = p && p[c];
|
|
273
|
+
return isNU(t) ? defaultValue : t;
|
|
274
|
+
}, v);
|
|
275
|
+
return pluckSub(px);
|
|
276
|
+
};
|
|
277
|
+
};
|
|
271
278
|
|
|
272
279
|
const hexToRgb = (hex) => {
|
|
273
280
|
const bigint = parseInt(hex.slice(1), 16);
|
|
@@ -279,17 +286,17 @@ const hexToRgb = (hex) => {
|
|
|
279
286
|
green: g / 255,
|
|
280
287
|
blue: b / 255,
|
|
281
288
|
};
|
|
282
|
-
}
|
|
289
|
+
};
|
|
283
290
|
|
|
284
|
-
const outside = (n, l, h) => n < l || n > h
|
|
285
|
-
const outsideInt = (n, l, h) => outside(n, l, h) || !is.integer(n)
|
|
291
|
+
const outside = (n, l, h) => n < l || n > h;
|
|
292
|
+
const outsideInt = (n, l, h) => outside(n, l, h) || !is.integer(n);
|
|
286
293
|
|
|
287
294
|
const zeroizeTime = (date) => {
|
|
288
295
|
const year = date.getFullYear();
|
|
289
296
|
const month = date.getMonth(); // Month is 0-indexed
|
|
290
297
|
const day = date.getDate();
|
|
291
298
|
return new Date(year, month, day, 0, 0, 0, 0);
|
|
292
|
-
}
|
|
299
|
+
};
|
|
293
300
|
|
|
294
301
|
const serialToDate = (serial) => {
|
|
295
302
|
const epochCorrection = 2209161600000; // Milliseconds between 1970-01-01 and 1899-12-30
|
|
@@ -298,76 +305,192 @@ const serialToDate = (serial) => {
|
|
|
298
305
|
return new Date(adjustedMs - epochCorrection);
|
|
299
306
|
};
|
|
300
307
|
|
|
301
|
-
const isEnum = (a) =>
|
|
302
|
-
|
|
308
|
+
const isEnum = (a) =>
|
|
309
|
+
is.object(a) && Reflect.has(a, "compareTo") && is.function(a.compareTo);
|
|
310
|
+
const hasFunction = (a, b = toString) => !isNU(a) && a[b] && is.function(a[b]);
|
|
303
311
|
|
|
304
312
|
const stringer = (value) => {
|
|
305
|
-
let func = is.date(value) ? "toISOString" : "toString"
|
|
313
|
+
let func = is.date(value) ? "toISOString" : "toString";
|
|
306
314
|
if (!hasFunction(value, func)) {
|
|
307
|
-
throw new Error(`dont know how to stringify ${value}`)
|
|
315
|
+
throw new Error(`dont know how to stringify ${value}`);
|
|
308
316
|
}
|
|
309
|
-
const t = value[func]()
|
|
317
|
+
const t = value[func]();
|
|
310
318
|
// drop time portion of iso date if that's what it is
|
|
311
|
-
return is.date(value) ? t.slice(0, 10) : t
|
|
312
|
-
|
|
313
|
-
}
|
|
314
|
-
const
|
|
315
|
-
const
|
|
316
|
-
const
|
|
317
|
-
const WHITE = '#ffffff'
|
|
319
|
+
return is.date(value) ? t.slice(0, 10) : t;
|
|
320
|
+
};
|
|
321
|
+
const WHITER = { red: 1, green: 1, blue: 1 };
|
|
322
|
+
const BLACKER = { red: 0, green: 0, blue: 0 };
|
|
323
|
+
const BLACK = "#000000";
|
|
324
|
+
const WHITE = "#ffffff";
|
|
318
325
|
|
|
319
326
|
const getEnumKeys = (value) => {
|
|
320
327
|
if (!isEnum(value)) {
|
|
321
|
-
throw `Expected value to be an Enum but got ${value}
|
|
328
|
+
throw `Expected value to be an Enum but got ${value}`;
|
|
322
329
|
}
|
|
323
|
-
return Object.keys(value)
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
330
|
+
return Object.keys(value).filter(
|
|
331
|
+
(f) => f !== "UNSUPPORTED" && !is.function(value[f]),
|
|
332
|
+
);
|
|
333
|
+
};
|
|
327
334
|
|
|
328
335
|
const colorNameToHex = {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
336
|
+
aliceblue: "#f0f8ff",
|
|
337
|
+
antiquewhite: "#faebd7",
|
|
338
|
+
aqua: "#00ffff",
|
|
339
|
+
aquamarine: "#7fffd4",
|
|
340
|
+
azure: "#f0ffff",
|
|
341
|
+
beige: "#f5f5dc",
|
|
342
|
+
bisque: "#ffe4c4",
|
|
343
|
+
black: "#000000",
|
|
344
|
+
blanchedalmond: "#ffebcd",
|
|
345
|
+
blue: "#0000ff",
|
|
346
|
+
blueviolet: "#8a2be2",
|
|
347
|
+
brown: "#a52a2a",
|
|
348
|
+
burlywood: "#deb887",
|
|
349
|
+
cadetblue: "#5f9ea0",
|
|
350
|
+
chartreuse: "#7fff00",
|
|
351
|
+
chocolate: "#d2691e",
|
|
352
|
+
coral: "#ff7f50",
|
|
353
|
+
cornflowerblue: "#6495ed",
|
|
354
|
+
cornsilk: "#fff8dc",
|
|
355
|
+
crimson: "#dc143c",
|
|
356
|
+
cyan: "#00ffff",
|
|
357
|
+
darkblue: "#00008b",
|
|
358
|
+
darkcyan: "#008b8b",
|
|
359
|
+
darkgoldenrod: "#b8860b",
|
|
360
|
+
darkgray: "#a9a9a9",
|
|
361
|
+
darkgreen: "#006400",
|
|
362
|
+
darkgrey: "#a9a9a9",
|
|
363
|
+
darkkhaki: "#bdb76b",
|
|
364
|
+
darkmagenta: "#8b008b",
|
|
365
|
+
darkolivegreen: "#556b2f",
|
|
366
|
+
darkorange: "#ff8c00",
|
|
367
|
+
darkorchid: "#9932cc",
|
|
368
|
+
darkred: "#8b0000",
|
|
369
|
+
darksalmon: "#e9967a",
|
|
370
|
+
darkseagreen: "#8fbc8f",
|
|
371
|
+
darkslateblue: "#483d8b",
|
|
372
|
+
darkslategray: "#2f4f4f",
|
|
373
|
+
darkslategrey: "#2f4f4f",
|
|
374
|
+
darkturquoise: "#00ced1",
|
|
375
|
+
darkviolet: "#9400d3",
|
|
376
|
+
deeppink: "#ff1493",
|
|
377
|
+
deepskyblue: "#00bfff",
|
|
378
|
+
dimgray: "#696969",
|
|
379
|
+
dimgrey: "#696969",
|
|
380
|
+
dodgerblue: "#1e90ff",
|
|
381
|
+
firebrick: "#b22222",
|
|
382
|
+
floralwhite: "#fffaf0",
|
|
383
|
+
forestgreen: "#228b22",
|
|
384
|
+
fuchsia: "#ff00ff",
|
|
385
|
+
gainsboro: "#dcdcdc",
|
|
386
|
+
ghostwhite: "#f8f8ff",
|
|
387
|
+
gold: "#ffd700",
|
|
388
|
+
goldenrod: "#daa520",
|
|
389
|
+
gray: "#808080",
|
|
390
|
+
green: "#008000",
|
|
391
|
+
greenyellow: "#adff2f",
|
|
392
|
+
grey: "#808080",
|
|
393
|
+
honeydew: "#f0fff0",
|
|
394
|
+
hotpink: "#ff69b4",
|
|
395
|
+
indianred: "#cd5c5c",
|
|
396
|
+
indigo: "#4b0082",
|
|
397
|
+
ivory: "#fffff0",
|
|
398
|
+
khaki: "#f0e68c",
|
|
399
|
+
lavender: "#e6e6fa",
|
|
400
|
+
lavenderblush: "#fff0f5",
|
|
401
|
+
lawngreen: "#7cfc00",
|
|
402
|
+
lemonchiffon: "#fffacd",
|
|
403
|
+
lightblue: "#add8e6",
|
|
404
|
+
lightcoral: "#f08080",
|
|
405
|
+
lightcyan: "#e0ffff",
|
|
406
|
+
lightgoldenrodyellow: "#fafad2",
|
|
407
|
+
lightgray: "#d3d3d3",
|
|
408
|
+
lightgreen: "#90ee90",
|
|
409
|
+
lightgrey: "#d3d3d3",
|
|
410
|
+
lightpink: "#ffb6c1",
|
|
411
|
+
lightsalmon: "#ffa07a",
|
|
412
|
+
lightseagreen: "#20b2aa",
|
|
413
|
+
lightskyblue: "#87cefa",
|
|
414
|
+
lightslategray: "#778899",
|
|
415
|
+
lightslategrey: "#778899",
|
|
416
|
+
lightsteelblue: "#b0c4de",
|
|
417
|
+
lightyellow: "#ffffe0",
|
|
418
|
+
lime: "#00ff00",
|
|
419
|
+
limegreen: "#32cd32",
|
|
420
|
+
linen: "#faf0e6",
|
|
421
|
+
magenta: "#ff00ff",
|
|
422
|
+
maroon: "#800000",
|
|
423
|
+
mediumaquamarine: "#66cdaa",
|
|
424
|
+
mediumblue: "#0000cd",
|
|
425
|
+
mediumorchid: "#ba55d3",
|
|
426
|
+
mediumpurple: "#9370db",
|
|
427
|
+
mediumseagreen: "#3cb371",
|
|
428
|
+
mediumslateblue: "#7b68ee",
|
|
429
|
+
mediumspringgreen: "#00fa9a",
|
|
430
|
+
mediumturquoise: "#48d1cc",
|
|
431
|
+
mediumvioletred: "#c71585",
|
|
432
|
+
midnightblue: "#191970",
|
|
433
|
+
mintcream: "#f5fffa",
|
|
434
|
+
mistyrose: "#ffe4e1",
|
|
435
|
+
moccasin: "#ffe4b5",
|
|
436
|
+
navajowhite: "#ffdead",
|
|
437
|
+
navy: "#000080",
|
|
438
|
+
oldlace: "#fdf5e6",
|
|
439
|
+
olive: "#808000",
|
|
440
|
+
olivedrab: "#6b8e23",
|
|
441
|
+
orange: "#ffa500",
|
|
442
|
+
orangered: "#ff4500",
|
|
443
|
+
orchid: "#da70d6",
|
|
444
|
+
palegoldenrod: "#eee8aa",
|
|
445
|
+
palegreen: "#98fb98",
|
|
446
|
+
paleturquoise: "#afeeee",
|
|
447
|
+
palevioletred: "#db7093",
|
|
448
|
+
papayawhip: "#ffefd5",
|
|
449
|
+
peachpuff: "#ffdab9",
|
|
450
|
+
peru: "#cd853f",
|
|
451
|
+
pink: "#ffc0cb",
|
|
452
|
+
plum: "#dda0dd",
|
|
453
|
+
powderblue: "#b0e0e6",
|
|
454
|
+
purple: "#800080",
|
|
455
|
+
red: "#ff0000",
|
|
456
|
+
rosybrown: "#bc8f8f",
|
|
457
|
+
royalblue: "#4169e1",
|
|
458
|
+
saddlebrown: "#8b4513",
|
|
459
|
+
salmon: "#fa8072",
|
|
460
|
+
sandybrown: "#f4a460",
|
|
461
|
+
seagreen: "#2e8b57",
|
|
462
|
+
seashell: "#fff5ee",
|
|
463
|
+
sienna: "#a0522d",
|
|
464
|
+
silver: "#c0c0c0",
|
|
465
|
+
skyblue: "#87ceeb",
|
|
466
|
+
slateblue: "#6a5acd",
|
|
467
|
+
slategray: "#708090",
|
|
468
|
+
slategrey: "#708090",
|
|
469
|
+
snow: "#fffafa",
|
|
470
|
+
springgreen: "#00ff7f",
|
|
471
|
+
steelblue: "#4682b4",
|
|
472
|
+
tan: "#d2b48c",
|
|
473
|
+
teal: "#008080",
|
|
474
|
+
thistle: "#d8bfd8",
|
|
475
|
+
tomato: "#ff6347",
|
|
476
|
+
turquoise: "#40e0d0",
|
|
477
|
+
violet: "#ee82ee",
|
|
478
|
+
wheat: "#f5deb3",
|
|
479
|
+
white: "#ffffff",
|
|
480
|
+
whitesmoke: "#f5f5f5",
|
|
481
|
+
yellow: "#ffff00",
|
|
482
|
+
yellowgreen: "#9acd32",
|
|
360
483
|
};
|
|
361
484
|
|
|
362
485
|
const normalizeColorStringToHex = (color) => {
|
|
363
486
|
if (!is.string(color)) return null;
|
|
364
|
-
const lowerColor = color.toLowerCase().replace(/\s/g,
|
|
487
|
+
const lowerColor = color.toLowerCase().replace(/\s/g, "");
|
|
365
488
|
if (colorNameToHex[lowerColor]) {
|
|
366
|
-
return colorNameToHex[lowerColor].
|
|
489
|
+
return colorNameToHex[lowerColor].toLowerCase();
|
|
367
490
|
}
|
|
368
491
|
// Check if it's a valid hex string
|
|
369
492
|
if (/^#[0-9a-f]{6}$/i.test(lowerColor)) {
|
|
370
|
-
return lowerColor.
|
|
493
|
+
return lowerColor.toLowerCase();
|
|
371
494
|
}
|
|
372
495
|
return null; // Invalid color string
|
|
373
496
|
};
|
|
@@ -375,12 +498,18 @@ const normalizeColorStringToHex = (color) => {
|
|
|
375
498
|
const deepEqual = (obj1, obj2) => {
|
|
376
499
|
if (obj1 === obj2) return true;
|
|
377
500
|
|
|
378
|
-
if (
|
|
501
|
+
if (
|
|
502
|
+
is.nullOrUndefined(obj1) ||
|
|
503
|
+
is.nullOrUndefined(obj2) ||
|
|
504
|
+
!is.object(obj1) ||
|
|
505
|
+
!is.object(obj2)
|
|
506
|
+
) {
|
|
379
507
|
return obj1 === obj2;
|
|
380
508
|
}
|
|
381
509
|
|
|
382
510
|
if (is.date(obj1) && is.date(obj2)) return obj1.getTime() === obj2.getTime();
|
|
383
|
-
if (is.regExp(obj1) && is.regExp(obj2))
|
|
511
|
+
if (is.regExp(obj1) && is.regExp(obj2))
|
|
512
|
+
return obj1.toString() === obj2.toString();
|
|
384
513
|
|
|
385
514
|
const keys1 = Object.keys(obj1);
|
|
386
515
|
const keys2 = Object.keys(obj2);
|
|
@@ -388,14 +517,16 @@ const deepEqual = (obj1, obj2) => {
|
|
|
388
517
|
if (keys1.length !== keys2.length) return false;
|
|
389
518
|
|
|
390
519
|
for (const key of keys1) {
|
|
391
|
-
if (
|
|
520
|
+
if (
|
|
521
|
+
!Object.prototype.hasOwnProperty.call(obj2, key) ||
|
|
522
|
+
!deepEqual(obj1[key], obj2[key])
|
|
523
|
+
) {
|
|
392
524
|
return false;
|
|
393
525
|
}
|
|
394
526
|
}
|
|
395
527
|
|
|
396
528
|
return true;
|
|
397
|
-
}
|
|
398
|
-
|
|
529
|
+
};
|
|
399
530
|
|
|
400
531
|
function stringCircular(obj, space = null) {
|
|
401
532
|
// First pass: remove circular references
|
|
@@ -410,19 +541,21 @@ function stringCircular(obj, space = null) {
|
|
|
410
541
|
function removeCircularReferences(obj) {
|
|
411
542
|
const seen = new WeakSet();
|
|
412
543
|
|
|
413
|
-
return JSON.parse(
|
|
414
|
-
|
|
415
|
-
if (
|
|
416
|
-
|
|
544
|
+
return JSON.parse(
|
|
545
|
+
JSON.stringify(obj, (key, value) => {
|
|
546
|
+
if (typeof value === "object" && value !== null) {
|
|
547
|
+
if (seen.has(value)) {
|
|
548
|
+
return "[Circular]";
|
|
549
|
+
}
|
|
550
|
+
seen.add(value);
|
|
417
551
|
}
|
|
418
|
-
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
}));
|
|
552
|
+
return value;
|
|
553
|
+
}),
|
|
554
|
+
);
|
|
422
555
|
}
|
|
423
556
|
|
|
424
557
|
function stabilizeKeyOrder(obj) {
|
|
425
|
-
if (obj === null || typeof obj !==
|
|
558
|
+
if (obj === null || typeof obj !== "object") {
|
|
426
559
|
return obj;
|
|
427
560
|
}
|
|
428
561
|
|
|
@@ -439,13 +572,160 @@ function stabilizeKeyOrder(obj) {
|
|
|
439
572
|
|
|
440
573
|
return result;
|
|
441
574
|
}
|
|
442
|
-
const lobify = (ob, mess =
|
|
443
|
-
let lob = ob
|
|
444
|
-
if (is.object(lob)) lob = stringCircular(lob)
|
|
445
|
-
slogger.log(mess, lob)
|
|
446
|
-
return ob
|
|
575
|
+
const lobify = (ob, mess = "") => {
|
|
576
|
+
let lob = ob;
|
|
577
|
+
if (is.object(lob)) lob = stringCircular(lob);
|
|
578
|
+
slogger.log(mess, lob);
|
|
579
|
+
return ob;
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Removes or transforms import/export statements from source code.
|
|
584
|
+
*
|
|
585
|
+
* Rules:
|
|
586
|
+
* - `export default X` → `X` (bare expression/value retained)
|
|
587
|
+
* - `export const/let/var/function/class X` → `const/let/var/function/class X`
|
|
588
|
+
* - `export { a, b, c }` → commented out
|
|
589
|
+
* - `export { a, b } from '…'` → commented out
|
|
590
|
+
* - `export * from '…'` → commented out
|
|
591
|
+
* - `import { … } from '…'` → commented out
|
|
592
|
+
* - `import x from '…'` → commented out
|
|
593
|
+
* - `import '…'` → commented out (side-effect import retained as comment)
|
|
594
|
+
*/
|
|
595
|
+
function stripImportsExports(source) {
|
|
596
|
+
const lines = source.split('\n');
|
|
597
|
+
const out = [];
|
|
598
|
+
let i = 0;
|
|
599
|
+
|
|
600
|
+
while (i < lines.length) {
|
|
601
|
+
const { fullStatement, lineCount } = collectStatement(lines, i);
|
|
602
|
+
const transformed = transformStatement(fullStatement);
|
|
603
|
+
out.push(transformed);
|
|
604
|
+
i += lineCount;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return out.join('\n');
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// ---------------------------------------------------------------------------
|
|
611
|
+
// Collect a complete statement (handles multi-line braces / parens)
|
|
612
|
+
// ---------------------------------------------------------------------------
|
|
613
|
+
function collectStatement(lines, startIndex) {
|
|
614
|
+
let statement = lines[startIndex];
|
|
615
|
+
let lineCount = 1;
|
|
616
|
+
|
|
617
|
+
// Only bother with multi-line collection for import/export openers
|
|
618
|
+
const trimmed = statement.trimStart();
|
|
619
|
+
if (!trimmed.startsWith('import') && !trimmed.startsWith('export')) {
|
|
620
|
+
return { fullStatement: statement, lineCount };
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// Keep pulling lines as long as the statement is clearly incomplete
|
|
624
|
+
while (isIncomplete(statement) && startIndex + lineCount < lines.length) {
|
|
625
|
+
statement += '\n' + lines[startIndex + lineCount];
|
|
626
|
+
lineCount++;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
return { fullStatement: statement, lineCount };
|
|
447
630
|
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Returns true if the statement so far is definitely not yet finished.
|
|
634
|
+
* Two independent signals — either one means "keep going":
|
|
635
|
+
* 1. Unbalanced brackets (more opens than closes)
|
|
636
|
+
* 2. Last non-empty line ends with a continuation token (=>, , \ ( = | || ?? &&)
|
|
637
|
+
*/
|
|
638
|
+
function isIncomplete(text) {
|
|
639
|
+
const stripped = removeStringsAndComments(text);
|
|
640
|
+
|
|
641
|
+
// 1. Unbalanced brackets
|
|
642
|
+
const opens = (stripped.match(/[\(\[\{]/g) || []).length;
|
|
643
|
+
const closes = (stripped.match(/[\)\]\}]/g) || []).length;
|
|
644
|
+
if (opens > closes) return true;
|
|
645
|
+
|
|
646
|
+
// 2. Trailing continuation token on the last non-empty line
|
|
647
|
+
const lastLine = text.split('\n').filter(l => l.trim()).pop() || '';
|
|
648
|
+
const trail = lastLine.trimEnd();
|
|
649
|
+
if (/(?:=>|[,\\(=|&]|\|\||\?\?|&&)$/.test(trail)) return true;
|
|
650
|
+
|
|
651
|
+
return false;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/** Naive removal of string literals and line comments to clean up bracket counting */
|
|
655
|
+
function removeStringsAndComments(text) {
|
|
656
|
+
return text
|
|
657
|
+
.replace(/`[^`]*`/gs, '""') // template literals
|
|
658
|
+
.replace(/"(?:[^"\\]|\\.)*"/g, '""') // double-quoted strings
|
|
659
|
+
.replace(/'(?:[^'\\]|\\.)*'/g, "''") // single-quoted strings
|
|
660
|
+
.replace(/\/\/.*/g, ''); // line comments
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// ---------------------------------------------------------------------------
|
|
664
|
+
// Transform a single (possibly multi-line) statement
|
|
665
|
+
// ---------------------------------------------------------------------------
|
|
666
|
+
function transformStatement(stmt) {
|
|
667
|
+
const trimmed = stmt.trimStart();
|
|
668
|
+
|
|
669
|
+
// ── export default <expr> ──────────────────────────────────────────────
|
|
670
|
+
if (/^export\s+default\s+/.test(trimmed)) {
|
|
671
|
+
return stmt.replace(/^(\s*)export\s+default\s+/, '$1');
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// ── export <declaration> ───────────────────────────────────────────────
|
|
675
|
+
if (/^export\s+(const|let|var|function\*?|async\s+function\*?|class)\s+/.test(trimmed)) {
|
|
676
|
+
return stmt.replace(/^(\s*)export\s+/, '$1');
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// ── export { … } [from '…'] or export * from '…' ──────────────────────
|
|
680
|
+
if (/^export\s*[\{*]/.test(trimmed) || /^export\s+\*/.test(trimmed)) {
|
|
681
|
+
return commentOut(stmt);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// ── import … ──────────────────────────────────────────────────────────
|
|
685
|
+
if (/^import\s/.test(trimmed)) {
|
|
686
|
+
return commentOut(stmt);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// Everything else — leave untouched
|
|
690
|
+
return stmt;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// ---------------------------------------------------------------------------
|
|
694
|
+
// Comment-out helper
|
|
695
|
+
// ---------------------------------------------------------------------------
|
|
696
|
+
function commentOut(stmt) {
|
|
697
|
+
return stmt
|
|
698
|
+
.split('\n')
|
|
699
|
+
.map((line, idx) => {
|
|
700
|
+
if (idx === 0) return line.replace(/^(\s*)/, '$1// ');
|
|
701
|
+
return '// ' + line;
|
|
702
|
+
})
|
|
703
|
+
.join('\n');
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Comment out all top-level ES6 import and export statements, while preserving
|
|
711
|
+
* function/class/const/let/var declarations.
|
|
712
|
+
* Used to convert ESM files to be compatible with Apps Script global evaluation.
|
|
713
|
+
* @param {string} content
|
|
714
|
+
* @returns {string}
|
|
715
|
+
*/
|
|
716
|
+
const stripEsmKeywords = (content) => {
|
|
717
|
+
if (!isNonEmptyString(content)) {
|
|
718
|
+
console.log(
|
|
719
|
+
"attempted to stripEsmKeywords on non-string; returning content",
|
|
720
|
+
content,
|
|
721
|
+
);
|
|
722
|
+
return content;
|
|
723
|
+
}
|
|
724
|
+
return stripImportsExports(content);
|
|
725
|
+
};
|
|
726
|
+
|
|
448
727
|
export const Utils = {
|
|
728
|
+
stripEsmKeywords,
|
|
449
729
|
lobify,
|
|
450
730
|
stringCircular,
|
|
451
731
|
hexToRgb,
|
|
@@ -483,6 +763,6 @@ export const Utils = {
|
|
|
483
763
|
deepEqual,
|
|
484
764
|
colorNameToHex,
|
|
485
765
|
normalizeColorStringToHex,
|
|
486
|
-
toHex: (n) => is.number(n) ? n.toString(16).padStart(8,
|
|
487
|
-
fromHex: (n) => is.string(n) ? parseInt(n, 16) : n,
|
|
488
|
-
}
|
|
766
|
+
toHex: (n) => (is.number(n) ? n.toString(16).padStart(8, "0") : n),
|
|
767
|
+
fromHex: (n) => (is.string(n) ? parseInt(n, 16) : n),
|
|
768
|
+
};
|