All files / src index.ts

96.67% Statements 58/60
87.5% Branches 21/24
100% Functions 11/11
96.36% Lines 53/55

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147      6x 6x 6x 6x 6x     6x 32x 32x 32x                     6x                                                       6x 33x 33x     6x   34x 8704x   61438x   34x 34x 561x 17x 17x       34x                 34x   782x     782x     438x     34x     6x 2x   2x   2x 2x 1x     2x     2x       2x 1x 1x   1x 1x   1x     1x     6x 30x   30x 1x 1x   1x 1x 1x     29x     6x            
import { Match } from './match';
import { Recogniser, Context } from './encoding';
 
import Utf8 from './encoding/utf8';
import * as unicode from './encoding/unicode';
import * as mbcs from './encoding/mbcs';
import * as sbcs from './encoding/sbcs';
import * as iso2022 from './encoding/iso2022';
 
let fsModule: any;
const loadFs = () => {
  Eif (typeof module === 'object' && typeof module.exports === 'object') {
    fsModule = fsModule ? fsModule : require('fs');
    return fsModule;
  }
  throw new Error('File system is not available');
}
 
interface FullOptions {
  sampleSize: number
}
 
type Options = Partial<FullOptions>
 
const recognisers: Recogniser[] = [
  new Utf8(),
  new unicode.UTF_16BE(),
  new unicode.UTF_16LE(),
  new unicode.UTF_32BE(),
  new unicode.UTF_32LE(),
  new mbcs.sjis(),
  new mbcs.big5(),
  new mbcs.euc_jp(),
  new mbcs.euc_kr(),
  new mbcs.gb_18030(),
  new iso2022.ISO_2022_JP(),
  new iso2022.ISO_2022_KR(),
  new iso2022.ISO_2022_CN(),
  new sbcs.ISO_8859_1(),
  new sbcs.ISO_8859_2(),
  new sbcs.ISO_8859_5(),
  new sbcs.ISO_8859_6(),
  new sbcs.ISO_8859_7(),
  new sbcs.ISO_8859_8(),
  new sbcs.ISO_8859_9(),
  new sbcs.windows_1251(),
  new sbcs.windows_1256(),
  new sbcs.KOI8_R(),
];
 
type DetectResult = Match[] | string | null;
 
export const detect = (buffer: Uint8Array): string | null => {
  const matches: Match[] = analyse(buffer);
  return matches.length > 0 ? matches[0].name : null;
};
 
export const analyse = (buffer: Uint8Array): Match[] => {
  // Tally up the byte occurrence statistics.
  const fByteStats = [];
  for (let i = 0; i < 256; i++) fByteStats[i] = 0;
 
  for (let i = buffer.length - 1; i >= 0; i--) fByteStats[buffer[i] & 0x00ff]++;
 
  let fC1Bytes = false;
  for (let i = 0x80; i <= 0x9f; i += 1) {
    if (fByteStats[i] !== 0) {
      fC1Bytes = true;
      break;
    }
  }
 
  const context: Context = {
    fByteStats,
    fC1Bytes,
    fRawInput: buffer,
    fRawLength: buffer.length,
    fInputBytes: buffer,
    fInputLen: buffer.length,
  };
 
  const matches = recognisers
    .map((rec) => {
      return rec.match(context);
    })
    .filter((match) => {
      return !!match;
    })
    .sort((a, b) => {
      return b!.confidence - a!.confidence;
    });
 
  return matches as Match[];
}
 
export const detectFile = (filepath: string, opts: Options = {}): Promise<DetectResult> =>
  new Promise((resolve, reject) => {
    let fd: any;
    const fs = loadFs();
 
    const handler = (err: Error | null | undefined, buffer: Buffer) => {
      if (fd) {
        fs.closeSync(fd);
      }
 
      Iif (err) {
        reject(err);
      } else {
        resolve(detect(buffer));
      }
    };
 
    if (opts && opts.sampleSize) {
      fd = fs.openSync(filepath, 'r');
      const sample: Buffer = Buffer.allocUnsafe(opts.sampleSize);
 
      fs.read(fd, sample, 0, opts.sampleSize, null, (err?: Error) => {
        handler(err, sample);
      });
      return;
    }
 
    fs.readFile(filepath, handler);
  });
 
export const detectFileSync = (filepath: string, opts: Options = {}): DetectResult => {
  const fs = loadFs();
 
  if (opts && opts.sampleSize) {
    const fd = fs.openSync(filepath, 'r');
    const sample = Buffer.allocUnsafe(opts.sampleSize);
 
    fs.readSync(fd, sample, 0, opts.sampleSize);
    fs.closeSync(fd);
    return detect(sample);
  }
 
  return detect(fs.readFileSync(filepath));
};
 
export default {
  analyse,
  detect,
  detectFileSync,
  detectFile,
};