UNPKG

@genesys225/fast-text-language-detection

Version:
593 lines (543 loc) 12.6 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('path'), require('fs')) : typeof define === 'function' && define.amd ? define(['path', 'fs'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.myLib = factory(global.require$$0, global.require$$0$1)); })(this, (function (require$$0, require$$0$1) { 'use strict'; function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0); var require$$0__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$0$1); function commonjsRequire (path) { throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.'); } var bindings = {exports: {}}; /** * Module dependencies. */ var sep = require$$0__default["default"].sep || '/'; /** * Module exports. */ var fileUriToPath_1 = fileUriToPath; /** * File URI to Path function. * * @param {String} uri * @return {String} path * @api public */ function fileUriToPath (uri) { if ('string' != typeof uri || uri.length <= 7 || 'file://' != uri.substring(0, 7)) { throw new TypeError('must pass in a file:// URI to convert to a file path'); } var rest = decodeURI(uri.substring(7)); var firstSlash = rest.indexOf('/'); var host = rest.substring(0, firstSlash); var path = rest.substring(firstSlash + 1); // 2. Scheme Definition // As a special case, <host> can be the string "localhost" or the empty // string; this is interpreted as "the machine from which the URL is // being interpreted". if ('localhost' == host) host = ''; if (host) { host = sep + sep + host; } // 3.2 Drives, drive letters, mount points, file system root // Drive letters are mapped into the top of a file URI in various ways, // depending on the implementation; some applications substitute // vertical bar ("|") for the colon after the drive letter, yielding // "file:///c|/tmp/test.txt". In some cases, the colon is left // unchanged, as in "file:///c:/tmp/test.txt". In other cases, the // colon is simply omitted, as in "file:///c/tmp/test.txt". path = path.replace(/^(.+)\|/, '$1:'); // for Windows, we need to invert the path separators from what a URI uses if (sep == '\\') { path = path.replace(/\//g, '\\'); } if (/^.+\:/.test(path)) ; else { // unix path… path = sep + path; } return host + path; } /** * Module dependencies. */ (function (module, exports) { var fs = require$$0__default$1["default"], path = require$$0__default["default"], fileURLToPath = fileUriToPath_1, join = path.join, dirname = path.dirname, exists = (fs.accessSync && function(path) { try { fs.accessSync(path); } catch (e) { return false; } return true; }) || fs.existsSync || path.existsSync, defaults = { arrow: process.env.NODE_BINDINGS_ARROW || ' → ', compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled', platform: process.platform, arch: process.arch, nodePreGyp: 'node-v' + process.versions.modules + '-' + process.platform + '-' + process.arch, version: process.versions.node, bindings: 'bindings.node', try: [ // node-gyp's linked version in the "build" dir ['module_root', 'build', 'bindings'], // node-waf and gyp_addon (a.k.a node-gyp) ['module_root', 'build', 'Debug', 'bindings'], ['module_root', 'build', 'Release', 'bindings'], // Debug files, for development (legacy behavior, remove for node v0.9) ['module_root', 'out', 'Debug', 'bindings'], ['module_root', 'Debug', 'bindings'], // Release files, but manually compiled (legacy behavior, remove for node v0.9) ['module_root', 'out', 'Release', 'bindings'], ['module_root', 'Release', 'bindings'], // Legacy from node-waf, node <= 0.4.x ['module_root', 'build', 'default', 'bindings'], // Production "Release" buildtype binary (meh...) ['module_root', 'compiled', 'version', 'platform', 'arch', 'bindings'], // node-qbs builds ['module_root', 'addon-build', 'release', 'install-root', 'bindings'], ['module_root', 'addon-build', 'debug', 'install-root', 'bindings'], ['module_root', 'addon-build', 'default', 'install-root', 'bindings'], // node-pre-gyp path ./lib/binding/{node_abi}-{platform}-{arch} ['module_root', 'lib', 'binding', 'nodePreGyp', 'bindings'] ] }; /** * The main `bindings()` function loads the compiled bindings for a given module. * It uses V8's Error API to determine the parent filename that this function is * being invoked from, which is then used to find the root directory. */ function bindings(opts) { // Argument surgery if (typeof opts == 'string') { opts = { bindings: opts }; } else if (!opts) { opts = {}; } // maps `defaults` onto `opts` object Object.keys(defaults).map(function(i) { if (!(i in opts)) opts[i] = defaults[i]; }); // Get the module root if (!opts.module_root) { opts.module_root = exports.getRoot(exports.getFileName()); } // Ensure the given bindings name ends with .node if (path.extname(opts.bindings) != '.node') { opts.bindings += '.node'; } // https://github.com/webpack/webpack/issues/4175#issuecomment-342931035 var requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : commonjsRequire; var tries = [], i = 0, l = opts.try.length, n, b, err; for (; i < l; i++) { n = join.apply( null, opts.try[i].map(function(p) { return opts[p] || p; }) ); tries.push(n); try { b = opts.path ? requireFunc.resolve(n) : requireFunc(n); if (!opts.path) { b.path = n; } return b; } catch (e) { if (e.code !== 'MODULE_NOT_FOUND' && e.code !== 'QUALIFIED_PATH_RESOLUTION_FAILED' && !/not find/i.test(e.message)) { throw e; } } } err = new Error( 'Could not locate the bindings file. Tried:\n' + tries .map(function(a) { return opts.arrow + a; }) .join('\n') ); err.tries = tries; throw err; } module.exports = exports = bindings; /** * Gets the filename of the JavaScript file that invokes this function. * Used to help find the root directory of a module. * Optionally accepts an filename argument to skip when searching for the invoking filename */ exports.getFileName = function getFileName(calling_file) { var origPST = Error.prepareStackTrace, origSTL = Error.stackTraceLimit, dummy = {}, fileName; Error.stackTraceLimit = 10; Error.prepareStackTrace = function(e, st) { for (var i = 0, l = st.length; i < l; i++) { fileName = st[i].getFileName(); if (fileName !== __filename) { if (calling_file) { if (fileName !== calling_file) { return; } } else { return; } } } }; // run the 'prepareStackTrace' function above Error.captureStackTrace(dummy); dummy.stack; // cleanup Error.prepareStackTrace = origPST; Error.stackTraceLimit = origSTL; // handle filename that starts with "file://" var fileSchema = 'file://'; if (fileName.indexOf(fileSchema) === 0) { fileName = fileURLToPath(fileName); } return fileName; }; /** * Gets the root directory of a module, given an arbitrary filename * somewhere in the module tree. The "root directory" is the directory * containing the `package.json` file. * * In: /home/nate/node-native-module/lib/index.js * Out: /home/nate/node-native-module */ exports.getRoot = function getRoot(file) { var dir = dirname(file), prev; while (true) { if (dir === '.') { // Avoids an infinite loop in rare cases, like the REPL dir = process.cwd(); } if ( exists(join(dir, 'package.json')) || exists(join(dir, 'node_modules')) ) { // Found the 'package.json' file or 'node_modules' dir; we're done return dir; } if (prev === dir) { // Got to the top throw new Error( 'Could not find module root given file: "' + file + '". Do you have a `package.json` file? ' ); } // Try the parent dir next prev = dir; dir = join(dir, '..'); } }; }(bindings, bindings.exports)); const FastText = bindings.exports('fasttext'); var main = FastText; /* internal requirements */ const path = require$$0__default["default"]; /* external requirements */ const { Classifier } = main; // from benchmark-testing/results/reliability_list_<verison>.json const reliabilityList = [ 'th', 'ml', 'my', 'ta', 'te', 'pa', 'am', 'kn', 'gu', 'si', 'bo', 'dv', 'ja', 'el', 'he', 'ko', 'hy', 'bn', 'mr', 'en', 'zh', 'tr', 'ru', 'de', 'ug', 'vi', 'eo', 'ka', 'hi', 'it', 'ar', 'fr', 'hu', 'lo', 'pl', 'km', 'es', 'fi', 'pt', 'mk', 'uk', 'ur', 'nl', 'lt', 'cs', ]; const languageIsoCodes = [ 'af', 'als', 'am', 'an', 'ar', 'arz', 'as', 'ast', 'av', 'az', 'azb', 'ba', 'bar', 'bcl', 'be', 'bg', 'bh', 'bn', 'bo', 'bpy', 'br', 'bs', 'bxr', 'ca', 'cbk', 'ce', 'ceb', 'ckb', 'co', 'cs', 'cv', 'cy', 'da', 'de', 'diq', 'dsb', 'dty', 'dv', 'el', 'eml', 'en', 'eo', 'es', 'et', 'eu', 'fa', 'fi', 'fr', 'frr', 'fy', 'ga', 'gd', 'gl', 'gn', 'gom', 'gu', 'gv', 'he', 'hi', 'hif', 'hr', 'hsb', 'ht', 'hu', 'hy', 'ia', 'id', 'ie', 'ilo', 'io', 'is', 'it', 'ja', 'jbo', 'jv', 'ka', 'kk', 'km', 'kn', 'ko', 'krc', 'ku', 'kv', 'kw', 'ky', 'la', 'lb', 'lez', 'li', 'lmo', 'lo', 'lrc', 'lt', 'lv', 'mai', 'mg', 'mhr', 'min', 'mk', 'ml', 'mn', 'mr', 'mrj', 'ms', 'mt', 'mwl', 'my', 'myv', 'mzn', 'nah', 'nap', 'nds', 'ne', 'new', 'nl', 'nn', 'no', 'oc', 'or', 'os', 'pa', 'pam', 'pfl', 'pl', 'pms', 'pnb', 'ps', 'pt', 'qu', 'rm', 'ro', 'ru', 'rue', 'sa', 'sah', 'sc', 'scn', 'sco', 'sd', 'sh', 'si', 'sk', 'sl', 'so', 'sq', 'sr', 'su', 'sv', 'sw', 'ta', 'te', 'tg', 'th', 'tk', 'tl', 'tr', 'tt', 'tyv', 'ug', 'uk', 'ur', 'uz', 'vec', 'vep', 'vi', 'vls', 'vo', 'wa', 'war', 'wuu', 'xal', 'xmf', 'yi', 'yo', 'yue', 'zh', ]; // Some characters can misconstrude the results // Removing \n and : because of this issue: https://github.com/indix/whatthelang/issues/12 /** * * @param { string } text * @returns */ function formatInput(text) { return text.replace(/[\n:]/g, '') } /* the API class */ class LanguageDetection { constructor(options = {}) { this.options = Object.assign( {}, { model: path.join(__dirname, '..', 'model', 'fast-text-lid-model.bin'), }, options ); this.classifier = new Classifier(this.options.model); this.languageIsoCodes = languageIsoCodes; } predict(text, k = 1) { return new Promise((resolve, reject) => { this.classifier.predict(formatInput(text), k, (err, res) => { if (err) reject(err); else { res = res.map((item) => { const lang = item.label.replace(/^__label__/, ''); return { lang, prob: item.value, isReliableLanguage: reliabilityList.includes(lang), } }); resolve(res); } }); }) } } var src = LanguageDetection; return src; }));