UNPKG

2.16 kBJavaScriptView Raw
1/**
2 * AFINN-based sentiment analysis for Node.js
3 *
4 * @package sentiment
5 * @author Andrew Sliwinski <andrewsliwinski@acm.org>
6 */
7
8/**
9 * Dependencies
10 */
11var afinn = require('../build/AFINN.json');
12var tokenize = require('./tokenize');
13
14/**
15 * These words "flip" the sentiment of the following word.
16 */
17var negators = {
18 'cant': 1,
19 'can\'t': 1,
20 'dont': 1,
21 'don\'t': 1,
22 'doesnt': 1,
23 'doesn\'t': 1,
24 'not': 1,
25 'non': 1,
26 'wont': 1,
27 'won\'t': 1,
28 'isnt': 1,
29 'isn\'t': 1
30};
31
32/**
33 * Performs sentiment analysis on the provided input 'phrase'.
34 *
35 * @param {String} Input phrase
36 * @param {Object} Optional sentiment additions to AFINN (hash k/v pairs)
37 *
38 * @return {Object}
39 */
40module.exports = function (phrase, inject, callback) {
41 // Parse arguments
42 if (typeof phrase === 'undefined') phrase = '';
43 if (typeof inject === 'undefined') inject = null;
44 if (typeof inject === 'function') callback = inject;
45 if (typeof callback === 'undefined') callback = null;
46
47 // Merge
48 if (inject !== null) {
49 afinn = Object.assign(afinn, inject);
50 }
51
52 // Storage objects
53 var tokens = tokenize(phrase),
54 score = 0,
55 words = [],
56 positive = [],
57 negative = [];
58
59 // Iterate over tokens
60 var len = tokens.length;
61 while (len--) {
62 var obj = tokens[len];
63 var item = afinn[obj];
64 if (!afinn.hasOwnProperty(obj)) continue;
65
66 // Check for negation
67 if (len > 0) {
68 var prevtoken = tokens[len-1];
69 if (negators[prevtoken]) item = -item;
70 }
71
72 words.push(obj);
73 if (item > 0) positive.push(obj);
74 if (item < 0) negative.push(obj);
75
76 score += item;
77 }
78
79 // Handle optional async interface
80 var result = {
81 score: score,
82 comparative: score / tokens.length,
83 tokens: tokens,
84 words: words,
85 positive: positive,
86 negative: negative
87 };
88
89 if (callback === null) return result;
90 process.nextTick(function () {
91 callback(null, result);
92 });
93};