@symbo.ls/connect 3.2.7
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/build.js +205 -0
- package/dist/assets/1024x1024.png +0 -0
- package/dist/assets/128x128.png +0 -0
- package/dist/assets/144x144.png +0 -0
- package/dist/assets/192x192.png +0 -0
- package/dist/assets/48x48.png +0 -0
- package/dist/assets/512x512.png +0 -0
- package/dist/assets/72x72.png +0 -0
- package/dist/assets/96x96.png +0 -0
- package/dist/assets/active_cursor.png +0 -0
- package/dist/assets/favicon.svg +6 -0
- package/dist/assets/old/144x144.png +0 -0
- package/dist/assets/old/192x192.png +0 -0
- package/dist/assets/old/48x48.png +0 -0
- package/dist/assets/old/48x48_faint.png +0 -0
- package/dist/assets/old/512x512.png +0 -0
- package/dist/assets/old/72x72.png +0 -0
- package/dist/assets/old/96x96.png +0 -0
- package/dist/auth.js +373 -0
- package/dist/content.css +46 -0
- package/dist/content.js +1171 -0
- package/dist/content.js.map +7 -0
- package/dist/devtools.html +7 -0
- package/dist/devtools.js +5 -0
- package/dist/manifest.json +87 -0
- package/dist/page-agent.js +727 -0
- package/dist/panel.css +2239 -0
- package/dist/panel.html +235 -0
- package/dist/panel.js +4973 -0
- package/dist/picker.html +111 -0
- package/dist/picker.js +300 -0
- package/dist/service_worker.js +219 -0
- package/dist/service_worker.js.map +7 -0
- package/dist/settings.css +128 -0
- package/dist/settings.html +26 -0
- package/dist/settings_ui.js +57 -0
- package/dist/settings_ui.js.map +7 -0
- package/package.json +20 -0
- package/src/content.js +104 -0
- package/src/grabber/clean.js +605 -0
- package/src/grabber/computed.js +78 -0
- package/src/grabber/parse.js +268 -0
- package/src/grabber/stylesheets.js +117 -0
- package/src/grabber/utils.js +238 -0
- package/src/service_worker.js +246 -0
- package/src/settings/settings_ui.js +52 -0
- package/src/settings/settings_utils.js +70 -0
- package/static/assets/1024x1024.png +0 -0
- package/static/assets/128x128.png +0 -0
- package/static/assets/144x144.png +0 -0
- package/static/assets/192x192.png +0 -0
- package/static/assets/48x48.png +0 -0
- package/static/assets/512x512.png +0 -0
- package/static/assets/72x72.png +0 -0
- package/static/assets/96x96.png +0 -0
- package/static/assets/active_cursor.png +0 -0
- package/static/assets/favicon.svg +6 -0
- package/static/assets/old/144x144.png +0 -0
- package/static/assets/old/192x192.png +0 -0
- package/static/assets/old/48x48.png +0 -0
- package/static/assets/old/48x48_faint.png +0 -0
- package/static/assets/old/512x512.png +0 -0
- package/static/assets/old/72x72.png +0 -0
- package/static/assets/old/96x96.png +0 -0
- package/static/auth.js +373 -0
- package/static/content.css +46 -0
- package/static/devtools.html +7 -0
- package/static/devtools.js +5 -0
- package/static/manifest.json +56 -0
- package/static/page-agent.js +727 -0
- package/static/panel.css +2239 -0
- package/static/panel.html +235 -0
- package/static/panel.js +4973 -0
- package/static/picker.html +111 -0
- package/static/picker.js +300 -0
- package/static/settings.css +128 -0
- package/static/settings.html +26 -0
package/dist/content.js
ADDED
|
@@ -0,0 +1,1171 @@
|
|
|
1
|
+
// node_modules/@domql/utils/globals.js
|
|
2
|
+
var window2 = globalThis;
|
|
3
|
+
var document2 = window2.document;
|
|
4
|
+
|
|
5
|
+
// node_modules/@domql/utils/node.js
|
|
6
|
+
var isDOMNode = (obj) => {
|
|
7
|
+
return typeof window2 !== "undefined" && (obj instanceof window2.Node || obj instanceof window2.Window || obj === window2 || obj === document);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// node_modules/@domql/utils/types.js
|
|
11
|
+
var isFunction = (arg) => typeof arg === "function";
|
|
12
|
+
var isNull = (arg) => arg === null;
|
|
13
|
+
var isArray = (arg) => Array.isArray(arg);
|
|
14
|
+
var isObjectLike = (arg) => {
|
|
15
|
+
if (arg === null) return false;
|
|
16
|
+
return typeof arg === "object";
|
|
17
|
+
};
|
|
18
|
+
var isUndefined = (arg) => {
|
|
19
|
+
return arg === void 0;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// node_modules/@domql/utils/array.js
|
|
23
|
+
var mergeArray = (arr, exclude = []) => {
|
|
24
|
+
return arr.reduce(
|
|
25
|
+
(a, c) => deepMerge(a, deepClone(c, { exclude }), exclude),
|
|
26
|
+
{}
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// node_modules/@domql/utils/object.js
|
|
31
|
+
var deepMerge = (element, extend, excludeFrom = [], level = Infinity) => {
|
|
32
|
+
for (const e in extend) {
|
|
33
|
+
const hasOwnProperty = Object.prototype.hasOwnProperty.call(extend, e);
|
|
34
|
+
if (!hasOwnProperty || excludeFrom.includes(e) || e.startsWith("__"))
|
|
35
|
+
continue;
|
|
36
|
+
const elementProp = element[e];
|
|
37
|
+
const extendProp = extend[e];
|
|
38
|
+
if (isObjectLike(elementProp) && isObjectLike(extendProp)) {
|
|
39
|
+
if (level > 0) {
|
|
40
|
+
deepMerge(elementProp, extendProp, excludeFrom, level - 1);
|
|
41
|
+
} else {
|
|
42
|
+
for (const k in extendProp) {
|
|
43
|
+
if (excludeFrom.includes(k) || elementProp[k] !== void 0) continue;
|
|
44
|
+
elementProp[k] = extendProp[k];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
} else if (elementProp === void 0) {
|
|
48
|
+
element[e] = extendProp;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return element;
|
|
52
|
+
};
|
|
53
|
+
var deepClone = (obj, options = {}) => {
|
|
54
|
+
const {
|
|
55
|
+
exclude = [],
|
|
56
|
+
cleanUndefined = false,
|
|
57
|
+
cleanNull = false,
|
|
58
|
+
window: targetWindow,
|
|
59
|
+
visited = /* @__PURE__ */ new WeakMap(),
|
|
60
|
+
handleExtend = false
|
|
61
|
+
} = options;
|
|
62
|
+
const contentWindow = targetWindow || window2 || globalThis;
|
|
63
|
+
if (!isObjectLike(obj) || isDOMNode(obj)) {
|
|
64
|
+
return obj;
|
|
65
|
+
}
|
|
66
|
+
if (visited.has(obj)) {
|
|
67
|
+
return visited.get(obj);
|
|
68
|
+
}
|
|
69
|
+
const clone = contentWindow ? isArray(obj) ? new contentWindow.Array() : new contentWindow.Object() : isArray(obj) ? [] : {};
|
|
70
|
+
visited.set(obj, clone);
|
|
71
|
+
for (const key in obj) {
|
|
72
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
|
|
73
|
+
if (exclude.includes(key) || key.startsWith("__") || key === "__proto__")
|
|
74
|
+
continue;
|
|
75
|
+
let value = obj[key];
|
|
76
|
+
if (cleanUndefined && isUndefined(value) || cleanNull && isNull(value))
|
|
77
|
+
continue;
|
|
78
|
+
if (isDOMNode(value)) {
|
|
79
|
+
clone[key] = value;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (handleExtend && key === "extend" && isArray(value)) {
|
|
83
|
+
clone[key] = mergeArray(value, exclude);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (isFunction(value) && options.window) {
|
|
87
|
+
clone[key] = contentWindow.eval("(" + value.toString() + ")");
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (value?.__ref && value?.node) {
|
|
91
|
+
value = value.parseDeep();
|
|
92
|
+
}
|
|
93
|
+
if (value?.__element) {
|
|
94
|
+
value = value.parse();
|
|
95
|
+
}
|
|
96
|
+
if (isObjectLike(value)) {
|
|
97
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
|
|
98
|
+
clone[key] = deepClone(value, {
|
|
99
|
+
...options,
|
|
100
|
+
visited
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
clone[key] = value;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return clone;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// node_modules/@domql/utils/cookie.js
|
|
110
|
+
var isMobile = (() => typeof navigator === "undefined" ? false : /Mobi/.test(navigator.userAgent))();
|
|
111
|
+
|
|
112
|
+
// src/grabber/utils.js
|
|
113
|
+
var allEqual = (arr) => arr.every((v) => v === arr[0]);
|
|
114
|
+
var capitalize = (string) => string.charAt(0).toUpperCase() + string.slice(1);
|
|
115
|
+
var toCamelCase = (str) => str.replace(
|
|
116
|
+
/[_\- ]+(?<first>[a-z])/giu,
|
|
117
|
+
(_, char, offSet) => offSet > 0 ? char.toUpperCase() : char
|
|
118
|
+
);
|
|
119
|
+
function extractCssVars(styles) {
|
|
120
|
+
const cssVariables = {};
|
|
121
|
+
for (const key in styles) {
|
|
122
|
+
if (Object.hasOwn(styles, key) && key.includes("--")) {
|
|
123
|
+
cssVariables[key] = styles[key];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return cssVariables;
|
|
127
|
+
}
|
|
128
|
+
function convertKeysToCamelCase(styles) {
|
|
129
|
+
const camelCased = {};
|
|
130
|
+
for (const key in styles) {
|
|
131
|
+
if (Object.hasOwn(styles, key) && !key.includes("--")) {
|
|
132
|
+
camelCased[toCamelCase(key)] = styles[key];
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return camelCased;
|
|
136
|
+
}
|
|
137
|
+
function findVarPattern(input) {
|
|
138
|
+
const regex = /var\(--(?<varName>[a-zA-Z0-9-]+)(?:,\s*[a-zA-Z0-9%-]+)?\)/gu;
|
|
139
|
+
const matches = [];
|
|
140
|
+
let match = regex.exec(input);
|
|
141
|
+
while (match !== null) {
|
|
142
|
+
const varName = `--${match.groups.varName}`;
|
|
143
|
+
matches.push(varName);
|
|
144
|
+
match = regex.exec(input);
|
|
145
|
+
}
|
|
146
|
+
return [...new Set(matches)];
|
|
147
|
+
}
|
|
148
|
+
var extractRootVars = (css, globalStyles) => {
|
|
149
|
+
const variables = extractCssVars(css);
|
|
150
|
+
let rootVars = Object.values(css).reduce((acc, value) => {
|
|
151
|
+
const vars = {};
|
|
152
|
+
if (value.includes("var(")) {
|
|
153
|
+
const varNames = findVarPattern(value);
|
|
154
|
+
varNames.forEach((v) => {
|
|
155
|
+
let val = variables[v];
|
|
156
|
+
if (val || val === "") {
|
|
157
|
+
vars[v] = val || " ";
|
|
158
|
+
} else {
|
|
159
|
+
val = globalStyles.getPropertyValue(v);
|
|
160
|
+
if (val || val === "") {
|
|
161
|
+
vars[v] = val || " ";
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return { ...acc, ...vars };
|
|
167
|
+
}, {});
|
|
168
|
+
if (Object.keys(rootVars).length) {
|
|
169
|
+
let checkingNested = true;
|
|
170
|
+
let nested = {};
|
|
171
|
+
while (checkingNested) {
|
|
172
|
+
const parsed = Object.values({
|
|
173
|
+
...rootVars,
|
|
174
|
+
...variables,
|
|
175
|
+
...nested
|
|
176
|
+
}).reduce(
|
|
177
|
+
/* eslint-disable-next-line no-loop-func -- checking the contents of rootVars and nested is safe */
|
|
178
|
+
(acc, value) => {
|
|
179
|
+
const vars = {};
|
|
180
|
+
if (value.includes("var(")) {
|
|
181
|
+
const varNames = findVarPattern(value);
|
|
182
|
+
varNames.forEach((v) => {
|
|
183
|
+
if (v in rootVars || v in nested) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
let val = variables[v];
|
|
187
|
+
if (val || val === "") {
|
|
188
|
+
vars[v] = val || " ";
|
|
189
|
+
} else {
|
|
190
|
+
val = globalStyles.getPropertyValue(v);
|
|
191
|
+
if (val || val === "") {
|
|
192
|
+
vars[v] = val || " ";
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return { ...acc, ...vars };
|
|
198
|
+
},
|
|
199
|
+
{}
|
|
200
|
+
);
|
|
201
|
+
if (Object.keys(parsed).length) {
|
|
202
|
+
nested = { ...nested, ...parsed };
|
|
203
|
+
} else {
|
|
204
|
+
checkingNested = false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
rootVars = { ...rootVars, ...nested };
|
|
208
|
+
}
|
|
209
|
+
return rootVars;
|
|
210
|
+
};
|
|
211
|
+
function isEqual(objA, objB, visited = /* @__PURE__ */ new WeakSet()) {
|
|
212
|
+
if (objA === objB) {
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
if (objA == null || objB == null) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
if (typeof objA !== "object" || typeof objB !== "object") {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
if (visited.has(objA) || visited.has(objB)) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
visited.add(objA);
|
|
225
|
+
visited.add(objB);
|
|
226
|
+
const keysA = Object.keys(objA);
|
|
227
|
+
const keysB = Object.keys(objB);
|
|
228
|
+
if (keysA.length !== keysB.length) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
for (const key of keysA) {
|
|
232
|
+
if (!keysB.includes(key) || !isEqual(objA[key], objB[key], visited)) {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
function cleanSharedProperties(children) {
|
|
239
|
+
const props = children.map((child) => child.props);
|
|
240
|
+
const shared = {};
|
|
241
|
+
const keys = Object.keys(props[0]);
|
|
242
|
+
for (const key of keys) {
|
|
243
|
+
const values = props.map((style) => style[key]);
|
|
244
|
+
if (values.every((value) => isEqual(value, values[0]))) {
|
|
245
|
+
const [val] = values;
|
|
246
|
+
shared[key] = val;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return shared;
|
|
250
|
+
}
|
|
251
|
+
function reformatChildren(children) {
|
|
252
|
+
const childrenObj = {};
|
|
253
|
+
const keyCounts = {};
|
|
254
|
+
children.forEach((child) => {
|
|
255
|
+
let key = child.extend ?? "Child";
|
|
256
|
+
if (Array.isArray(key)) {
|
|
257
|
+
key = child.extend.shift();
|
|
258
|
+
if (!child.extend.length) {
|
|
259
|
+
delete child.extend;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (!(key in keyCounts)) {
|
|
263
|
+
keyCounts[key] = 0;
|
|
264
|
+
}
|
|
265
|
+
keyCounts[key]++;
|
|
266
|
+
const newKey = keyCounts[key] > 1 ? `${key}_${keyCounts[key]}` : key;
|
|
267
|
+
childrenObj[newKey] = { ...child };
|
|
268
|
+
});
|
|
269
|
+
return childrenObj;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/grabber/clean.js
|
|
273
|
+
function consolidateValues(values) {
|
|
274
|
+
const uniqueValues = new Set(values);
|
|
275
|
+
if (uniqueValues.size === 1) {
|
|
276
|
+
return values[0];
|
|
277
|
+
}
|
|
278
|
+
if (uniqueValues.size === 2) {
|
|
279
|
+
const [vertical, horizontal] = values;
|
|
280
|
+
if (vertical === horizontal) {
|
|
281
|
+
return `${vertical}`;
|
|
282
|
+
}
|
|
283
|
+
} else if (uniqueValues.size === 4) {
|
|
284
|
+
const [topLeft, topRight, bottomRight, bottomLeft] = values;
|
|
285
|
+
if (topLeft === topRight && bottomLeft === bottomRight) {
|
|
286
|
+
return `${topLeft} ${bottomLeft}`;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return values.join(" ");
|
|
290
|
+
}
|
|
291
|
+
function consolidateTextDecoration(style) {
|
|
292
|
+
const updatedStyle = deepClone(style);
|
|
293
|
+
const decorationProps = [
|
|
294
|
+
"textDecorationThickness",
|
|
295
|
+
"textDecorationStyle",
|
|
296
|
+
"textDecorationColor"
|
|
297
|
+
];
|
|
298
|
+
const thickness = style.textDecorationThickness && style.textDecorationThickness !== "initial" ? style.textDecorationThickness : "";
|
|
299
|
+
const styleProp = style.textDecorationStyle && style.textDecorationStyle !== "initial" ? style.textDecorationStyle : "";
|
|
300
|
+
const color = style.textDecorationColor && style.textDecorationColor !== "initial" ? style.textDecorationColor : "";
|
|
301
|
+
const consolidatedTextDecoration = [thickness, styleProp, color].filter(Boolean).join(" ").trim();
|
|
302
|
+
if (consolidatedTextDecoration) {
|
|
303
|
+
updatedStyle.textDecoration = consolidatedTextDecoration;
|
|
304
|
+
}
|
|
305
|
+
decorationProps.forEach((prop) => delete updatedStyle[prop]);
|
|
306
|
+
return updatedStyle;
|
|
307
|
+
}
|
|
308
|
+
function consolidateBorderRadius(style) {
|
|
309
|
+
const radiusProps = [
|
|
310
|
+
"borderBottomLeftRadius",
|
|
311
|
+
"borderBottomRightRadius",
|
|
312
|
+
"borderEndEndRadius",
|
|
313
|
+
"borderEndStartRadius",
|
|
314
|
+
"borderStartEndRadius",
|
|
315
|
+
"borderStartStartRadius",
|
|
316
|
+
"borderTopLeftRadius",
|
|
317
|
+
"borderTopRightRadius"
|
|
318
|
+
];
|
|
319
|
+
const sides = ["TopLeft", "TopRight", "BottomRight", "BottomLeft"];
|
|
320
|
+
const radii = [];
|
|
321
|
+
sides.forEach((side) => {
|
|
322
|
+
const radius = style[`border${side}Radius`];
|
|
323
|
+
if (radius && radius !== "initial") {
|
|
324
|
+
radii.push(radius);
|
|
325
|
+
} else {
|
|
326
|
+
radii.push("0");
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
const consolidatedRadius = consolidateValues(radii).trim();
|
|
330
|
+
const updated = { ...style };
|
|
331
|
+
if (consolidatedRadius && consolidatedRadius !== "0") {
|
|
332
|
+
updated.borderRadius = consolidatedRadius;
|
|
333
|
+
}
|
|
334
|
+
radiusProps.forEach((prop) => delete updated[prop]);
|
|
335
|
+
return updated;
|
|
336
|
+
}
|
|
337
|
+
function consolidateAndUpdateBorderProperties(style) {
|
|
338
|
+
const updatedStyle = deepClone(style);
|
|
339
|
+
const result = {};
|
|
340
|
+
const sides = ["Top", "Right", "Bottom", "Left"];
|
|
341
|
+
const properties = ["Width", "Style", "Color"];
|
|
342
|
+
const borderProps = {};
|
|
343
|
+
sides.forEach((side) => {
|
|
344
|
+
properties.forEach((prop) => {
|
|
345
|
+
const key = `border${side}${prop}`;
|
|
346
|
+
if (updatedStyle[key] && updatedStyle[key] !== "initial") {
|
|
347
|
+
borderProps[key] = updatedStyle[key];
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
const allSidesEqual = properties.every(
|
|
352
|
+
(prop) => allEqual(sides.map((side) => borderProps[`border${side}${prop}`]))
|
|
353
|
+
);
|
|
354
|
+
if (allSidesEqual) {
|
|
355
|
+
const width = borderProps.borderTopWidth;
|
|
356
|
+
const borderStyle = borderProps.borderTopStyle;
|
|
357
|
+
const color = borderProps.borderTopColor;
|
|
358
|
+
if (width && borderStyle && color) {
|
|
359
|
+
result.border = `${width} ${borderStyle} ${color}`;
|
|
360
|
+
} else {
|
|
361
|
+
if (width) {
|
|
362
|
+
result.borderWidth = width;
|
|
363
|
+
}
|
|
364
|
+
if (borderStyle) {
|
|
365
|
+
result.borderStyle = borderStyle;
|
|
366
|
+
}
|
|
367
|
+
if (color) {
|
|
368
|
+
result.borderColor = color;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
} else {
|
|
372
|
+
const logicalSides = ["BlockStart", "BlockEnd", "InlineStart", "InlineEnd"];
|
|
373
|
+
const logicalEqual = properties.every(
|
|
374
|
+
(prop) => allEqual(logicalSides.map((side) => borderProps[`border${side}${prop}`]))
|
|
375
|
+
);
|
|
376
|
+
if (logicalEqual) {
|
|
377
|
+
const blockWidth = borderProps.borderBlockStartWidth;
|
|
378
|
+
const blockStyle = borderProps.borderBlockStartStyle;
|
|
379
|
+
const blockColor = borderProps.borderBlockStartColor;
|
|
380
|
+
const inlineWidth = borderProps.borderInlineStartWidth;
|
|
381
|
+
const inlineStyle = borderProps.borderInlineStartStyle;
|
|
382
|
+
const inlineColor = borderProps.borderInlineStartColor;
|
|
383
|
+
if (blockWidth === inlineWidth && blockStyle === inlineStyle && blockColor === inlineColor) {
|
|
384
|
+
result.border = `${blockWidth} ${blockStyle} ${blockColor}`;
|
|
385
|
+
} else {
|
|
386
|
+
if (blockWidth) {
|
|
387
|
+
result.borderBlockWidth = blockWidth;
|
|
388
|
+
}
|
|
389
|
+
if (blockStyle) {
|
|
390
|
+
result.borderBlockStyle = blockStyle;
|
|
391
|
+
}
|
|
392
|
+
if (blockColor) {
|
|
393
|
+
result.borderBlockColor = blockColor;
|
|
394
|
+
}
|
|
395
|
+
if (inlineWidth && inlineWidth !== blockWidth) {
|
|
396
|
+
result.borderInlineWidth = inlineWidth;
|
|
397
|
+
}
|
|
398
|
+
if (inlineStyle && inlineStyle !== blockStyle) {
|
|
399
|
+
result.borderInlineStyle = inlineStyle;
|
|
400
|
+
}
|
|
401
|
+
if (inlineColor && inlineColor !== blockColor) {
|
|
402
|
+
result.borderInlineColor = inlineColor;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
} else {
|
|
406
|
+
logicalSides.forEach((side) => {
|
|
407
|
+
const width = borderProps[`border${side}Width`];
|
|
408
|
+
const borderStyle = borderProps[`border${side}Style`];
|
|
409
|
+
const color = borderProps[`border${side}Color`];
|
|
410
|
+
if (width && borderStyle && color) {
|
|
411
|
+
result[`border${side}`] = `${width} ${borderStyle} ${color}`;
|
|
412
|
+
} else {
|
|
413
|
+
if (width) {
|
|
414
|
+
result[`border${side}Width`] = width;
|
|
415
|
+
}
|
|
416
|
+
if (borderStyle) {
|
|
417
|
+
result[`border${side}Style`] = borderStyle;
|
|
418
|
+
}
|
|
419
|
+
if (color) {
|
|
420
|
+
result[`border${side}Color`] = color;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
;
|
|
427
|
+
[
|
|
428
|
+
"borderImageSource",
|
|
429
|
+
"borderImageSlice",
|
|
430
|
+
"borderImageWidth",
|
|
431
|
+
"borderImageOutset",
|
|
432
|
+
"borderImageRepeat"
|
|
433
|
+
].forEach((prop) => {
|
|
434
|
+
if (updatedStyle[prop] && updatedStyle[prop] !== "initial") {
|
|
435
|
+
result[prop] = updatedStyle[prop];
|
|
436
|
+
}
|
|
437
|
+
delete updatedStyle[prop];
|
|
438
|
+
});
|
|
439
|
+
sides.forEach((side) => {
|
|
440
|
+
properties.forEach((prop) => {
|
|
441
|
+
delete updatedStyle[`border${side}${prop}`];
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
[
|
|
445
|
+
"border",
|
|
446
|
+
"borderWidth",
|
|
447
|
+
"borderStyle",
|
|
448
|
+
"borderColor",
|
|
449
|
+
"borderBlock",
|
|
450
|
+
"borderInline"
|
|
451
|
+
].forEach((prop) => {
|
|
452
|
+
delete updatedStyle[prop];
|
|
453
|
+
});
|
|
454
|
+
return { ...updatedStyle, ...result };
|
|
455
|
+
}
|
|
456
|
+
function consolidateSpacing(style, property = "padding") {
|
|
457
|
+
const updatedStyle = deepClone(style);
|
|
458
|
+
const propertyMap = {
|
|
459
|
+
top: style[`${property}Top`] || style[`${property}BlockStart`] || style[`${property}Block`],
|
|
460
|
+
right: style[`${property}Right`] || style[`${property}InlineEnd`] || style[`${property}Inline`],
|
|
461
|
+
bottom: style[`${property}Bottom`] || style[`${property}BlockEnd`] || style[`${property}Block`],
|
|
462
|
+
left: style[`${property}Left`] || style[`${property}InlineStart`] || style[`${property}Inline`]
|
|
463
|
+
};
|
|
464
|
+
const consolidatedValues = ["top", "right", "bottom", "left"].map(
|
|
465
|
+
(side) => propertyMap[side] || "0"
|
|
466
|
+
);
|
|
467
|
+
if (consolidatedValues.every((value) => value === "0")) {
|
|
468
|
+
return updatedStyle;
|
|
469
|
+
}
|
|
470
|
+
const [top, right, bottom, left] = consolidatedValues;
|
|
471
|
+
let result = consolidatedValues.join(" ");
|
|
472
|
+
if (right === left) {
|
|
473
|
+
if (top === bottom) {
|
|
474
|
+
if (top === right) {
|
|
475
|
+
result = top;
|
|
476
|
+
} else {
|
|
477
|
+
result = `${top} ${right}`;
|
|
478
|
+
}
|
|
479
|
+
} else {
|
|
480
|
+
result = `${top} ${right} ${bottom}`;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
;
|
|
484
|
+
[
|
|
485
|
+
`${property}Top`,
|
|
486
|
+
`${property}Right`,
|
|
487
|
+
`${property}Bottom`,
|
|
488
|
+
`${property}Left`,
|
|
489
|
+
`${property}BlockStart`,
|
|
490
|
+
`${property}BlockEnd`,
|
|
491
|
+
`${property}InlineStart`,
|
|
492
|
+
`${property}InlineEnd`,
|
|
493
|
+
`${property}Block`,
|
|
494
|
+
`${property}Inline`,
|
|
495
|
+
property
|
|
496
|
+
].forEach((prop) => {
|
|
497
|
+
delete updatedStyle[prop];
|
|
498
|
+
});
|
|
499
|
+
updatedStyle[property] = result;
|
|
500
|
+
return updatedStyle;
|
|
501
|
+
}
|
|
502
|
+
function splitPropsFromStyles(style) {
|
|
503
|
+
const updatedStyle = deepClone(style);
|
|
504
|
+
const props = {};
|
|
505
|
+
const stylesWithProps = [
|
|
506
|
+
"alignContent",
|
|
507
|
+
"alignItems",
|
|
508
|
+
"alignSelf",
|
|
509
|
+
"animation",
|
|
510
|
+
"animationDelay",
|
|
511
|
+
"animationDirection",
|
|
512
|
+
"animationDuration",
|
|
513
|
+
"animationFillMode",
|
|
514
|
+
"animationIterationCount",
|
|
515
|
+
"animationName",
|
|
516
|
+
"animationPlayState",
|
|
517
|
+
"animationTimingFunction",
|
|
518
|
+
"appearance",
|
|
519
|
+
"aspectRatio",
|
|
520
|
+
"background",
|
|
521
|
+
"backgroundColor",
|
|
522
|
+
"backgroundPosition",
|
|
523
|
+
"backgroundRepeat",
|
|
524
|
+
"backgroundSize",
|
|
525
|
+
"backfaceVisibility",
|
|
526
|
+
"backdropFilter",
|
|
527
|
+
"blockSize",
|
|
528
|
+
"border",
|
|
529
|
+
"borderBottom",
|
|
530
|
+
"borderColor",
|
|
531
|
+
"borderLeft",
|
|
532
|
+
"borderRadius",
|
|
533
|
+
"borderRight",
|
|
534
|
+
"borderStyle",
|
|
535
|
+
"borderTop",
|
|
536
|
+
"borderWidth",
|
|
537
|
+
"bottom",
|
|
538
|
+
"boxShadow",
|
|
539
|
+
"boxSize",
|
|
540
|
+
"boxSizing",
|
|
541
|
+
"caretColor",
|
|
542
|
+
"columns",
|
|
543
|
+
"columnCount",
|
|
544
|
+
"columnFill",
|
|
545
|
+
"columnGap",
|
|
546
|
+
"columnRule",
|
|
547
|
+
"columnRule",
|
|
548
|
+
"columnSpan",
|
|
549
|
+
"columnWidth",
|
|
550
|
+
"color",
|
|
551
|
+
"content",
|
|
552
|
+
"cursor",
|
|
553
|
+
"depth",
|
|
554
|
+
"direction",
|
|
555
|
+
"direction",
|
|
556
|
+
"display",
|
|
557
|
+
"filter",
|
|
558
|
+
"flex",
|
|
559
|
+
"flexAlign",
|
|
560
|
+
"flexDirection",
|
|
561
|
+
"flexFlow",
|
|
562
|
+
"flexWrap",
|
|
563
|
+
"float",
|
|
564
|
+
"gap",
|
|
565
|
+
"gridArea",
|
|
566
|
+
"gridColumn",
|
|
567
|
+
"gridColumnStart",
|
|
568
|
+
"gridRow",
|
|
569
|
+
"gridRowStart",
|
|
570
|
+
"height",
|
|
571
|
+
"heightRange",
|
|
572
|
+
"horizontalInset",
|
|
573
|
+
"inlineSize",
|
|
574
|
+
"inset",
|
|
575
|
+
"justifyContent",
|
|
576
|
+
"justifyItems",
|
|
577
|
+
"left",
|
|
578
|
+
"maxBlockSize",
|
|
579
|
+
"maxHeight",
|
|
580
|
+
"maxInlineSize",
|
|
581
|
+
"maxSize",
|
|
582
|
+
"maxWidth",
|
|
583
|
+
"mixBlendMode",
|
|
584
|
+
"minBlockSize",
|
|
585
|
+
"minHeight",
|
|
586
|
+
"minInlineSize",
|
|
587
|
+
"minSize",
|
|
588
|
+
"minWidth",
|
|
589
|
+
"margin",
|
|
590
|
+
"marginBlock",
|
|
591
|
+
"marginBlockEnd",
|
|
592
|
+
"marginBlockStart",
|
|
593
|
+
"marginInline",
|
|
594
|
+
"marginInlineEnd",
|
|
595
|
+
"marginInlineStart",
|
|
596
|
+
"objectFit",
|
|
597
|
+
"opacity",
|
|
598
|
+
"order",
|
|
599
|
+
"overflow",
|
|
600
|
+
"overflowX",
|
|
601
|
+
"overflowY",
|
|
602
|
+
"outline",
|
|
603
|
+
"outlineOffset",
|
|
604
|
+
"overscrollBehavior",
|
|
605
|
+
"padding",
|
|
606
|
+
"paddingBlock",
|
|
607
|
+
"paddingBlockEnd",
|
|
608
|
+
"paddingBlockStart",
|
|
609
|
+
"paddingInline",
|
|
610
|
+
"paddingInlineEnd",
|
|
611
|
+
"paddingInlineStart",
|
|
612
|
+
"perspective",
|
|
613
|
+
"perspectiveOrigin",
|
|
614
|
+
"pointerEvents",
|
|
615
|
+
"position",
|
|
616
|
+
"right",
|
|
617
|
+
"resize",
|
|
618
|
+
"round",
|
|
619
|
+
"rowGap",
|
|
620
|
+
"scrollPadding",
|
|
621
|
+
"shape",
|
|
622
|
+
"shapeDirection",
|
|
623
|
+
"shapeDirectionColor",
|
|
624
|
+
"shadow",
|
|
625
|
+
"size",
|
|
626
|
+
"textShadow",
|
|
627
|
+
"textStroke",
|
|
628
|
+
"theme",
|
|
629
|
+
"top",
|
|
630
|
+
"transform",
|
|
631
|
+
"transformOrigin",
|
|
632
|
+
"transition",
|
|
633
|
+
"transitionDelay",
|
|
634
|
+
"transitionDuration",
|
|
635
|
+
"transitionProperty",
|
|
636
|
+
"transitionTimingFunction",
|
|
637
|
+
"userSelect",
|
|
638
|
+
"verticalAlign",
|
|
639
|
+
"verticalInset",
|
|
640
|
+
"visibility",
|
|
641
|
+
"width",
|
|
642
|
+
"widthRange",
|
|
643
|
+
"willChange",
|
|
644
|
+
"zIndex",
|
|
645
|
+
"zoom"
|
|
646
|
+
];
|
|
647
|
+
stylesWithProps.forEach((key) => {
|
|
648
|
+
if (key in updatedStyle) {
|
|
649
|
+
props[key] = updatedStyle[key];
|
|
650
|
+
delete updatedStyle[key];
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
return { props, style: updatedStyle };
|
|
654
|
+
}
|
|
655
|
+
function consolidateStyles(style) {
|
|
656
|
+
let updatedStyle = deepClone(style);
|
|
657
|
+
if (style.outlineWidth || style.outlineStyle || style.outlineColor) {
|
|
658
|
+
updatedStyle.outline = `${style.outlineWidth || "initial"} ${style.outlineStyle || "initial"} ${style.outlineColor || "initial"}`;
|
|
659
|
+
delete updatedStyle.outlineWidth;
|
|
660
|
+
delete updatedStyle.outlineStyle;
|
|
661
|
+
delete updatedStyle.outlineColor;
|
|
662
|
+
}
|
|
663
|
+
const insetProps = [
|
|
664
|
+
"insetInlineStart",
|
|
665
|
+
"insetBlockEnd",
|
|
666
|
+
"insetInlineEnd",
|
|
667
|
+
"insetBlockStart"
|
|
668
|
+
];
|
|
669
|
+
const insetValues = insetProps.map((prop) => style[prop] || "0");
|
|
670
|
+
if (insetValues.some((val) => val !== "0")) {
|
|
671
|
+
updatedStyle.inset = consolidateValues(insetValues);
|
|
672
|
+
insetProps.forEach((prop) => delete updatedStyle[prop]);
|
|
673
|
+
}
|
|
674
|
+
if (style.transition && style.transitionProperty && style.transitionDuration) {
|
|
675
|
+
updatedStyle.transition = `${style.transition} ${style.transitionProperty} ${style.transitionDuration}`;
|
|
676
|
+
delete updatedStyle.transitionProperty;
|
|
677
|
+
delete updatedStyle.transitionDuration;
|
|
678
|
+
}
|
|
679
|
+
const sizeProps = ["inlineSize", "blockSize"];
|
|
680
|
+
const sizeValues = sizeProps.map((prop) => style[prop] || "0");
|
|
681
|
+
if (sizeValues.some((val) => val !== "0")) {
|
|
682
|
+
updatedStyle.size = consolidateValues(sizeValues);
|
|
683
|
+
sizeProps.forEach((prop) => delete updatedStyle[prop]);
|
|
684
|
+
}
|
|
685
|
+
let gapValues = [];
|
|
686
|
+
if (style.gap) {
|
|
687
|
+
gapValues = [...gapValues, ...style.gap.split(" ")];
|
|
688
|
+
delete updatedStyle.gap;
|
|
689
|
+
}
|
|
690
|
+
const gapProps = ["rowGap", "columnGap"];
|
|
691
|
+
gapValues = [...gapValues, ...gapProps.map((prop) => style[prop] || "0")];
|
|
692
|
+
if (gapValues.some((val) => val !== "0")) {
|
|
693
|
+
updatedStyle.gap = consolidateValues(gapValues);
|
|
694
|
+
gapProps.forEach((prop) => delete updatedStyle[prop]);
|
|
695
|
+
}
|
|
696
|
+
if (style.webkitTextStroke) {
|
|
697
|
+
updatedStyle.textStroke = style.webkitTextStroke;
|
|
698
|
+
delete updatedStyle.webkitTextStroke;
|
|
699
|
+
}
|
|
700
|
+
updatedStyle = consolidateBorderRadius(updatedStyle);
|
|
701
|
+
updatedStyle = consolidateAndUpdateBorderProperties(updatedStyle);
|
|
702
|
+
updatedStyle = consolidateSpacing(updatedStyle, "padding");
|
|
703
|
+
updatedStyle = consolidateSpacing(updatedStyle, "margin");
|
|
704
|
+
updatedStyle = consolidateSpacing(updatedStyle, "borderWidth");
|
|
705
|
+
updatedStyle = consolidateTextDecoration(updatedStyle);
|
|
706
|
+
if (style.minWidth && style.maxWidth) {
|
|
707
|
+
updatedStyle.widthRange = `${style.minWidth} ${style.maxWidth}`;
|
|
708
|
+
delete updatedStyle.minWidth;
|
|
709
|
+
delete updatedStyle.maxWidth;
|
|
710
|
+
}
|
|
711
|
+
if (style.minHeight && style.maxHeight) {
|
|
712
|
+
style.heightRange = `${style.minHeight} ${style.maxHeight}`;
|
|
713
|
+
delete updatedStyle.minHeight;
|
|
714
|
+
delete updatedStyle.maxHeight;
|
|
715
|
+
}
|
|
716
|
+
return updatedStyle;
|
|
717
|
+
}
|
|
718
|
+
function consolidateFlexCSS(props) {
|
|
719
|
+
const updatedProps = deepClone(props);
|
|
720
|
+
if (props.alignItems || props.justifyContent) {
|
|
721
|
+
updatedProps.align = `${props.alignItems || ""} ${props.justifyContent || ""}`.trim();
|
|
722
|
+
delete updatedProps.alignItems;
|
|
723
|
+
delete updatedProps.justifyContent;
|
|
724
|
+
}
|
|
725
|
+
if (props.flexDirection || props.flexWrap) {
|
|
726
|
+
updatedProps.flow = `${props.flexDirection || "row"} ${props.flexWrap || ""}`.trim();
|
|
727
|
+
delete updatedProps.flexDirection;
|
|
728
|
+
delete updatedProps.flexWrap;
|
|
729
|
+
}
|
|
730
|
+
return updatedProps;
|
|
731
|
+
}
|
|
732
|
+
function consolidateGridCSS(props) {
|
|
733
|
+
const updatedProps = deepClone(props);
|
|
734
|
+
if (props.gridTemplateColumns) {
|
|
735
|
+
updatedProps.columns = props.gridTemplateColumns;
|
|
736
|
+
delete updatedProps.gridTemplateColumns;
|
|
737
|
+
}
|
|
738
|
+
if (props.gridTemplateRows) {
|
|
739
|
+
updatedProps.rows = props.gridTemplateRows;
|
|
740
|
+
delete updatedProps.gridTemplateRows;
|
|
741
|
+
}
|
|
742
|
+
return updatedProps;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// src/grabber/computed.js
|
|
746
|
+
function getComputedStyles(node) {
|
|
747
|
+
const computedStyle = window.getComputedStyle(node);
|
|
748
|
+
const style = {};
|
|
749
|
+
for (let i = 0; i < computedStyle.length; i++) {
|
|
750
|
+
const property = computedStyle[i];
|
|
751
|
+
const value = computedStyle.getPropertyValue(property);
|
|
752
|
+
style[property] = value;
|
|
753
|
+
}
|
|
754
|
+
return style;
|
|
755
|
+
}
|
|
756
|
+
function getStyleDefaultsFromEmptyNode(tag) {
|
|
757
|
+
const node = document.createElement(tag);
|
|
758
|
+
document.body.appendChild(node);
|
|
759
|
+
const computed = getComputedStyles(node);
|
|
760
|
+
document.body.removeChild(node);
|
|
761
|
+
return computed;
|
|
762
|
+
}
|
|
763
|
+
function getAppliedComputedStyles(node, defaults) {
|
|
764
|
+
const css = getComputedStyles(node);
|
|
765
|
+
const styles = {};
|
|
766
|
+
Object.keys(css).forEach((prop) => {
|
|
767
|
+
const value = css[prop];
|
|
768
|
+
const ignoreAllVals = [
|
|
769
|
+
"width",
|
|
770
|
+
"height",
|
|
771
|
+
"inline-size",
|
|
772
|
+
"block-size",
|
|
773
|
+
"transform-origin",
|
|
774
|
+
"perspective-origin"
|
|
775
|
+
];
|
|
776
|
+
const ignoreAutoVals = [
|
|
777
|
+
"margin",
|
|
778
|
+
"margin-top",
|
|
779
|
+
"margin-bottom",
|
|
780
|
+
"margin-left",
|
|
781
|
+
"margin-right",
|
|
782
|
+
"padding",
|
|
783
|
+
"padding-top",
|
|
784
|
+
"padding-bottom",
|
|
785
|
+
"padding-left",
|
|
786
|
+
"padding-right",
|
|
787
|
+
"top",
|
|
788
|
+
"bottom",
|
|
789
|
+
"left",
|
|
790
|
+
"right",
|
|
791
|
+
"min-width",
|
|
792
|
+
"min-height",
|
|
793
|
+
"min-block-size",
|
|
794
|
+
"min-inline-size"
|
|
795
|
+
];
|
|
796
|
+
const skipDefault = [["flex-direction", (s) => s.display === "flex"]];
|
|
797
|
+
const defaultIsValid = skipDefault.some(([p, con]) => prop === p && con(css)) || value !== defaults[prop];
|
|
798
|
+
if (!ignoreAllVals.includes(prop) && value && defaultIsValid && !(ignoreAutoVals.includes(prop) && value === "auto")) {
|
|
799
|
+
styles[prop] = value;
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
return styles;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// src/settings/settings_utils.js
|
|
806
|
+
var storageKey = "settings";
|
|
807
|
+
var getSettings = async () => (await chrome.storage.local.get(storageKey)).settings;
|
|
808
|
+
|
|
809
|
+
// src/grabber/stylesheets.js
|
|
810
|
+
var getRelevantRules = (node, rules) => {
|
|
811
|
+
let relevantRules = [];
|
|
812
|
+
for (const rule of rules) {
|
|
813
|
+
const { selectorText, conditionText, media, cssRules } = rule;
|
|
814
|
+
if (selectorText && node.matches(selectorText)) {
|
|
815
|
+
relevantRules.push(rule);
|
|
816
|
+
} else if ((conditionText || media && media.length > 0) && cssRules) {
|
|
817
|
+
relevantRules = [
|
|
818
|
+
...relevantRules,
|
|
819
|
+
...getRelevantRules(node, rule.cssRules)
|
|
820
|
+
];
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
return relevantRules;
|
|
824
|
+
};
|
|
825
|
+
var extractStylesFromRule = (rule, defaults = {}) => {
|
|
826
|
+
const { style } = rule;
|
|
827
|
+
const results = {};
|
|
828
|
+
for (let k = 0; k < style.length; k++) {
|
|
829
|
+
const prop = style[k];
|
|
830
|
+
const value = style.getPropertyValue(prop);
|
|
831
|
+
const defaultValue = defaults[prop];
|
|
832
|
+
if (value && value !== defaultValue) {
|
|
833
|
+
results[prop] = value;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
return results;
|
|
837
|
+
};
|
|
838
|
+
var processMediaQueries = (rule, parentRule) => {
|
|
839
|
+
const { conditionText } = parentRule;
|
|
840
|
+
let key = `@media ${conditionText}`;
|
|
841
|
+
if (["(prefers-color-scheme: dark)", "(prefers-color-scheme: light)"].includes(
|
|
842
|
+
conditionText
|
|
843
|
+
)) {
|
|
844
|
+
key = conditionText.includes("dark") ? "@dark" : "@light";
|
|
845
|
+
}
|
|
846
|
+
return { [key]: { ...extractStylesFromRule(rule) } };
|
|
847
|
+
};
|
|
848
|
+
var getAppliedStylesheets = (node) => {
|
|
849
|
+
let styles = {};
|
|
850
|
+
let conditionalStyles = {};
|
|
851
|
+
for (const styleSheet of document.styleSheets) {
|
|
852
|
+
let baseRules = null;
|
|
853
|
+
try {
|
|
854
|
+
baseRules = styleSheet.cssRules;
|
|
855
|
+
} catch (error) {
|
|
856
|
+
console.log("Could not access stylesheet rules:", { styleSheet, error });
|
|
857
|
+
}
|
|
858
|
+
if (baseRules !== null) {
|
|
859
|
+
const rules = getRelevantRules(node, baseRules);
|
|
860
|
+
for (const rule of rules) {
|
|
861
|
+
const { parentRule } = rule;
|
|
862
|
+
if (parentRule && parentRule.conditionText) {
|
|
863
|
+
conditionalStyles = {
|
|
864
|
+
...conditionalStyles,
|
|
865
|
+
...processMediaQueries(rule, parentRule)
|
|
866
|
+
};
|
|
867
|
+
} else if (rule.selectorText.includes(":hover")) {
|
|
868
|
+
const hoverKey = ":hover";
|
|
869
|
+
conditionalStyles[hoverKey] = {
|
|
870
|
+
...conditionalStyles[hoverKey],
|
|
871
|
+
...extractStylesFromRule(rule)
|
|
872
|
+
};
|
|
873
|
+
} else {
|
|
874
|
+
styles = { ...styles, ...extractStylesFromRule(rule) };
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
return [styles, conditionalStyles];
|
|
880
|
+
};
|
|
881
|
+
var getInlineStyles = (node, defaults) => {
|
|
882
|
+
const styles = {};
|
|
883
|
+
for (let i = 0; i < node.style.length; i++) {
|
|
884
|
+
const prop = node.style[i];
|
|
885
|
+
const val = node.style.getPropertyValue(prop);
|
|
886
|
+
if (val && val !== defaults[prop]) {
|
|
887
|
+
styles[prop] = val;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
return styles;
|
|
891
|
+
};
|
|
892
|
+
function getAllAppliedSheetStyles(node, defaults) {
|
|
893
|
+
const inlineStyles = getInlineStyles(node, defaults);
|
|
894
|
+
const [stylesheetStyles, conditionalStyles] = getAppliedStylesheets(node);
|
|
895
|
+
return [{ ...stylesheetStyles, ...inlineStyles }, conditionalStyles];
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// src/grabber/parse.js
|
|
899
|
+
function getNodeText(node) {
|
|
900
|
+
if (node.nodeType === window.Node.TEXT_NODE) {
|
|
901
|
+
return window.Node.TEXT_NODE;
|
|
902
|
+
}
|
|
903
|
+
let val = "";
|
|
904
|
+
for (const child of node.childNodes) {
|
|
905
|
+
if (child.nodeType === window.Node.TEXT_NODE && child.textContent.trim() !== "") {
|
|
906
|
+
val += child.textContent.trim();
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
if (val.trim() !== "") {
|
|
910
|
+
return val;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
function parseNodeAttributes(node) {
|
|
914
|
+
const attributes = {};
|
|
915
|
+
if (node && node.attributes) {
|
|
916
|
+
for (const { name, value } of node.attributes) {
|
|
917
|
+
if (name !== "class" && name !== "style") {
|
|
918
|
+
attributes[name] = value;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
return Object.keys(attributes).length ? attributes : null;
|
|
923
|
+
}
|
|
924
|
+
function extendsFromTag(props) {
|
|
925
|
+
const extend = [];
|
|
926
|
+
const tag = (props.tag ?? "div").toLowerCase();
|
|
927
|
+
if (tag === "a") {
|
|
928
|
+
extend.push("Link");
|
|
929
|
+
}
|
|
930
|
+
const validTags = [
|
|
931
|
+
"input",
|
|
932
|
+
"button",
|
|
933
|
+
"img",
|
|
934
|
+
"span",
|
|
935
|
+
"strong",
|
|
936
|
+
"section",
|
|
937
|
+
"picture",
|
|
938
|
+
"form",
|
|
939
|
+
"dialog",
|
|
940
|
+
"p",
|
|
941
|
+
"hr",
|
|
942
|
+
"h1",
|
|
943
|
+
"h2",
|
|
944
|
+
"h3",
|
|
945
|
+
"h4",
|
|
946
|
+
"h5",
|
|
947
|
+
"h6",
|
|
948
|
+
"header",
|
|
949
|
+
"footer",
|
|
950
|
+
"progress",
|
|
951
|
+
"select",
|
|
952
|
+
"textarea",
|
|
953
|
+
"aside",
|
|
954
|
+
"pre",
|
|
955
|
+
"code",
|
|
956
|
+
"svg",
|
|
957
|
+
"label",
|
|
958
|
+
"hgroup"
|
|
959
|
+
];
|
|
960
|
+
if (validTags.includes(tag)) {
|
|
961
|
+
extend.push(capitalize(tag));
|
|
962
|
+
}
|
|
963
|
+
return extend;
|
|
964
|
+
}
|
|
965
|
+
async function parseElement(node, rootStyles) {
|
|
966
|
+
const tag = node.tagName.toLowerCase();
|
|
967
|
+
const defaults = getStyleDefaultsFromEmptyNode(tag);
|
|
968
|
+
const settings = await getSettings();
|
|
969
|
+
const [sheets, conditionalSheets] = settings.useStylesheets ?? true ? getAllAppliedSheetStyles(node, defaults) : {};
|
|
970
|
+
const computed = settings.useComputed ? getAppliedComputedStyles(node, defaults) : {};
|
|
971
|
+
const rawStyles = {
|
|
972
|
+
...sheets,
|
|
973
|
+
...computed
|
|
974
|
+
};
|
|
975
|
+
let rootVars = extractRootVars(rawStyles, rootStyles);
|
|
976
|
+
const camelCased = convertKeysToCamelCase(rawStyles);
|
|
977
|
+
const camelCasedConditionals = {};
|
|
978
|
+
Object.entries(conditionalSheets).forEach(([query, cSheet]) => {
|
|
979
|
+
rootVars = { ...extractRootVars(cSheet, rootStyles), ...rootVars };
|
|
980
|
+
const { props: props2, style: style2 } = splitPropsFromStyles(
|
|
981
|
+
convertKeysToCamelCase(cSheet)
|
|
982
|
+
);
|
|
983
|
+
camelCasedConditionals[query] = {};
|
|
984
|
+
if (Object.keys(props2).length) {
|
|
985
|
+
camelCasedConditionals[query] = props2;
|
|
986
|
+
}
|
|
987
|
+
if (Object.keys(style2).length) {
|
|
988
|
+
camelCasedConditionals[query].style = style2;
|
|
989
|
+
}
|
|
990
|
+
});
|
|
991
|
+
let props = { ...rootVars };
|
|
992
|
+
if (tag !== "div") {
|
|
993
|
+
props.tag = tag;
|
|
994
|
+
}
|
|
995
|
+
const { props: styleProps, style } = splitPropsFromStyles(
|
|
996
|
+
consolidateStyles(camelCased)
|
|
997
|
+
);
|
|
998
|
+
props = { ...props, ...styleProps };
|
|
999
|
+
const text = getNodeText(node);
|
|
1000
|
+
let children = [];
|
|
1001
|
+
const childPromises = [];
|
|
1002
|
+
if (node.children.length > 0) {
|
|
1003
|
+
const ignore = ["STYLE", "SCRIPT"];
|
|
1004
|
+
for (const childNode of node.children) {
|
|
1005
|
+
if (!ignore.includes(childNode.tagName)) {
|
|
1006
|
+
if (childNode.tagName === "svg") {
|
|
1007
|
+
const html = childNode.innerHTML;
|
|
1008
|
+
const attr2 = parseNodeAttributes(childNode);
|
|
1009
|
+
children.push({
|
|
1010
|
+
extend: ["Svg"],
|
|
1011
|
+
attr: attr2,
|
|
1012
|
+
props: { html }
|
|
1013
|
+
});
|
|
1014
|
+
} else {
|
|
1015
|
+
childPromises.push(parseElement(childNode, rootStyles));
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
const results = await Promise.all(childPromises);
|
|
1021
|
+
children = [...children, ...results];
|
|
1022
|
+
let childProps = null;
|
|
1023
|
+
if (children.length > 1) {
|
|
1024
|
+
childProps = cleanSharedProperties(children);
|
|
1025
|
+
Object.keys(childProps).forEach((key) => {
|
|
1026
|
+
children.forEach((child) => delete child.props[key]);
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
const attr = parseNodeAttributes(node);
|
|
1030
|
+
const copyAttrFromThese = ["a", "img", "input", "button", "iframe"];
|
|
1031
|
+
if (attr && copyAttrFromThese.includes(tag)) {
|
|
1032
|
+
Object.keys(attr).forEach((prop) => {
|
|
1033
|
+
props[prop] = attr[prop];
|
|
1034
|
+
delete attr[prop];
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
if (tag === "img" && props.src && props.src.startsWith("/")) {
|
|
1038
|
+
props.src = window.location.origin + props.src;
|
|
1039
|
+
}
|
|
1040
|
+
if (tag === "a" && props.href && props.href.startsWith("/")) {
|
|
1041
|
+
props.href = window.location.origin + props.href;
|
|
1042
|
+
}
|
|
1043
|
+
const extend = extendsFromTag(props);
|
|
1044
|
+
if (extend.length === 1) {
|
|
1045
|
+
delete props.tag;
|
|
1046
|
+
}
|
|
1047
|
+
if (props.display === "flex") {
|
|
1048
|
+
props = consolidateFlexCSS(props);
|
|
1049
|
+
delete props.display;
|
|
1050
|
+
extend.push("Flex");
|
|
1051
|
+
}
|
|
1052
|
+
if (props.display === "grid") {
|
|
1053
|
+
props = consolidateGridCSS(props);
|
|
1054
|
+
delete props.display;
|
|
1055
|
+
extend.push("Grid");
|
|
1056
|
+
}
|
|
1057
|
+
let element = {
|
|
1058
|
+
props: { ...props }
|
|
1059
|
+
};
|
|
1060
|
+
if (Object.keys(style).length) {
|
|
1061
|
+
element.props.style = style;
|
|
1062
|
+
}
|
|
1063
|
+
if (Object.keys(camelCasedConditionals).length) {
|
|
1064
|
+
element.props = { ...element.props, ...camelCasedConditionals };
|
|
1065
|
+
}
|
|
1066
|
+
if (text) {
|
|
1067
|
+
element.props.text = text;
|
|
1068
|
+
}
|
|
1069
|
+
if (attr && Object.keys(attr).length) {
|
|
1070
|
+
element.props.attr = attr;
|
|
1071
|
+
}
|
|
1072
|
+
if (extend.length) {
|
|
1073
|
+
element.extend = extend;
|
|
1074
|
+
}
|
|
1075
|
+
if (children.length) {
|
|
1076
|
+
if (childProps && Object.keys(childProps).length) {
|
|
1077
|
+
element.props.childProps = childProps;
|
|
1078
|
+
}
|
|
1079
|
+
element = { ...element, ...reformatChildren(children) };
|
|
1080
|
+
} else if (childProps) {
|
|
1081
|
+
console.warn("childProps without children");
|
|
1082
|
+
}
|
|
1083
|
+
return element;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
// src/content.js
|
|
1087
|
+
function injectPageAgent() {
|
|
1088
|
+
const script = document.createElement("script");
|
|
1089
|
+
script.src = chrome.runtime.getURL("page-agent.js");
|
|
1090
|
+
script.onload = () => script.remove();
|
|
1091
|
+
(document.head || document.documentElement).appendChild(script);
|
|
1092
|
+
}
|
|
1093
|
+
injectPageAgent();
|
|
1094
|
+
async function addToLibrary(node) {
|
|
1095
|
+
const rootStyles = window.getComputedStyle(document.documentElement);
|
|
1096
|
+
const obj = await parseElement(node, rootStyles);
|
|
1097
|
+
const store = { domqlStr: JSON.stringify(obj) };
|
|
1098
|
+
console.log("%c[Symbols] saving domql", "color: green", store);
|
|
1099
|
+
chrome.storage.local.set(store);
|
|
1100
|
+
chrome.runtime.sendMessage({ type: "open_platform" });
|
|
1101
|
+
return obj;
|
|
1102
|
+
}
|
|
1103
|
+
var focusNodeClass = "symbols-grabber-hovered";
|
|
1104
|
+
var isListenerActive = false;
|
|
1105
|
+
var focusedNode = null;
|
|
1106
|
+
document.body.addEventListener(
|
|
1107
|
+
"mouseover",
|
|
1108
|
+
(event) => {
|
|
1109
|
+
const { target } = event;
|
|
1110
|
+
if (target && isListenerActive) {
|
|
1111
|
+
if (focusedNode && focusedNode !== target) {
|
|
1112
|
+
focusedNode.classList.remove(focusNodeClass);
|
|
1113
|
+
}
|
|
1114
|
+
focusedNode = target;
|
|
1115
|
+
focusedNode.classList.add(focusNodeClass);
|
|
1116
|
+
}
|
|
1117
|
+
},
|
|
1118
|
+
true
|
|
1119
|
+
);
|
|
1120
|
+
chrome.runtime.onMessage.addListener((msg, sender, respond) => {
|
|
1121
|
+
if (sender.id === chrome.runtime.id) {
|
|
1122
|
+
const { type, state } = msg;
|
|
1123
|
+
if (type === "toggle" && typeof state === "number") {
|
|
1124
|
+
console.log(
|
|
1125
|
+
`%c[Symbols] grabber ${state ? "enabled" : "disabled"}`,
|
|
1126
|
+
`color: ${state ? "green" : "red"}`
|
|
1127
|
+
);
|
|
1128
|
+
isListenerActive = Boolean(state);
|
|
1129
|
+
document.body.classList.toggle("symbols-grabber-active", isListenerActive);
|
|
1130
|
+
if (!state) {
|
|
1131
|
+
document.querySelectorAll(`.${focusNodeClass}`).forEach((el) => {
|
|
1132
|
+
el.classList.remove(focusNodeClass);
|
|
1133
|
+
});
|
|
1134
|
+
focusedNode = null;
|
|
1135
|
+
}
|
|
1136
|
+
document.body.addEventListener(
|
|
1137
|
+
"click",
|
|
1138
|
+
(event) => {
|
|
1139
|
+
const { target } = event;
|
|
1140
|
+
if (target && isListenerActive) {
|
|
1141
|
+
event.preventDefault();
|
|
1142
|
+
event.stopImmediatePropagation();
|
|
1143
|
+
if (target.classList.contains(focusNodeClass)) {
|
|
1144
|
+
target.classList.remove(focusNodeClass);
|
|
1145
|
+
}
|
|
1146
|
+
addToLibrary(target).then(
|
|
1147
|
+
(domql) => {
|
|
1148
|
+
target.classList.add(focusNodeClass);
|
|
1149
|
+
respond({ success: true, domql });
|
|
1150
|
+
},
|
|
1151
|
+
(error) => {
|
|
1152
|
+
console.error("[Symbols] error adding to library", error);
|
|
1153
|
+
respond({ success: false, error: error.message || error });
|
|
1154
|
+
}
|
|
1155
|
+
);
|
|
1156
|
+
isListenerActive = false;
|
|
1157
|
+
}
|
|
1158
|
+
},
|
|
1159
|
+
{ capture: true, once: true }
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
return true;
|
|
1164
|
+
});
|
|
1165
|
+
console.log("[Symbols] Content script loaded (inspector + grabber)");
|
|
1166
|
+
/*! Bundled license information:
|
|
1167
|
+
|
|
1168
|
+
@domql/utils/env.js:
|
|
1169
|
+
(* @preserve-env *)
|
|
1170
|
+
*/
|
|
1171
|
+
//# sourceMappingURL=content.js.map
|