CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes48downloads
index.js201 linesDownload Raw Back to edition-es2017-esm
1/* eslint no-use-before-define:0 */2import * as pathUtil from 'path';3import textExtensions from 'textextensions';4import binaryExtensions from 'binaryextensions';5/**6 * Determine if the filename and/or buffer is text.7 * Determined by extension checks first (if filename is available), otherwise if unknown extension or no filename, will perform a slower buffer encoding detection.8 * This order is done, as extension checks are quicker, and also because encoding checks cannot guarantee accuracy for chars between utf8 and utf16.9 * The extension checks are performed using the resources https://github.com/bevry/textextensions and https://github.com/bevry/binaryextensions10 * @param filename The filename for the file/buffer if available11 * @param buffer The buffer for the file if available12 * @returns Will be `null` if neither `filename` nor `buffer` were provided. Otherwise will be a boolean value with the detection result.13 */14export function isText(filename, buffer) {15    // Test extensions16    if (filename) {17        // Extract filename18        const parts = pathUtil.basename(filename).split('.').reverse();19        // Cycle extensions20        for (const extension of parts) {21            if (textExtensions.indexOf(extension) !== -1) {22                return true;23            }24            if (binaryExtensions.indexOf(extension) !== -1) {25                return false;26            }27        }28    }29    // Fallback to encoding if extension check was not enough30    if (buffer) {31        return getEncoding(buffer) === 'utf8';32    }33    // No buffer was provided34    return null;35}36/**37 * Determine if the filename and/or buffer is binary.38 * Determined by extension checks first (if filename is available), otherwise if unknown extension or no filename, will perform a slower buffer encoding detection.39 * This order is done, as extension checks are quicker, and also because encoding checks cannot guarantee accuracy for chars between utf8 and utf16.40 * The extension checks are performed using the resources https://github.com/bevry/textextensions and https://github.com/bevry/binaryextensions41 * @param filename The filename for the file/buffer if available42 * @param buffer The buffer for the file if available43 * @returns Will be `null` if neither `filename` nor `buffer` were provided. Otherwise will be a boolean value with the detection result.44 */45export function isBinary(filename, buffer) {46    const text = isText(filename, buffer);47    if (text == null)48        return null;49    return !text;50}51/**52 * Get the encoding of a buffer.53 * Checks the start, middle, and end of the buffer for characters that are unrecognized within UTF8 encoding.54 * History has shown that inspection at all three locations is necessary.55 * @returns Will be `null` if `buffer` was not provided. Otherwise will be either `'utf8'` or `'binary'`56 */57export function getEncoding(buffer, opts) {58    var _a, _b;59    // Check60    if (!buffer)61        return null;62    // Prepare63    const textEncoding = 'utf8';64    const binaryEncoding = 'binary';65    const chunkLength = (_a = opts === null || opts === void 0 ? void 0 : opts.chunkLength) !== null && _a !== void 0 ? _a : 24;66    let chunkBegin = (_b = opts === null || opts === void 0 ? void 0 : opts.chunkBegin) !== null && _b !== void 0 ? _b : 0;67    // Discover68    if ((opts === null || opts === void 0 ? void 0 : opts.chunkBegin) == null) {69        // Start70        let encoding = getEncoding(buffer, { chunkLength, chunkBegin });71        if (encoding === textEncoding) {72            // Middle73            chunkBegin = Math.max(0, Math.floor(buffer.length / 2) - chunkLength);74            encoding = getEncoding(buffer, {75                chunkLength,76                chunkBegin,77            });78            if (encoding === textEncoding) {79                // End80                chunkBegin = Math.max(0, buffer.length - chunkLength);81                encoding = getEncoding(buffer, {82                    chunkLength,83                    chunkBegin,84                });85            }86        }87        // Return88        return encoding;89    }90    else {91        // Extract92        chunkBegin = getChunkBegin(buffer, chunkBegin);93        if (chunkBegin === -1) {94            return binaryEncoding;95        }96        const chunkEnd = getChunkEnd(buffer, Math.min(buffer.length, chunkBegin + chunkLength));97        if (chunkEnd > buffer.length) {98            return binaryEncoding;99        }100        const contentChunkUTF8 = buffer.toString(textEncoding, chunkBegin, chunkEnd);101        // Detect encoding102        for (let i = 0; i < contentChunkUTF8.length; ++i) {103            const charCode = contentChunkUTF8.charCodeAt(i);104            if (charCode === 65533 || charCode <= 8) {105                // 8 and below are control characters (e.g. backspace, null, eof, etc.)106                // 65533 is the unknown character107                // console.log(charCode, contentChunkUTF8[i])108                return binaryEncoding;109            }110        }111        // Return112        return textEncoding;113    }114}115// ====================================116// The functions below are created to handle multibyte utf8 characters.117// To understand how the encoding works, check this article: https://en.wikipedia.org/wiki/UTF-8#Encoding118// @todo add documentation for these119function getChunkBegin(buf, chunkBegin) {120    // If it's the beginning, just return.121    if (chunkBegin === 0) {122        return 0;123    }124    if (!isLaterByteOfUtf8(buf[chunkBegin])) {125        return chunkBegin;126    }127    let begin = chunkBegin - 3;128    if (begin >= 0) {129        if (isFirstByteOf4ByteChar(buf[begin])) {130            return begin;131        }132    }133    begin = chunkBegin - 2;134    if (begin >= 0) {135        if (isFirstByteOf4ByteChar(buf[begin]) ||136            isFirstByteOf3ByteChar(buf[begin])) {137            return begin;138        }139    }140    begin = chunkBegin - 1;141    if (begin >= 0) {142        // Is it a 4-byte, 3-byte utf8 character?143        if (isFirstByteOf4ByteChar(buf[begin]) ||144            isFirstByteOf3ByteChar(buf[begin]) ||145            isFirstByteOf2ByteChar(buf[begin])) {146            return begin;147        }148    }149    return -1;150}151function getChunkEnd(buf, chunkEnd) {152    // If it's the end, just return.153    if (chunkEnd === buf.length) {154        return chunkEnd;155    }156    let index = chunkEnd - 3;157    if (index >= 0) {158        if (isFirstByteOf4ByteChar(buf[index])) {159            return chunkEnd + 1;160        }161    }162    index = chunkEnd - 2;163    if (index >= 0) {164        if (isFirstByteOf4ByteChar(buf[index])) {165            return chunkEnd + 2;166        }167        if (isFirstByteOf3ByteChar(buf[index])) {168            return chunkEnd + 1;169        }170    }171    index = chunkEnd - 1;172    if (index >= 0) {173        if (isFirstByteOf4ByteChar(buf[index])) {174            return chunkEnd + 3;175        }176        if (isFirstByteOf3ByteChar(buf[index])) {177            return chunkEnd + 2;178        }179        if (isFirstByteOf2ByteChar(buf[index])) {180            return chunkEnd + 1;181        }182    }183    return chunkEnd;184}185function isFirstByteOf4ByteChar(byte) {186    // eslint-disable-next-line no-bitwise187    return byte >> 3 === 30; // 11110xxx?188}189function isFirstByteOf3ByteChar(byte) {190    // eslint-disable-next-line no-bitwise191    return byte >> 4 === 14; // 1110xxxx?192}193function isFirstByteOf2ByteChar(byte) {194    // eslint-disable-next-line no-bitwise195    return byte >> 5 === 6; // 110xxxxx?196}197function isLaterByteOfUtf8(byte) {198    // eslint-disable-next-line no-bitwise199    return byte >> 6 === 2; // 10xxxxxx?200}201 
basant307/AI_Governance_Project · CoolFace