@addon-core/inject-css 0.3.1 → 0.4.0
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 +224 -72
- package/dist/index.cjs +556 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +90 -9
- package/dist/index.js +543 -79
- package/dist/index.js.map +1 -1
- package/package.json +29 -10
package/dist/index.js
CHANGED
|
@@ -2,125 +2,589 @@
|
|
|
2
2
|
import { isManifestVersion3 } from "@addon-core/browser";
|
|
3
3
|
|
|
4
4
|
// src/InjectCssV2.ts
|
|
5
|
-
import { insertCssTab } from "@addon-core/browser";
|
|
5
|
+
import { browser, insertCssTab, removeCssTab } from "@addon-core/browser";
|
|
6
|
+
|
|
7
|
+
// src/errors.ts
|
|
8
|
+
var InjectCssBaseError = class extends Error {
|
|
9
|
+
code;
|
|
10
|
+
cause;
|
|
11
|
+
constructor(name, code, message, cause) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = name;
|
|
14
|
+
this.code = code;
|
|
15
|
+
if (cause !== void 0) {
|
|
16
|
+
this.cause = cause;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
var InvalidInjectCssTargetError = class extends InjectCssBaseError {
|
|
21
|
+
constructor(message) {
|
|
22
|
+
super("InvalidInjectCssTargetError", "ERR_INJECT_CSS_INVALID_TARGET", `Invalid InjectCss target: ${message}`);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var UnsupportedInjectCssTargetError = class extends InjectCssBaseError {
|
|
26
|
+
constructor(message, cause) {
|
|
27
|
+
super(
|
|
28
|
+
"UnsupportedInjectCssTargetError",
|
|
29
|
+
"ERR_INJECT_CSS_UNSUPPORTED_TARGET",
|
|
30
|
+
`Unsupported InjectCss target: ${message}`,
|
|
31
|
+
cause
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var InvalidInjectCssOptionsError = class extends InjectCssBaseError {
|
|
36
|
+
constructor(message) {
|
|
37
|
+
super(
|
|
38
|
+
"InvalidInjectCssOptionsError",
|
|
39
|
+
"ERR_INJECT_CSS_INVALID_OPTIONS",
|
|
40
|
+
`Invalid InjectCss options: ${message}`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var UnsupportedInjectCssOptionError = class extends InjectCssBaseError {
|
|
45
|
+
constructor(message, cause) {
|
|
46
|
+
super(
|
|
47
|
+
"UnsupportedInjectCssOptionError",
|
|
48
|
+
"ERR_INJECT_CSS_UNSUPPORTED_OPTION",
|
|
49
|
+
`Unsupported InjectCss option: ${message}`,
|
|
50
|
+
cause
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var UnsupportedInjectCssOperationError = class extends InjectCssBaseError {
|
|
55
|
+
operation;
|
|
56
|
+
constructor(operation, message, cause) {
|
|
57
|
+
super(
|
|
58
|
+
"UnsupportedInjectCssOperationError",
|
|
59
|
+
"ERR_INJECT_CSS_UNSUPPORTED_OPERATION",
|
|
60
|
+
`Unsupported InjectCss operation "${operation}": ${message}`,
|
|
61
|
+
cause
|
|
62
|
+
);
|
|
63
|
+
this.operation = operation;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var InvalidInjectCssCodeError = class extends InjectCssBaseError {
|
|
67
|
+
constructor(message) {
|
|
68
|
+
super("InvalidInjectCssCodeError", "ERR_INJECT_CSS_INVALID_CODE", `Invalid InjectCss code: ${message}`);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var InvalidInjectCssFilesError = class extends InjectCssBaseError {
|
|
72
|
+
constructor(message) {
|
|
73
|
+
super("InvalidInjectCssFilesError", "ERR_INJECT_CSS_INVALID_FILES", `Invalid InjectCss files: ${message}`);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
var InjectCssTimeoutError = class extends InjectCssBaseError {
|
|
77
|
+
target;
|
|
78
|
+
timeoutMs;
|
|
79
|
+
operation;
|
|
80
|
+
constructor(target, timeoutMs, operation = "insert") {
|
|
81
|
+
const action = operation === "insert" ? "injection" : "removal";
|
|
82
|
+
super("InjectCssTimeoutError", "ERR_INJECT_CSS_TIMEOUT", `CSS ${action} timed out after ${timeoutMs} ms.`);
|
|
83
|
+
this.target = target;
|
|
84
|
+
this.timeoutMs = timeoutMs;
|
|
85
|
+
this.operation = operation;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
var InjectCssFrameDeliveryError = class extends InjectCssBaseError {
|
|
89
|
+
tabId;
|
|
90
|
+
frameId;
|
|
91
|
+
operation;
|
|
92
|
+
constructor(tabId, frameId, cause, operation = "insert") {
|
|
93
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
94
|
+
const action = operation === "insert" ? "injection" : "removal";
|
|
95
|
+
super(
|
|
96
|
+
"InjectCssFrameDeliveryError",
|
|
97
|
+
"ERR_INJECT_CSS_FRAME_DELIVERY",
|
|
98
|
+
`CSS ${action} failed in frame ${frameId} of tab ${tabId}: ${message}`,
|
|
99
|
+
cause
|
|
100
|
+
);
|
|
101
|
+
this.tabId = tabId;
|
|
102
|
+
this.frameId = frameId;
|
|
103
|
+
this.operation = operation;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
var InjectCssDeliveryError = class extends InjectCssBaseError {
|
|
107
|
+
target;
|
|
108
|
+
operation;
|
|
109
|
+
constructor(target, cause, operation = "insert") {
|
|
110
|
+
const causeMessage = cause instanceof Error ? cause.message : String(cause);
|
|
111
|
+
const action = operation === "insert" ? "injection" : "removal";
|
|
112
|
+
const message = cause instanceof InjectCssFrameDeliveryError ? causeMessage : `CSS ${action} failed: ${causeMessage}`;
|
|
113
|
+
super("InjectCssDeliveryError", "ERR_INJECT_CSS_DELIVERY", message, cause);
|
|
114
|
+
this.target = target;
|
|
115
|
+
this.operation = operation;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// src/validation.ts
|
|
120
|
+
var TARGET_KEYS = /* @__PURE__ */ new Set(["tabId", "allFrames", "frameIds", "documentIds"]);
|
|
121
|
+
var EXECUTION_OPTION_KEYS = /* @__PURE__ */ new Set(["matchAboutBlank", "runAt", "origin", "timeoutMs"]);
|
|
122
|
+
var INJECT_CSS_OPTION_KEYS = /* @__PURE__ */ new Set(["target", ...EXECUTION_OPTION_KEYS]);
|
|
123
|
+
var RUN_AT_VALUES = /* @__PURE__ */ new Set(["document_start", "document_end", "document_idle"]);
|
|
124
|
+
var ORIGIN_VALUES = /* @__PURE__ */ new Set(["AUTHOR", "USER"]);
|
|
125
|
+
var isObject = (value) => {
|
|
126
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
127
|
+
};
|
|
128
|
+
var assertKnownKeys = (value, keys, subject) => {
|
|
129
|
+
const unknownKeys = Object.keys(value).filter((key) => !keys.has(key));
|
|
130
|
+
if (unknownKeys.length > 0) {
|
|
131
|
+
throw new InvalidInjectCssOptionsError(
|
|
132
|
+
`${subject} contains unknown ${unknownKeys.length === 1 ? "field" : "fields"}: ${unknownKeys.map((key) => `"${key}"`).join(", ")}.`
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
var cloneTarget = (target) => {
|
|
137
|
+
if ("frameIds" in target && target.frameIds !== void 0) {
|
|
138
|
+
return { tabId: target.tabId, frameIds: [...target.frameIds] };
|
|
139
|
+
}
|
|
140
|
+
if ("documentIds" in target && target.documentIds !== void 0) {
|
|
141
|
+
return { tabId: target.tabId, documentIds: [...target.documentIds] };
|
|
142
|
+
}
|
|
143
|
+
if ("allFrames" in target && target.allFrames === true) {
|
|
144
|
+
return { tabId: target.tabId, allFrames: true };
|
|
145
|
+
}
|
|
146
|
+
return { tabId: target.tabId };
|
|
147
|
+
};
|
|
148
|
+
var validateInjectCssTarget = (value) => {
|
|
149
|
+
if (!isObject(value)) {
|
|
150
|
+
throw new InvalidInjectCssTargetError("target must be an object.");
|
|
151
|
+
}
|
|
152
|
+
const unknownKeys = Object.keys(value).filter((key) => !TARGET_KEYS.has(key));
|
|
153
|
+
if (unknownKeys.length > 0) {
|
|
154
|
+
throw new InvalidInjectCssTargetError(
|
|
155
|
+
`target contains unknown ${unknownKeys.length === 1 ? "field" : "fields"}: ${unknownKeys.map((key) => `"${key}"`).join(", ")}.`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
if (!Number.isInteger(value.tabId) || value.tabId < 0) {
|
|
159
|
+
throw new InvalidInjectCssTargetError('"tabId" must be a non-negative integer.');
|
|
160
|
+
}
|
|
161
|
+
const selectors = ["allFrames", "frameIds", "documentIds"].filter((key) => value[key] !== void 0);
|
|
162
|
+
if (selectors.length > 1) {
|
|
163
|
+
throw new InvalidInjectCssTargetError('"allFrames", "frameIds", and "documentIds" are mutually exclusive.');
|
|
164
|
+
}
|
|
165
|
+
if (value.allFrames !== void 0 && value.allFrames !== true) {
|
|
166
|
+
throw new InvalidInjectCssTargetError('"allFrames" must be exactly true when provided.');
|
|
167
|
+
}
|
|
168
|
+
if (value.frameIds !== void 0) {
|
|
169
|
+
if (!Array.isArray(value.frameIds) || value.frameIds.length === 0) {
|
|
170
|
+
throw new InvalidInjectCssTargetError('"frameIds" must contain at least one frame ID.');
|
|
171
|
+
}
|
|
172
|
+
if (value.frameIds.some((frameId) => !Number.isInteger(frameId) || frameId < 0)) {
|
|
173
|
+
throw new InvalidInjectCssTargetError("frame ID must be a non-negative integer.");
|
|
174
|
+
}
|
|
175
|
+
if (new Set(value.frameIds).size !== value.frameIds.length) {
|
|
176
|
+
throw new InvalidInjectCssTargetError('"frameIds" must not contain duplicate frame IDs.');
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (value.documentIds !== void 0) {
|
|
180
|
+
if (!Array.isArray(value.documentIds) || value.documentIds.length === 0) {
|
|
181
|
+
throw new InvalidInjectCssTargetError('"documentIds" must contain at least one document ID.');
|
|
182
|
+
}
|
|
183
|
+
if (value.documentIds.some((documentId) => typeof documentId !== "string" || documentId.trim().length === 0)) {
|
|
184
|
+
throw new InvalidInjectCssTargetError("document ID must be a non-empty string.");
|
|
185
|
+
}
|
|
186
|
+
if (new Set(value.documentIds).size !== value.documentIds.length) {
|
|
187
|
+
throw new InvalidInjectCssTargetError('"documentIds" must not contain duplicate document IDs.');
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return cloneTarget(value);
|
|
191
|
+
};
|
|
192
|
+
var validateInjectCssExecutionOptions = (value) => {
|
|
193
|
+
if (!isObject(value)) {
|
|
194
|
+
throw new InvalidInjectCssOptionsError("execution options must be an object.");
|
|
195
|
+
}
|
|
196
|
+
assertKnownKeys(value, EXECUTION_OPTION_KEYS, "execution options");
|
|
197
|
+
if (value.matchAboutBlank !== void 0 && typeof value.matchAboutBlank !== "boolean") {
|
|
198
|
+
throw new InvalidInjectCssOptionsError('"matchAboutBlank" must be a boolean.');
|
|
199
|
+
}
|
|
200
|
+
if (value.runAt !== void 0 && (typeof value.runAt !== "string" || !RUN_AT_VALUES.has(value.runAt))) {
|
|
201
|
+
throw new InvalidInjectCssOptionsError('"runAt" must be "document_start", "document_end", or "document_idle".');
|
|
202
|
+
}
|
|
203
|
+
if (value.origin !== void 0 && (typeof value.origin !== "string" || !ORIGIN_VALUES.has(value.origin))) {
|
|
204
|
+
throw new InvalidInjectCssOptionsError('"origin" must be "AUTHOR" or "USER".');
|
|
205
|
+
}
|
|
206
|
+
if (value.timeoutMs !== void 0 && (typeof value.timeoutMs !== "number" || !Number.isInteger(value.timeoutMs) || value.timeoutMs <= 0)) {
|
|
207
|
+
throw new InvalidInjectCssOptionsError('"timeoutMs" must be a positive integer.');
|
|
208
|
+
}
|
|
209
|
+
return { ...value };
|
|
210
|
+
};
|
|
211
|
+
var validateInjectCssOptions = (value) => {
|
|
212
|
+
if (!isObject(value)) {
|
|
213
|
+
throw new InvalidInjectCssOptionsError("options must be an object.");
|
|
214
|
+
}
|
|
215
|
+
assertKnownKeys(value, INJECT_CSS_OPTION_KEYS, "options");
|
|
216
|
+
const { target, ...execution } = value;
|
|
217
|
+
return {
|
|
218
|
+
target: validateInjectCssTarget(target),
|
|
219
|
+
execution: validateInjectCssExecutionOptions(execution)
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
var validateInjectCssCode = (value) => {
|
|
223
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
224
|
+
throw new InvalidInjectCssCodeError("code must be a non-empty string.");
|
|
225
|
+
}
|
|
226
|
+
return value;
|
|
227
|
+
};
|
|
228
|
+
var validateInjectCssFiles = (files) => {
|
|
229
|
+
const fileList = typeof files === "string" ? [files] : files;
|
|
230
|
+
if (!Array.isArray(fileList) || fileList.length === 0) {
|
|
231
|
+
throw new InvalidInjectCssFilesError("at least one file is required.");
|
|
232
|
+
}
|
|
233
|
+
if (fileList.some((file) => typeof file !== "string" || file.trim().length === 0)) {
|
|
234
|
+
throw new InvalidInjectCssFilesError("each file must be a non-empty string.");
|
|
235
|
+
}
|
|
236
|
+
return [...fileList];
|
|
237
|
+
};
|
|
6
238
|
|
|
7
239
|
// src/AbstractInjectCss.ts
|
|
240
|
+
var DEFAULT_TIMEOUT_MS = 4e3;
|
|
8
241
|
var AbstractInjectCss_default = class {
|
|
9
|
-
|
|
10
|
-
|
|
242
|
+
_target;
|
|
243
|
+
_execution;
|
|
244
|
+
constructor(options) {
|
|
245
|
+
const normalized = validateInjectCssOptions(options);
|
|
246
|
+
this._target = normalized.target;
|
|
247
|
+
this._execution = normalized.execution;
|
|
248
|
+
}
|
|
249
|
+
target(target) {
|
|
250
|
+
const normalizedTarget = validateInjectCssTarget(target);
|
|
251
|
+
this.assertAdapterSupport(normalizedTarget, this._execution);
|
|
252
|
+
this._target = normalizedTarget;
|
|
253
|
+
return this;
|
|
11
254
|
}
|
|
12
255
|
options(options) {
|
|
13
|
-
|
|
256
|
+
const normalizedOptions = validateInjectCssExecutionOptions(options);
|
|
257
|
+
const nextExecution = { ...this._execution, ...normalizedOptions };
|
|
258
|
+
this.assertAdapterSupport(this._target, nextExecution);
|
|
259
|
+
this._execution = nextExecution;
|
|
14
260
|
return this;
|
|
15
261
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
262
|
+
validateCode(css) {
|
|
263
|
+
return validateInjectCssCode(css);
|
|
264
|
+
}
|
|
265
|
+
normalizeFiles(files) {
|
|
266
|
+
return validateInjectCssFiles(files);
|
|
19
267
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return typeof frameId === "boolean" ? frameId : void 0;
|
|
268
|
+
snapshotTarget() {
|
|
269
|
+
return validateInjectCssTarget(this._target);
|
|
23
270
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
271
|
+
snapshotExecution() {
|
|
272
|
+
return { ...this._execution };
|
|
273
|
+
}
|
|
274
|
+
get timeoutMs() {
|
|
275
|
+
return this._execution.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
276
|
+
}
|
|
277
|
+
async withTimeout(task, target, timeoutMs, operation = "insert") {
|
|
278
|
+
return new Promise((resolve, reject) => {
|
|
279
|
+
let settled = false;
|
|
280
|
+
const finish = (callback) => {
|
|
281
|
+
if (settled) return;
|
|
282
|
+
settled = true;
|
|
283
|
+
clearTimeout(timeoutId);
|
|
284
|
+
callback();
|
|
285
|
+
};
|
|
286
|
+
const timeoutId = setTimeout(() => {
|
|
287
|
+
finish(() => reject(new InjectCssTimeoutError(target, timeoutMs, operation)));
|
|
288
|
+
}, timeoutMs);
|
|
289
|
+
task.then(
|
|
290
|
+
(value) => finish(() => resolve(value)),
|
|
291
|
+
(error) => finish(() => reject(error))
|
|
292
|
+
);
|
|
293
|
+
});
|
|
27
294
|
}
|
|
295
|
+
deliveryError(target, error, operation = "insert") {
|
|
296
|
+
if (error instanceof InjectCssDeliveryError || error instanceof InjectCssTimeoutError) {
|
|
297
|
+
return error;
|
|
298
|
+
}
|
|
299
|
+
return new InjectCssDeliveryError(target, error, operation);
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
// src/native-errors.ts
|
|
304
|
+
var UNSUPPORTED_API_PATTERN = /(not supported|unsupported|not (?:available|implemented)|is not a function)\b/i;
|
|
305
|
+
var UNSUPPORTED_FIELD_PATTERN = /(not supported|unsupported|unexpected|unknown|unrecognized|invalid|not (?:a )?valid)\b/i;
|
|
306
|
+
var UNSUPPORTED_TARGET_FIELD_PATTERN = /(not supported|unsupported|unexpected|unknown|unrecognized)\b/i;
|
|
307
|
+
var getNativeErrorMessage = (error) => {
|
|
308
|
+
return error instanceof Error ? error.message : String(error);
|
|
309
|
+
};
|
|
310
|
+
var isUnsupportedRemovalCapabilityError = (error) => {
|
|
311
|
+
const message = getNativeErrorMessage(error);
|
|
312
|
+
return /remove\s*css/i.test(message) && UNSUPPORTED_API_PATTERN.test(message);
|
|
313
|
+
};
|
|
314
|
+
var isUnsupportedOriginCapabilityError = (error) => {
|
|
315
|
+
const message = getNativeErrorMessage(error);
|
|
316
|
+
return /\b(?:(?:css|style)[\s_-]*)?origin\b/i.test(message) && UNSUPPORTED_FIELD_PATTERN.test(message);
|
|
317
|
+
};
|
|
318
|
+
var isUnsupportedDocumentTargetCapabilityError = (error) => {
|
|
319
|
+
const message = getNativeErrorMessage(error);
|
|
320
|
+
return /documentIds?/i.test(message) && UNSUPPORTED_TARGET_FIELD_PATTERN.test(message);
|
|
28
321
|
};
|
|
29
322
|
|
|
30
323
|
// src/InjectCssV2.ts
|
|
31
324
|
var InjectCssV2_default = class extends AbstractInjectCss_default {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
await
|
|
44
|
-
}
|
|
45
|
-
|
|
325
|
+
constructor(options) {
|
|
326
|
+
super(options);
|
|
327
|
+
this.assertAdapterSupport(this._target, this._execution);
|
|
328
|
+
}
|
|
329
|
+
async insert(css) {
|
|
330
|
+
const code = this.validateCode(css);
|
|
331
|
+
const target = this.snapshotTarget();
|
|
332
|
+
const execution = this.snapshotExecution();
|
|
333
|
+
const timeoutMs = this.timeoutMs;
|
|
334
|
+
const details = this.createDetails("insert", execution, { code });
|
|
335
|
+
try {
|
|
336
|
+
await this.withTimeout(this.execute("insert", target, details), target, timeoutMs);
|
|
337
|
+
} catch (error) {
|
|
338
|
+
this.throwDeliveryError("insert", target, execution, error);
|
|
46
339
|
}
|
|
47
340
|
}
|
|
48
341
|
async file(files) {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
342
|
+
const fileList = this.normalizeFiles(files);
|
|
343
|
+
await this.deliverFiles("insert", fileList);
|
|
344
|
+
}
|
|
345
|
+
async remove(css) {
|
|
346
|
+
const code = this.validateCode(css);
|
|
347
|
+
await this.removeSource({ code });
|
|
348
|
+
}
|
|
349
|
+
async removeFile(files) {
|
|
350
|
+
const fileList = this.normalizeFiles(files);
|
|
351
|
+
await this.deliverFiles("remove", fileList);
|
|
352
|
+
}
|
|
353
|
+
assertAdapterSupport(target, _execution) {
|
|
354
|
+
if ("documentIds" in target && target.documentIds !== void 0) {
|
|
355
|
+
throw new UnsupportedInjectCssTargetError('"documentIds" are not supported by the MV2 adapter.');
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
createDetails(operation, execution, source) {
|
|
359
|
+
return {
|
|
360
|
+
...source,
|
|
361
|
+
...operation === "insert" && execution.runAt !== void 0 ? { runAt: execution.runAt } : {},
|
|
362
|
+
...execution.origin !== void 0 ? { cssOrigin: execution.origin.toLowerCase() } : {},
|
|
363
|
+
...execution.matchAboutBlank !== void 0 ? { matchAboutBlank: execution.matchAboutBlank } : {}
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
async execute(operation, target, details) {
|
|
367
|
+
const deliver = operation === "insert" ? insertCssTab : removeCssTab;
|
|
368
|
+
if ("allFrames" in target && target.allFrames === true) {
|
|
369
|
+
await deliver(target.tabId, { ...details, allFrames: true });
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
if ("frameIds" in target && target.frameIds !== void 0) {
|
|
373
|
+
await Promise.all(
|
|
374
|
+
target.frameIds.map(
|
|
375
|
+
(frameId) => this.executeFrame(operation, target.tabId, frameId, { ...details, frameId })
|
|
376
|
+
)
|
|
377
|
+
);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
await deliver(target.tabId, details);
|
|
381
|
+
}
|
|
382
|
+
async executeFrame(operation, tabId, frameId, details) {
|
|
383
|
+
try {
|
|
384
|
+
const deliver = operation === "insert" ? insertCssTab : removeCssTab;
|
|
385
|
+
await deliver(tabId, details);
|
|
386
|
+
} catch (error) {
|
|
387
|
+
throw new InjectCssFrameDeliveryError(tabId, frameId, error, operation);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
async removeSource(source) {
|
|
391
|
+
const target = this.snapshotTarget();
|
|
392
|
+
const execution = this.snapshotExecution();
|
|
393
|
+
const timeoutMs = this.timeoutMs;
|
|
394
|
+
this.assertRemovalSupport();
|
|
395
|
+
try {
|
|
396
|
+
await this.withTimeout(
|
|
397
|
+
this.execute("remove", target, this.createDetails("remove", execution, source)),
|
|
398
|
+
target,
|
|
399
|
+
timeoutMs,
|
|
400
|
+
"remove"
|
|
401
|
+
);
|
|
402
|
+
} catch (error) {
|
|
403
|
+
this.throwDeliveryError("remove", target, execution, error);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
async deliverFiles(operation, fileList) {
|
|
407
|
+
const target = this.snapshotTarget();
|
|
408
|
+
const execution = this.snapshotExecution();
|
|
409
|
+
const timeoutMs = this.timeoutMs;
|
|
410
|
+
let stopped = false;
|
|
411
|
+
if (operation === "remove") {
|
|
412
|
+
this.assertRemovalSupport();
|
|
413
|
+
}
|
|
414
|
+
const task = (async () => {
|
|
415
|
+
for (const file of fileList) {
|
|
416
|
+
if (stopped) return;
|
|
417
|
+
await this.execute(operation, target, this.createDetails(operation, execution, { file }));
|
|
65
418
|
}
|
|
419
|
+
})();
|
|
420
|
+
try {
|
|
421
|
+
await this.withTimeout(task, target, timeoutMs, operation);
|
|
422
|
+
} catch (error) {
|
|
423
|
+
stopped = true;
|
|
424
|
+
this.throwDeliveryError(operation, target, execution, error);
|
|
66
425
|
}
|
|
67
|
-
await Promise.all(injectTasks);
|
|
68
426
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
427
|
+
assertRemovalSupport() {
|
|
428
|
+
if (typeof browser().tabs?.removeCSS !== "function") {
|
|
429
|
+
throw new UnsupportedInjectCssOperationError(
|
|
430
|
+
"remove",
|
|
431
|
+
'the current MV2 browser does not expose "tabs.removeCSS".'
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
throwDeliveryError(operation, target, execution, error) {
|
|
436
|
+
if (operation === "remove" && isUnsupportedRemovalCapabilityError(error)) {
|
|
437
|
+
throw new UnsupportedInjectCssOperationError(
|
|
438
|
+
"remove",
|
|
439
|
+
'the current MV2 browser does not support "tabs.removeCSS".',
|
|
440
|
+
error
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
if (execution.origin !== void 0 && isUnsupportedOriginCapabilityError(error)) {
|
|
444
|
+
throw new UnsupportedInjectCssOptionError('"origin" is not supported by the current browser.', error);
|
|
445
|
+
}
|
|
446
|
+
throw this.deliveryError(target, error, operation);
|
|
72
447
|
}
|
|
73
448
|
};
|
|
74
449
|
|
|
75
450
|
// src/InjectCssV3.ts
|
|
76
|
-
import { insertCss } from "@addon-core/browser";
|
|
451
|
+
import { browser as browser2, insertCss, removeCss } from "@addon-core/browser";
|
|
77
452
|
var InjectCssV3_default = class extends AbstractInjectCss_default {
|
|
453
|
+
constructor(options) {
|
|
454
|
+
super(options);
|
|
455
|
+
this.assertAdapterSupport(this._target, this._execution);
|
|
456
|
+
}
|
|
78
457
|
async insert(css) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
458
|
+
const code = this.validateCode(css);
|
|
459
|
+
const target = this.snapshotTarget();
|
|
460
|
+
const execution = this.snapshotExecution();
|
|
461
|
+
const timeoutMs = this.timeoutMs;
|
|
462
|
+
await this.execute(
|
|
463
|
+
"insert",
|
|
464
|
+
target,
|
|
465
|
+
execution,
|
|
466
|
+
{
|
|
467
|
+
target: this.toNativeTarget(target),
|
|
468
|
+
css: code,
|
|
469
|
+
...execution.origin !== void 0 ? { origin: execution.origin } : {}
|
|
470
|
+
},
|
|
471
|
+
timeoutMs
|
|
472
|
+
);
|
|
84
473
|
}
|
|
85
|
-
async file(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
474
|
+
async file(files) {
|
|
475
|
+
const fileList = this.normalizeFiles(files);
|
|
476
|
+
const target = this.snapshotTarget();
|
|
477
|
+
const execution = this.snapshotExecution();
|
|
478
|
+
const timeoutMs = this.timeoutMs;
|
|
479
|
+
await this.execute(
|
|
480
|
+
"insert",
|
|
481
|
+
target,
|
|
482
|
+
execution,
|
|
483
|
+
{
|
|
484
|
+
target: this.toNativeTarget(target),
|
|
485
|
+
files: fileList,
|
|
486
|
+
...execution.origin !== void 0 ? { origin: execution.origin } : {}
|
|
487
|
+
},
|
|
488
|
+
timeoutMs
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
async remove(css) {
|
|
492
|
+
const code = this.validateCode(css);
|
|
493
|
+
await this.removeInjection({ css: code });
|
|
494
|
+
}
|
|
495
|
+
async removeFile(files) {
|
|
496
|
+
const fileList = this.normalizeFiles(files);
|
|
497
|
+
await this.removeInjection({ files: fileList });
|
|
91
498
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return { ...target, frameIds: this.frameIds };
|
|
499
|
+
assertAdapterSupport(_target, execution) {
|
|
500
|
+
if (execution.matchAboutBlank !== void 0) {
|
|
501
|
+
throw new UnsupportedInjectCssOptionError('"matchAboutBlank" is not supported by the MV3 adapter.');
|
|
96
502
|
}
|
|
97
|
-
if (
|
|
98
|
-
|
|
503
|
+
if (execution.runAt !== void 0) {
|
|
504
|
+
throw new UnsupportedInjectCssOptionError('"runAt" is not supported by the MV3 adapter.');
|
|
99
505
|
}
|
|
100
|
-
|
|
506
|
+
}
|
|
507
|
+
async execute(operation, target, execution, injection, timeoutMs) {
|
|
101
508
|
try {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
509
|
+
const task = operation === "insert" ? insertCss(injection) : removeCss(injection);
|
|
510
|
+
await this.withTimeout(task, target, timeoutMs, operation);
|
|
511
|
+
} catch (error) {
|
|
512
|
+
if ("documentIds" in target && target.documentIds !== void 0 && isUnsupportedDocumentTargetCapabilityError(error)) {
|
|
513
|
+
throw new UnsupportedInjectCssTargetError(
|
|
514
|
+
'"documentIds" are not supported by the current browser.',
|
|
515
|
+
error
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
if (operation === "remove" && isUnsupportedRemovalCapabilityError(error)) {
|
|
519
|
+
throw new UnsupportedInjectCssOperationError(
|
|
520
|
+
"remove",
|
|
521
|
+
'the current MV3 browser does not support "scripting.removeCSS".',
|
|
522
|
+
error
|
|
523
|
+
);
|
|
109
524
|
}
|
|
525
|
+
if (execution.origin !== void 0 && isUnsupportedOriginCapabilityError(error)) {
|
|
526
|
+
throw new UnsupportedInjectCssOptionError('"origin" is not supported by the current browser.', error);
|
|
527
|
+
}
|
|
528
|
+
throw this.deliveryError(target, error, operation);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
async removeInjection(source) {
|
|
532
|
+
const target = this.snapshotTarget();
|
|
533
|
+
const execution = this.snapshotExecution();
|
|
534
|
+
const timeoutMs = this.timeoutMs;
|
|
535
|
+
this.assertRemovalSupport();
|
|
536
|
+
await this.execute(
|
|
537
|
+
"remove",
|
|
538
|
+
target,
|
|
539
|
+
execution,
|
|
540
|
+
{
|
|
541
|
+
target: this.toNativeTarget(target),
|
|
542
|
+
...source,
|
|
543
|
+
...execution.origin !== void 0 ? { origin: execution.origin } : {}
|
|
544
|
+
},
|
|
545
|
+
timeoutMs
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
assertRemovalSupport() {
|
|
549
|
+
if (typeof browser2().scripting?.removeCSS !== "function") {
|
|
550
|
+
throw new UnsupportedInjectCssOperationError(
|
|
551
|
+
"remove",
|
|
552
|
+
'the current MV3 browser does not expose "scripting.removeCSS".'
|
|
553
|
+
);
|
|
110
554
|
}
|
|
111
|
-
return target;
|
|
112
555
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
556
|
+
toNativeTarget(target) {
|
|
557
|
+
if ("frameIds" in target && target.frameIds !== void 0) {
|
|
558
|
+
return { tabId: target.tabId, frameIds: [...target.frameIds] };
|
|
559
|
+
}
|
|
560
|
+
if ("documentIds" in target && target.documentIds !== void 0) {
|
|
561
|
+
return { tabId: target.tabId, documentIds: [...target.documentIds] };
|
|
562
|
+
}
|
|
563
|
+
if ("allFrames" in target && target.allFrames === true) {
|
|
564
|
+
return { tabId: target.tabId, allFrames: true };
|
|
565
|
+
}
|
|
566
|
+
return { tabId: target.tabId };
|
|
116
567
|
}
|
|
117
568
|
};
|
|
118
569
|
|
|
119
570
|
// src/index.ts
|
|
120
|
-
var
|
|
571
|
+
var injectCss = (options) => {
|
|
121
572
|
return isManifestVersion3() ? new InjectCssV3_default(options) : new InjectCssV2_default(options);
|
|
122
573
|
};
|
|
574
|
+
var index_default = injectCss;
|
|
123
575
|
export {
|
|
124
|
-
|
|
576
|
+
InjectCssBaseError,
|
|
577
|
+
InjectCssDeliveryError,
|
|
578
|
+
InjectCssFrameDeliveryError,
|
|
579
|
+
InjectCssTimeoutError,
|
|
580
|
+
InvalidInjectCssCodeError,
|
|
581
|
+
InvalidInjectCssFilesError,
|
|
582
|
+
InvalidInjectCssOptionsError,
|
|
583
|
+
InvalidInjectCssTargetError,
|
|
584
|
+
UnsupportedInjectCssOperationError,
|
|
585
|
+
UnsupportedInjectCssOptionError,
|
|
586
|
+
UnsupportedInjectCssTargetError,
|
|
587
|
+
index_default as default,
|
|
588
|
+
injectCss
|
|
125
589
|
};
|
|
126
590
|
//# sourceMappingURL=index.js.map
|