Files
ezbookkeeping/src/lib/file.ts
T

102 lines
2.9 KiB
TypeScript

import chardet, { type Match } from 'chardet';
import type { ImportFileTypeAndExtensions } from '@/core/file.ts';
import { UTF_8, CHARDET_ENCODING_NAME_MAPPING } from '@/consts/file.ts';
import { isString } from './common.ts';
export function getFileExtension(filename: string): string {
if (!filename || !isString(filename)) {
return '';
}
const parts = filename.split('.');
return parts[parts.length - 1] as string;
}
export function findExtensionByType(items: ImportFileTypeAndExtensions[] | undefined, type: string): string | undefined {
if (!items || items.length < 1) {
return undefined;
}
for (const item of items) {
if (item.type === type) {
return item.extensions;
}
}
return undefined;
}
export function isFileExtensionSupported(filename: string, supportedExtensions: string): boolean {
if (!supportedExtensions) {
return false;
}
const supportedExtensionsArray = supportedExtensions.split(',');
const fileExtension = getFileExtension(filename).toLowerCase();
for (const supportedExtension of supportedExtensionsArray) {
if (getFileExtension(supportedExtension).toLowerCase() === fileExtension) {
return true;
}
}
return false;
}
export function detectFileEncoding(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const arrayBuffer = reader.result as ArrayBuffer;
const uint8Array = new Uint8Array(arrayBuffer);
const possibleEncodings: Match[] = chardet.analyse(uint8Array);
if (!possibleEncodings || possibleEncodings.length < 1) {
reject(new Error('unable to detect file encoding'));
return;
}
const mostPossibleEncoding: Match = possibleEncodings[0] as Match;
if (!mostPossibleEncoding.name || mostPossibleEncoding.confidence < 50) {
// check whether all characters are ASCII
let isAllAscii = true;
for (const byte of uint8Array) {
if (byte > 0x7F) {
isAllAscii = false;
break;
}
}
if (isAllAscii) {
resolve(UTF_8);
return;
}
reject(new Error('unable to detect file encoding'));
return;
}
const encoding = CHARDET_ENCODING_NAME_MAPPING[mostPossibleEncoding.name];
if (!encoding) {
reject(new Error(`unsupported file encoding: ${mostPossibleEncoding.name}`));
return;
}
resolve(encoding);
};
reader.onerror = () => {
reject(new Error('failed to read file for encoding detection'));
};
reader.readAsArrayBuffer(file);
});
}