| | |
| | |
| | |
| |
|
| |
|
| | import { DEFAULT_BINARY_DETECTION_OPTIONS } from '$lib/constants/binary-detection';
|
| | import type { BinaryDetectionOptions } from '$lib/types';
|
| | import { FileExtensionText } from '$lib/enums';
|
| |
|
| | |
| | |
| | |
| | |
| |
|
| | export function isTextFileByName(filename: string): boolean {
|
| | const textExtensions = Object.values(FileExtensionText);
|
| |
|
| | return textExtensions.some((ext: FileExtensionText) => filename.toLowerCase().endsWith(ext));
|
| | }
|
| |
|
| | |
| | |
| | |
| | |
| |
|
| | export async function readFileAsText(file: File): Promise<string> {
|
| | return new Promise((resolve, reject) => {
|
| | const reader = new FileReader();
|
| |
|
| | reader.onload = (event) => {
|
| | if (event.target?.result !== null && event.target?.result !== undefined) {
|
| | resolve(event.target.result as string);
|
| | } else {
|
| | reject(new Error('Failed to read file'));
|
| | }
|
| | };
|
| |
|
| | reader.onerror = () => reject(new Error('File reading error'));
|
| |
|
| | reader.readAsText(file);
|
| | });
|
| | }
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | export function isLikelyTextFile(
|
| | content: string,
|
| | options: Partial<BinaryDetectionOptions> = {}
|
| | ): boolean {
|
| | if (!content) return true;
|
| |
|
| | const config = { ...DEFAULT_BINARY_DETECTION_OPTIONS, ...options };
|
| | const sample = content.substring(0, config.prefixLength);
|
| |
|
| | let nullCount = 0;
|
| | let suspiciousControlCount = 0;
|
| |
|
| | for (let i = 0; i < sample.length; i++) {
|
| | const charCode = sample.charCodeAt(i);
|
| |
|
| |
|
| | if (charCode === 0) {
|
| | nullCount++;
|
| |
|
| | continue;
|
| | }
|
| |
|
| |
|
| |
|
| | if (charCode < 32 && charCode !== 9 && charCode !== 10 && charCode !== 13) {
|
| |
|
| | if (charCode < 8 || (charCode > 13 && charCode < 27)) {
|
| | suspiciousControlCount++;
|
| | }
|
| | }
|
| |
|
| |
|
| | if (charCode === 0xfffd) {
|
| | suspiciousControlCount++;
|
| | }
|
| | }
|
| |
|
| |
|
| | if (nullCount > config.maxAbsoluteNullBytes) return false;
|
| |
|
| |
|
| | if (suspiciousControlCount / sample.length > config.suspiciousCharThresholdRatio) return false;
|
| |
|
| | return true;
|
| | }
|
| |
|