{"version":3,"sources":["jsdelivr-header.js","/npm/multilang-sentiment@2.0.0/lib/index.js"],"names":[],"mappings":"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","file":"/npm/multilang-sentiment@2.0.0/lib/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/multilang-sentiment@2.0.0/lib/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","var tokenize = require('./tokenize');\r\nvar Fuse = require('fuse.js');\r\nvar utils = require('./utils');\r\n\r\nvar langLists = [];\r\nvar fuseDbs = [];\r\nvar fuseOpts = {\r\n  includeMatches: true,\r\n  threshold: 0.2,\r\n  location: 0,\r\n  distance: 10,\r\n  maxPatternLength: 20,\r\n  minMatchCharLength: 1,\r\n  keys: ['word'],\r\n};\r\n\r\n// Will not perform a fuzzy search on long texts\r\nvar fuzzySearchMaxLength = 100;\r\n\r\n// Defines the distance, expressed in number of\r\n// tokens, within which a negator has effect\r\nvar maxNegationDistance = 5;\r\n\r\n// Volatile list of already built languages\r\nvar builtLanguages = [];\r\n\r\n/**\r\n * Builds the Fuse DBs and creates dictionaries.\r\n * In case the given language has been already built, the\r\n * iteration is skipped.\r\n * @param {Object} langs The list of supported languages\r\n */\r\nfunction buildFuseDbs(langs) {\r\n  langs.forEach(function (lang) {\r\n    if (builtLanguages.indexOf(lang) > -1) {\r\n      return;\r\n    }\r\n\r\n    var afinnWords = [];\r\n    langLists[lang] = require('../build/output/build-' + lang + '.json');\r\n    Object.keys(langLists[lang]).forEach(function (k) {\r\n      afinnWords.push({\r\n        word: k,\r\n      });\r\n    });\r\n    fuseDbs[lang] = new Fuse(afinnWords, fuseOpts);\r\n    builtLanguages.push(lang);\r\n  });\r\n}\r\n\r\n/**\r\n * Performs sentiment analysis on the provided input 'phrase'.\r\n *\r\n * @param {String} phrase The phrase to be analyzed\r\n * @param {String} lang The language to be used\r\n * @param {Object} inject Custom additions (words/tokens)\r\n * @param {Function} callback An optional callback\r\n * @return {Object}\r\n */\r\n// TODO: Support multiple langs to be passed\r\nmodule.exports = function (phrase, lang, inject, callback) {\r\n  // Parse arguments\r\n  if (typeof phrase === 'undefined') phrase = '';\r\n  if (typeof lang === 'undefined') lang = 'en';\r\n  if (typeof inject === 'undefined') inject = null;\r\n  if (typeof inject === 'function') callback = inject;\r\n  if (typeof callback === 'undefined') callback = null;\r\n\r\n  // Let's build fuse dbs at bootstrap\r\n  buildFuseDbs([lang]);\r\n\r\n  var i, j;\r\n  var customTokens = [];\r\n  var afinnLang = Object.assign({}, langLists[lang]);\r\n  var fuse = fuseDbs[lang];\r\n\r\n  // Merge custom words/tokens with our dictionary\r\n  if (inject !== null) {\r\n    if (typeof inject.words !== 'undefined') {\r\n      for (i in inject.words) {\r\n        inject.words[i] = {\r\n          coeff: inject.words[i],\r\n          lang: lang,\r\n        };\r\n      }\r\n      afinnLang = Object.assign(afinnLang, inject.words);\r\n    }\r\n\r\n    if (typeof inject.tokens !== 'undefined') {\r\n      for (i in inject.tokens) {\r\n        customTokens.push({\r\n          value: inject.tokens[i],\r\n          negate: utils.isNegator(inject.tokens[i], lang),\r\n        });\r\n      }\r\n    }\r\n  }\r\n\r\n  // Storage objects\r\n  var tokens = customTokens.length > 0 ? customTokens : tokenize(phrase, lang),\r\n    score = 0,\r\n    positiveScore = 0,\r\n    negativeScore = 0,\r\n    words = [],\r\n    positive = [],\r\n    negative = [];\r\n\r\n  // Iterate over tokens\r\n  var nearNegator = false,\r\n    nearNegatorCount = 0,\r\n    tokensLen = tokens.length;\r\n\r\n  for (i = 0; i < tokensLen; i++) {\r\n    var tokenizedWord = tokens[i].value;\r\n    if (tokenizedWord === '') continue;\r\n\r\n    if (tokens[i].negate) {\r\n      nearNegator = true;\r\n      continue;\r\n    }\r\n\r\n    if (nearNegatorCount >= maxNegationDistance) {\r\n      nearNegator = false;\r\n      nearNegatorCount = 0;\r\n    }\r\n    nearNegatorCount++;\r\n\r\n    if (\r\n      !Object.prototype.hasOwnProperty.call(afinnLang, tokenizedWord) &&\r\n      tokens.length < fuzzySearchMaxLength\r\n    ) {\r\n      // TODO: Handling of typos or plurals in single words\r\n      // has to be further improved.The following implementation\r\n      // is a good compromise.\r\n\r\n      var foundSimilar = false;\r\n      var search = fuse.search(tokenizedWord);\r\n\r\n      for (j in search) {\r\n        var fuseItem = search[j];\r\n        var fuseWord = fuseItem.item.word;\r\n        var partialFuseWord = fuseWord.substring(0, fuseWord.length - 1);\r\n        var partialWord = tokenizedWord.substring(0, tokenizedWord.length - 1);\r\n\r\n        if (\r\n          fuseItem &&\r\n          fuseItem.item &&\r\n          fuseItem.item.word &&\r\n          // To avoid false-positives the words\r\n          // should be identical except for\r\n          // the final char\r\n          partialFuseWord === partialWord\r\n        ) {\r\n          foundSimilar = true;\r\n          tokenizedWord = fuseItem.matches[0].value;\r\n          break;\r\n        }\r\n      }\r\n\r\n      if (!foundSimilar) {\r\n        continue;\r\n      }\r\n    }\r\n\r\n    words.push(tokenizedWord);\r\n\r\n    var item = Object.assign({}, afinnLang[tokenizedWord]);\r\n    item.coeff = nearNegator ? -item.coeff : item.coeff;\r\n\r\n    if (item.coeff > 0) {\r\n      positive.push(tokenizedWord);\r\n      positiveScore += item.coeff;\r\n    } else if (item.coeff < 0) {\r\n      negative.push(tokenizedWord);\r\n      negativeScore += item.coeff;\r\n    }\r\n\r\n    if (isNaN(item.coeff)) {\r\n      continue;\r\n    }\r\n\r\n    score += item.coeff;\r\n  }\r\n\r\n  let positiveOverNegativeScore =\r\n    +(positiveScore / negativeScore).toFixed(2) || 0;\r\n\r\n  if (positiveScore === 0) {\r\n    positiveOverNegativeScore = negativeScore;\r\n  } else if (negativeScore === 0) {\r\n    positiveOverNegativeScore = positiveScore;\r\n  } else {\r\n    if (positiveOverNegativeScore === Number.POSITIVE_INFINITY) {\r\n      positiveOverNegativeScore = positiveScore;\r\n    } else if (positiveOverNegativeScore === Number.NEGATIVE_INFINITY) {\r\n      positiveOverNegativeScore = negativeScore;\r\n    }\r\n  }\r\n\r\n  const comparativeScore =\r\n    score !== 0\r\n      ? +(score / tokens.length + positiveOverNegativeScore).toFixed(2)\r\n      : 0;\r\n\r\n  let category;\r\n  if (score === 0) {\r\n    category = 'neutral';\r\n  } else if (comparativeScore > 0) {\r\n    category = 'positive';\r\n  } else {\r\n    category = 'negative';\r\n  }\r\n\r\n  var result = {\r\n    score,\r\n    positiveScore,\r\n    negativeScore,\r\n    comparative: comparativeScore,\r\n    category,\r\n    tokens,\r\n    words,\r\n    positive,\r\n    negative,\r\n  };\r\n\r\n  if (callback === null) {\r\n    return result;\r\n  }\r\n\r\n  process.nextTick(function () {\r\n    callback(null, result);\r\n  });\r\n};\r\n"]}