CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sentiment

AFINN-based sentiment analysis for Node.js with multi-language support and custom scoring strategies

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

Sentiment

Sentiment is a high-performance AFINN-based sentiment analysis library for Node.js that uses the AFINN-165 wordlist and Emoji Sentiment Ranking to analyze the emotional tone of text input. It provides comprehensive sentiment scoring with detailed breakdowns, supports multiple languages through a plugin system, and offers custom scoring strategies for handling negation and emphasis.

Package Information

  • Package Name: sentiment
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install sentiment

Core Imports

const Sentiment = require('sentiment');

ES6 import (if using a transpiler):

import Sentiment from 'sentiment';

Basic Usage

const Sentiment = require('sentiment');
const sentiment = new Sentiment();

// Analyze sentiment of text
const result = sentiment.analyze('Cats are totally amazing!');
console.log(result);
// {
//   score: 4,
//   comparative: 1,
//   calculation: [{ amazing: 4 }],
//   tokens: ['cats', 'are', 'totally', 'amazing'],
//   words: ['amazing'],
//   positive: ['amazing'],
//   negative: []
// }

// Override AFINN wordlist
const customResult = sentiment.analyze('Cats are stupid.', {
  extras: { 'cats': 5, 'stupid': -1 }
});
console.log(customResult.score); // 4 (5 + -1)

Architecture

Sentiment analysis is built around several key components:

  • AFINN Wordlist: Pre-scored word database with values from -5 (negative) to +5 (positive)
  • Emoji Support: Sentiment rankings for emojis integrated into all languages
  • Tokenization: Text preprocessing that splits input into individual words and emojis
  • Language System: Pluggable language support with custom scoring strategies
  • Scoring Strategy: Per-language logic for handling negation, emphasis, and context

Capabilities

Sentiment Analysis

Analyzes the emotional tone of input text and returns detailed sentiment metrics.

/**
 * Performs sentiment analysis on the provided input phrase
 * @param {string} phrase - Input phrase to analyze
 * @param {object} [opts] - Analysis options
 * @param {string} [opts.language='en'] - Language code for analysis (defaults to 'en')
 * @param {object} [opts.extras={}] - Additional word/score pairs to add or overwrite
 * @param {function} [callback] - Optional callback function
 * @returns {object} Sentiment analysis result
 */
analyze(phrase, opts, callback);

Usage Examples:

const sentiment = new Sentiment();

// Basic analysis
const result = sentiment.analyze('I love sunny days!');

// With language specification
const frenchResult = sentiment.analyze('Je suis heureux', { 
  language: 'fr' 
});

// With custom word overrides
const customResult = sentiment.analyze('This product is okay', {
  extras: { 'okay': 2 }
});

// With callback (async)
sentiment.analyze('Hello world', (err, result) => {
  console.log(result.score);
});

Language Registration

Registers support for additional languages with custom word lists and scoring strategies.

/**
 * Registers a new language for sentiment analysis
 * @param {string} languageCode - Two-digit language code (e.g., 'fr', 'es')
 * @param {object} language - Language configuration object
 * @param {object} language.labels - Word-to-score mapping for the language
 * @param {object} [language.scoringStrategy] - Custom scoring strategy for the language
 */
registerLanguage(languageCode, language);

Usage Examples:

const sentiment = new Sentiment();

// Register French language
sentiment.registerLanguage('fr', {
  labels: {
    'bon': 3,
    'mauvais': -3,
    'excellent': 5,
    'horrible': -5
  }
});

// Register with custom scoring strategy
sentiment.registerLanguage('es', {
  labels: {
    'bueno': 3,
    'malo': -3
  },
  scoringStrategy: {
    apply: function(tokens, cursor, tokenScore) {
      // Custom negation handling for Spanish
      if (cursor > 0 && tokens[cursor - 1] === 'no') {
        return -tokenScore;
      }
      return tokenScore;
    }
  }
});

// Use registered language
const result = sentiment.analyze('Très bon!', { language: 'fr' });

Types

Sentiment Constructor

/**
 * Creates a new Sentiment analyzer instance  
 * @param {object} [options] - Configuration options (none currently supported)
 */
function Sentiment(options);

Analysis Result

interface AnalysisResult {
  /** Total sentiment score calculated by summing individual word scores */
  score: number;
  /** Comparative score (score divided by number of tokens) */
  comparative: number;
  /** Array of objects showing which words contributed to the score */
  calculation: Array<{[word: string]: number}>;
  /** All tokens (words/emojis) found in the input text */
  tokens: string[];
  /** Words from input that were found in the sentiment wordlist */
  words: string[];
  /** Words with positive sentiment scores */
  positive: string[];
  /** Words with negative sentiment scores */
  negative: string[];
}

Language Object

interface LanguageObject {
  /** Word-to-score mapping where keys are words and values are sentiment scores (-5 to +5) */
  labels: {[word: string]: number};
  /** Optional custom scoring strategy for handling context and negation */
  scoringStrategy?: ScoringStrategy;
}

interface ScoringStrategy {
  /**
   * Applies contextual scoring logic to individual tokens
   * @param {string[]} tokens - All tokens in the phrase being analyzed
   * @param {number} cursor - Index of the current token being scored
   * @param {number} tokenScore - Base sentiment score for the current token
   * @returns {number} Modified sentiment score for the token
   */
  apply(tokens: string[], cursor: number, tokenScore: number): number;
}

Analysis Options

interface AnalysisOptions {
  /** Two-digit language code for analysis (defaults to 'en') */
  language?: string;
  /** Additional word/score pairs to add or override in the wordlist */
  extras?: {[word: string]: number};
}

Error Handling

The sentiment library handles several error conditions:

  • Invalid language code: Throws Error: No language found: <code> when requesting an unregistered language
  • Missing language labels: Throws Error: language.labels must be defined! when registering a language without required labels
  • Malformed input: Gracefully handles undefined, null, or non-string input by treating it as empty string

Example:

const sentiment = new Sentiment();

try {
  // This will throw an error
  sentiment.analyze('Hello', { language: 'xx' });
} catch (error) {
  console.log(error.message); // "No language found: xx"
}

try {
  // This will throw an error  
  sentiment.registerLanguage('fr', { /* missing labels */ });
} catch (error) {
  console.log(error.message); // "language.labels must be defined!"
}

docs

index.md

tile.json