├── LICENSE ├── README.md ├── efrt-unpack.js ├── index.html └── efrt-unpack.es5.js /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 monolithpl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fraze finder 2 | Highlight collocations, chunks, idioms, phrasal verbs and semi-fixed lexical phrases in texts. Perfect for building collocation awareness in ESL students. Analyze your text [here](http://monolithpl.github.io/fraze-finder/) 3 | 4 | ### features 5 | - highlights and lists chunks in a given text 6 | - very fast lookups using a slightly modified version of [Steve Hanov's succinct bit string trie implementation](http://www.hanovsolutions.com/trie/Bits.js) 7 | - fully client-side and portable - works offline, too! 8 | - zero framework rubbish - pure vanilla javascript with zero overhead - tiny code with zero external dependencies 9 | - responsive mobile-first layout 10 | 11 | ### demo 12 | [check it out here](http://monolithpl.github.io/fraze-finder/) 13 | 14 | ### further reading 15 | Read up on the usefulness of teaching chunks / collocations in EFL classrooms here: 16 | - [Why has the lexical approach been so long in coming?](http://www.theguardian.com/education/2013/mar/26/leixical-approach-revolution) 17 | - Seth Lindstromberg: [Teaching Chunks of Language](http://www.hltmag.co.uk/dec08/idea.htm) 18 | - [Lexical Approach](https://en.wikipedia.org/wiki/Lexical_approach) 19 | - [Optimizing a Lexical Approach to Instructed Second Language Acquisition](http://www.victoria.ac.nz/lals/about/oldnews/attachments/VUW_seminar.ppt) 20 | 21 | ### implementation details 22 | Read more about performance-first string lookups in javascript using tries here: 23 | - [Succinct Data Structures: Cramming 80,000 words into a Javascript file](http://stevehanov.ca/blog/index.php?id=120) 24 | - [John Resig's Revised JavaScript Dictionary Search](http://ejohn.org/blog/revised-javascript-dictionary-search/) 25 | - [Create optimized wordlist data structures for mobile webapps](https://www.united-coders.com/christian-harms/create-optimized-wordlist-data-structures-for-mobile-webapps/) 26 | 27 | MIT License 28 | 29 | Copyright 2016-7 Wiktor Jakubczyc 30 | -------------------------------------------------------------------------------- /efrt-unpack.js: -------------------------------------------------------------------------------- 1 | /* efrt trie-compression v2.0.3 github.com/nlp-compromise/efrt - MIT */ 2 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.unpack = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= range; n -= range, places++, range *= BASE) { 22 | } 23 | while (places--) { 24 | const d = n % BASE; 25 | s = String.fromCharCode((d < 10 ? 48 : 55) + d) + s; 26 | n = (n - d) / BASE; 27 | } 28 | return s; 29 | }; 30 | 31 | 32 | const fromAlphaCode = function(s) { 33 | if (cache[s] !== undefined) { 34 | return cache[s]; 35 | } 36 | let n = 0; 37 | let places = 1; 38 | let range = BASE; 39 | let pow = 1; 40 | 41 | for (; places < s.length; n += range, places++, range *= BASE) { 42 | } 43 | for (let i = s.length - 1; i >= 0; i--, pow *= BASE) { 44 | let d = s.charCodeAt(i) - 48; 45 | if (d > 10) { 46 | d -= 7; 47 | } 48 | n += d * pow; 49 | } 50 | return n; 51 | }; 52 | 53 | module.exports = { 54 | toAlphaCode: toAlphaCode, 55 | fromAlphaCode: fromAlphaCode 56 | }; 57 | 58 | },{}],2:[function(_dereq_,module,exports){ 59 | 'use strict'; 60 | const unpack = _dereq_('./unpack'); 61 | 62 | module.exports = function(str) { 63 | //turn the weird string into a key-value object again 64 | let obj = str.split('|').reduce((h, s) => { 65 | let arr = s.split('¦'); 66 | h[arr[0]] = arr[1]; 67 | return h; 68 | }, {}); 69 | let all = {}; 70 | Object.keys(obj).forEach(function(cat) { 71 | let arr = unpack(obj[cat]); 72 | //special case, for botched-boolean 73 | if (cat === 'true') { 74 | cat = true; 75 | } 76 | for (var i = 0; i < arr.length; i++) { 77 | let k = arr[i]; 78 | if (all.hasOwnProperty(k) === true) { 79 | if (Array.isArray(all[k]) === false) { 80 | all[k] = [all[k], cat]; 81 | } else { 82 | all[k].push(cat); 83 | } 84 | } else { 85 | all[k] = cat; 86 | } 87 | } 88 | }); 89 | return all; 90 | }; 91 | 92 | },{"./unpack":4}],3:[function(_dereq_,module,exports){ 93 | 'use strict'; 94 | const encoding = _dereq_('../encoding'); 95 | 96 | //the symbols are at the top of the array. 97 | module.exports = function(t) { 98 | //... process these lines 99 | const reSymbol = new RegExp('([0-9A-Z]+):([0-9A-Z]+)'); 100 | for(let i = 0; i < t.nodes.length; i++) { 101 | const m = reSymbol.exec(t.nodes[i]); 102 | if (!m) { 103 | t.symCount = i; 104 | break; 105 | } 106 | t.syms[encoding.fromAlphaCode(m[1])] = encoding.fromAlphaCode(m[2]); 107 | } 108 | //remove from main node list 109 | t.nodes = t.nodes.slice(t.symCount, t.nodes.length); 110 | }; 111 | 112 | },{"../encoding":1}],4:[function(_dereq_,module,exports){ 113 | 'use strict'; 114 | const parseSymbols = _dereq_('./symbols'); 115 | const encoding = _dereq_('../encoding'); 116 | 117 | // References are either absolute (symbol) or relative (1 - based) 118 | const indexFromRef = function(trie, ref, index) { 119 | const dnode = encoding.fromAlphaCode(ref); 120 | if (dnode < trie.symCount) { 121 | return trie.syms[dnode]; 122 | } 123 | return index + dnode + 1 - trie.symCount; 124 | }; 125 | 126 | const toArray = function(trie) { 127 | let all = []; 128 | const crawl = (index, pref) => { 129 | let node = trie.nodes[index]; 130 | if (node[0] === '!') { 131 | all.push(pref); 132 | node = node.slice(1); //ok, we tried. remove it. 133 | } 134 | let matches = node.split(/([A-Z0-9,]+)/g); 135 | for (let i = 0; i < matches.length; i += 2) { 136 | let str = matches[i]; 137 | let ref = matches[i + 1]; 138 | if (!str) { 139 | continue; 140 | } 141 | 142 | let have = pref + str; 143 | //branch's end 144 | if (ref === ',' || ref === undefined) { 145 | all.push(have); 146 | continue; 147 | } 148 | let newIndex = indexFromRef(trie, ref, index); 149 | crawl(newIndex, have); 150 | } 151 | }; 152 | crawl(0, ''); 153 | return all; 154 | }; 155 | 156 | //PackedTrie - Trie traversal of the Trie packed-string representation. 157 | const unpack = function(str) { 158 | let trie = { 159 | nodes: str.split(';'), //that's all ;)! 160 | syms: [], 161 | symCount: 0 162 | }; 163 | //process symbols, if they have them 164 | if (str.match(':')) { 165 | parseSymbols(trie); 166 | } 167 | return toArray(trie); 168 | }; 169 | 170 | module.exports = unpack; 171 | 172 | },{"../encoding":1,"./symbols":3}]},{},[2])(2) 173 | }); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 162 | 163 |

frazefinder

164 |
165 |
166 |
167 |
168 | 169 |
170 |
171 | 172 | 173 |
174 |
expressions / collocations list
175 |
176 |
177 |
178 | 179 | 180 | 181 | 225 | -------------------------------------------------------------------------------- /efrt-unpack.es5.js: -------------------------------------------------------------------------------- 1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.unpack = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= range; n -= range, places++, range *= BASE) {} 22 | while (places--) { 23 | var d = n % BASE; 24 | s = String.fromCharCode((d < 10 ? 48 : 55) + d) + s; 25 | n = (n - d) / BASE; 26 | } 27 | return s; 28 | }; 29 | 30 | var fromAlphaCode = function fromAlphaCode(s) { 31 | if (cache[s] !== undefined) { 32 | return cache[s]; 33 | } 34 | var n = 0; 35 | var places = 1; 36 | var range = BASE; 37 | var pow = 1; 38 | 39 | for (; places < s.length; n += range, places++, range *= BASE) {} 40 | for (var i = s.length - 1; i >= 0; i--, pow *= BASE) { 41 | var d = s.charCodeAt(i) - 48; 42 | if (d > 10) { 43 | d -= 7; 44 | } 45 | n += d * pow; 46 | } 47 | return n; 48 | }; 49 | 50 | module.exports = { 51 | toAlphaCode: toAlphaCode, 52 | fromAlphaCode: fromAlphaCode 53 | }; 54 | 55 | },{}],2:[function(_dereq_,module,exports){ 56 | 'use strict'; 57 | 58 | var unpack = _dereq_('./unpack'); 59 | 60 | module.exports = function (str) { 61 | //turn the weird string into a key-value object again 62 | var obj = str.split('|').reduce(function (h, s) { 63 | var arr = s.split('¦'); 64 | h[arr[0]] = arr[1]; 65 | return h; 66 | }, {}); 67 | var all = {}; 68 | Object.keys(obj).forEach(function (cat) { 69 | var arr = unpack(obj[cat]); 70 | //special case, for botched-boolean 71 | if (cat === 'true') { 72 | cat = true; 73 | } 74 | for (var i = 0; i < arr.length; i++) { 75 | var k = arr[i]; 76 | if (all.hasOwnProperty(k) === true) { 77 | if (Array.isArray(all[k]) === false) { 78 | all[k] = [all[k], cat]; 79 | } else { 80 | all[k].push(cat); 81 | } 82 | } else { 83 | all[k] = cat; 84 | } 85 | } 86 | }); 87 | return all; 88 | }; 89 | 90 | },{"./unpack":4}],3:[function(_dereq_,module,exports){ 91 | 'use strict'; 92 | 93 | var encoding = _dereq_('../encoding'); 94 | 95 | //the symbols are at the top of the array. 96 | module.exports = function (t) { 97 | //... process these lines 98 | var reSymbol = new RegExp('([0-9A-Z]+):([0-9A-Z]+)'); 99 | for (var i = 0; i < t.nodes.length; i++) { 100 | var m = reSymbol.exec(t.nodes[i]); 101 | if (!m) { 102 | t.symCount = i; 103 | break; 104 | } 105 | t.syms[encoding.fromAlphaCode(m[1])] = encoding.fromAlphaCode(m[2]); 106 | } 107 | //remove from main node list 108 | t.nodes = t.nodes.slice(t.symCount, t.nodes.length); 109 | }; 110 | 111 | },{"../encoding":1}],4:[function(_dereq_,module,exports){ 112 | 'use strict'; 113 | 114 | var parseSymbols = _dereq_('./symbols'); 115 | var encoding = _dereq_('../encoding'); 116 | 117 | // References are either absolute (symbol) or relative (1 - based) 118 | var indexFromRef = function indexFromRef(trie, ref, index) { 119 | var dnode = encoding.fromAlphaCode(ref); 120 | if (dnode < trie.symCount) { 121 | return trie.syms[dnode]; 122 | } 123 | return index + dnode + 1 - trie.symCount; 124 | }; 125 | 126 | var toArray = function toArray(trie) { 127 | var all = []; 128 | var crawl = function crawl(index, pref) { 129 | var node = trie.nodes[index]; 130 | if (node[0] === '!') { 131 | all.push(pref); 132 | node = node.slice(1); //ok, we tried. remove it. 133 | } 134 | var matches = node.split(/([A-Z0-9,]+)/g); 135 | for (var i = 0; i < matches.length; i += 2) { 136 | var str = matches[i]; 137 | var ref = matches[i + 1]; 138 | if (!str) { 139 | continue; 140 | } 141 | 142 | var have = pref + str; 143 | //branch's end 144 | if (ref === ',' || ref === undefined) { 145 | all.push(have); 146 | continue; 147 | } 148 | var newIndex = indexFromRef(trie, ref, index); 149 | crawl(newIndex, have); 150 | } 151 | }; 152 | crawl(0, ''); 153 | return all; 154 | }; 155 | 156 | //PackedTrie - Trie traversal of the Trie packed-string representation. 157 | var unpack = function unpack(str) { 158 | var trie = { 159 | nodes: str.split(';'), //that's all ;)! 160 | syms: [], 161 | symCount: 0 162 | }; 163 | //process symbols, if they have them 164 | if (str.match(':')) { 165 | parseSymbols(trie); 166 | } 167 | return toArray(trie); 168 | }; 169 | 170 | module.exports = unpack; 171 | 172 | },{"../encoding":1,"./symbols":3}]},{},[2])(2) 173 | });(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.unpack = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= range; n -= range, places++, range *= BASE) {} 194 | while (places--) { 195 | var d = n % BASE; 196 | s = String.fromCharCode((d < 10 ? 48 : 55) + d) + s; 197 | n = (n - d) / BASE; 198 | } 199 | return s; 200 | }; 201 | 202 | var fromAlphaCode = function fromAlphaCode(s) { 203 | if (cache[s] !== undefined) { 204 | return cache[s]; 205 | } 206 | var n = 0; 207 | var places = 1; 208 | var range = BASE; 209 | var pow = 1; 210 | 211 | for (; places < s.length; n += range, places++, range *= BASE) {} 212 | for (var i = s.length - 1; i >= 0; i--, pow *= BASE) { 213 | var d = s.charCodeAt(i) - 48; 214 | if (d > 10) { 215 | d -= 7; 216 | } 217 | n += d * pow; 218 | } 219 | return n; 220 | }; 221 | 222 | module.exports = { 223 | toAlphaCode: toAlphaCode, 224 | fromAlphaCode: fromAlphaCode 225 | }; 226 | 227 | },{}],2:[function(_dereq_,module,exports){ 228 | 'use strict'; 229 | 230 | var unpack = _dereq_('./unpack'); 231 | 232 | module.exports = function (str) { 233 | //turn the weird string into a key-value object again 234 | var obj = str.split('|').reduce(function (h, s) { 235 | var arr = s.split('¦'); 236 | h[arr[0]] = arr[1]; 237 | return h; 238 | }, {}); 239 | var all = {}; 240 | Object.keys(obj).forEach(function (cat) { 241 | var arr = unpack(obj[cat]); 242 | //special case, for botched-boolean 243 | if (cat === 'true') { 244 | cat = true; 245 | } 246 | for (var i = 0; i < arr.length; i++) { 247 | var k = arr[i]; 248 | if (all.hasOwnProperty(k) === true) { 249 | if (Array.isArray(all[k]) === false) { 250 | all[k] = [all[k], cat]; 251 | } else { 252 | all[k].push(cat); 253 | } 254 | } else { 255 | all[k] = cat; 256 | } 257 | } 258 | }); 259 | return all; 260 | }; 261 | 262 | },{"./unpack":4}],3:[function(_dereq_,module,exports){ 263 | 'use strict'; 264 | 265 | var encoding = _dereq_('../encoding'); 266 | 267 | //the symbols are at the top of the array. 268 | module.exports = function (t) { 269 | //... process these lines 270 | var reSymbol = new RegExp('([0-9A-Z]+):([0-9A-Z]+)'); 271 | for (var i = 0; i < t.nodes.length; i++) { 272 | var m = reSymbol.exec(t.nodes[i]); 273 | if (!m) { 274 | t.symCount = i; 275 | break; 276 | } 277 | t.syms[encoding.fromAlphaCode(m[1])] = encoding.fromAlphaCode(m[2]); 278 | } 279 | //remove from main node list 280 | t.nodes = t.nodes.slice(t.symCount, t.nodes.length); 281 | }; 282 | 283 | },{"../encoding":1}],4:[function(_dereq_,module,exports){ 284 | 'use strict'; 285 | 286 | var parseSymbols = _dereq_('./symbols'); 287 | var encoding = _dereq_('../encoding'); 288 | 289 | // References are either absolute (symbol) or relative (1 - based) 290 | var indexFromRef = function indexFromRef(trie, ref, index) { 291 | var dnode = encoding.fromAlphaCode(ref); 292 | if (dnode < trie.symCount) { 293 | return trie.syms[dnode]; 294 | } 295 | return index + dnode + 1 - trie.symCount; 296 | }; 297 | 298 | var toArray = function toArray(trie) { 299 | var all = []; 300 | var crawl = function crawl(index, pref) { 301 | var node = trie.nodes[index]; 302 | if (node[0] === '!') { 303 | all.push(pref); 304 | node = node.slice(1); //ok, we tried. remove it. 305 | } 306 | var matches = node.split(/([A-Z0-9,]+)/g); 307 | for (var i = 0; i < matches.length; i += 2) { 308 | var str = matches[i]; 309 | var ref = matches[i + 1]; 310 | if (!str) { 311 | continue; 312 | } 313 | 314 | var have = pref + str; 315 | //branch's end 316 | if (ref === ',' || ref === undefined) { 317 | all.push(have); 318 | continue; 319 | } 320 | var newIndex = indexFromRef(trie, ref, index); 321 | crawl(newIndex, have); 322 | } 323 | }; 324 | crawl(0, ''); 325 | return all; 326 | }; 327 | 328 | //PackedTrie - Trie traversal of the Trie packed-string representation. 329 | var unpack = function unpack(str) { 330 | var trie = { 331 | nodes: str.split(';'), //that's all ;)! 332 | syms: [], 333 | symCount: 0 334 | }; 335 | //process symbols, if they have them 336 | if (str.match(':')) { 337 | parseSymbols(trie); 338 | } 339 | return toArray(trie); 340 | }; 341 | 342 | module.exports = unpack; 343 | 344 | },{"../encoding":1,"./symbols":3}]},{},[2])(2) 345 | });(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.unpack = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= range; n -= range, places++, range *= BASE) {} 366 | while (places--) { 367 | var d = n % BASE; 368 | s = String.fromCharCode((d < 10 ? 48 : 55) + d) + s; 369 | n = (n - d) / BASE; 370 | } 371 | return s; 372 | }; 373 | 374 | var fromAlphaCode = function fromAlphaCode(s) { 375 | if (cache[s] !== undefined) { 376 | return cache[s]; 377 | } 378 | var n = 0; 379 | var places = 1; 380 | var range = BASE; 381 | var pow = 1; 382 | 383 | for (; places < s.length; n += range, places++, range *= BASE) {} 384 | for (var i = s.length - 1; i >= 0; i--, pow *= BASE) { 385 | var d = s.charCodeAt(i) - 48; 386 | if (d > 10) { 387 | d -= 7; 388 | } 389 | n += d * pow; 390 | } 391 | return n; 392 | }; 393 | 394 | module.exports = { 395 | toAlphaCode: toAlphaCode, 396 | fromAlphaCode: fromAlphaCode 397 | }; 398 | 399 | },{}],2:[function(_dereq_,module,exports){ 400 | 'use strict'; 401 | 402 | var unpack = _dereq_('./unpack'); 403 | 404 | module.exports = function (str) { 405 | //turn the weird string into a key-value object again 406 | var obj = str.split('|').reduce(function (h, s) { 407 | var arr = s.split('¦'); 408 | h[arr[0]] = arr[1]; 409 | return h; 410 | }, {}); 411 | var all = {}; 412 | Object.keys(obj).forEach(function (cat) { 413 | var arr = unpack(obj[cat]); 414 | //special case, for botched-boolean 415 | if (cat === 'true') { 416 | cat = true; 417 | } 418 | for (var i = 0; i < arr.length; i++) { 419 | var k = arr[i]; 420 | if (all.hasOwnProperty(k) === true) { 421 | if (Array.isArray(all[k]) === false) { 422 | all[k] = [all[k], cat]; 423 | } else { 424 | all[k].push(cat); 425 | } 426 | } else { 427 | all[k] = cat; 428 | } 429 | } 430 | }); 431 | return all; 432 | }; 433 | 434 | },{"./unpack":4}],3:[function(_dereq_,module,exports){ 435 | 'use strict'; 436 | 437 | var encoding = _dereq_('../encoding'); 438 | 439 | //the symbols are at the top of the array. 440 | module.exports = function (t) { 441 | //... process these lines 442 | var reSymbol = new RegExp('([0-9A-Z]+):([0-9A-Z]+)'); 443 | for (var i = 0; i < t.nodes.length; i++) { 444 | var m = reSymbol.exec(t.nodes[i]); 445 | if (!m) { 446 | t.symCount = i; 447 | break; 448 | } 449 | t.syms[encoding.fromAlphaCode(m[1])] = encoding.fromAlphaCode(m[2]); 450 | } 451 | //remove from main node list 452 | t.nodes = t.nodes.slice(t.symCount, t.nodes.length); 453 | }; 454 | 455 | },{"../encoding":1}],4:[function(_dereq_,module,exports){ 456 | 'use strict'; 457 | 458 | var parseSymbols = _dereq_('./symbols'); 459 | var encoding = _dereq_('../encoding'); 460 | 461 | // References are either absolute (symbol) or relative (1 - based) 462 | var indexFromRef = function indexFromRef(trie, ref, index) { 463 | var dnode = encoding.fromAlphaCode(ref); 464 | if (dnode < trie.symCount) { 465 | return trie.syms[dnode]; 466 | } 467 | return index + dnode + 1 - trie.symCount; 468 | }; 469 | 470 | var toArray = function toArray(trie) { 471 | var all = []; 472 | var crawl = function crawl(index, pref) { 473 | var node = trie.nodes[index]; 474 | if (node[0] === '!') { 475 | all.push(pref); 476 | node = node.slice(1); //ok, we tried. remove it. 477 | } 478 | var matches = node.split(/([A-Z0-9,]+)/g); 479 | for (var i = 0; i < matches.length; i += 2) { 480 | var str = matches[i]; 481 | var ref = matches[i + 1]; 482 | if (!str) { 483 | continue; 484 | } 485 | 486 | var have = pref + str; 487 | //branch's end 488 | if (ref === ',' || ref === undefined) { 489 | all.push(have); 490 | continue; 491 | } 492 | var newIndex = indexFromRef(trie, ref, index); 493 | crawl(newIndex, have); 494 | } 495 | }; 496 | crawl(0, ''); 497 | return all; 498 | }; 499 | 500 | //PackedTrie - Trie traversal of the Trie packed-string representation. 501 | var unpack = function unpack(str) { 502 | var trie = { 503 | nodes: str.split(';'), //that's all ;)! 504 | syms: [], 505 | symCount: 0 506 | }; 507 | //process symbols, if they have them 508 | if (str.match(':')) { 509 | parseSymbols(trie); 510 | } 511 | return toArray(trie); 512 | }; 513 | 514 | module.exports = unpack; 515 | 516 | },{"../encoding":1,"./symbols":3}]},{},[2])(2) 517 | });(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.unpack = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= range; n -= range, places++, range *= BASE) {} 538 | while (places--) { 539 | var d = n % BASE; 540 | s = String.fromCharCode((d < 10 ? 48 : 55) + d) + s; 541 | n = (n - d) / BASE; 542 | } 543 | return s; 544 | }; 545 | 546 | var fromAlphaCode = function fromAlphaCode(s) { 547 | if (cache[s] !== undefined) { 548 | return cache[s]; 549 | } 550 | var n = 0; 551 | var places = 1; 552 | var range = BASE; 553 | var pow = 1; 554 | 555 | for (; places < s.length; n += range, places++, range *= BASE) {} 556 | for (var i = s.length - 1; i >= 0; i--, pow *= BASE) { 557 | var d = s.charCodeAt(i) - 48; 558 | if (d > 10) { 559 | d -= 7; 560 | } 561 | n += d * pow; 562 | } 563 | return n; 564 | }; 565 | 566 | module.exports = { 567 | toAlphaCode: toAlphaCode, 568 | fromAlphaCode: fromAlphaCode 569 | }; 570 | 571 | },{}],2:[function(_dereq_,module,exports){ 572 | 'use strict'; 573 | 574 | var unpack = _dereq_('./unpack'); 575 | 576 | module.exports = function (str) { 577 | //turn the weird string into a key-value object again 578 | var obj = str.split('|').reduce(function (h, s) { 579 | var arr = s.split('¦'); 580 | h[arr[0]] = arr[1]; 581 | return h; 582 | }, {}); 583 | var all = {}; 584 | Object.keys(obj).forEach(function (cat) { 585 | var arr = unpack(obj[cat]); 586 | //special case, for botched-boolean 587 | if (cat === 'true') { 588 | cat = true; 589 | } 590 | for (var i = 0; i < arr.length; i++) { 591 | var k = arr[i]; 592 | if (all.hasOwnProperty(k) === true) { 593 | if (Array.isArray(all[k]) === false) { 594 | all[k] = [all[k], cat]; 595 | } else { 596 | all[k].push(cat); 597 | } 598 | } else { 599 | all[k] = cat; 600 | } 601 | } 602 | }); 603 | return all; 604 | }; 605 | 606 | },{"./unpack":4}],3:[function(_dereq_,module,exports){ 607 | 'use strict'; 608 | 609 | var encoding = _dereq_('../encoding'); 610 | 611 | //the symbols are at the top of the array. 612 | module.exports = function (t) { 613 | //... process these lines 614 | var reSymbol = new RegExp('([0-9A-Z]+):([0-9A-Z]+)'); 615 | for (var i = 0; i < t.nodes.length; i++) { 616 | var m = reSymbol.exec(t.nodes[i]); 617 | if (!m) { 618 | t.symCount = i; 619 | break; 620 | } 621 | t.syms[encoding.fromAlphaCode(m[1])] = encoding.fromAlphaCode(m[2]); 622 | } 623 | //remove from main node list 624 | t.nodes = t.nodes.slice(t.symCount, t.nodes.length); 625 | }; 626 | 627 | },{"../encoding":1}],4:[function(_dereq_,module,exports){ 628 | 'use strict'; 629 | 630 | var parseSymbols = _dereq_('./symbols'); 631 | var encoding = _dereq_('../encoding'); 632 | 633 | // References are either absolute (symbol) or relative (1 - based) 634 | var indexFromRef = function indexFromRef(trie, ref, index) { 635 | var dnode = encoding.fromAlphaCode(ref); 636 | if (dnode < trie.symCount) { 637 | return trie.syms[dnode]; 638 | } 639 | return index + dnode + 1 - trie.symCount; 640 | }; 641 | 642 | var toArray = function toArray(trie) { 643 | var all = []; 644 | var crawl = function crawl(index, pref) { 645 | var node = trie.nodes[index]; 646 | if (node[0] === '!') { 647 | all.push(pref); 648 | node = node.slice(1); //ok, we tried. remove it. 649 | } 650 | var matches = node.split(/([A-Z0-9,]+)/g); 651 | for (var i = 0; i < matches.length; i += 2) { 652 | var str = matches[i]; 653 | var ref = matches[i + 1]; 654 | if (!str) { 655 | continue; 656 | } 657 | 658 | var have = pref + str; 659 | //branch's end 660 | if (ref === ',' || ref === undefined) { 661 | all.push(have); 662 | continue; 663 | } 664 | var newIndex = indexFromRef(trie, ref, index); 665 | crawl(newIndex, have); 666 | } 667 | }; 668 | crawl(0, ''); 669 | return all; 670 | }; 671 | 672 | //PackedTrie - Trie traversal of the Trie packed-string representation. 673 | var unpack = function unpack(str) { 674 | var trie = { 675 | nodes: str.split(';'), //that's all ;)! 676 | syms: [], 677 | symCount: 0 678 | }; 679 | //process symbols, if they have them 680 | if (str.match(':')) { 681 | parseSymbols(trie); 682 | } 683 | return toArray(trie); 684 | }; 685 | 686 | module.exports = unpack; 687 | 688 | },{"../encoding":1,"./symbols":3}]},{},[2])(2) 689 | });(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.unpack = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= range; n -= range, places++, range *= BASE) {} 710 | while (places--) { 711 | var d = n % BASE; 712 | s = String.fromCharCode((d < 10 ? 48 : 55) + d) + s; 713 | n = (n - d) / BASE; 714 | } 715 | return s; 716 | }; 717 | 718 | var fromAlphaCode = function fromAlphaCode(s) { 719 | if (cache[s] !== undefined) { 720 | return cache[s]; 721 | } 722 | var n = 0; 723 | var places = 1; 724 | var range = BASE; 725 | var pow = 1; 726 | 727 | for (; places < s.length; n += range, places++, range *= BASE) {} 728 | for (var i = s.length - 1; i >= 0; i--, pow *= BASE) { 729 | var d = s.charCodeAt(i) - 48; 730 | if (d > 10) { 731 | d -= 7; 732 | } 733 | n += d * pow; 734 | } 735 | return n; 736 | }; 737 | 738 | module.exports = { 739 | toAlphaCode: toAlphaCode, 740 | fromAlphaCode: fromAlphaCode 741 | }; 742 | 743 | },{}],2:[function(_dereq_,module,exports){ 744 | 'use strict'; 745 | 746 | var unpack = _dereq_('./unpack'); 747 | 748 | module.exports = function (str) { 749 | //turn the weird string into a key-value object again 750 | var obj = str.split('|').reduce(function (h, s) { 751 | var arr = s.split('¦'); 752 | h[arr[0]] = arr[1]; 753 | return h; 754 | }, {}); 755 | var all = {}; 756 | Object.keys(obj).forEach(function (cat) { 757 | var arr = unpack(obj[cat]); 758 | //special case, for botched-boolean 759 | if (cat === 'true') { 760 | cat = true; 761 | } 762 | for (var i = 0; i < arr.length; i++) { 763 | var k = arr[i]; 764 | if (all.hasOwnProperty(k) === true) { 765 | if (Array.isArray(all[k]) === false) { 766 | all[k] = [all[k], cat]; 767 | } else { 768 | all[k].push(cat); 769 | } 770 | } else { 771 | all[k] = cat; 772 | } 773 | } 774 | }); 775 | return all; 776 | }; 777 | 778 | },{"./unpack":4}],3:[function(_dereq_,module,exports){ 779 | 'use strict'; 780 | 781 | var encoding = _dereq_('../encoding'); 782 | 783 | //the symbols are at the top of the array. 784 | module.exports = function (t) { 785 | //... process these lines 786 | var reSymbol = new RegExp('([0-9A-Z]+):([0-9A-Z]+)'); 787 | for (var i = 0; i < t.nodes.length; i++) { 788 | var m = reSymbol.exec(t.nodes[i]); 789 | if (!m) { 790 | t.symCount = i; 791 | break; 792 | } 793 | t.syms[encoding.fromAlphaCode(m[1])] = encoding.fromAlphaCode(m[2]); 794 | } 795 | //remove from main node list 796 | t.nodes = t.nodes.slice(t.symCount, t.nodes.length); 797 | }; 798 | 799 | },{"../encoding":1}],4:[function(_dereq_,module,exports){ 800 | 'use strict'; 801 | 802 | var parseSymbols = _dereq_('./symbols'); 803 | var encoding = _dereq_('../encoding'); 804 | 805 | // References are either absolute (symbol) or relative (1 - based) 806 | var indexFromRef = function indexFromRef(trie, ref, index) { 807 | var dnode = encoding.fromAlphaCode(ref); 808 | if (dnode < trie.symCount) { 809 | return trie.syms[dnode]; 810 | } 811 | return index + dnode + 1 - trie.symCount; 812 | }; 813 | 814 | var toArray = function toArray(trie) { 815 | var all = []; 816 | var crawl = function crawl(index, pref) { 817 | var node = trie.nodes[index]; 818 | if (node[0] === '!') { 819 | all.push(pref); 820 | node = node.slice(1); //ok, we tried. remove it. 821 | } 822 | var matches = node.split(/([A-Z0-9,]+)/g); 823 | for (var i = 0; i < matches.length; i += 2) { 824 | var str = matches[i]; 825 | var ref = matches[i + 1]; 826 | if (!str) { 827 | continue; 828 | } 829 | 830 | var have = pref + str; 831 | //branch's end 832 | if (ref === ',' || ref === undefined) { 833 | all.push(have); 834 | continue; 835 | } 836 | var newIndex = indexFromRef(trie, ref, index); 837 | crawl(newIndex, have); 838 | } 839 | }; 840 | crawl(0, ''); 841 | return all; 842 | }; 843 | 844 | //PackedTrie - Trie traversal of the Trie packed-string representation. 845 | var unpack = function unpack(str) { 846 | var trie = { 847 | nodes: str.split(';'), //that's all ;)! 848 | syms: [], 849 | symCount: 0 850 | }; 851 | //process symbols, if they have them 852 | if (str.match(':')) { 853 | parseSymbols(trie); 854 | } 855 | return toArray(trie); 856 | }; 857 | 858 | module.exports = unpack; 859 | 860 | },{"../encoding":1,"./symbols":3}]},{},[2])(2) 861 | });(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.unpack = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= range; n -= range, places++, range *= BASE) {} 882 | while (places--) { 883 | var d = n % BASE; 884 | s = String.fromCharCode((d < 10 ? 48 : 55) + d) + s; 885 | n = (n - d) / BASE; 886 | } 887 | return s; 888 | }; 889 | 890 | var fromAlphaCode = function fromAlphaCode(s) { 891 | if (cache[s] !== undefined) { 892 | return cache[s]; 893 | } 894 | var n = 0; 895 | var places = 1; 896 | var range = BASE; 897 | var pow = 1; 898 | 899 | for (; places < s.length; n += range, places++, range *= BASE) {} 900 | for (var i = s.length - 1; i >= 0; i--, pow *= BASE) { 901 | var d = s.charCodeAt(i) - 48; 902 | if (d > 10) { 903 | d -= 7; 904 | } 905 | n += d * pow; 906 | } 907 | return n; 908 | }; 909 | 910 | module.exports = { 911 | toAlphaCode: toAlphaCode, 912 | fromAlphaCode: fromAlphaCode 913 | }; 914 | 915 | },{}],2:[function(_dereq_,module,exports){ 916 | 'use strict'; 917 | 918 | var unpack = _dereq_('./unpack'); 919 | 920 | module.exports = function (str) { 921 | //turn the weird string into a key-value object again 922 | var obj = str.split('|').reduce(function (h, s) { 923 | var arr = s.split('¦'); 924 | h[arr[0]] = arr[1]; 925 | return h; 926 | }, {}); 927 | var all = {}; 928 | Object.keys(obj).forEach(function (cat) { 929 | var arr = unpack(obj[cat]); 930 | //special case, for botched-boolean 931 | if (cat === 'true') { 932 | cat = true; 933 | } 934 | for (var i = 0; i < arr.length; i++) { 935 | var k = arr[i]; 936 | if (all.hasOwnProperty(k) === true) { 937 | if (Array.isArray(all[k]) === false) { 938 | all[k] = [all[k], cat]; 939 | } else { 940 | all[k].push(cat); 941 | } 942 | } else { 943 | all[k] = cat; 944 | } 945 | } 946 | }); 947 | return all; 948 | }; 949 | 950 | },{"./unpack":4}],3:[function(_dereq_,module,exports){ 951 | 'use strict'; 952 | 953 | var encoding = _dereq_('../encoding'); 954 | 955 | //the symbols are at the top of the array. 956 | module.exports = function (t) { 957 | //... process these lines 958 | var reSymbol = new RegExp('([0-9A-Z]+):([0-9A-Z]+)'); 959 | for (var i = 0; i < t.nodes.length; i++) { 960 | var m = reSymbol.exec(t.nodes[i]); 961 | if (!m) { 962 | t.symCount = i; 963 | break; 964 | } 965 | t.syms[encoding.fromAlphaCode(m[1])] = encoding.fromAlphaCode(m[2]); 966 | } 967 | //remove from main node list 968 | t.nodes = t.nodes.slice(t.symCount, t.nodes.length); 969 | }; 970 | 971 | },{"../encoding":1}],4:[function(_dereq_,module,exports){ 972 | 'use strict'; 973 | 974 | var parseSymbols = _dereq_('./symbols'); 975 | var encoding = _dereq_('../encoding'); 976 | 977 | // References are either absolute (symbol) or relative (1 - based) 978 | var indexFromRef = function indexFromRef(trie, ref, index) { 979 | var dnode = encoding.fromAlphaCode(ref); 980 | if (dnode < trie.symCount) { 981 | return trie.syms[dnode]; 982 | } 983 | return index + dnode + 1 - trie.symCount; 984 | }; 985 | 986 | var toArray = function toArray(trie) { 987 | var all = []; 988 | var crawl = function crawl(index, pref) { 989 | var node = trie.nodes[index]; 990 | if (node[0] === '!') { 991 | all.push(pref); 992 | node = node.slice(1); //ok, we tried. remove it. 993 | } 994 | var matches = node.split(/([A-Z0-9,]+)/g); 995 | for (var i = 0; i < matches.length; i += 2) { 996 | var str = matches[i]; 997 | var ref = matches[i + 1]; 998 | if (!str) { 999 | continue; 1000 | } 1001 | 1002 | var have = pref + str; 1003 | //branch's end 1004 | if (ref === ',' || ref === undefined) { 1005 | all.push(have); 1006 | continue; 1007 | } 1008 | var newIndex = indexFromRef(trie, ref, index); 1009 | crawl(newIndex, have); 1010 | } 1011 | }; 1012 | crawl(0, ''); 1013 | return all; 1014 | }; 1015 | 1016 | //PackedTrie - Trie traversal of the Trie packed-string representation. 1017 | var unpack = function unpack(str) { 1018 | var trie = { 1019 | nodes: str.split(';'), //that's all ;)! 1020 | syms: [], 1021 | symCount: 0 1022 | }; 1023 | //process symbols, if they have them 1024 | if (str.match(':')) { 1025 | parseSymbols(trie); 1026 | } 1027 | return toArray(trie); 1028 | }; 1029 | 1030 | module.exports = unpack; 1031 | 1032 | },{"../encoding":1,"./symbols":3}]},{},[2])(2) 1033 | }); --------------------------------------------------------------------------------