Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

typo-js

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

typo-js - npm Package Compare versions

Comparing version 1.0.1 to 1.0.2

7

package.json
{
"name": "typo-js",
"version": "1.0.1",
"version": "1.0.2",
"description": "A Hunspell-style spellchecker.",

@@ -23,3 +23,6 @@ "main": "typo.js",

"homepage": "https://github.com/cfinke/Typo.js#readme",
"tonicExample": "var Typo = require('typo-js'); var dictionary = new Typo('en_US'); dictionary.check('mispelled');"
"tonicExample": "var Typo = require('typo-js'); var dictionary = new Typo('en_US'); dictionary.check('mispelled');",
"browser": {
"fs": false
}
}

@@ -1,2 +0,6 @@

'use strict';
/* globals chrome: false */
/* globals __dirname: false */
/* globals require: false */
/* globals Buffer: false */
/* globals module: false */

@@ -8,2 +12,7 @@ /**

var Typo;
(function () {
"use strict";
/**

@@ -30,10 +39,14 @@ * Typo constructor.

* {Object} [flags]: flag information.
* {Boolean} [asyncLoad]: If true, affData and wordsData will be loaded
* asynchronously.
* {Function} [loadedCallback]: Called when both affData and wordsData
* have been loaded. Only used if asyncLoad is set to true. The parameter
* is the instantiated Typo object.
*
*
* @returns {Typo} A Typo object.
*/
var Typo = function (dictionary, affData, wordsData, settings) {
Typo = function (dictionary, affData, wordsData, settings) {
settings = settings || {};
this.dictionary = null;

@@ -51,49 +64,104 @@

this.memoized = {};
this.loaded = false;
var self = this;
var path;
// Loop-control variables.
var i, j, _len, _jlen;
if (dictionary) {
this.dictionary = dictionary;
self.dictionary = dictionary;
if (typeof window !== 'undefined' && 'chrome' in window && 'extension' in window.chrome && 'getURL' in window.chrome.extension) {
if (!affData) affData = this._readFile(chrome.extension.getURL("lib/typo/dictionaries/" + dictionary + "/" + dictionary + ".aff"));
if (!wordsData) wordsData = this._readFile(chrome.extension.getURL("lib/typo/dictionaries/" + dictionary + "/" + dictionary + ".dic"));
} else {
// If the data is preloaded, just setup the Typo object.
if (affData && wordsData) {
setup();
}
// Loading data for Chrome extentions.
else if (typeof window !== 'undefined' && 'chrome' in window && 'extension' in window.chrome && 'getURL' in window.chrome.extension) {
if (settings.dictionaryPath) {
var path = settings.dictionaryPath;
path = settings.dictionaryPath;
}
else {
path = "typo/dictionaries";
}
if (!affData) readDataFile(chrome.extension.getURL(path + "/" + dictionary + "/" + dictionary + ".aff"), setAffData);
if (!wordsData) readDataFile(chrome.extension.getURL(path + "/" + dictionary + "/" + dictionary + ".dic"), setWordsData);
}
else {
if (settings.dictionaryPath) {
path = settings.dictionaryPath;
}
else if (typeof __dirname !== 'undefined') {
var path = __dirname + '/dictionaries';
path = __dirname + '/dictionaries';
}
else {
var path = './dictionaries';
path = './dictionaries';
}
if (!affData) affData = this._readFile(path + "/" + dictionary + "/" + dictionary + ".aff");
if (!wordsData) wordsData = this._readFile(path + "/" + dictionary + "/" + dictionary + ".dic");
if (!affData) readDataFile(path + "/" + dictionary + "/" + dictionary + ".aff", setAffData);
if (!wordsData) readDataFile(path + "/" + dictionary + "/" + dictionary + ".dic", setWordsData);
}
}
function readDataFile(url, setFunc) {
var response = self._readFile(url, null, settings.asyncLoad);
this.rules = this._parseAFF(affData);
if (settings.asyncLoad) {
response.then(function(data) {
setFunc(data);
});
}
else {
setFunc(response);
}
}
function setAffData(data) {
affData = data;
if (wordsData) {
setup();
}
}
function setWordsData(data) {
wordsData = data;
if (affData) {
setup();
}
}
function setup() {
self.rules = self._parseAFF(affData);
// Save the rule codes that are used in compound rules.
this.compoundRuleCodes = {};
self.compoundRuleCodes = {};
for (var i = 0, _len = this.compoundRules.length; i < _len; i++) {
var rule = this.compoundRules[i];
for (i = 0, _len = self.compoundRules.length; i < _len; i++) {
var rule = self.compoundRules[i];
for (var j = 0, _jlen = rule.length; j < _jlen; j++) {
this.compoundRuleCodes[rule[j]] = [];
for (j = 0, _jlen = rule.length; j < _jlen; j++) {
self.compoundRuleCodes[rule[j]] = [];
}
}
// If we add this ONLYINCOMPOUND flag to this.compoundRuleCodes, then _parseDIC
// If we add this ONLYINCOMPOUND flag to self.compoundRuleCodes, then _parseDIC
// will do the work of saving the list of words that are compound-only.
if ("ONLYINCOMPOUND" in this.flags) {
this.compoundRuleCodes[this.flags.ONLYINCOMPOUND] = [];
if ("ONLYINCOMPOUND" in self.flags) {
self.compoundRuleCodes[self.flags.ONLYINCOMPOUND] = [];
}
this.dictionaryTable = this._parseDIC(wordsData);
self.dictionaryTable = self._parseDIC(wordsData);
// Get rid of any codes from the compound rule codes that are never used
// (or that were special regex characters). Not especially necessary...
for (var i in this.compoundRuleCodes) {
if (this.compoundRuleCodes[i].length == 0) {
delete this.compoundRuleCodes[i];
for (i in self.compoundRuleCodes) {
if (self.compoundRuleCodes[i].length === 0) {
delete self.compoundRuleCodes[i];
}

@@ -105,12 +173,12 @@ }

// testing for compound words is probably slow.
for (var i = 0, _len = this.compoundRules.length; i < _len; i++) {
var ruleText = this.compoundRules[i];
for (i = 0, _len = self.compoundRules.length; i < _len; i++) {
var ruleText = self.compoundRules[i];
var expressionText = "";
for (var j = 0, _jlen = ruleText.length; j < _jlen; j++) {
for (j = 0, _jlen = ruleText.length; j < _jlen; j++) {
var character = ruleText[j];
if (character in this.compoundRuleCodes) {
expressionText += "(" + this.compoundRuleCodes[character].join("|") + ")";
if (character in self.compoundRuleCodes) {
expressionText += "(" + self.compoundRuleCodes[character].join("|") + ")";
}

@@ -122,4 +190,10 @@ else {

this.compoundRules[i] = new RegExp(expressionText, "i");
self.compoundRules[i] = new RegExp(expressionText, "i");
}
self.loaded = true;
if (settings.asyncLoad && settings.loadedCallback) {
settings.loadedCallback(self);
}
}

@@ -139,3 +213,5 @@

for (var i in obj) {
this[i] = obj[i];
if (obj.hasOwnProperty(i)) {
this[i] = obj[i];
}
}

@@ -151,11 +227,32 @@

* @param {String} [charset="ISO8859-1"] The expected charset of the file
* @returns string The file data.
* @param {Boolean} async If true, the file will be read asynchronously. For node.js this does nothing, all
* files are read synchronously.
* @returns {String} The file data if async is false, otherwise a promise object. If running node.js, the data is
* always returned.
*/
_readFile : function (path, charset) {
if (!charset) charset = "utf8";
_readFile : function (path, charset, async) {
charset = charset || "utf8";
if (typeof XMLHttpRequest !== 'undefined') {
var promise;
var req = new XMLHttpRequest();
req.open("GET", path, false);
req.open("GET", path, async);
if (async) {
promise = new Promise(function(resolve, reject) {
req.onload = function() {
if (req.status === 200) {
resolve(req.responseText);
}
else {
reject(req.statusText);
}
};
req.onerror = function() {
reject(req.statusText);
}
});
}

@@ -167,3 +264,3 @@ if (req.overrideMimeType)

return req.responseText;
return async ? promise : req.responseText;
}

@@ -206,2 +303,5 @@ else if (typeof require !== 'undefined') {

var line, subline, numEntries, lineParts;
var i, j, _len, _jlen;
// Remove comment lines

@@ -212,4 +312,4 @@ data = this._removeAffixComments(data);

for (var i = 0, _len = lines.length; i < _len; i++) {
var line = lines[i];
for (i = 0, _len = lines.length; i < _len; i++) {
line = lines[i];

@@ -223,10 +323,10 @@ var definitionParts = line.split(/\s+/);

var combineable = definitionParts[2];
var numEntries = parseInt(definitionParts[3], 10);
numEntries = parseInt(definitionParts[3], 10);
var entries = [];
for (var j = i + 1, _jlen = i + 1 + numEntries; j < _jlen; j++) {
var line = lines[j];
for (j = i + 1, _jlen = i + 1 + numEntries; j < _jlen; j++) {
subline = lines[j];
var lineParts = line.split(/\s+/);
lineParts = subline.split(/\s+/);
var charactersToRemove = lineParts[2];

@@ -274,8 +374,8 @@

else if (ruleType === "COMPOUNDRULE") {
var numEntries = parseInt(definitionParts[1], 10);
numEntries = parseInt(definitionParts[1], 10);
for (var j = i + 1, _jlen = i + 1 + numEntries; j < _jlen; j++) {
var line = lines[j];
for (j = i + 1, _jlen = i + 1 + numEntries; j < _jlen; j++) {
line = lines[j];
var lineParts = line.split(/\s+/);
lineParts = line.split(/\s+/);
this.compoundRules.push(lineParts[1]);

@@ -287,3 +387,3 @@ }

else if (ruleType === "REP") {
var lineParts = line.split(/\s+/);
lineParts = line.split(/\s+/);

@@ -347,7 +447,13 @@ if (lineParts.length === 3) {

// Some dictionaries will list the same word multiple times with different rule sets.
if (!(word in dictionaryTable) || typeof dictionaryTable[word] != 'object') {
dictionaryTable[word] = [];
if (!dictionaryTable.hasOwnProperty(word)) {
dictionaryTable[word] = null;
}
dictionaryTable[word].push(rules);
if (rules.length > 0) {
if (dictionaryTable[word] === null) {
dictionaryTable[word] = [];
}
dictionaryTable[word].push(rules);
}
}

@@ -454,3 +560,3 @@

else if (this.flags.FLAG === "num") {
return textCode.split(",");
return textCodes.split(",");
}

@@ -524,2 +630,6 @@ },

check : function (aWord) {
if (!this.loaded) {
throw "Dictionary not loaded.";
}
// Remove leading and trailing whitespace

@@ -573,8 +683,14 @@ var trimmedWord = aWord.replace(/^\s\s*/, '').replace(/\s\s*$/, '');

checkExact : function (word) {
if (!this.loaded) {
throw "Dictionary not loaded.";
}
var ruleCodes = this.dictionaryTable[word];
var i, _len;
if (typeof ruleCodes === 'undefined') {
// Check if this might be a compound word.
if ("COMPOUNDMIN" in this.flags && word.length >= this.flags.COMPOUNDMIN) {
for (var i = 0, _len = this.compoundRules.length; i < _len; i++) {
for (i = 0, _len = this.compoundRules.length; i < _len; i++) {
if (word.match(this.compoundRules[i])) {

@@ -585,7 +701,10 @@ return true;

}
return false;
}
else if (ruleCodes === null) {
// a null (but not undefined) value for an entry in the dictionary table
// means that the word is in the dictionary but has no flags.
return true;
}
else if (typeof ruleCodes === 'object') { // this.dictionary['hasOwnProperty'] will be a function.
for (var i = 0, _len = ruleCodes.length; i < _len; i++) {
for (i = 0, _len = ruleCodes.length; i < _len; i++) {
if (!this.hasFlag(word, "ONLYINCOMPOUND", ruleCodes[i])) {

@@ -595,5 +714,5 @@ return true;

}
return false;
}
return false;
},

@@ -610,5 +729,9 @@

hasFlag : function (word, flag, wordFlags) {
if (!this.loaded) {
throw "Dictionary not loaded.";
}
if (flag in this.flags) {
if (typeof wordFlags === 'undefined') {
var wordFlags = Array.prototype.concat.apply([], this.dictionaryTable[word]);
wordFlags = Array.prototype.concat.apply([], this.dictionaryTable[word]);
}

@@ -638,3 +761,17 @@

suggest : function (word, limit) {
if (!limit) limit = 5;
if (!this.loaded) {
throw "Dictionary not loaded.";
}
limit = limit || 5;
if (this.memoized.hasOwnProperty(word)) {
var memoizedLimit = this.memoized[word]['limit'];
// Only return the cached list if it's big enough or if there weren't enough suggestions
// to fill a smaller limit.
if (limit <= memoizedLimit || this.memoized[word]['suggestions'].length < memoizedLimit) {
return this.memoized[word]['suggestions'].slice(0, limit);
}
}

@@ -683,59 +820,34 @@ if (this.check(word)) return [];

for (var ii = 0, _iilen = words.length; ii < _iilen; ii++) {
var ii, i, j, _iilen, _len, _jlen;
for (ii = 0, _iilen = words.length; ii < _iilen; ii++) {
var word = words[ii];
var splits = [];
for (var i = 0, _len = word.length + 1; i < _len; i++) {
splits.push([ word.substring(0, i), word.substring(i, word.length) ]);
}
var deletes = [];
for (var i = 0, _len = splits.length; i < _len; i++) {
var s = splits[i];
for (i = 0, _len = word.length + 1; i < _len; i++) {
var s = [ word.substring(0, i), word.substring(i) ];
if (s[1]) {
deletes.push(s[0] + s[1].substring(1));
rv.push(s[0] + s[1].substring(1));
}
}
var transposes = [];
for (var i = 0, _len = splits.length; i < _len; i++) {
var s = splits[i];
if (s[1].length > 1) {
transposes.push(s[0] + s[1][1] + s[1][0] + s[1].substring(2));
// Eliminate transpositions of identical letters
if (s[1].length > 1 && s[1][1] !== s[1][0]) {
rv.push(s[0] + s[1][1] + s[1][0] + s[1].substring(2));
}
}
var replaces = [];
for (var i = 0, _len = splits.length; i < _len; i++) {
var s = splits[i];
if (s[1]) {
for (var j = 0, _jlen = self.alphabet.length; j < _jlen; j++) {
replaces.push(s[0] + self.alphabet[j] + s[1].substring(1));
for (j = 0, _jlen = self.alphabet.length; j < _jlen; j++) {
// Eliminate replacement of a letter by itself
if (self.alphabet[j] != s[1].substring(0,1)){
rv.push(s[0] + self.alphabet[j] + s[1].substring(1));
}
}
}
}
var inserts = [];
for (var i = 0, _len = splits.length; i < _len; i++) {
var s = splits[i];
if (s[1]) {
for (var j = 0, _jlen = self.alphabet.length; j < _jlen; j++) {
replaces.push(s[0] + self.alphabet[j] + s[1]);
for (j = 0, _jlen = self.alphabet.length; j < _jlen; j++) {
rv.push(s[0] + self.alphabet[j] + s[1]);
}
}
}
rv = rv.concat(deletes);
rv = rv.concat(transposes);
rv = rv.concat(replaces);
rv = rv.concat(inserts);
}

@@ -749,3 +861,3 @@

for (var i = 0; i < words.length; i++) {
for (var i = 0, _len = words.length; i < _len; i++) {
if (self.check(words[i])) {

@@ -764,8 +876,10 @@ rv.push(words[i]);

var corrections = known(ed1).concat(known(ed2));
var corrections = known(ed1.concat(ed2));
var i, _len;
// Sort the edits based on how many different ways they were created.
var weighted_corrections = {};
for (var i = 0, _len = corrections.length; i < _len; i++) {
for (i = 0, _len = corrections.length; i < _len; i++) {
if (!(corrections[i] in weighted_corrections)) {

@@ -781,4 +895,6 @@ weighted_corrections[corrections[i]] = 1;

for (var i in weighted_corrections) {
sorted_corrections.push([ i, weighted_corrections[i] ]);
for (i in weighted_corrections) {
if (weighted_corrections.hasOwnProperty(i)) {
sorted_corrections.push([ i, weighted_corrections[i] ]);
}
}

@@ -797,4 +913,20 @@

var rv = [];
var capitalization_scheme = "lowercase";
for (var i = 0, _len = Math.min(limit, sorted_corrections.length); i < _len; i++) {
if (word.toUpperCase() === word) {
capitalization_scheme = "uppercase";
}
else if (word.substr(0, 1).toUpperCase() + word.substr(1).toLowerCase() === word) {
capitalization_scheme = "capitalized";
}
for (i = 0, _len = Math.min(limit, sorted_corrections.length); i < _len; i++) {
if ("uppercase" === capitalization_scheme) {
sorted_corrections[i][0] = sorted_corrections[i][0].toUpperCase();
}
else if ("capitalized" === capitalization_scheme) {
sorted_corrections[i][0] = sorted_corrections[i][0].substr(0, 1).toUpperCase() + sorted_corrections[i][0].substr(1);
}
if (!self.hasFlag(sorted_corrections[i][0], "NOSUGGEST")) {

@@ -808,5 +940,11 @@ rv.push(sorted_corrections[i][0]);

return correct(word);
this.memoized[word] = {
'suggestions': correct(word),
'limit': limit
};
return this.memoized[word]['suggestions'];
}
};
})();

@@ -813,0 +951,0 @@ // Support for use as a node.js module.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc