@esposter/shared 4.3.2 → 4.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 +8 -19
- package/dist/index.d.ts +34 -438
- package/dist/index.js +238 -324
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -3,47 +3,42 @@ import { ResultAsync, fromThrowable } from "neverthrow";
|
|
|
3
3
|
import { parse } from "node-html-parser";
|
|
4
4
|
import mimeDatabase from "mime-db/db.json" with { type: "json" };
|
|
5
5
|
import { defaultTreeAdapter, html as html$1, parseFragment } from "parse5";
|
|
6
|
-
|
|
6
|
+
// src/models/error/ForbiddenError.ts
|
|
7
7
|
var ForbiddenError = class extends Error {
|
|
8
8
|
constructor(message) {
|
|
9
9
|
super(message);
|
|
10
10
|
this.name = "ForbiddenError";
|
|
11
11
|
}
|
|
12
12
|
};
|
|
13
|
-
|
|
14
|
-
//#region src/models/error/InvalidOperationError.ts
|
|
13
|
+
// src/models/error/InvalidOperationError.ts
|
|
15
14
|
var InvalidOperationError = class extends Error {
|
|
16
15
|
constructor(operation, name, message) {
|
|
17
16
|
super(`Invalid operation: ${operation}, name: ${name}, ${message}`);
|
|
18
17
|
this.name = "InvalidOperationError";
|
|
19
18
|
}
|
|
20
19
|
};
|
|
21
|
-
|
|
22
|
-
//#region src/models/error/NotFoundError.ts
|
|
20
|
+
// src/models/error/NotFoundError.ts
|
|
23
21
|
var NotFoundError = class extends Error {
|
|
24
22
|
constructor(name, id) {
|
|
25
23
|
super(`${name} is not found for id: ${id}`);
|
|
26
24
|
this.name = "NotFoundError";
|
|
27
25
|
}
|
|
28
26
|
};
|
|
29
|
-
|
|
30
|
-
//#region src/models/error/NotInitializedError.ts
|
|
27
|
+
// src/models/error/NotInitializedError.ts
|
|
31
28
|
var NotInitializedError = class extends Error {
|
|
32
29
|
constructor(name) {
|
|
33
30
|
super(`${name} is not initialized`);
|
|
34
31
|
this.name = "NotInitializedError";
|
|
35
32
|
}
|
|
36
33
|
};
|
|
37
|
-
|
|
38
|
-
//#region src/models/error/WordFilteredError.ts
|
|
34
|
+
// src/models/error/WordFilteredError.ts
|
|
39
35
|
var WordFilteredError = class extends Error {
|
|
40
36
|
constructor(message) {
|
|
41
37
|
super(message);
|
|
42
38
|
this.name = "WordFilteredError";
|
|
43
39
|
}
|
|
44
40
|
};
|
|
45
|
-
|
|
46
|
-
//#region src/models/shared/Operation.ts
|
|
41
|
+
// src/models/shared/Operation.ts
|
|
47
42
|
let Operation = /* @__PURE__ */ function(Operation) {
|
|
48
43
|
Operation["Create"] = "Create";
|
|
49
44
|
Operation["Delete"] = "Delete";
|
|
@@ -53,8 +48,7 @@ let Operation = /* @__PURE__ */ function(Operation) {
|
|
|
53
48
|
Operation["Update"] = "Update";
|
|
54
49
|
return Operation;
|
|
55
50
|
}({});
|
|
56
|
-
|
|
57
|
-
//#region src/models/eventEmitter/TypedEventEmitter.ts
|
|
51
|
+
// src/models/eventEmitter/TypedEventEmitter.ts
|
|
58
52
|
var TypedEventEmitter = class {
|
|
59
53
|
#entriesMap = /* @__PURE__ */ new Map();
|
|
60
54
|
emit(event, ...args) {
|
|
@@ -89,8 +83,7 @@ var TypedEventEmitter = class {
|
|
|
89
83
|
else this.#entriesMap.set(event, entries);
|
|
90
84
|
}
|
|
91
85
|
};
|
|
92
|
-
|
|
93
|
-
//#region src/models/jsonPatch/JsonPatchOperationType.ts
|
|
86
|
+
// src/models/jsonPatch/JsonPatchOperationType.ts
|
|
94
87
|
let JsonPatchOperationType = /* @__PURE__ */ function(JsonPatchOperationType) {
|
|
95
88
|
JsonPatchOperationType["Add"] = "add";
|
|
96
89
|
JsonPatchOperationType["Copy"] = "copy";
|
|
@@ -100,28 +93,24 @@ let JsonPatchOperationType = /* @__PURE__ */ function(JsonPatchOperationType) {
|
|
|
100
93
|
JsonPatchOperationType["Test"] = "test";
|
|
101
94
|
return JsonPatchOperationType;
|
|
102
95
|
}({});
|
|
103
|
-
|
|
104
|
-
//#region src/models/message/MentionType.ts
|
|
96
|
+
// src/models/message/MentionType.ts
|
|
105
97
|
let MentionType = /* @__PURE__ */ function(MentionType) {
|
|
106
98
|
MentionType["Role"] = "role";
|
|
107
99
|
MentionType["User"] = "user";
|
|
108
100
|
return MentionType;
|
|
109
101
|
}({});
|
|
110
|
-
|
|
111
|
-
//#region src/models/object/ObjectMethod.ts
|
|
102
|
+
// src/models/object/ObjectMethod.ts
|
|
112
103
|
let ObjectMethod = /* @__PURE__ */ function(ObjectMethod) {
|
|
113
104
|
ObjectMethod["ToString"] = "toString";
|
|
114
105
|
ObjectMethod["ValueOf"] = "valueOf";
|
|
115
106
|
return ObjectMethod;
|
|
116
107
|
}({});
|
|
117
|
-
|
|
118
|
-
//#region src/services/app/constants.ts
|
|
108
|
+
// src/services/app/constants.ts
|
|
119
109
|
const MAX_READ_LIMIT = 1e3;
|
|
120
110
|
const SITE_NAME = "Esposter";
|
|
121
111
|
const KIBIBYTE = 1024;
|
|
122
112
|
const GIBIBYTE = KIBIBYTE ** 2 * KIBIBYTE;
|
|
123
|
-
|
|
124
|
-
//#region src/models/router/RoutePath.ts
|
|
113
|
+
// src/models/router/RoutePath.ts
|
|
125
114
|
const RoutePath = {
|
|
126
115
|
About: "/about",
|
|
127
116
|
Achievements: "/achievements",
|
|
@@ -160,24 +149,24 @@ const RoutePath = {
|
|
|
160
149
|
UserSettings: "/user/settings",
|
|
161
150
|
View: (type, id) => `/view/${type}/${id}`
|
|
162
151
|
};
|
|
163
|
-
|
|
164
|
-
//#region src/models/shared/ItemEntityType.ts
|
|
152
|
+
// src/models/shared/ItemEntityType.ts
|
|
165
153
|
const createItemEntityTypeSchema = (schema) => z.object({ type: schema });
|
|
166
|
-
|
|
167
|
-
//#region src/models/shared/ItemMetadata.ts
|
|
154
|
+
// src/models/shared/ItemMetadata.ts
|
|
168
155
|
var ItemMetadata = class {
|
|
169
156
|
createdAt = /* @__PURE__ */ new Date();
|
|
170
157
|
deletedAt = null;
|
|
171
158
|
updatedAt = /* @__PURE__ */ new Date();
|
|
172
159
|
};
|
|
173
|
-
|
|
174
|
-
|
|
160
|
+
// src/util/object/getPropertyNames.ts
|
|
161
|
+
const getPropertyNames = () => new Proxy({}, { get: (_target, property) => property });
|
|
162
|
+
// src/models/shared/ItemMetadataPropertyNames.ts
|
|
163
|
+
const ItemMetadataPropertyNames = getPropertyNames();
|
|
164
|
+
// src/util/reactivity/getRawData.ts
|
|
175
165
|
const getRawData = (data) => {
|
|
176
166
|
const raw = data && data.__v_raw;
|
|
177
167
|
return raw ? getRawData(raw) : data;
|
|
178
168
|
};
|
|
179
|
-
|
|
180
|
-
//#region src/util/reactivity/toRawDeep.ts
|
|
169
|
+
// src/util/reactivity/toRawDeep.ts
|
|
181
170
|
const toRawDeep = (data) => {
|
|
182
171
|
const rawData = getRawData(data);
|
|
183
172
|
for (const key in rawData) if (Object.hasOwn(rawData, key)) {
|
|
@@ -186,28 +175,23 @@ const toRawDeep = (data) => {
|
|
|
186
175
|
}
|
|
187
176
|
return rawData;
|
|
188
177
|
};
|
|
189
|
-
|
|
190
|
-
//#region src/models/shared/Serializable.ts
|
|
178
|
+
// src/models/shared/Serializable.ts
|
|
191
179
|
var Serializable = class {
|
|
192
180
|
toJSON() {
|
|
193
181
|
return structuredClone(toRawDeep(this));
|
|
194
182
|
}
|
|
195
183
|
};
|
|
196
|
-
|
|
197
|
-
//#region src/services/error/toAppError.ts
|
|
184
|
+
// src/services/error/toAppError.ts
|
|
198
185
|
const toAppError = (error) => {
|
|
199
186
|
if (error instanceof Error) return error;
|
|
200
187
|
else if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string") return new Error(error.message, { cause: error });
|
|
201
188
|
else return new Error(String(error), { cause: error });
|
|
202
189
|
};
|
|
203
|
-
|
|
204
|
-
//#region src/services/error/getResult.ts
|
|
190
|
+
// src/services/error/getResult.ts
|
|
205
191
|
const getResult = (callback) => fromThrowable(callback, toAppError)();
|
|
206
|
-
|
|
207
|
-
//#region src/services/error/getResultAsync.ts
|
|
192
|
+
// src/services/error/getResultAsync.ts
|
|
208
193
|
const getResultAsync = (callback) => ResultAsync.fromThrowable(callback, toAppError)();
|
|
209
|
-
|
|
210
|
-
//#region src/services/error/reportFinalizerError.ts
|
|
194
|
+
// src/services/error/reportFinalizerError.ts
|
|
211
195
|
const reportFinalizerError = (callbackResult, finalizerError) => {
|
|
212
196
|
callbackResult.match(() => {
|
|
213
197
|
throw finalizerError;
|
|
@@ -215,11 +199,9 @@ const reportFinalizerError = (callbackResult, finalizerError) => {
|
|
|
215
199
|
console.error(finalizerError);
|
|
216
200
|
});
|
|
217
201
|
};
|
|
218
|
-
|
|
219
|
-
//#region src/util/function/noop.ts
|
|
202
|
+
// src/util/function/noop.ts
|
|
220
203
|
const noop = () => {};
|
|
221
|
-
|
|
222
|
-
//#region src/services/error/withFinalizer.ts
|
|
204
|
+
// src/services/error/withFinalizer.ts
|
|
223
205
|
const withFinalizer = (callback, finalizer) => {
|
|
224
206
|
const callbackResult = getResult(callback);
|
|
225
207
|
if (finalizer) getResult(finalizer).match(noop, (error) => {
|
|
@@ -229,26 +211,27 @@ const withFinalizer = (callback, finalizer) => {
|
|
|
229
211
|
throw error;
|
|
230
212
|
});
|
|
231
213
|
};
|
|
232
|
-
|
|
233
|
-
//#region src/services/error/withFinalizerAsync.ts
|
|
214
|
+
// src/services/error/withFinalizerAsync.ts
|
|
234
215
|
const withFinalizerAsync = async (callback, finalizer) => {
|
|
235
|
-
const callbackResult = await getResultAsync(async () =>
|
|
236
|
-
|
|
216
|
+
const callbackResult = await getResultAsync(async () => {
|
|
217
|
+
return await callback();
|
|
218
|
+
});
|
|
219
|
+
if (finalizer) await getResultAsync(async () => {
|
|
220
|
+
await finalizer();
|
|
221
|
+
}).match(noop, (error) => {
|
|
237
222
|
reportFinalizerError(callbackResult, error);
|
|
238
223
|
});
|
|
239
224
|
return callbackResult.match((value) => value, (error) => {
|
|
240
225
|
throw error;
|
|
241
226
|
});
|
|
242
227
|
};
|
|
243
|
-
|
|
244
|
-
//#region src/services/history/createHistory.ts
|
|
228
|
+
// src/services/history/createHistory.ts
|
|
245
229
|
const createHistory = (limit) => ({
|
|
246
230
|
future: [],
|
|
247
231
|
limit,
|
|
248
232
|
past: []
|
|
249
233
|
});
|
|
250
|
-
|
|
251
|
-
//#region src/services/history/pushHistory.ts
|
|
234
|
+
// src/services/history/pushHistory.ts
|
|
252
235
|
const pushHistory = (history, entry) => {
|
|
253
236
|
const past = [...history.past, entry];
|
|
254
237
|
return {
|
|
@@ -257,8 +240,7 @@ const pushHistory = (history, entry) => {
|
|
|
257
240
|
past: past.slice(Math.max(past.length - history.limit, 0))
|
|
258
241
|
};
|
|
259
242
|
};
|
|
260
|
-
|
|
261
|
-
//#region src/services/history/redoHistory.ts
|
|
243
|
+
// src/services/history/redoHistory.ts
|
|
262
244
|
const redoHistory = (history) => {
|
|
263
245
|
const [entry] = history.future;
|
|
264
246
|
if (entry === void 0) return { history };
|
|
@@ -270,8 +252,7 @@ const redoHistory = (history) => {
|
|
|
270
252
|
}
|
|
271
253
|
};
|
|
272
254
|
};
|
|
273
|
-
|
|
274
|
-
//#region src/services/history/undoHistory.ts
|
|
255
|
+
// src/services/history/undoHistory.ts
|
|
275
256
|
const undoHistory = (history) => {
|
|
276
257
|
const entry = history.past.at(-1);
|
|
277
258
|
if (entry === void 0) return { history };
|
|
@@ -284,11 +265,9 @@ const undoHistory = (history) => {
|
|
|
284
265
|
}
|
|
285
266
|
};
|
|
286
267
|
};
|
|
287
|
-
|
|
288
|
-
//#region src/services/indexedDb/getRequestError.ts
|
|
268
|
+
// src/services/indexedDb/getRequestError.ts
|
|
289
269
|
const getRequestError = (request) => request.error ?? new DOMException("The request failed without an error", "UnknownError");
|
|
290
|
-
|
|
291
|
-
//#region src/services/indexedDb/getTransactionDone.ts
|
|
270
|
+
// src/services/indexedDb/getTransactionDone.ts
|
|
292
271
|
const getTransactionDone = (transaction) => new Promise((resolve, reject) => {
|
|
293
272
|
transaction.addEventListener("complete", () => {
|
|
294
273
|
resolve();
|
|
@@ -297,8 +276,7 @@ const getTransactionDone = (transaction) => new Promise((resolve, reject) => {
|
|
|
297
276
|
reject(transaction.error ?? new DOMException("The transaction was aborted", "AbortError"));
|
|
298
277
|
});
|
|
299
278
|
});
|
|
300
|
-
|
|
301
|
-
//#region src/services/indexedDb/requestToPromise.ts
|
|
279
|
+
// src/services/indexedDb/requestToPromise.ts
|
|
302
280
|
const requestToPromise = (request) => new Promise((resolve, reject) => {
|
|
303
281
|
request.addEventListener("success", () => {
|
|
304
282
|
resolve(request.result);
|
|
@@ -307,14 +285,12 @@ const requestToPromise = (request) => new Promise((resolve, reject) => {
|
|
|
307
285
|
reject(getRequestError(request));
|
|
308
286
|
});
|
|
309
287
|
});
|
|
310
|
-
|
|
311
|
-
//#region src/services/indexedDb/wrapIndex.ts
|
|
288
|
+
// src/services/indexedDb/wrapIndex.ts
|
|
312
289
|
const wrapIndex = (index) => ({
|
|
313
290
|
getAll: (query, count) => requestToPromise(index.getAll(query, count)),
|
|
314
291
|
getAllKeys: (query, count) => requestToPromise(index.getAllKeys(query, count))
|
|
315
292
|
});
|
|
316
|
-
|
|
317
|
-
//#region src/services/indexedDb/wrapObjectStore.ts
|
|
293
|
+
// src/services/indexedDb/wrapObjectStore.ts
|
|
318
294
|
const wrapObjectStore = (objectStore) => {
|
|
319
295
|
const reader = {
|
|
320
296
|
get: (key) => requestToPromise(objectStore.get(key)),
|
|
@@ -335,17 +311,14 @@ const wrapObjectStore = (objectStore) => {
|
|
|
335
311
|
...creator
|
|
336
312
|
};
|
|
337
313
|
};
|
|
338
|
-
|
|
339
|
-
//#region src/services/indexedDb/getTransactionObjectStore.ts
|
|
314
|
+
// src/services/indexedDb/getTransactionObjectStore.ts
|
|
340
315
|
const getTransactionObjectStore = (transaction) => (name) => wrapObjectStore(transaction.objectStore(name));
|
|
341
|
-
|
|
342
|
-
//#region src/services/indexedDb/wrapTransaction.ts
|
|
316
|
+
// src/services/indexedDb/wrapTransaction.ts
|
|
343
317
|
const wrapTransaction = (transaction) => ({
|
|
344
318
|
done: getTransactionDone(transaction),
|
|
345
319
|
objectStore: getTransactionObjectStore(transaction)
|
|
346
320
|
});
|
|
347
|
-
|
|
348
|
-
//#region src/services/indexedDb/wrapDatabase.ts
|
|
321
|
+
// src/services/indexedDb/wrapDatabase.ts
|
|
349
322
|
const wrapDatabase = (database) => {
|
|
350
323
|
const getReadonlyObjectStore = (storeName) => wrapObjectStore(database.transaction(storeName, "readonly").objectStore(storeName));
|
|
351
324
|
const getReadwriteObjectStore = (storeName) => wrapObjectStore(database.transaction(storeName, "readwrite").objectStore(storeName));
|
|
@@ -366,19 +339,28 @@ const wrapDatabase = (database) => {
|
|
|
366
339
|
transaction
|
|
367
340
|
};
|
|
368
341
|
};
|
|
369
|
-
|
|
370
|
-
//#region src/services/indexedDb/wrapUpgradeDatabase.ts
|
|
342
|
+
// src/services/indexedDb/wrapUpgradeDatabase.ts
|
|
371
343
|
const wrapUpgradeDatabase = (database) => ({
|
|
372
344
|
...wrapDatabase(database),
|
|
373
345
|
createObjectStore: (name, options) => wrapObjectStore(database.createObjectStore(name, options))
|
|
374
346
|
});
|
|
375
|
-
|
|
376
|
-
|
|
347
|
+
// src/util/function/getSynchronizedFunction.ts
|
|
348
|
+
const pendingPromises = /* @__PURE__ */ new Set();
|
|
349
|
+
const getSynchronizedFunction = (asyncFunction) => (...args) => {
|
|
350
|
+
const promise = withFinalizerAsync(() => asyncFunction(...args), () => {
|
|
351
|
+
pendingPromises.delete(promise);
|
|
352
|
+
});
|
|
353
|
+
pendingPromises.add(promise);
|
|
354
|
+
};
|
|
355
|
+
const waitForSynchronizedFunctions = async () => {
|
|
356
|
+
await Promise.allSettled(pendingPromises);
|
|
357
|
+
};
|
|
358
|
+
// src/services/indexedDb/wrapUpgradeTransaction.ts
|
|
377
359
|
const wrapUpgradeTransaction = (transaction) => {
|
|
378
360
|
const done = getTransactionDone(transaction);
|
|
379
|
-
getResultAsync(() => done).match(noop, (error) => {
|
|
361
|
+
getSynchronizedFunction(() => getResultAsync(() => done).match(noop, (error) => {
|
|
380
362
|
if (transaction.error) console.error(error);
|
|
381
|
-
});
|
|
363
|
+
}))();
|
|
382
364
|
return {
|
|
383
365
|
get done() {
|
|
384
366
|
return done;
|
|
@@ -386,8 +368,7 @@ const wrapUpgradeTransaction = (transaction) => {
|
|
|
386
368
|
objectStore: getTransactionObjectStore(transaction)
|
|
387
369
|
};
|
|
388
370
|
};
|
|
389
|
-
|
|
390
|
-
//#region src/services/indexedDb/openDatabase.ts
|
|
371
|
+
// src/services/indexedDb/openDatabase.ts
|
|
391
372
|
const openDatabase = (name, version, options = {}) => new Promise((resolve, reject) => {
|
|
392
373
|
const request = indexedDB.open(name, version);
|
|
393
374
|
request.addEventListener("blocked", (event) => {
|
|
@@ -415,36 +396,30 @@ const openDatabase = (name, version, options = {}) => new Promise((resolve, reje
|
|
|
415
396
|
reject(getRequestError(request));
|
|
416
397
|
});
|
|
417
398
|
});
|
|
418
|
-
|
|
419
|
-
//#region src/services/jsonPatch/constants.ts
|
|
399
|
+
// src/services/jsonPatch/constants.ts
|
|
420
400
|
const APPEND_SEGMENT = "-";
|
|
421
401
|
const JSON_POINTER_REGEX = /^(?:\/(?:[^/~]|~[01])*)*$/u;
|
|
422
|
-
|
|
423
|
-
//#region src/services/jsonPatch/parseArrayIndex.ts
|
|
402
|
+
// src/services/jsonPatch/parseArrayIndex.ts
|
|
424
403
|
const ARRAY_INDEX_REGEX = /^(?:0|[1-9]\d*)$/u;
|
|
425
404
|
const parseArrayIndex = (segment, maxIndex) => {
|
|
426
405
|
const index = Number(segment);
|
|
427
406
|
return ARRAY_INDEX_REGEX.test(segment) && index <= maxIndex ? index : void 0;
|
|
428
407
|
};
|
|
429
|
-
|
|
430
|
-
//#region src/services/jsonPatch/parseJsonPointer.ts
|
|
408
|
+
// src/services/jsonPatch/parseJsonPointer.ts
|
|
431
409
|
const parseJsonPointer = (pointer) => {
|
|
432
410
|
if (pointer === "") return [];
|
|
433
411
|
else if (!JSON_POINTER_REGEX.test(pointer)) throw new InvalidOperationError("Read", pointer, "not a JSON Pointer");
|
|
434
412
|
return pointer.slice(1).split("/").map((segment) => segment.replaceAll("~1", "/").replaceAll("~0", "~"));
|
|
435
413
|
};
|
|
436
|
-
|
|
437
|
-
//#region src/services/jsonPatch/toJsonPointer.ts
|
|
414
|
+
// src/services/jsonPatch/toJsonPointer.ts
|
|
438
415
|
const toJsonPointer = (segments) => segments.map((segment) => `/${segment.replaceAll("~", "~0").replaceAll("/", "~1")}`).join("");
|
|
439
|
-
|
|
440
|
-
//#region src/util/object/checkIsPlainObject.ts
|
|
416
|
+
// src/util/object/checkIsPlainObject.ts
|
|
441
417
|
const checkIsPlainObject = (data) => {
|
|
442
418
|
if (typeof data !== "object" || data === null) return false;
|
|
443
419
|
const prototype = Object.getPrototypeOf(data);
|
|
444
420
|
return prototype === null || prototype === Object.prototype;
|
|
445
421
|
};
|
|
446
|
-
|
|
447
|
-
//#region src/services/jsonPatch/readJsonValue.ts
|
|
422
|
+
// src/services/jsonPatch/readJsonValue.ts
|
|
448
423
|
const readJsonValue = (document, segments) => {
|
|
449
424
|
let value = document;
|
|
450
425
|
for (const segment of segments) {
|
|
@@ -455,8 +430,7 @@ const readJsonValue = (document, segments) => {
|
|
|
455
430
|
}
|
|
456
431
|
return value;
|
|
457
432
|
};
|
|
458
|
-
|
|
459
|
-
//#region src/services/jsonPatch/updateJsonValue.ts
|
|
433
|
+
// src/services/jsonPatch/updateJsonValue.ts
|
|
460
434
|
const updateJsonValue = (document, segments, update) => {
|
|
461
435
|
const [segment, ...restSegments] = segments;
|
|
462
436
|
if (segment === void 0) return update(document);
|
|
@@ -468,8 +442,7 @@ const updateJsonValue = (document, segments, update) => {
|
|
|
468
442
|
};
|
|
469
443
|
else throw new InvalidOperationError("Update", toJsonPointer(segments), "no such member");
|
|
470
444
|
};
|
|
471
|
-
|
|
472
|
-
//#region src/services/jsonPatch/addJsonValue.ts
|
|
445
|
+
// src/services/jsonPatch/addJsonValue.ts
|
|
473
446
|
const addJsonValue = (document, path, value) => {
|
|
474
447
|
const segments = parseJsonPointer(path);
|
|
475
448
|
const parentSegments = segments.slice(0, -1);
|
|
@@ -509,8 +482,7 @@ const addJsonValue = (document, path, value) => {
|
|
|
509
482
|
};
|
|
510
483
|
else throw new InvalidOperationError("Update", path, "its parent holds no members");
|
|
511
484
|
};
|
|
512
|
-
|
|
513
|
-
//#region src/services/jsonPatch/removeJsonValue.ts
|
|
485
|
+
// src/services/jsonPatch/removeJsonValue.ts
|
|
514
486
|
const removeJsonValue = (document, path) => {
|
|
515
487
|
const segments = parseJsonPointer(path);
|
|
516
488
|
const parentSegments = segments.slice(0, -1);
|
|
@@ -538,28 +510,23 @@ const removeJsonValue = (document, path) => {
|
|
|
538
510
|
};
|
|
539
511
|
} else throw new InvalidOperationError("Delete", path, "no such member");
|
|
540
512
|
};
|
|
541
|
-
|
|
542
|
-
//#region src/util/object/checkIsCustomMethod.ts
|
|
513
|
+
// src/util/object/checkIsCustomMethod.ts
|
|
543
514
|
const checkIsCustomMethod = (value, methodName) => {
|
|
544
515
|
const method = Reflect.get(value, methodName);
|
|
545
516
|
return typeof method === "function" && method !== Object.prototype[methodName];
|
|
546
517
|
};
|
|
547
|
-
|
|
548
|
-
//#region src/util/object/checkIsSameBytes.ts
|
|
518
|
+
// src/util/object/checkIsSameBytes.ts
|
|
549
519
|
const toBytes = (view) => ArrayBuffer.isView(view) ? new Uint8Array(view.buffer, view.byteOffset, view.byteLength) : new Uint8Array(view);
|
|
550
520
|
const checkIsSameBytes = (first, second) => {
|
|
551
521
|
const firstBytes = toBytes(first);
|
|
552
522
|
const secondBytes = toBytes(second);
|
|
553
523
|
return firstBytes.length === secondBytes.length && firstBytes.every((byte, index) => byte === secondBytes[index]);
|
|
554
524
|
};
|
|
555
|
-
|
|
556
|
-
//#region src/util/object/checkIsSameValueZero.ts
|
|
525
|
+
// src/util/object/checkIsSameValueZero.ts
|
|
557
526
|
const checkIsSameValueZero = (first, second) => first === second || Number.isNaN(first) && Number.isNaN(second);
|
|
558
|
-
|
|
559
|
-
//#region src/util/object/getEnumerableKeys.ts
|
|
527
|
+
// src/util/object/getEnumerableKeys.ts
|
|
560
528
|
const getEnumerableKeys = (value) => Reflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key));
|
|
561
|
-
|
|
562
|
-
//#region src/util/object/checkIsDeepEqual.ts
|
|
529
|
+
// src/util/object/checkIsDeepEqual.ts
|
|
563
530
|
const checkIsBinary = (value) => ArrayBuffer.isView(value) || value instanceof ArrayBuffer || typeof SharedArrayBuffer !== "undefined" && value instanceof SharedArrayBuffer;
|
|
564
531
|
const checkIsDeepEqual = (first, second) => {
|
|
565
532
|
if (first === second) return true;
|
|
@@ -589,13 +556,11 @@ const checkIsDeepEqual = (first, second) => {
|
|
|
589
556
|
if (firstKeys.length !== getEnumerableKeys(second).length) return false;
|
|
590
557
|
return firstKeys.every((key) => Object.prototype.propertyIsEnumerable.call(second, key) && checkIsDeepEqual(Reflect.get(first, key), Reflect.get(second, key)));
|
|
591
558
|
};
|
|
592
|
-
|
|
593
|
-
//#region src/util/validation/exhaustiveGuard.ts
|
|
559
|
+
// src/util/validation/exhaustiveGuard.ts
|
|
594
560
|
const exhaustiveGuard = (value) => {
|
|
595
561
|
throw new InvalidOperationError("Read", exhaustiveGuard.name, JSON.stringify(value));
|
|
596
562
|
};
|
|
597
|
-
|
|
598
|
-
//#region src/services/jsonPatch/applyPatch.ts
|
|
563
|
+
// src/services/jsonPatch/applyPatch.ts
|
|
599
564
|
const applyPatch = (document, operation) => {
|
|
600
565
|
switch (operation.op) {
|
|
601
566
|
case "add": return addJsonValue(document, operation.path, operation.value);
|
|
@@ -637,8 +602,7 @@ const applyPatch = (document, operation) => {
|
|
|
637
602
|
default: return exhaustiveGuard(operation);
|
|
638
603
|
}
|
|
639
604
|
};
|
|
640
|
-
|
|
641
|
-
//#region src/services/jsonPatch/applyPatches.ts
|
|
605
|
+
// src/services/jsonPatch/applyPatches.ts
|
|
642
606
|
const applyPatches = (document, operations) => {
|
|
643
607
|
let patchedDocument = document;
|
|
644
608
|
const inverseGroups = [];
|
|
@@ -652,8 +616,7 @@ const applyPatches = (document, operations) => {
|
|
|
652
616
|
inverses: inverseGroups.toReversed().flat()
|
|
653
617
|
};
|
|
654
618
|
};
|
|
655
|
-
|
|
656
|
-
//#region src/services/message/constants.ts
|
|
619
|
+
// src/services/message/constants.ts
|
|
657
620
|
const MENTION_ID_ATTRIBUTE = "data-id";
|
|
658
621
|
const MENTION_ITEM_TYPE_ATTRIBUTE = "data-mention-type";
|
|
659
622
|
const MENTION_LABEL_ATTRIBUTE = "data-label";
|
|
@@ -666,11 +629,13 @@ const CUSTOM_EMOJI_ID_ATTRIBUTE = "data-custom-emoji-id";
|
|
|
666
629
|
const CUSTOM_EMOJI_NAME_ATTRIBUTE = "data-custom-emoji-name";
|
|
667
630
|
const SPOILER_ATTRIBUTE = "data-spoiler";
|
|
668
631
|
const SPOILER_SELECTOR = `span[${SPOILER_ATTRIBUTE}]`;
|
|
669
|
-
|
|
670
|
-
|
|
632
|
+
// src/services/message/emoji/checkIsOnlyReactor.ts
|
|
633
|
+
const checkIsOnlyReactor = (userIds, userId) => userIds.length === 1 && userIds[0] === userId;
|
|
634
|
+
// src/services/message/emoji/getUpdatedUserIds.ts
|
|
635
|
+
const getUpdatedUserIds = (userIds, newUserId) => userIds.includes(newUserId) ? userIds.filter((id) => id !== newUserId) : [...userIds, newUserId];
|
|
636
|
+
// src/services/message/getMentions.ts
|
|
671
637
|
const getMentions = (message) => parse(message).querySelectorAll(MENTION_SELECTOR);
|
|
672
|
-
|
|
673
|
-
//#region src/services/mime/constants.ts
|
|
638
|
+
// src/services/mime/constants.ts
|
|
674
639
|
const MEDIA_TYPE_REGEX = /^\s*(?<mediaType>[^;\s]*)(?:;|\s|$)/u;
|
|
675
640
|
const PATH_SEPARATOR_REGEX = /[/\\]/u;
|
|
676
641
|
const TEXT_MEDIA_TYPE_REGEX = /^text\//iu;
|
|
@@ -696,26 +661,22 @@ const TypeScoreMap = /* @__PURE__ */ new Map([
|
|
|
696
661
|
["video", 3]
|
|
697
662
|
]);
|
|
698
663
|
const DEFAULT_TYPE_SCORE = 0;
|
|
699
|
-
|
|
700
|
-
//#region src/services/mime/getMediaType.ts
|
|
664
|
+
// src/services/mime/getMediaType.ts
|
|
701
665
|
const getMediaType = (value) => MEDIA_TYPE_REGEX.exec(value)?.groups?.mediaType ?? "";
|
|
702
|
-
|
|
703
|
-
//#region src/services/mime/getMimeTypeEntryMap.ts
|
|
666
|
+
// src/services/mime/getMimeTypeEntryMap.ts
|
|
704
667
|
let mimeTypeEntryMap;
|
|
705
668
|
const getMimeTypeEntryMap = () => {
|
|
706
669
|
mimeTypeEntryMap ??= new Map(Object.entries(mimeDatabase));
|
|
707
670
|
return mimeTypeEntryMap;
|
|
708
671
|
};
|
|
709
|
-
|
|
710
|
-
//#region src/services/mime/charset.ts
|
|
672
|
+
// src/services/mime/charset.ts
|
|
711
673
|
const charset = (type) => {
|
|
712
674
|
const mediaType = getMediaType(type);
|
|
713
675
|
const dataCharset = getMimeTypeEntryMap().get(mediaType.toLowerCase())?.charset;
|
|
714
676
|
if (dataCharset) return dataCharset;
|
|
715
677
|
return TEXT_MEDIA_TYPE_REGEX.test(mediaType) ? DEFAULT_TEXT_CHARSET : false;
|
|
716
678
|
};
|
|
717
|
-
|
|
718
|
-
//#region src/services/mime/getMimeScore.ts
|
|
679
|
+
// src/services/mime/getMimeScore.ts
|
|
719
680
|
const getMimeScore = (mimeType, source = "") => {
|
|
720
681
|
if (mimeType === "application/octet-stream") return 0;
|
|
721
682
|
const [type = "", subtype = ""] = mimeType.split("/");
|
|
@@ -726,8 +687,7 @@ const getMimeScore = (mimeType, source = "") => {
|
|
|
726
687
|
const lengthScore = 1 - mimeType.length / 100;
|
|
727
688
|
return facetScore + sourceScore + typeScore + lengthScore;
|
|
728
689
|
};
|
|
729
|
-
|
|
730
|
-
//#region src/services/mime/getExtensionMimeTypeMap.ts
|
|
690
|
+
// src/services/mime/getExtensionMimeTypeMap.ts
|
|
731
691
|
let extensionMimeTypeMap;
|
|
732
692
|
const getPreferredMimeType = (currentMimeType, candidateMimeType) => {
|
|
733
693
|
if (currentMimeType === void 0) return candidateMimeType;
|
|
@@ -742,8 +702,7 @@ const getExtensionMimeTypeMap = () => {
|
|
|
742
702
|
}
|
|
743
703
|
return extensionMimeTypeMap;
|
|
744
704
|
};
|
|
745
|
-
|
|
746
|
-
//#region src/services/mime/lookup.ts
|
|
705
|
+
// src/services/mime/lookup.ts
|
|
747
706
|
const getExtension = (path) => {
|
|
748
707
|
const name = path.split(PATH_SEPARATOR_REGEX).at(-1) ?? "";
|
|
749
708
|
const dotIndex = name.lastIndexOf(".");
|
|
@@ -755,8 +714,7 @@ const lookup = (path) => {
|
|
|
755
714
|
if (!extension) return false;
|
|
756
715
|
return getExtensionMimeTypeMap().get(extension) ?? false;
|
|
757
716
|
};
|
|
758
|
-
|
|
759
|
-
//#region src/services/mime/contentType.ts
|
|
717
|
+
// src/services/mime/contentType.ts
|
|
760
718
|
const contentType = (value) => {
|
|
761
719
|
const mediaType = value.includes("/") ? value : lookup(value);
|
|
762
720
|
if (!mediaType) return false;
|
|
@@ -764,17 +722,13 @@ const contentType = (value) => {
|
|
|
764
722
|
const mediaCharset = charset(mediaType);
|
|
765
723
|
return mediaCharset ? `${mediaType}; charset=${mediaCharset.toLowerCase()}` : mediaType;
|
|
766
724
|
};
|
|
767
|
-
|
|
768
|
-
//#region src/services/mime/extension.ts
|
|
725
|
+
// src/services/mime/extension.ts
|
|
769
726
|
const extension = (type) => getMimeTypeEntryMap().get(getMediaType(type).toLowerCase())?.extensions?.[0] ?? false;
|
|
770
|
-
|
|
771
|
-
//#region src/services/prettier/css.ts
|
|
727
|
+
// src/services/prettier/css.ts
|
|
772
728
|
const css = String.raw;
|
|
773
|
-
|
|
774
|
-
//#region src/services/prettier/html.ts
|
|
729
|
+
// src/services/prettier/html.ts
|
|
775
730
|
const html = String.raw;
|
|
776
|
-
|
|
777
|
-
//#region src/services/profanity/englishProfaneWords.ts
|
|
731
|
+
// src/services/profanity/englishProfaneWords.ts
|
|
778
732
|
const englishProfaneWords = [
|
|
779
733
|
"4r5e",
|
|
780
734
|
"5h1t",
|
|
@@ -1226,8 +1180,7 @@ const englishProfaneWords = [
|
|
|
1226
1180
|
"willies",
|
|
1227
1181
|
"willy"
|
|
1228
1182
|
];
|
|
1229
|
-
|
|
1230
|
-
//#region src/services/profanity/checkContainsProfanity.ts
|
|
1183
|
+
// src/services/profanity/checkContainsProfanity.ts
|
|
1231
1184
|
const WORD_CHARACTER_CLASS = String.raw`\p{L}\p{N}\p{M}`;
|
|
1232
1185
|
const PROFANE_WORD_ALTERNATION = englishProfaneWords.map((word) => word.replaceAll(/[.*+?^${}()|[\]\\]/gu, String.raw`\$&`)).join("|");
|
|
1233
1186
|
const WHOLE_WORD_PROFANITY_REGEX = new RegExp(`(?<![${WORD_CHARACTER_CLASS}])(?:${PROFANE_WORD_ALTERNATION})(?![${WORD_CHARACTER_CLASS}])`, "iu");
|
|
@@ -1236,11 +1189,9 @@ const checkContainsProfanity = (text, { isWholeWord = true } = {}) => {
|
|
|
1236
1189
|
if (typeof text !== "string") return false;
|
|
1237
1190
|
return (isWholeWord ? WHOLE_WORD_PROFANITY_REGEX : SUBSTRING_PROFANITY_REGEX).test(text);
|
|
1238
1191
|
};
|
|
1239
|
-
|
|
1240
|
-
//#region src/services/sanitizeHtml/checkIsWhitespaceCharacter.ts
|
|
1192
|
+
// src/services/sanitizeHtml/checkIsWhitespaceCharacter.ts
|
|
1241
1193
|
const checkIsWhitespaceCharacter = (character) => character.trim() === "";
|
|
1242
|
-
|
|
1243
|
-
//#region src/services/sanitizeHtml/checkIsUnsafeUrlCharacter.ts
|
|
1194
|
+
// src/services/sanitizeHtml/checkIsUnsafeUrlCharacter.ts
|
|
1244
1195
|
const FIRST_PRINTABLE_CODE_POINT = 32;
|
|
1245
1196
|
const DELETE_CODE_POINT = 127;
|
|
1246
1197
|
const LAST_C1_CONTROL_CODE_POINT = 159;
|
|
@@ -1249,13 +1200,11 @@ const checkIsUnsafeUrlCharacter = (character) => {
|
|
|
1249
1200
|
const codePoint = character.codePointAt(0) ?? 0;
|
|
1250
1201
|
return checkIsWhitespaceCharacter(character) || codePoint < FIRST_PRINTABLE_CODE_POINT || codePoint >= DELETE_CODE_POINT && codePoint <= LAST_C1_CONTROL_CODE_POINT || character === GRAVE_ACCENT;
|
|
1251
1202
|
};
|
|
1252
|
-
|
|
1253
|
-
//#region src/util/array/takeOne.ts
|
|
1203
|
+
// src/util/array/takeOne.ts
|
|
1254
1204
|
const takeOne = (values, index = 0) => {
|
|
1255
1205
|
return values[index];
|
|
1256
1206
|
};
|
|
1257
|
-
|
|
1258
|
-
//#region src/services/sanitizeHtml/checkIsAllowedUrl.ts
|
|
1207
|
+
// src/services/sanitizeHtml/checkIsAllowedUrl.ts
|
|
1259
1208
|
const PATH_DELIMITER_REGEX = /[/?#]/u;
|
|
1260
1209
|
const NON_SCHEME_CHARACTERS_REGEX = /[^a-z\d+.-]/giu;
|
|
1261
1210
|
const SCHEME_SEPARATOR = ":";
|
|
@@ -1267,8 +1216,18 @@ const checkIsAllowedUrl = (url, allowedSchemes) => {
|
|
|
1267
1216
|
const scheme = beforePath.slice(0, separatorIndex).replaceAll(NON_SCHEME_CHARACTERS_REGEX, "").toLowerCase();
|
|
1268
1217
|
return allowedSchemes.includes(scheme);
|
|
1269
1218
|
};
|
|
1270
|
-
|
|
1271
|
-
|
|
1219
|
+
// src/services/sanitizeHtml/getTagPolicy.ts
|
|
1220
|
+
const getTagPolicy = (tagPolicies, tagName) => Object.hasOwn(tagPolicies, tagName) ? tagPolicies[tagName] : void 0;
|
|
1221
|
+
// src/services/sanitizeHtml/checkIsSourceAllowed.ts
|
|
1222
|
+
const checkIsSourceAllowed = (element, allowedSources) => {
|
|
1223
|
+
const sourceRules = getTagPolicy(allowedSources, element.tagName);
|
|
1224
|
+
if (!sourceRules) return true;
|
|
1225
|
+
return Object.entries(sourceRules).every(([name, patterns]) => {
|
|
1226
|
+
const attribute = element.attrs.find((attr) => attr.name === name);
|
|
1227
|
+
return attribute !== void 0 && patterns.some((pattern) => pattern.test(attribute.value));
|
|
1228
|
+
});
|
|
1229
|
+
};
|
|
1230
|
+
// src/services/sanitizeHtml/constants.ts
|
|
1272
1231
|
const HTML_NAMESPACE = html$1.NS.HTML;
|
|
1273
1232
|
const DEFAULT_ALLOWED_TAGS = [
|
|
1274
1233
|
"address",
|
|
@@ -1402,23 +1361,19 @@ const MAX_NESTING_DEPTH = 256;
|
|
|
1402
1361
|
const SRCSET_DESCRIPTOR_REGEX = /^(?:\d+w|\d*\.?\d+x|\d+h)$/u;
|
|
1403
1362
|
const ESCAPED_TEXT_CHARACTERS_REGEX = /[&<>]/gu;
|
|
1404
1363
|
const ESCAPED_ATTRIBUTE_CHARACTERS_REGEX = /[&"<>]/gu;
|
|
1405
|
-
const SANITIZER_ADVISORY_WATCH_SINCE = "2026-10-
|
|
1406
|
-
|
|
1407
|
-
//#region src/services/sanitizeHtml/getChildNodes.ts
|
|
1364
|
+
const SANITIZER_ADVISORY_WATCH_SINCE = "2026-10-23";
|
|
1365
|
+
// src/services/sanitizeHtml/getChildNodes.ts
|
|
1408
1366
|
const getChildNodes = (element) => "content" in element ? element.content.childNodes : element.childNodes;
|
|
1409
|
-
|
|
1410
|
-
//#region src/services/sanitizeHtml/collectText.ts
|
|
1367
|
+
// src/services/sanitizeHtml/collectText.ts
|
|
1411
1368
|
const collectText = (nodes, depth) => depth > 256 ? "" : nodes.map((node) => {
|
|
1412
1369
|
if ("value" in node) return node.value;
|
|
1413
1370
|
if (!("tagName" in node) || NON_TEXT_TAGS.includes(node.tagName)) return "";
|
|
1414
1371
|
return collectText(getChildNodes(node), depth + 1);
|
|
1415
1372
|
}).join("");
|
|
1416
|
-
|
|
1417
|
-
//#region src/services/sanitizeHtml/escapeCharacters.ts
|
|
1373
|
+
// src/services/sanitizeHtml/escapeCharacters.ts
|
|
1418
1374
|
const NON_BREAKING_SPACE = String.fromCodePoint(160);
|
|
1419
1375
|
const escapeCharacters = (value, charactersRegex, entities) => value.replace(charactersRegex, (character) => entities[character] ?? character).replaceAll(NON_BREAKING_SPACE, " ");
|
|
1420
|
-
|
|
1421
|
-
//#region src/services/sanitizeHtml/escapeAttribute.ts
|
|
1376
|
+
// src/services/sanitizeHtml/escapeAttribute.ts
|
|
1422
1377
|
const ESCAPED_ATTRIBUTE_CHARACTERS = {
|
|
1423
1378
|
"\"": """,
|
|
1424
1379
|
"&": "&",
|
|
@@ -1426,26 +1381,22 @@ const ESCAPED_ATTRIBUTE_CHARACTERS = {
|
|
|
1426
1381
|
">": ">"
|
|
1427
1382
|
};
|
|
1428
1383
|
const escapeAttribute = (value) => escapeCharacters(value, ESCAPED_ATTRIBUTE_CHARACTERS_REGEX, ESCAPED_ATTRIBUTE_CHARACTERS);
|
|
1429
|
-
|
|
1430
|
-
//#region src/services/sanitizeHtml/escapeText.ts
|
|
1384
|
+
// src/services/sanitizeHtml/escapeText.ts
|
|
1431
1385
|
const ESCAPED_TEXT_CHARACTERS = {
|
|
1432
1386
|
"&": "&",
|
|
1433
1387
|
"<": "<",
|
|
1434
1388
|
">": ">"
|
|
1435
1389
|
};
|
|
1436
1390
|
const escapeText = (text) => escapeCharacters(text, ESCAPED_TEXT_CHARACTERS_REGEX, ESCAPED_TEXT_CHARACTERS);
|
|
1437
|
-
|
|
1438
|
-
//#region src/services/sanitizeHtml/matchesClassPattern.ts
|
|
1391
|
+
// src/services/sanitizeHtml/matchesClassPattern.ts
|
|
1439
1392
|
const matchesClassPattern = (className, pattern) => pattern.endsWith("*") ? className.startsWith(pattern.slice(0, -1)) : className === pattern;
|
|
1440
|
-
|
|
1441
|
-
//#region src/services/sanitizeHtml/filterClasses.ts
|
|
1393
|
+
// src/services/sanitizeHtml/filterClasses.ts
|
|
1442
1394
|
const filterClasses = (value, patterns) => {
|
|
1443
1395
|
if (!patterns) return void 0;
|
|
1444
1396
|
const classNames = value.split(/\s+/u).filter((className) => className && patterns.some((pattern) => matchesClassPattern(className, pattern)));
|
|
1445
1397
|
return classNames.length > 0 ? classNames.join(" ") : void 0;
|
|
1446
1398
|
};
|
|
1447
|
-
|
|
1448
|
-
//#region src/services/sanitizeHtml/filterSrcset.ts
|
|
1399
|
+
// src/services/sanitizeHtml/filterSrcset.ts
|
|
1449
1400
|
const COMMA = ",";
|
|
1450
1401
|
const OPENING_PARENTHESIS = "(";
|
|
1451
1402
|
const CLOSING_PARENTHESIS = ")";
|
|
@@ -1477,8 +1428,7 @@ const filterSrcset = (value, allowedSchemes) => {
|
|
|
1477
1428
|
}
|
|
1478
1429
|
return candidates.length > 0 ? candidates.join(", ") : void 0;
|
|
1479
1430
|
};
|
|
1480
|
-
|
|
1481
|
-
//#region src/services/sanitizeHtml/filterStyle.ts
|
|
1431
|
+
// src/services/sanitizeHtml/filterStyle.ts
|
|
1482
1432
|
const DECLARATION_SEPARATOR = ";";
|
|
1483
1433
|
const PROPERTY_SEPARATOR = ":";
|
|
1484
1434
|
const IMPORTANT_SUFFIX = "!important";
|
|
@@ -1503,9 +1453,7 @@ const filterStyle = (value, rules) => {
|
|
|
1503
1453
|
if (declarations.size === 0) return void 0;
|
|
1504
1454
|
return Array.from(declarations, ([property, { important, propertyValue }]) => `${property}${PROPERTY_SEPARATOR}${propertyValue}${important ? IMPORTANT_SUFFIX : ""}`).join(DECLARATION_SEPARATOR);
|
|
1505
1455
|
};
|
|
1506
|
-
|
|
1507
|
-
//#region src/services/sanitizeHtml/filterAttributes.ts
|
|
1508
|
-
const getTagPolicy = (tagPolicies, tagName) => Object.hasOwn(tagPolicies, tagName) ? tagPolicies[tagName] : void 0;
|
|
1456
|
+
// src/services/sanitizeHtml/filterAttributes.ts
|
|
1509
1457
|
const checkIsMetaRefresh = (tagName, attributes) => tagName === "meta" && attributes["http-equiv"]?.trim().toLowerCase() === "refresh";
|
|
1510
1458
|
const filterAttributes = (element, policy) => {
|
|
1511
1459
|
const { tagName } = element;
|
|
@@ -1530,28 +1478,25 @@ const filterValue = (tagName, name, value, policy) => {
|
|
|
1530
1478
|
if (URL_ATTRIBUTES.includes(name)) return checkIsAllowedUrl(value, policy.allowedSchemes) ? value : void 0;
|
|
1531
1479
|
return value;
|
|
1532
1480
|
};
|
|
1533
|
-
|
|
1534
|
-
//#region src/services/sanitizeHtml/renderNode.ts
|
|
1481
|
+
// src/services/sanitizeHtml/renderNode.ts
|
|
1535
1482
|
const renderNode = (node, policy, depth) => {
|
|
1536
1483
|
if (node.nodeName === "#text") return escapeText(node.value);
|
|
1537
1484
|
if (!("tagName" in node) || depth > 256) return "";
|
|
1538
1485
|
const element = node;
|
|
1539
1486
|
const children = getChildNodes(element).map((child) => renderNode(child, policy, depth + 1)).join("");
|
|
1540
|
-
if (!(element.namespaceURI === HTML_NAMESPACE && !NON_TEXT_TAGS.includes(element.tagName) && policy.allowedTags.includes(element.tagName))) return NON_TEXT_TAGS.includes(element.tagName) ? "" : children;
|
|
1487
|
+
if (!(element.namespaceURI === HTML_NAMESPACE && !NON_TEXT_TAGS.includes(element.tagName) && policy.allowedTags.includes(element.tagName) && checkIsSourceAllowed(element, policy.allowedSources))) return NON_TEXT_TAGS.includes(element.tagName) ? "" : children;
|
|
1541
1488
|
const attributes = Object.entries(filterAttributes(element, policy)).map(([name, value]) => ` ${name}="${escapeAttribute(value)}"`).join("");
|
|
1542
1489
|
const opening = `<${element.tagName}${attributes}>`;
|
|
1543
1490
|
return VOID_TAGS.includes(element.tagName) ? opening : `${opening}${children}</${element.tagName}>`;
|
|
1544
1491
|
};
|
|
1545
|
-
|
|
1546
|
-
//#region src/services/sanitizeHtml/filterHtml.ts
|
|
1492
|
+
// src/services/sanitizeHtml/filterHtml.ts
|
|
1547
1493
|
const filterHtml = (html, policy) => {
|
|
1548
1494
|
const context = defaultTreeAdapter.createElement("body", HTML_NAMESPACE, []);
|
|
1549
1495
|
const childNodes = parseFragment(context, html, {}).childNodes;
|
|
1550
1496
|
const output = childNodes.map((node) => renderNode(node, policy, 0)).join("");
|
|
1551
1497
|
return parseFragment(context, output, {}).childNodes.map((node) => renderNode(node, policy, 0)).join("") === output ? output : escapeText(collectText(childNodes, 0));
|
|
1552
1498
|
};
|
|
1553
|
-
|
|
1554
|
-
//#region src/services/sanitizeHtml/sanitizeHtml.ts
|
|
1499
|
+
// src/services/sanitizeHtml/sanitizeHtml.ts
|
|
1555
1500
|
const appendStyle = (style, declarations) => style ? `${style}; ${declarations}` : declarations;
|
|
1556
1501
|
const transformCellAlign = ({ align, ...attributes }) => align ? {
|
|
1557
1502
|
...attributes,
|
|
@@ -1590,6 +1535,7 @@ const sanitizeHtml = (html, options) => filterHtml(html, {
|
|
|
1590
1535
|
},
|
|
1591
1536
|
allowedClasses: options?.allowedClasses ?? {},
|
|
1592
1537
|
allowedSchemes: DEFAULT_ALLOWED_SCHEMES,
|
|
1538
|
+
allowedSources: options?.allowedSources ?? {},
|
|
1593
1539
|
allowedStyles: {
|
|
1594
1540
|
...options?.allowedStyles,
|
|
1595
1541
|
...TABLE_ALLOWED_STYLES
|
|
@@ -1603,87 +1549,85 @@ const sanitizeHtml = (html, options) => filterHtml(html, {
|
|
|
1603
1549
|
th: transformCellAlign
|
|
1604
1550
|
}
|
|
1605
1551
|
});
|
|
1606
|
-
|
|
1607
|
-
//#region src/services/sanitizeHtml/sanitizeTextHtml.ts
|
|
1552
|
+
// src/services/sanitizeHtml/sanitizeTextHtml.ts
|
|
1608
1553
|
const COLOR_REGEXES = [
|
|
1609
1554
|
/^#[\da-fA-F]{3,8}$/u,
|
|
1610
1555
|
/^rgba?\(\d{1,3},\s*\d{1,3},\s*\d{1,3}(?:,\s*[\d.]+)?\)$/u,
|
|
1611
1556
|
/^[a-z]+$/iu
|
|
1612
1557
|
];
|
|
1613
|
-
const
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
"type"
|
|
1619
|
-
],
|
|
1620
|
-
li: ["data-checked", "data-type"],
|
|
1621
|
-
span: [
|
|
1622
|
-
CUSTOM_EMOJI_ID_ATTRIBUTE,
|
|
1623
|
-
CUSTOM_EMOJI_NAME_ATTRIBUTE,
|
|
1624
|
-
MENTION_ID_ATTRIBUTE,
|
|
1625
|
-
MENTION_ITEM_TYPE_ATTRIBUTE,
|
|
1626
|
-
MENTION_LABEL_ATTRIBUTE,
|
|
1627
|
-
MENTION_TYPE_ATTRIBUTE,
|
|
1628
|
-
SPOILER_ATTRIBUTE,
|
|
1629
|
-
"style"
|
|
1630
|
-
],
|
|
1631
|
-
ul: ["data-type"]
|
|
1632
|
-
},
|
|
1633
|
-
allowedClasses: {
|
|
1634
|
-
code: ["language-*"],
|
|
1635
|
-
pre: ["language-*"],
|
|
1636
|
-
span: ["hljs*"]
|
|
1637
|
-
},
|
|
1638
|
-
allowedStyles: { span: {
|
|
1639
|
-
"background-color": COLOR_REGEXES,
|
|
1640
|
-
"border-radius": [/^[\d.]+(?<unit>px|em|rem|%)$/u],
|
|
1641
|
-
color: COLOR_REGEXES
|
|
1642
|
-
} },
|
|
1643
|
-
allowedTags: [
|
|
1644
|
-
...DEFAULT_ALLOWED_TAGS,
|
|
1645
|
-
"input",
|
|
1646
|
-
"label"
|
|
1558
|
+
const KIT_ALLOWED_ATTRIBUTES = {
|
|
1559
|
+
input: [
|
|
1560
|
+
"checked",
|
|
1561
|
+
"disabled",
|
|
1562
|
+
"type"
|
|
1647
1563
|
],
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1564
|
+
li: ["data-checked", "data-type"],
|
|
1565
|
+
span: [
|
|
1566
|
+
CUSTOM_EMOJI_ID_ATTRIBUTE,
|
|
1567
|
+
CUSTOM_EMOJI_NAME_ATTRIBUTE,
|
|
1568
|
+
MENTION_ID_ATTRIBUTE,
|
|
1569
|
+
MENTION_ITEM_TYPE_ATTRIBUTE,
|
|
1570
|
+
MENTION_LABEL_ATTRIBUTE,
|
|
1571
|
+
MENTION_TYPE_ATTRIBUTE,
|
|
1572
|
+
SPOILER_ATTRIBUTE,
|
|
1573
|
+
"style"
|
|
1574
|
+
],
|
|
1575
|
+
ul: ["data-type"]
|
|
1576
|
+
};
|
|
1577
|
+
const sanitizeTextHtml = (html, allowance = {}) => {
|
|
1578
|
+
const allowedAttributes = { ...KIT_ALLOWED_ATTRIBUTES };
|
|
1579
|
+
for (const [tagName, attributes] of Object.entries(allowance.allowedAttributes ?? {})) allowedAttributes[tagName] = [.../* @__PURE__ */ new Set([...allowedAttributes[tagName] ?? [], ...attributes])];
|
|
1580
|
+
return sanitizeHtml(html, {
|
|
1581
|
+
allowedAttributes,
|
|
1582
|
+
allowedClasses: {
|
|
1583
|
+
code: ["language-*"],
|
|
1584
|
+
pre: ["language-*"],
|
|
1585
|
+
span: ["hljs*"]
|
|
1586
|
+
},
|
|
1587
|
+
allowedSources: allowance.allowedSources,
|
|
1588
|
+
allowedStyles: { span: {
|
|
1589
|
+
"background-color": COLOR_REGEXES,
|
|
1590
|
+
"border-radius": [/^[\d.]+(?<unit>px|em|rem|%)$/u],
|
|
1591
|
+
color: COLOR_REGEXES
|
|
1592
|
+
} },
|
|
1593
|
+
allowedTags: [
|
|
1594
|
+
...DEFAULT_ALLOWED_TAGS,
|
|
1595
|
+
"input",
|
|
1596
|
+
"label",
|
|
1597
|
+
...allowance.allowedTags ?? []
|
|
1598
|
+
],
|
|
1599
|
+
transformAttributes: { input: ({ checked }) => ({
|
|
1600
|
+
...checked === void 0 ? {} : { checked },
|
|
1601
|
+
disabled: "",
|
|
1602
|
+
type: "checkbox"
|
|
1603
|
+
}) }
|
|
1604
|
+
});
|
|
1605
|
+
};
|
|
1606
|
+
// src/services/shared/applyItemMetadataMixin.ts
|
|
1656
1607
|
const applyItemMetadataMixin = (Base) => class ItemWithMetadata extends Base {
|
|
1657
1608
|
createdAt = /* @__PURE__ */ new Date();
|
|
1658
1609
|
deletedAt = null;
|
|
1659
1610
|
updatedAt = /* @__PURE__ */ new Date();
|
|
1660
1611
|
};
|
|
1661
|
-
|
|
1662
|
-
//#region src/util/text/normalizeString.ts
|
|
1612
|
+
// src/util/text/normalizeString.ts
|
|
1663
1613
|
const normalizeString = (value) => value?.trim() ?? "";
|
|
1664
|
-
|
|
1665
|
-
//#region src/services/zod/createNormalizedStringSchema.ts
|
|
1614
|
+
// src/services/zod/createNormalizedStringSchema.ts
|
|
1666
1615
|
const createNormalizedStringSchema = (maxLength, schema = z.string()) => schema.transform(normalizeString).pipe(z.string().max(maxLength));
|
|
1667
|
-
|
|
1668
|
-
//#region src/util/id/constants.ts
|
|
1616
|
+
// src/util/id/constants.ts
|
|
1669
1617
|
const ID_SEPARATOR = "|";
|
|
1670
|
-
|
|
1671
|
-
//#region src/services/zod/createUniqueArraySchema.ts
|
|
1618
|
+
// src/services/zod/createUniqueArraySchema.ts
|
|
1672
1619
|
const getItemKey = (item, key) => {
|
|
1673
1620
|
const record = item;
|
|
1674
1621
|
return typeof key === "string" ? record[key] : key.map((part) => record[part]).join("|");
|
|
1675
1622
|
};
|
|
1676
1623
|
const createUniqueArraySchema = (schema, key) => schema.array().refine((array) => new Set(key === void 0 ? array : array.map((item) => getItemKey(item, key))).size === array.length, { error: "Array items must be unique" });
|
|
1677
|
-
|
|
1678
|
-
//#region src/services/zstd/constants.ts
|
|
1624
|
+
// src/services/zstd/constants.ts
|
|
1679
1625
|
const DEFAULT_COMPRESSION_LEVEL = 12;
|
|
1680
1626
|
const MIN_WINDOW_LOG = 10;
|
|
1681
1627
|
const MAX_WINDOW_LOG = 27;
|
|
1682
|
-
|
|
1683
|
-
//#region src/services/zstd/getWindowLog.ts
|
|
1628
|
+
// src/services/zstd/getWindowLog.ts
|
|
1684
1629
|
const getWindowLog = (dictionaryByteCount, inputByteCount) => Math.min(27, Math.max(10, Math.ceil(Math.log2(dictionaryByteCount + inputByteCount + 1))));
|
|
1685
|
-
|
|
1686
|
-
//#region src/test/constants.ts
|
|
1630
|
+
// src/test/constants.ts
|
|
1687
1631
|
const ALL_SPECIAL_VALUES = [
|
|
1688
1632
|
{
|
|
1689
1633
|
isPlainObject: true,
|
|
@@ -1730,15 +1674,13 @@ const ALL_SPECIAL_VALUES = [
|
|
|
1730
1674
|
value: /(?:)/u
|
|
1731
1675
|
}
|
|
1732
1676
|
];
|
|
1733
|
-
|
|
1734
|
-
//#region src/util/array/chunk.ts
|
|
1677
|
+
// src/util/array/chunk.ts
|
|
1735
1678
|
const chunk = (array, size) => {
|
|
1736
1679
|
const chunks = [];
|
|
1737
1680
|
for (let index = 0; index < array.length; index += size) chunks.push(array.slice(index, index + size));
|
|
1738
1681
|
return chunks;
|
|
1739
1682
|
};
|
|
1740
|
-
|
|
1741
|
-
//#region src/util/array/chunkBySerializedSize.ts
|
|
1683
|
+
// src/util/array/chunkBySerializedSize.ts
|
|
1742
1684
|
const ARRAY_SERIALIZATION_BYTES = 1;
|
|
1743
1685
|
const chunkBySerializedSize = (items, maxBytes, maxCount) => {
|
|
1744
1686
|
const textEncoder = new TextEncoder();
|
|
@@ -1758,17 +1700,13 @@ const chunkBySerializedSize = (items, maxBytes, maxCount) => {
|
|
|
1758
1700
|
if (currentChunk.length > 0) chunks.push(currentChunk);
|
|
1759
1701
|
return chunks;
|
|
1760
1702
|
};
|
|
1761
|
-
|
|
1762
|
-
//#region src/util/array/takeRandom.ts
|
|
1703
|
+
// src/util/array/takeRandom.ts
|
|
1763
1704
|
const takeRandom = (values, random) => takeOne(values, Math.floor(random() * values.length));
|
|
1764
|
-
|
|
1765
|
-
//#region src/util/date/getZonedDateTime.ts
|
|
1705
|
+
// src/util/date/getZonedDateTime.ts
|
|
1766
1706
|
const getZonedDateTime = (date) => Temporal.Instant.fromEpochMilliseconds(date.getTime()).toZonedDateTimeISO(Temporal.Now.timeZoneId());
|
|
1767
|
-
|
|
1768
|
-
//#region src/util/date/getEndOfDay.ts
|
|
1707
|
+
// src/util/date/getEndOfDay.ts
|
|
1769
1708
|
const getEndOfDay = (date) => /* @__PURE__ */ new Date(getZonedDateTime(date).startOfDay().add({ days: 1 }).epochMilliseconds - 1);
|
|
1770
|
-
|
|
1771
|
-
//#region src/util/dom/checkIsNestedControl.ts
|
|
1709
|
+
// src/util/dom/checkIsNestedControl.ts
|
|
1772
1710
|
const NESTED_INTERACTION_SELECTOR = [
|
|
1773
1711
|
"a[href]",
|
|
1774
1712
|
"button",
|
|
@@ -1798,19 +1736,16 @@ const checkIsNestedControl = (event) => {
|
|
|
1798
1736
|
const interactiveElement = target.closest(NESTED_INTERACTION_SELECTOR);
|
|
1799
1737
|
return Boolean(interactiveElement && interactiveElement !== currentTarget && currentTarget.contains(interactiveElement));
|
|
1800
1738
|
};
|
|
1801
|
-
|
|
1802
|
-
//#region src/util/dom/checkIsNestedInteraction.ts
|
|
1739
|
+
// src/util/dom/checkIsNestedInteraction.ts
|
|
1803
1740
|
const checkIsNestedInteraction = (event) => checkIsNestedControl(event) || Boolean(window.getSelection()?.toString());
|
|
1804
|
-
|
|
1805
|
-
//#region src/util/dom/downloadUrl.ts
|
|
1741
|
+
// src/util/dom/downloadUrl.ts
|
|
1806
1742
|
const downloadUrl = (url, filename) => {
|
|
1807
1743
|
const anchor = window.document.createElement("a");
|
|
1808
1744
|
anchor.href = url;
|
|
1809
1745
|
anchor.download = filename;
|
|
1810
1746
|
anchor.click();
|
|
1811
1747
|
};
|
|
1812
|
-
|
|
1813
|
-
//#region src/util/dom/downloadFile.ts
|
|
1748
|
+
// src/util/dom/downloadFile.ts
|
|
1814
1749
|
const downloadFile = (filename, blobPart, type) => {
|
|
1815
1750
|
const url = URL.createObjectURL(new Blob([blobPart], { type }));
|
|
1816
1751
|
downloadUrl(url, filename);
|
|
@@ -1818,34 +1753,18 @@ const downloadFile = (filename, blobPart, type) => {
|
|
|
1818
1753
|
URL.revokeObjectURL(url);
|
|
1819
1754
|
}, 0);
|
|
1820
1755
|
};
|
|
1821
|
-
|
|
1822
|
-
//#region src/util/environment/checkIsServer.ts
|
|
1756
|
+
// src/util/environment/checkIsServer.ts
|
|
1823
1757
|
const checkIsServer = () => typeof window === "undefined";
|
|
1824
|
-
|
|
1825
|
-
//#region src/util/function/getSynchronizedFunction.ts
|
|
1826
|
-
const pendingPromises = /* @__PURE__ */ new Set();
|
|
1827
|
-
const getSynchronizedFunction = (asyncFunction) => (...args) => {
|
|
1828
|
-
const promise = asyncFunction(...args).finally(() => {
|
|
1829
|
-
pendingPromises.delete(promise);
|
|
1830
|
-
});
|
|
1831
|
-
pendingPromises.add(promise);
|
|
1832
|
-
};
|
|
1833
|
-
const waitForSynchronizedFunctions = async () => {
|
|
1834
|
-
await Promise.allSettled(pendingPromises);
|
|
1835
|
-
};
|
|
1836
|
-
//#endregion
|
|
1837
|
-
//#region src/util/id/uuid/constants.ts
|
|
1758
|
+
// src/util/id/uuid/constants.ts
|
|
1838
1759
|
const UUIDV4_REGEX = /^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/iu;
|
|
1839
|
-
|
|
1840
|
-
//#region src/util/map/getOrCreate.ts
|
|
1760
|
+
// src/util/map/getOrCreate.ts
|
|
1841
1761
|
const getOrCreate = (map, key, create) => {
|
|
1842
1762
|
if (map.has(key)) return map.get(key);
|
|
1843
1763
|
const value = create();
|
|
1844
1764
|
map.set(key, value);
|
|
1845
1765
|
return value;
|
|
1846
1766
|
};
|
|
1847
|
-
|
|
1848
|
-
//#region src/util/object/clonePlainDeep.ts
|
|
1767
|
+
// src/util/object/clonePlainDeep.ts
|
|
1849
1768
|
const clone = (data, copies) => {
|
|
1850
1769
|
if (!Array.isArray(data) && !checkIsPlainObject(data)) return data;
|
|
1851
1770
|
else if (copies.has(data)) return copies.get(data);
|
|
@@ -1862,11 +1781,7 @@ const clone = (data, copies) => {
|
|
|
1862
1781
|
}
|
|
1863
1782
|
};
|
|
1864
1783
|
const clonePlainDeep = (data) => clone(data, /* @__PURE__ */ new WeakMap());
|
|
1865
|
-
|
|
1866
|
-
//#region src/util/object/getPropertyNames.ts
|
|
1867
|
-
const getPropertyNames = () => new Proxy({}, { get: (_target, property) => property });
|
|
1868
|
-
//#endregion
|
|
1869
|
-
//#region src/util/object/jsonDateParse.ts
|
|
1784
|
+
// src/util/object/jsonDateParse.ts
|
|
1870
1785
|
const ISO_DATE_REGEX = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})T(?<hours>\d{2}):(?<minutes>\d{2}):(?<seconds>\d{2}(?:\.{0,1}\d*))(?:Z|(?<sign>\+|-)(?<offset>[\d|:]*))?$/u;
|
|
1871
1786
|
const MS_AJAX_DATE_REGEX = /^\/Date\((?<timestamp>-?\d+(?:[-+]\d+)?)\)[/\\]$/u;
|
|
1872
1787
|
const jsonDateParse = (text) => JSON.parse(text, (_key, value) => {
|
|
@@ -1877,11 +1792,9 @@ const jsonDateParse = (text) => JSON.parse(text, (_key, value) => {
|
|
|
1877
1792
|
const timestampParts = takeOne(msAjaxDateMatch, 1).split(/[-+,.]/u);
|
|
1878
1793
|
return new Date(timestampParts[0] ? Number(timestampParts[0]) : 0 - Number(timestampParts[1]));
|
|
1879
1794
|
});
|
|
1880
|
-
|
|
1881
|
-
//#region src/util/object/mergeObjectsStrict.ts
|
|
1795
|
+
// src/util/object/mergeObjectsStrict.ts
|
|
1882
1796
|
const mergeObjectsStrict = (...objects) => Object.assign({}, ...objects);
|
|
1883
|
-
|
|
1884
|
-
//#region src/util/object/omitDeep.ts
|
|
1797
|
+
// src/util/object/omitDeep.ts
|
|
1885
1798
|
const checkIsWalkable = (value) => Object.prototype.toString.call(value) === "[object Object]";
|
|
1886
1799
|
const omitValue = (value, omittedKeys) => {
|
|
1887
1800
|
if (Array.isArray(value)) return value.map((element) => omitValue(element, omittedKeys));
|
|
@@ -1891,8 +1804,7 @@ const omitValue = (value, omittedKeys) => {
|
|
|
1891
1804
|
return omittedValue;
|
|
1892
1805
|
};
|
|
1893
1806
|
const omitDeep = (value, ...keys) => omitValue(value, new Set(keys));
|
|
1894
|
-
|
|
1895
|
-
//#region src/util/promise/createEvictingPromiseCache.ts
|
|
1807
|
+
// src/util/promise/createEvictingPromiseCache.ts
|
|
1896
1808
|
const createEvictingPromiseCache = (getKey, load) => {
|
|
1897
1809
|
const promiseMap = /* @__PURE__ */ new Map();
|
|
1898
1810
|
return (...args) => {
|
|
@@ -1905,8 +1817,7 @@ const createEvictingPromiseCache = (getKey, load) => {
|
|
|
1905
1817
|
});
|
|
1906
1818
|
};
|
|
1907
1819
|
};
|
|
1908
|
-
|
|
1909
|
-
//#region src/util/promise/settleAll.ts
|
|
1820
|
+
// src/util/promise/settleAll.ts
|
|
1910
1821
|
const settleAll = async (tasks, concurrencyLimit = tasks.length) => {
|
|
1911
1822
|
if (tasks.length === 0) return [];
|
|
1912
1823
|
const values = [];
|
|
@@ -1920,11 +1831,9 @@ const settleAll = async (tasks, concurrencyLimit = tasks.length) => {
|
|
|
1920
1831
|
}
|
|
1921
1832
|
return values;
|
|
1922
1833
|
};
|
|
1923
|
-
|
|
1924
|
-
//#region src/util/text/capitalize.ts
|
|
1834
|
+
// src/util/text/capitalize.ts
|
|
1925
1835
|
const capitalize = (string) => `${string.charAt(0).toUpperCase()}${string.slice(1)}`;
|
|
1926
|
-
|
|
1927
|
-
//#region src/util/text/dedent.ts
|
|
1836
|
+
// src/util/text/dedent.ts
|
|
1928
1837
|
const ESCAPE_CHARACTER = "\\";
|
|
1929
1838
|
const LINE_FEED = "\n";
|
|
1930
1839
|
const LINE_FEED_CHARACTER = {
|
|
@@ -2123,8 +2032,7 @@ const createDedent = (options) => {
|
|
|
2123
2032
|
return dedent;
|
|
2124
2033
|
};
|
|
2125
2034
|
const dedent = createDedent({});
|
|
2126
|
-
|
|
2127
|
-
//#region src/util/text/encodeUrlSubDelimiters.ts
|
|
2035
|
+
// src/util/text/encodeUrlSubDelimiters.ts
|
|
2128
2036
|
const EncodedSubDelimiterMap = {
|
|
2129
2037
|
"!": "%21",
|
|
2130
2038
|
"'": "%27",
|
|
@@ -2133,36 +2041,51 @@ const EncodedSubDelimiterMap = {
|
|
|
2133
2041
|
"*": "%2A"
|
|
2134
2042
|
};
|
|
2135
2043
|
const encodeUrlSubDelimiters = (value) => Object.entries(EncodedSubDelimiterMap).reduce((encoded, [subDelimiter, encodedSubDelimiter]) => encoded.replaceAll(subDelimiter, encodedSubDelimiter), value);
|
|
2136
|
-
|
|
2137
|
-
//#region src/util/text/getDecodedUriComponent.ts
|
|
2044
|
+
// src/util/text/getDecodedUriComponent.ts
|
|
2138
2045
|
const getDecodedUriComponent = (value, fallback) => getResult(() => decodeURIComponent(value)).unwrapOr(fallback);
|
|
2139
|
-
|
|
2140
|
-
//#region src/util/text/streamToText.ts
|
|
2046
|
+
// src/util/text/streamToText.ts
|
|
2141
2047
|
const streamToText = async (readable) => {
|
|
2142
2048
|
readable.setEncoding("utf8");
|
|
2143
2049
|
let data = "";
|
|
2144
2050
|
for await (const chunk of readable) data += chunk.toString();
|
|
2145
2051
|
return data;
|
|
2146
2052
|
};
|
|
2147
|
-
|
|
2148
|
-
//#region src/util/text/toKebabCase.ts
|
|
2053
|
+
// src/util/text/toKebabCase.ts
|
|
2149
2054
|
const toKebabCase = (string) => string.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/gu)?.map((x) => x.toLowerCase()).join("-") ?? "";
|
|
2150
|
-
|
|
2151
|
-
//#region src/util/text/truncate.ts
|
|
2055
|
+
// src/util/text/truncate.ts
|
|
2152
2056
|
const SUFFIX = "...";
|
|
2153
2057
|
const truncate = (string, length) => {
|
|
2154
2058
|
if (string.length <= length) return string;
|
|
2155
2059
|
else if (length < 3) return string.slice(0, length);
|
|
2156
2060
|
else return `${string.slice(0, length - 3)}${SUFFIX}`;
|
|
2157
2061
|
};
|
|
2158
|
-
|
|
2159
|
-
//#region src/util/text/uncapitalize.ts
|
|
2062
|
+
// src/util/text/uncapitalize.ts
|
|
2160
2063
|
const uncapitalize = (string) => `${string.charAt(0).toLowerCase()}${string.slice(1)}`;
|
|
2161
|
-
|
|
2162
|
-
//#region src/util/time/constants.ts
|
|
2064
|
+
// src/util/time/constants.ts
|
|
2163
2065
|
const MILLISECONDS_PER_SECOND = 1e3;
|
|
2164
|
-
|
|
2165
|
-
|
|
2066
|
+
// src/util/time/getExponentialBackoffDelayMs.ts
|
|
2067
|
+
const getExponentialBackoffDelayMs = (attempt, baseDelayMs, maxDelayMs) => Math.min(baseDelayMs * 2 ** attempt, maxDelayMs);
|
|
2068
|
+
// src/util/time/sleep.ts
|
|
2069
|
+
const sleep = (durationMs) => new Promise((resolve) => {
|
|
2070
|
+
setTimeout(() => {
|
|
2071
|
+
resolve();
|
|
2072
|
+
}, durationMs);
|
|
2073
|
+
});
|
|
2074
|
+
// src/util/time/createExponentialBackoff.ts
|
|
2075
|
+
const createExponentialBackoff = (baseDelayMs, maxDelayMs) => {
|
|
2076
|
+
let failureCount = 0;
|
|
2077
|
+
return async (operation) => {
|
|
2078
|
+
if (failureCount > 0) await sleep(getExponentialBackoffDelayMs(failureCount - 1, baseDelayMs, maxDelayMs));
|
|
2079
|
+
return getResultAsync(operation).match((value) => {
|
|
2080
|
+
failureCount = 0;
|
|
2081
|
+
return value;
|
|
2082
|
+
}, (error) => {
|
|
2083
|
+
failureCount += 1;
|
|
2084
|
+
throw error;
|
|
2085
|
+
});
|
|
2086
|
+
};
|
|
2087
|
+
};
|
|
2088
|
+
// src/util/time/hrtime.ts
|
|
2166
2089
|
const hrtime = (previousHrTime) => {
|
|
2167
2090
|
if (checkIsServer()) return process.hrtime(previousHrTime);
|
|
2168
2091
|
const clocktime = performance.now() * .001;
|
|
@@ -2178,20 +2101,11 @@ const hrtime = (previousHrTime) => {
|
|
|
2178
2101
|
}
|
|
2179
2102
|
return [seconds, nanoseconds];
|
|
2180
2103
|
};
|
|
2181
|
-
|
|
2182
|
-
//#region src/util/time/now.ts
|
|
2104
|
+
// src/util/time/now.ts
|
|
2183
2105
|
const loadNanoseconds = hrtime();
|
|
2184
2106
|
const loadMilliseconds = Date.now();
|
|
2185
2107
|
const now = () => {
|
|
2186
2108
|
const [seconds, nanoseconds] = hrtime(loadNanoseconds);
|
|
2187
2109
|
return (BigInt(loadMilliseconds) * 10n ** 6n + (BigInt(seconds) * 10n ** 9n + BigInt(nanoseconds))).toString();
|
|
2188
2110
|
};
|
|
2189
|
-
|
|
2190
|
-
//#region src/util/time/sleep.ts
|
|
2191
|
-
const sleep = (durationMs) => new Promise((resolve) => {
|
|
2192
|
-
setTimeout(() => {
|
|
2193
|
-
resolve();
|
|
2194
|
-
}, durationMs);
|
|
2195
|
-
});
|
|
2196
|
-
//#endregion
|
|
2197
|
-
export { ALL_SPECIAL_VALUES, APPEND_SEGMENT, CHARSET_PARAMETER_REGEX, CUSTOM_EMOJI_ID_ATTRIBUTE, CUSTOM_EMOJI_NAME_ATTRIBUTE, DEFAULT_ALLOWED_ATTRIBUTES, DEFAULT_ALLOWED_SCHEMES, DEFAULT_ALLOWED_TAGS, DEFAULT_COMPRESSION_LEVEL, DEFAULT_FACET_SCORE, DEFAULT_LINK_ATTRIBUTES, DEFAULT_SOURCE_SCORE, DEFAULT_TEXT_CHARSET, DEFAULT_TYPE_SCORE, ESCAPED_ATTRIBUTE_CHARACTERS_REGEX, ESCAPED_TEXT_CHARACTERS_REGEX, FacetScoreMap, ForbiddenError, GIBIBYTE, HTML_NAMESPACE, ID_SEPARATOR, IMPORTANT_REGEX, InvalidOperationError, ItemMetadata, JSON_POINTER_REGEX, JsonPatchOperationType, KIBIBYTE, MAX_NESTING_DEPTH, MAX_READ_LIMIT, MAX_WINDOW_LOG, MEDIA_TYPE_REGEX, MENTION_EVERYONE_ID, MENTION_HERE_ID, MENTION_ID_ATTRIBUTE, MENTION_ITEM_TYPE_ATTRIBUTE, MENTION_LABEL_ATTRIBUTE, MENTION_SELECTOR, MENTION_TYPE, MENTION_TYPE_ATTRIBUTE, MILLISECONDS_PER_SECOND, MIN_WINDOW_LOG, MentionType, NON_TEXT_TAGS, NotFoundError, NotInitializedError, ObjectMethod, Operation, PATH_SEPARATOR_REGEX, RoutePath, SANITIZER_ADVISORY_WATCH_SINCE, SITE_NAME, SPOILER_ATTRIBUTE, SPOILER_SELECTOR, SRCSET_ATTRIBUTE, SRCSET_DESCRIPTOR_REGEX, Serializable, SourceScoreMap, TEXT_MEDIA_TYPE_REGEX, TypeScoreMap, TypedEventEmitter, URL_ATTRIBUTES, UUIDV4_REGEX, VOID_TAGS, WordFilteredError, addJsonValue, applyItemMetadataMixin, applyPatch, applyPatches, capitalize, charset, checkContainsProfanity, checkIsAllowedUrl, checkIsCustomMethod, checkIsDeepEqual, checkIsNestedControl, checkIsNestedInteraction, checkIsPlainObject, checkIsSameBytes, checkIsSameValueZero, checkIsServer, checkIsUnsafeUrlCharacter, checkIsWhitespaceCharacter, chunk, chunkBySerializedSize, clonePlainDeep, collectText, contentType, createEvictingPromiseCache, createHistory, createItemEntityTypeSchema, createNormalizedStringSchema, createUniqueArraySchema, css, dedent, downloadFile, downloadUrl, encodeUrlSubDelimiters, englishProfaneWords, escapeAttribute, escapeCharacters, escapeText, exhaustiveGuard, extension, filterAttributes, filterClasses, filterHtml, filterSrcset, filterStyle, getChildNodes, getDecodedUriComponent, getEndOfDay, getEnumerableKeys, getExtensionMimeTypeMap, getMediaType, getMentions, getMimeScore, getMimeTypeEntryMap, getOrCreate, getPropertyNames, getRawData, getRequestError, getResult, getResultAsync, getSynchronizedFunction, getTransactionDone, getTransactionObjectStore, getWindowLog, getZonedDateTime, hrtime, html, jsonDateParse, lookup, matchesClassPattern, mergeObjectsStrict, noop, normalizeString, now, omitDeep, openDatabase, parseArrayIndex, parseJsonPointer, pushHistory, readJsonValue, redoHistory, removeJsonValue, renderNode, reportFinalizerError, requestToPromise, sanitizeHtml, sanitizeTextHtml, settleAll, sleep, streamToText, takeOne, takeRandom, toAppError, toJsonPointer, toKebabCase, toRawDeep, truncate, uncapitalize, undoHistory, updateJsonValue, waitForSynchronizedFunctions, withFinalizer, withFinalizerAsync, wrapDatabase, wrapIndex, wrapObjectStore, wrapTransaction, wrapUpgradeDatabase, wrapUpgradeTransaction };
|
|
2111
|
+
export { ALL_SPECIAL_VALUES, APPEND_SEGMENT, CHARSET_PARAMETER_REGEX, CUSTOM_EMOJI_ID_ATTRIBUTE, CUSTOM_EMOJI_NAME_ATTRIBUTE, DEFAULT_ALLOWED_ATTRIBUTES, DEFAULT_ALLOWED_SCHEMES, DEFAULT_ALLOWED_TAGS, DEFAULT_COMPRESSION_LEVEL, DEFAULT_FACET_SCORE, DEFAULT_LINK_ATTRIBUTES, DEFAULT_SOURCE_SCORE, DEFAULT_TEXT_CHARSET, DEFAULT_TYPE_SCORE, ESCAPED_ATTRIBUTE_CHARACTERS_REGEX, ESCAPED_TEXT_CHARACTERS_REGEX, FacetScoreMap, ForbiddenError, GIBIBYTE, HTML_NAMESPACE, ID_SEPARATOR, IMPORTANT_REGEX, InvalidOperationError, ItemMetadata, ItemMetadataPropertyNames, JSON_POINTER_REGEX, JsonPatchOperationType, KIBIBYTE, MAX_NESTING_DEPTH, MAX_READ_LIMIT, MAX_WINDOW_LOG, MEDIA_TYPE_REGEX, MENTION_EVERYONE_ID, MENTION_HERE_ID, MENTION_ID_ATTRIBUTE, MENTION_ITEM_TYPE_ATTRIBUTE, MENTION_LABEL_ATTRIBUTE, MENTION_SELECTOR, MENTION_TYPE, MENTION_TYPE_ATTRIBUTE, MILLISECONDS_PER_SECOND, MIN_WINDOW_LOG, MentionType, NON_TEXT_TAGS, NotFoundError, NotInitializedError, ObjectMethod, Operation, PATH_SEPARATOR_REGEX, RoutePath, SANITIZER_ADVISORY_WATCH_SINCE, SITE_NAME, SPOILER_ATTRIBUTE, SPOILER_SELECTOR, SRCSET_ATTRIBUTE, SRCSET_DESCRIPTOR_REGEX, Serializable, SourceScoreMap, TEXT_MEDIA_TYPE_REGEX, TypeScoreMap, TypedEventEmitter, URL_ATTRIBUTES, UUIDV4_REGEX, VOID_TAGS, WordFilteredError, addJsonValue, applyItemMetadataMixin, applyPatch, applyPatches, capitalize, charset, checkContainsProfanity, checkIsAllowedUrl, checkIsCustomMethod, checkIsDeepEqual, checkIsNestedControl, checkIsNestedInteraction, checkIsOnlyReactor, checkIsPlainObject, checkIsSameBytes, checkIsSameValueZero, checkIsServer, checkIsSourceAllowed, checkIsUnsafeUrlCharacter, checkIsWhitespaceCharacter, chunk, chunkBySerializedSize, clonePlainDeep, collectText, contentType, createEvictingPromiseCache, createExponentialBackoff, createHistory, createItemEntityTypeSchema, createNormalizedStringSchema, createUniqueArraySchema, css, dedent, downloadFile, downloadUrl, encodeUrlSubDelimiters, englishProfaneWords, escapeAttribute, escapeCharacters, escapeText, exhaustiveGuard, extension, filterAttributes, filterClasses, filterHtml, filterSrcset, filterStyle, getChildNodes, getDecodedUriComponent, getEndOfDay, getEnumerableKeys, getExponentialBackoffDelayMs, getExtensionMimeTypeMap, getMediaType, getMentions, getMimeScore, getMimeTypeEntryMap, getOrCreate, getPropertyNames, getRawData, getRequestError, getResult, getResultAsync, getSynchronizedFunction, getTagPolicy, getTransactionDone, getTransactionObjectStore, getUpdatedUserIds, getWindowLog, getZonedDateTime, hrtime, html, jsonDateParse, lookup, matchesClassPattern, mergeObjectsStrict, noop, normalizeString, now, omitDeep, openDatabase, parseArrayIndex, parseJsonPointer, pushHistory, readJsonValue, redoHistory, removeJsonValue, renderNode, reportFinalizerError, requestToPromise, sanitizeHtml, sanitizeTextHtml, settleAll, sleep, streamToText, takeOne, takeRandom, toAppError, toJsonPointer, toKebabCase, toRawDeep, truncate, uncapitalize, undoHistory, updateJsonValue, waitForSynchronizedFunctions, withFinalizer, withFinalizerAsync, wrapDatabase, wrapIndex, wrapObjectStore, wrapTransaction, wrapUpgradeDatabase, wrapUpgradeTransaction };
|