| 34 | * @return {object} a dictionary module |
| 35 | */ |
| 36 | var spell = function dictionary(dict_store) { |
| 37 | var dict = |
| 38 | dict_store && typeof dict_store.get === 'function' ? dict_store.get() : {} |
| 39 | , noop = function(){} |
| 40 | , alphabet = "abcdefghijklmnopqrstuvwxyz".split("") |
| 41 | ; |
| 42 | |
| 43 | function spell_store(cb) { |
| 44 | if (dict_store && typeof dict_store.store === 'function') { |
| 45 | dict_store.store(dict, cb); |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | function spell_train(corpus,regex) { |
| 50 | var match, word; |
| 51 | regex = regex || /[a-z]+/g; |
| 52 | corpus = corpus.toLowerCase(); |
| 53 | while ((match = regex.exec(corpus))) { |
| 54 | word = match[0]; |
| 55 | spell_add_word(word, 1); |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | function spell_edits(word, alphabetOverride) { |
| 60 | var edits = [] |
| 61 | , thisAlphabet = alphabetOverride ? alphabetOverride : alphabet |
| 62 | , i |
| 63 | , j |
| 64 | ; |
| 65 | for (i=0; i < word.length; i++) { // deletion |
| 66 | edits.push(word.slice(0, i) + word.slice(i+1)); |
| 67 | } |
| 68 | for (i=0; i < word.length-1; i++) { // transposition |
| 69 | edits.push( word.slice(0, i) + word.slice(i+1, i+2) + |
| 70 | word.slice(i, i+1) + word.slice(i+2)); |
| 71 | } |
| 72 | for (i=0; i < word.length; i++) { // alteration |
| 73 | for(j in thisAlphabet) { |
| 74 | edits.push(word.slice(0, i) + thisAlphabet[j] + word.slice(i+1)); |
| 75 | } |
| 76 | } |
| 77 | for (i=0; i <= word.length; i++) { // insertion |
| 78 | for(j in thisAlphabet) { |
| 79 | edits.push(word.slice(0, i) + thisAlphabet[j] + word.slice(i)); |
| 80 | } |
| 81 | } |
| 82 | return edits; |
| 83 | } |
| 84 | |
| 85 | function is_empty(obj) { |
| 86 | for (var key in obj) { if (obj.hasOwnProperty(key)) return false; } |
| 87 | return true; |
| 88 | } |
| 89 | |
| 90 | function spell_order(candidates, min, max) { |
| 91 | var ordered_candidates = [] |
| 92 | , current |
| 93 | , i |