2023-11-17 20:51:13 +03:00
|
|
|
/**
|
|
|
|
* Module: Utility functions.
|
|
|
|
*/
|
|
|
|
|
2023-12-13 14:32:57 +03:00
|
|
|
import { AxiosHeaderValue, AxiosResponse } from 'axios';
|
|
|
|
|
2023-11-17 20:51:13 +03:00
|
|
|
/**
|
|
|
|
* Checks if arguments is Node.
|
|
|
|
*/
|
2023-07-15 17:46:19 +03:00
|
|
|
export function assertIsNode(e: EventTarget | null): asserts e is Node {
|
2023-11-17 20:51:13 +03:00
|
|
|
if (e === null || !('nodeType' in e)) {
|
2023-12-26 14:23:51 +03:00
|
|
|
throw new TypeError(`Expected 'Node' but received '${e?.constructor.name ?? 'null'}'`);
|
2023-07-15 17:46:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-04 18:46:52 +03:00
|
|
|
/**
|
|
|
|
* Wrapper class for generalized text matching.
|
2023-12-28 14:04:44 +03:00
|
|
|
*
|
2023-10-04 18:46:52 +03:00
|
|
|
* If possible create regexp, otherwise use symbol matching.
|
2023-12-28 14:04:44 +03:00
|
|
|
*/
|
2023-10-04 18:46:52 +03:00
|
|
|
export class TextMatcher {
|
2023-12-28 14:04:44 +03:00
|
|
|
protected query: RegExp | string;
|
|
|
|
|
2023-10-04 18:46:52 +03:00
|
|
|
constructor(query: string, isPlainText?: boolean, isCaseSensitive?: boolean) {
|
|
|
|
if (isPlainText) {
|
|
|
|
query = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
this.query = new RegExp(query, isCaseSensitive ? '' : 'i');
|
2023-12-28 14:04:44 +03:00
|
|
|
} catch (exception: unknown) {
|
2023-10-04 18:46:52 +03:00
|
|
|
this.query = query;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
test(text: string): boolean {
|
|
|
|
if (typeof this.query === 'string') {
|
|
|
|
return text.indexOf(this.query) !== -1;
|
|
|
|
} else {
|
|
|
|
return !!text.match(this.query);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-11-06 22:21:36 +03:00
|
|
|
|
|
|
|
/**
|
2023-12-26 14:23:51 +03:00
|
|
|
* Text substitution guided by mapping and regular expression.
|
2023-12-28 14:04:44 +03:00
|
|
|
*/
|
2023-11-06 22:21:36 +03:00
|
|
|
export function applyPattern(text: string, mapping: { [key: string]: string }, pattern: RegExp): string {
|
|
|
|
if (text === '' || pattern === null) {
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
let posInput = 0;
|
|
|
|
let output = '';
|
|
|
|
const patternMatches = text.matchAll(pattern);
|
|
|
|
for (const segment of patternMatches) {
|
|
|
|
const entity = segment[0];
|
2024-04-01 19:07:20 +03:00
|
|
|
const start = segment.index ?? 0;
|
2023-11-06 22:21:36 +03:00
|
|
|
if (entity in mapping) {
|
|
|
|
output += text.substring(posInput, start);
|
|
|
|
output += mapping[entity];
|
|
|
|
posInput = start + segment[0].length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
output += text.substring(posInput);
|
|
|
|
return output;
|
|
|
|
}
|
2023-12-13 14:32:57 +03:00
|
|
|
|
|
|
|
/**
|
2023-12-26 14:23:51 +03:00
|
|
|
* Check if Axios response is html.
|
2023-12-28 14:04:44 +03:00
|
|
|
*/
|
2023-12-13 14:32:57 +03:00
|
|
|
export function isResponseHtml(response?: AxiosResponse) {
|
|
|
|
if (!response) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const header = response.headers['content-type'] as AxiosHeaderValue;
|
|
|
|
if (!header) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (typeof header === 'number' || typeof header === 'boolean') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call
|
|
|
|
return header.includes('text/html');
|
2023-12-28 14:04:44 +03:00
|
|
|
}
|
2024-04-07 21:31:38 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert base64 string to Blob uint8.
|
|
|
|
*/
|
|
|
|
export function convertBase64ToBlob(base64String: string): Uint8Array {
|
|
|
|
const arr = base64String.split(',');
|
|
|
|
const bstr = atob(arr[1]);
|
|
|
|
let n = bstr.length;
|
|
|
|
const uint8Array = new Uint8Array(n);
|
|
|
|
while (n--) {
|
|
|
|
uint8Array[n] = bstr.charCodeAt(n);
|
|
|
|
}
|
|
|
|
return uint8Array;
|
|
|
|
}
|
2024-05-17 11:43:42 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Prompt user of confirming discarding changes before continue.
|
|
|
|
*/
|
|
|
|
export function promptUnsaved(): boolean {
|
|
|
|
return window.confirm('Присутствуют несохраненные изменения. Продолжить без их учета?');
|
|
|
|
}
|