-
Notifications
You must be signed in to change notification settings - Fork 35
/
coverage.html
359 lines (311 loc) · 175 KB
/
coverage.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
<!DOCTYPE html><html><head><title>Coverage</title><meta charset="utf-8"><script>
headings = [];
onload = function(){
headings = document.querySelectorAll('h2');
};
onscroll = function(e){
var heading = find(window.scrollY);
if (!heading) return;
var links = document.querySelectorAll('#menu a')
, link;
for (var i = 0, len = links.length; i < len; ++i) {
link = links[i];
link.className = link.getAttribute('href') == '#' + heading.id
? 'active'
: '';
}
};
function find(y) {
var i = headings.length
, heading;
while (i--) {
heading = headings[i];
if (y >= heading.offsetTop) {
return heading;
}
}
}
</script>
<style>
body {
font: 14px/1.6 "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 0;
color: #2C2C2C;
border-top: 2px solid #ddd;
}
#coverage {
padding: 60px 400px 60px 60px;
}
h1 a {
color: inherit;
font-weight: inherit;
}
h1 a:hover {
text-decoration: none;
}
.onload h1 {
opacity: 1;
}
h2 {
width: 80%;
margin-top: 80px;
margin-bottom: 0;
font-weight: 100;
letter-spacing: 1px;
border-bottom: 1px solid #eee;
}
a {
color: #8A6343;
font-weight: bold;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
ul {
margin-top: 20px;
padding: 0 15px;
width: 100%;
}
ul li {
float: left;
width: 40%;
margin-top: 5px;
margin-right: 60px;
list-style: none;
border-bottom: 1px solid #eee;
padding: 5px 0;
font-size: 12px;
}
ul::after {
content: '.';
height: 0;
display: block;
visibility: hidden;
clear: both;
}
code {
font: 12px monaco, monospace;
}
pre {
margin: 30px;
padding: 30px;
border: 1px solid #eee;
border-bottom-color: #ddd;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
-webkit-box-shadow: inset 0 0 10px #eee;
-moz-box-shadow: inset 0 0 10px #eee;
box-shadow: inset 0 0 10px #eee;
overflow-x: auto;
}
img {
margin: 30px;
padding: 1px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
-webkit-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
-moz-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
max-width: 100%;
}
footer {
background: #eee;
width: 100%;
padding: 50px 0;
text-align: right;
border-top: 1px solid #ddd;
}
footer span {
display: block;
margin-right: 30px;
color: #888;
font-size: 12px;
}
#menu {
position: fixed;
font-size: 12px;
overflow-y: auto;
top: 0;
right: 0;
margin: 0;
height: 100%;
padding: 15px 0;
text-align: right;
border-left: 1px solid #eee;
max-width: 400px;
overflow: auto;
white-space: nowrap;
-moz-box-shadow: 0 0 2px #888
, inset 5px 0 20px rgba(0,0,0,.5)
, inset 5px 0 3px rgba(0,0,0,.3);
-webkit-box-shadow: 0 0 2px #888
, inset 5px 0 20px rgba(0,0,0,.5)
, inset 5px 0 3px rgba(0,0,0,.3);
box-shadow: 0 0 2px #888
, inset 5px 0 20px rgba(0,0,0,.5)
, inset 5px 0 3px rgba(0,0,0,.3);
-webkit-font-smoothing: antialiased;
background: url("data:image/png;base64,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");
}
#menu::after {
display: block;
content: '';
padding-top: 80px;
}
#logo {
position: fixed;
bottom: 10px;
right: 10px;
background: rgba(255,255,255,.1);
font-size: 11px;
display: block;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
border-radius: 20px;
-webkit-box-shadow: 0 0 3px rgba(0,0,0,.2);
-moz-box-shadow: 0 0 3px rgba(0,0,0,.2);
box-shadow: 0 0 3px rgba(0,0,0,.2);
color: inherit;
}
#menu li a {
display: block;
color: white;
padding: 0 35px 0 25px;
-webkit-transition: background 300ms;
-moz-transition: background 300ms;
}
#menu li {
position: relative;
list-style: none;
}
#menu a:hover,
#menu a.active {
text-decoration: none;
background: rgba(255,255,255,.1);
}
#menu li:hover .cov {
opacity: 1;
}
#menu li .dirname {
opacity: .60;
padding-right: 2px;
}
#menu li .basename {
opacity: 1;
}
#menu .cov {
background: rgba(0,0,0,.4);
position: absolute;
top: 0;
right: 8px;
font-size: 9px;
opacity: .6;
text-align: left;
width: 17px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
padding: 2px 3px;
text-align: center;
}
#stats:nth-child(2n) {
display: inline-block;
margin-top: 15px;
border: 1px solid #eee;
padding: 10px;
-webkit-box-shadow: inset 0 0 2px #eee;
-moz-box-shadow: inset 0 0 2px #eee;
box-shadow: inset 0 0 2px #eee;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
#stats div {
float: left;
padding: 0 5px;
}
#stats::after {
display: block;
content: '';
clear: both;
}
#stats .sloc::after {
content: ' SLOC';
color: #b6b6b6;
}
#stats .percentage::after {
content: ' coverage';
color: #b6b6b6;
}
#stats .hits,
#stats .misses {
display: none;
}
.high {
color: #00d4b4;
}
.medium {
color: #e87d0d;
}
.low {
color: #d4081a;
}
.terrible {
color: #d4081a;
font-weight: bold;
}
table {
width: 80%;
margin-top: 10px;
border-collapse: collapse;
border: 1px solid #cbcbcb;
color: #363636;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
table thead {
display: none;
}
table td.line,
table td.hits {
width: 20px;
background: #eaeaea;
text-align: center;
font-size: 11px;
padding: 0 10px;
color: #949494;
}
table td.hits {
width: 10px;
padding: 2px 5px;
color: rgba(0,0,0,.2);
background: #f0f0f0;
}
tr.miss td.line,
tr.miss td.hits {
background: #e6c3c7;
}
tr.miss td {
background: #f8d5d8;
}
td.source {
padding-left: 15px;
line-height: 15px;
white-space: pre;
font: 12px monaco, monospace;
}
code .comment { color: #ddd }
code .init { color: #2F6FAD }
code .string { color: #5890AD }
code .keyword { color: #8A6343 }
code .number { color: #2F6FAD }
</style>
</head><body><div id="coverage"><h1 id="overview">Coverage</h1><div id="menu"><li><a href="#overview">overview</a></li><li><span class="cov low">45</span><a href="#/Users/deNULL/dev/web/az/dist/az.js"><span class="dirname">/Users/deNULL/dev/web/az/dist/</span><span class="basename">az.js</span></a></li><a id="logo" href="http://mochajs.org/">m</a></div><div id="stats" class="low"><div class="percentage">45%</div><div class="sloc">652</div><div class="hits">297</div><div class="misses">355</div></div><div id="files"><div class="file"><h2 id="/Users/deNULL/dev/web/az/dist/az.js">/Users/deNULL/dev/web/az/dist/az.js</h2><div id="stats" class="low"><div class="percentage">45%</div><div class="sloc">652</div><div class="hits">297</div><div class="misses">355</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr class="hit"><td class="line">1</td><td class="hits">1</td><td class="source">;(function (global, factory) {</td></tr><tr class="hit"><td class="line">2</td><td class="hits">1</td><td class="source"> typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> typeof define === 'function' && define.amd ? define('Az', factory) :</td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source"> global.Az = factory()</td></tr><tr class="hit"><td class="line">5</td><td class="hits">1</td><td class="source">}(this, function () { 'use strict';</td></tr><tr class="hit"><td class="line">6</td><td class="hits">1</td><td class="source"> if (typeof require != 'undefined' && typeof exports === 'object' && typeof module !== 'undefined') {</td></tr><tr class="hit"><td class="line">7</td><td class="hits">1</td><td class="source"> var fs = require('fs');</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">10</td><td class="hits">1</td><td class="source"> var Az = {</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> load: function(url, responseType, callback) {</td></tr><tr class="hit"><td class="line">12</td><td class="hits">10</td><td class="source"> if (fs) {</td></tr><tr class="hit"><td class="line">13</td><td class="hits">10</td><td class="source"> fs.readFile(url, { encoding: responseType == 'json' ? 'utf8' : null }, function (err, data) {</td></tr><tr class="hit"><td class="line">14</td><td class="hits">10</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">15</td><td class="hits">0</td><td class="source"> callback(err);</td></tr><tr class="miss"><td class="line">16</td><td class="hits">0</td><td class="source"> return;</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">19</td><td class="hits">10</td><td class="source"> if (responseType == 'json') {</td></tr><tr class="hit"><td class="line">20</td><td class="hits">4</td><td class="source"> callback(null, JSON.parse(data));</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">22</td><td class="hits">6</td><td class="source"> if (responseType == 'arraybuffer') {</td></tr><tr class="hit"><td class="line">23</td><td class="hits">6</td><td class="source"> callback(null, data.buffer);</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="miss"><td class="line">25</td><td class="hits">0</td><td class="source"> callback(new Error('Unknown responseType'));</td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> });</td></tr><tr class="hit"><td class="line">28</td><td class="hits">10</td><td class="source"> return;</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">31</td><td class="hits">0</td><td class="source"> var xhr = new XMLHttpRequest();</td></tr><tr class="miss"><td class="line">32</td><td class="hits">0</td><td class="source"> xhr.open('GET', url, true);</td></tr><tr class="miss"><td class="line">33</td><td class="hits">0</td><td class="source"> xhr.responseType = responseType;</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">35</td><td class="hits">0</td><td class="source"> xhr.onload = function (e) {</td></tr><tr class="miss"><td class="line">36</td><td class="hits">0</td><td class="source"> if (xhr.response) {</td></tr><tr class="miss"><td class="line">37</td><td class="hits">0</td><td class="source"> callback && callback(null, xhr.response);</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">39</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">41</td><td class="hits">0</td><td class="source"> xhr.send(null);</td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">45</td><td class="hits">1</td><td class="source"> return Az;</td></tr><tr><td class="line">46</td><td class="hits"></td><td class="source">}));</td></tr><tr class="hit"><td class="line">47</td><td class="hits">1</td><td class="source">;(function (global, factory) {</td></tr><tr class="hit"><td class="line">48</td><td class="hits">1</td><td class="source"> typeof exports === 'object' && typeof module !== 'undefined' ? (module.exports = module.exports || {}) && (module.exports.DAWG = factory(module.exports)) :</td></tr><tr><td class="line">49</td><td class="hits"></td><td class="source"> typeof define === 'function' && define.amd ? define('Az.DAWG', ['Az'], factory) :</td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> (global.Az = global.Az || {}) && (global.Az.DAWG = factory(global.Az))</td></tr><tr class="hit"><td class="line">51</td><td class="hits">1</td><td class="source">}(this, function (Az) { 'use strict';</td></tr><tr class="hit"><td class="line">52</td><td class="hits">1</td><td class="source"> var ROOT = 0,</td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> MISSING = -1,</td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> PRECISION_MASK = 0xFFFFFFFF,</td></tr><tr><td class="line">55</td><td class="hits"></td><td class="source"> HAS_LEAF_BIT = 1 << 8,</td></tr><tr><td class="line">56</td><td class="hits"></td><td class="source"> EXTENSION_BIT = 1 << 9,</td></tr><tr><td class="line">57</td><td class="hits"></td><td class="source"> OFFSET_MAX = 1 << 21,</td></tr><tr><td class="line">58</td><td class="hits"></td><td class="source"> IS_LEAF_BIT = 1 << 31;</td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">60</td><td class="hits">1</td><td class="source"> var CP1251 = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15, 16: 16,</td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> 17: 17, 18: 18, 19: 19, 20: 20, 21: 21, 22: 22, 23: 23, 24: 24, 25: 25, 26: 26, 27: 27, 28: 28, 29: 29, 30: 30, 31: 31, 32: 32,</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> 33: 33, 34: 34, 35: 35, 36: 36, 37: 37, 38: 38, 39: 39, 40: 40, 41: 41, 42: 42, 43: 43, 44: 44, 45: 45, 46: 46, 47: 47, 48: 48,</td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> 49: 49, 50: 50, 51: 51, 52: 52, 53: 53, 54: 54, 55: 55, 56: 56, 57: 57, 58: 58, 59: 59, 60: 60, 61: 61, 62: 62, 63: 63, 64: 64,</td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> 65: 65, 66: 66, 67: 67, 68: 68, 69: 69, 70: 70, 71: 71, 72: 72, 73: 73, 74: 74, 75: 75, 76: 76, 77: 77, 78: 78, 79: 79, 80: 80,</td></tr><tr><td class="line">65</td><td class="hits"></td><td class="source"> 81: 81, 82: 82, 83: 83, 84: 84, 85: 85, 86: 86, 87: 87, 88: 88, 89: 89, 90: 90, 91: 91, 92: 92, 93: 93, 94: 94, 95: 95, 96: 96,</td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> 97: 97, 98: 98, 99: 99, 100: 100, 101: 101, 102: 102, 103: 103, 104: 104, 105: 105, 106: 106, 107: 107, 108: 108, 109: 109, 110: 110, 111: 111, 112: 112,</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> 113: 113, 114: 114, 115: 115, 116: 116, 117: 117, 118: 118, 119: 119, 120: 120, 121: 121, 122: 122, 123: 123, 124: 124, 125: 125, 126: 126, 127: 127,</td></tr><tr><td class="line">68</td><td class="hits"></td><td class="source"> 1027: 129, 8225: 135, 1046: 198, 8222: 132, 1047: 199, 1168: 165, 1048: 200, 1113: 154, 1049: 201, 1045: 197, 1050: 202, 1028: 170, 160: 160, 1040: 192,</td></tr><tr><td class="line">69</td><td class="hits"></td><td class="source"> 1051: 203, 164: 164, 166: 166, 167: 167, 169: 169, 171: 171, 172: 172, 173: 173, 174: 174, 1053: 205, 176: 176, 177: 177, 1114: 156, 181: 181, 182: 182,</td></tr><tr><td class="line">70</td><td class="hits"></td><td class="source"> 183: 183, 8221: 148, 187: 187, 1029: 189, 1056: 208, 1057: 209, 1058: 210, 8364: 136, 1112: 188, 1115: 158, 1059: 211, 1060: 212, 1030: 178, 1061: 213,</td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> 1062: 214, 1063: 215, 1116: 157, 1064: 216, 1065: 217, 1031: 175, 1066: 218, 1067: 219, 1068: 220, 1069: 221, 1070: 222, 1032: 163, 8226: 149, 1071: 223,</td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> 1072: 224, 8482: 153, 1073: 225, 8240: 137, 1118: 162, 1074: 226, 1110: 179, 8230: 133, 1075: 227, 1033: 138, 1076: 228, 1077: 229, 8211: 150, 1078: 230,</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> 1119: 159, 1079: 231, 1042: 194, 1080: 232, 1034: 140, 1025: 168, 1081: 233, 1082: 234, 8212: 151, 1083: 235, 1169: 180, 1084: 236, 1052: 204, 1085: 237,</td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> 1035: 142, 1086: 238, 1087: 239, 1088: 240, 1089: 241, 1090: 242, 1036: 141, 1041: 193, 1091: 243, 1092: 244, 8224: 134, 1093: 245, 8470: 185, 1094: 246,</td></tr><tr><td class="line">75</td><td class="hits"></td><td class="source"> 1054: 206, 1095: 247, 1096: 248, 8249: 139, 1097: 249, 1098: 250, 1044: 196, 1099: 251, 1111: 191, 1055: 207, 1100: 252, 1038: 161, 8220: 147, 1101: 253,</td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> 8250: 155, 1102: 254, 8216: 145, 1103: 255, 1043: 195, 1105: 184, 1039: 143, 1026: 128, 1106: 144, 8218: 130, 1107: 131, 8217: 146, 1108: 186, 1109: 190};</td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">78</td><td class="hits"></td><td class="source"> // Based on all common ЙЦУКЕН-keyboards (both Windows and Apple variations)</td></tr><tr class="hit"><td class="line">79</td><td class="hits">1</td><td class="source"> var COMMON_TYPOS = {</td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source"> 'й': 'ёцыф', 'ц': 'йфыву', 'у': 'цывак', 'к': 'увапе', 'е': 'капрн', 'н': 'епрог', 'г': 'нролш', 'ш': 'голдщ', 'щ': 'шлджз', 'з': 'щджэх-', 'х': 'зжэъ-', 'ъ': 'хэ-ё',</td></tr><tr><td class="line">81</td><td class="hits"></td><td class="source"> 'ф': 'йцычяё', 'ы': 'йцувсчяф', 'в': 'цукамсчы', 'а': 'укепимсв', 'п': 'кенртима', 'р': 'енгоьтип', 'о': 'нгшлбьтр', 'л': 'гшщдюбьо', 'д': 'шщзжюбл', 'ж': 'щзхэюд', 'э': 'зхъжё',</td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source"> 'ё': 'йфяъэ', 'я': 'ёфыч', 'ч': 'яфывс', 'с': 'чывам', 'м': 'свапи', 'и': 'мапрт', 'т': 'ипроь', 'ь': 'тролб', 'б': 'ьолдю', 'ю': 'блдж',</td></tr><tr><td class="line">83</td><td class="hits"></td><td class="source"> '1': 'ёйц', '2': 'йцу', '3': 'цук', '4': 'уке', '5': 'кен', '6': 'енг', '7': 'нгш', '8': 'гшщ', '9': 'шщз', '0': 'щзх-', '-': 'зхъ', '=': '-хъ', '\\': 'ъэ', '.': 'южэ'</td></tr><tr><td class="line">84</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">85</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">86</td><td class="hits">1</td><td class="source"> function offset(base) {</td></tr><tr class="hit"><td class="line">87</td><td class="hits">1</td><td class="source"> return ((base >> 10) << ((base & EXTENSION_BIT) >> 6)) & PRECISION_MASK;</td></tr><tr><td class="line">88</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">90</td><td class="hits">1</td><td class="source"> function label(base) {</td></tr><tr class="hit"><td class="line">91</td><td class="hits">1</td><td class="source"> return base & (IS_LEAF_BIT | 0xFF) & PRECISION_MASK;</td></tr><tr><td class="line">92</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">93</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">94</td><td class="hits">1</td><td class="source"> function hasLeaf(base) {</td></tr><tr class="miss"><td class="line">95</td><td class="hits">0</td><td class="source"> return (base & HAS_LEAF_BIT & PRECISION_MASK) != 0;</td></tr><tr><td class="line">96</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">97</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">98</td><td class="hits">1</td><td class="source"> function value(base) {</td></tr><tr class="miss"><td class="line">99</td><td class="hits">0</td><td class="source"> return base & ~IS_LEAF_BIT & PRECISION_MASK;</td></tr><tr><td class="line">100</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">101</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">102</td><td class="hits">1</td><td class="source"> var DAWG = function(units, guide, format) {</td></tr><tr class="hit"><td class="line">103</td><td class="hits">5</td><td class="source"> this.units = units;</td></tr><tr class="hit"><td class="line">104</td><td class="hits">5</td><td class="source"> this.guide = guide;</td></tr><tr class="hit"><td class="line">105</td><td class="hits">5</td><td class="source"> this.format = format;</td></tr><tr><td class="line">106</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">107</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">108</td><td class="hits">1</td><td class="source"> DAWG.fromArrayBuffer = function(data, format) {</td></tr><tr class="hit"><td class="line">109</td><td class="hits">5</td><td class="source"> var dv = new DataView(data),</td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source"> unitsLength = dv.getUint32(0, true),</td></tr><tr><td class="line">111</td><td class="hits"></td><td class="source"> guideLength = dv.getUint32(unitsLength * 4 + 4, true);</td></tr><tr class="hit"><td class="line">112</td><td class="hits">5</td><td class="source"> return new DAWG(</td></tr><tr><td class="line">113</td><td class="hits"></td><td class="source"> new Uint32Array(data, 4, unitsLength),</td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> new Uint8Array(data, unitsLength * 4 + 8, guideLength * 2),</td></tr><tr><td class="line">115</td><td class="hits"></td><td class="source"> format);</td></tr><tr><td class="line">116</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">117</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">118</td><td class="hits">1</td><td class="source"> DAWG.load = function(url, format, callback) {</td></tr><tr class="hit"><td class="line">119</td><td class="hits">5</td><td class="source"> Az.load(url, 'arraybuffer', function(err, data) {</td></tr><tr class="hit"><td class="line">120</td><td class="hits">5</td><td class="source"> callback(err, err ? null : DAWG.fromArrayBuffer(data, format));</td></tr><tr><td class="line">121</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">122</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">123</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">124</td><td class="hits">1</td><td class="source"> DAWG.prototype.followByte = function(c, index) {</td></tr><tr class="hit"><td class="line">125</td><td class="hits">1</td><td class="source"> var o = offset(this.units[index]);</td></tr><tr class="hit"><td class="line">126</td><td class="hits">1</td><td class="source"> var nextIndex = (index ^ o ^ (c & 0xFF)) & PRECISION_MASK;</td></tr><tr><td class="line">127</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">128</td><td class="hits">1</td><td class="source"> if (label(this.units[nextIndex]) != (c & 0xFF)) {</td></tr><tr class="hit"><td class="line">129</td><td class="hits">1</td><td class="source"> return MISSING;</td></tr><tr><td class="line">130</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">131</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">132</td><td class="hits">0</td><td class="source"> return nextIndex;</td></tr><tr><td class="line">133</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">134</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">135</td><td class="hits">1</td><td class="source"> DAWG.prototype.followString = function(str, index) {</td></tr><tr class="miss"><td class="line">136</td><td class="hits">0</td><td class="source"> index = index || ROOT;</td></tr><tr class="miss"><td class="line">137</td><td class="hits">0</td><td class="source"> for (var i = 0; i < str.length; i++) {</td></tr><tr class="miss"><td class="line">138</td><td class="hits">0</td><td class="source"> var code = str.charCodeAt(i);</td></tr><tr class="miss"><td class="line">139</td><td class="hits">0</td><td class="source"> if (!(code in CP1251)) {</td></tr><tr class="miss"><td class="line">140</td><td class="hits">0</td><td class="source"> return MISSING;</td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">142</td><td class="hits">0</td><td class="source"> index = this.followByte(CP1251[code], index);</td></tr><tr class="miss"><td class="line">143</td><td class="hits">0</td><td class="source"> if (index == MISSING) {</td></tr><tr class="miss"><td class="line">144</td><td class="hits">0</td><td class="source"> return MISSING;</td></tr><tr><td class="line">145</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">146</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">147</td><td class="hits">0</td><td class="source"> return index;</td></tr><tr><td class="line">148</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">149</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">150</td><td class="hits">1</td><td class="source"> DAWG.prototype.hasValue = function(index) {</td></tr><tr class="miss"><td class="line">151</td><td class="hits">0</td><td class="source"> return hasLeaf(this.units[index]);</td></tr><tr><td class="line">152</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">153</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">154</td><td class="hits">1</td><td class="source"> DAWG.prototype.value = function(index) {</td></tr><tr class="miss"><td class="line">155</td><td class="hits">0</td><td class="source"> var o = offset(this.units[index]);</td></tr><tr class="miss"><td class="line">156</td><td class="hits">0</td><td class="source"> var valueIndex = (index ^ o) & PRECISION_MASK;</td></tr><tr class="miss"><td class="line">157</td><td class="hits">0</td><td class="source"> return value(this.units[valueIndex]);</td></tr><tr><td class="line">158</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">159</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">160</td><td class="hits">1</td><td class="source"> DAWG.prototype.find = function(str) {</td></tr><tr class="miss"><td class="line">161</td><td class="hits">0</td><td class="source"> var index = this.followString(str);</td></tr><tr class="miss"><td class="line">162</td><td class="hits">0</td><td class="source"> if (index == MISSING) {</td></tr><tr class="miss"><td class="line">163</td><td class="hits">0</td><td class="source"> return MISSING;</td></tr><tr><td class="line">164</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">165</td><td class="hits">0</td><td class="source"> if (!this.hasValue(index)) {</td></tr><tr class="miss"><td class="line">166</td><td class="hits">0</td><td class="source"> return MISSING;</td></tr><tr><td class="line">167</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">168</td><td class="hits">0</td><td class="source"> return this.value(index);</td></tr><tr><td class="line">169</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">170</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">171</td><td class="hits">1</td><td class="source"> DAWG.prototype.iterateAll = function(index) {</td></tr><tr class="miss"><td class="line">172</td><td class="hits">0</td><td class="source"> var results = [];</td></tr><tr class="miss"><td class="line">173</td><td class="hits">0</td><td class="source"> var stack = [index];</td></tr><tr class="miss"><td class="line">174</td><td class="hits">0</td><td class="source"> var key = [];</td></tr><tr class="miss"><td class="line">175</td><td class="hits">0</td><td class="source"> var last = ROOT;</td></tr><tr class="miss"><td class="line">176</td><td class="hits">0</td><td class="source"> var label;</td></tr><tr><td class="line">177</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">178</td><td class="hits">0</td><td class="source"> while (true) {</td></tr><tr class="miss"><td class="line">179</td><td class="hits">0</td><td class="source"> index = stack[stack.length - 1];</td></tr><tr><td class="line">180</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">181</td><td class="hits">0</td><td class="source"> if (last != ROOT) {</td></tr><tr class="miss"><td class="line">182</td><td class="hits">0</td><td class="source"> label = this.guide[index << 1];</td></tr><tr class="miss"><td class="line">183</td><td class="hits">0</td><td class="source"> if (label) {</td></tr><tr class="miss"><td class="line">184</td><td class="hits">0</td><td class="source"> index = this.followByte(label, index);</td></tr><tr class="miss"><td class="line">185</td><td class="hits">0</td><td class="source"> if (index == MISSING) {</td></tr><tr class="miss"><td class="line">186</td><td class="hits">0</td><td class="source"> return results;</td></tr><tr><td class="line">187</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">188</td><td class="hits">0</td><td class="source"> key.push(label);</td></tr><tr class="miss"><td class="line">189</td><td class="hits">0</td><td class="source"> stack.push(index);</td></tr><tr><td class="line">190</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="miss"><td class="line">191</td><td class="hits">0</td><td class="source"> do {</td></tr><tr class="miss"><td class="line">192</td><td class="hits">0</td><td class="source"> label = this.guide[(index << 1) + 1];</td></tr><tr class="miss"><td class="line">193</td><td class="hits">0</td><td class="source"> key.pop();</td></tr><tr class="miss"><td class="line">194</td><td class="hits">0</td><td class="source"> stack.pop();</td></tr><tr class="miss"><td class="line">195</td><td class="hits">0</td><td class="source"> if (!stack.length) {</td></tr><tr class="miss"><td class="line">196</td><td class="hits">0</td><td class="source"> return results;</td></tr><tr><td class="line">197</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">198</td><td class="hits">0</td><td class="source"> index = stack[stack.length - 1];</td></tr><tr class="miss"><td class="line">199</td><td class="hits">0</td><td class="source"> if (label) {</td></tr><tr class="miss"><td class="line">200</td><td class="hits">0</td><td class="source"> index = this.followByte(label, index);</td></tr><tr class="miss"><td class="line">201</td><td class="hits">0</td><td class="source"> if (index == MISSING) {</td></tr><tr class="miss"><td class="line">202</td><td class="hits">0</td><td class="source"> return results;</td></tr><tr><td class="line">203</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">204</td><td class="hits">0</td><td class="source"> key.push(label);</td></tr><tr class="miss"><td class="line">205</td><td class="hits">0</td><td class="source"> stack.push(index);</td></tr><tr><td class="line">206</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">207</td><td class="hits"></td><td class="source"> } while (!label);</td></tr><tr><td class="line">208</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">209</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">210</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">211</td><td class="hits">0</td><td class="source"> while (!this.hasValue(index)) {</td></tr><tr class="miss"><td class="line">212</td><td class="hits">0</td><td class="source"> var label = this.guide[index << 1];</td></tr><tr class="miss"><td class="line">213</td><td class="hits">0</td><td class="source"> index = this.followByte(label, index);</td></tr><tr class="miss"><td class="line">214</td><td class="hits">0</td><td class="source"> if (index == MISSING) {</td></tr><tr class="miss"><td class="line">215</td><td class="hits">0</td><td class="source"> return results;</td></tr><tr><td class="line">216</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">217</td><td class="hits">0</td><td class="source"> key.push(label);</td></tr><tr class="miss"><td class="line">218</td><td class="hits">0</td><td class="source"> stack.push(index);</td></tr><tr><td class="line">219</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">220</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">221</td><td class="hits"></td><td class="source"> // Only three formats supported</td></tr><tr class="miss"><td class="line">222</td><td class="hits">0</td><td class="source"> if (this.format == 'words') {</td></tr><tr class="miss"><td class="line">223</td><td class="hits">0</td><td class="source"> results.push([</td></tr><tr><td class="line">224</td><td class="hits"></td><td class="source"> ((key[0] ^ 1) << 6) + (key[1] >> 1),</td></tr><tr><td class="line">225</td><td class="hits"></td><td class="source"> ((key[2] ^ 1) << 6) + (key[3] >> 1)</td></tr><tr><td class="line">226</td><td class="hits"></td><td class="source"> ]);</td></tr><tr><td class="line">227</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="miss"><td class="line">228</td><td class="hits">0</td><td class="source"> if (this.format == 'probs') {</td></tr><tr class="miss"><td class="line">229</td><td class="hits">0</td><td class="source"> results.push([</td></tr><tr><td class="line">230</td><td class="hits"></td><td class="source"> ((key[0] ^ 1) << 6) + (key[1] >> 1),</td></tr><tr><td class="line">231</td><td class="hits"></td><td class="source"> ((key[2] ^ 1) << 6) + (key[3] >> 1),</td></tr><tr><td class="line">232</td><td class="hits"></td><td class="source"> ((key[4] ^ 1) << 6) + (key[5] >> 1)</td></tr><tr><td class="line">233</td><td class="hits"></td><td class="source"> ]);</td></tr><tr><td class="line">234</td><td class="hits"></td><td class="source"> } else {</td></tr><tr><td class="line">235</td><td class="hits"></td><td class="source"> // Raw bytes</td></tr><tr class="miss"><td class="line">236</td><td class="hits">0</td><td class="source"> results.push(key.slice());</td></tr><tr><td class="line">237</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">238</td><td class="hits">0</td><td class="source"> last = index;</td></tr><tr><td class="line">239</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">240</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">241</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">242</td><td class="hits"></td><td class="source"> // Features:</td></tr><tr><td class="line">243</td><td class="hits"></td><td class="source"> // replaces (е -> ё) (DONE)</td></tr><tr><td class="line">244</td><td class="hits"></td><td class="source"> // stutter (ннет -> нет, гоол -> гол, д-да -> да)</td></tr><tr><td class="line">245</td><td class="hits"></td><td class="source"> // typos (count-limited):</td></tr><tr><td class="line">246</td><td class="hits"></td><td class="source"> // swaps (солво -> слово)</td></tr><tr><td class="line">247</td><td class="hits"></td><td class="source"> // extra letters (свлово -> слово)</td></tr><tr><td class="line">248</td><td class="hits"></td><td class="source"> // missing letters (сово -> слово)</td></tr><tr><td class="line">249</td><td class="hits"></td><td class="source"> // wrong letters (сково -> слово)</td></tr><tr class="hit"><td class="line">250</td><td class="hits">1</td><td class="source"> DAWG.prototype.findAll = function(str, replaces, mstutter, mtypos) {</td></tr><tr class="hit"><td class="line">251</td><td class="hits">1</td><td class="source"> mtypos = mtypos || 0;</td></tr><tr class="hit"><td class="line">252</td><td class="hits">1</td><td class="source"> mstutter = mstutter || 0;</td></tr><tr class="hit"><td class="line">253</td><td class="hits">1</td><td class="source"> var results = [],</td></tr><tr><td class="line">254</td><td class="hits"></td><td class="source"> prefixes = [['', 0, 0, 0, ROOT]],</td></tr><tr><td class="line">255</td><td class="hits"></td><td class="source"> prefix, index, len, code, cur, typos, stutter;</td></tr><tr><td class="line">256</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">257</td><td class="hits">1</td><td class="source"> while (prefixes.length) {</td></tr><tr class="hit"><td class="line">258</td><td class="hits">1</td><td class="source"> prefix = prefixes.pop();</td></tr><tr class="hit"><td class="line">259</td><td class="hits">1</td><td class="source"> index = prefix[4], stutter = prefix[3], typos = prefix[2], len = prefix[1], prefix = prefix[0];</td></tr><tr><td class="line">260</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">261</td><td class="hits"></td><td class="source"> // Done</td></tr><tr class="hit"><td class="line">262</td><td class="hits">1</td><td class="source"> if (len == str.length) {</td></tr><tr class="miss"><td class="line">263</td><td class="hits">0</td><td class="source"> if (this.format == 'int') {</td></tr><tr class="miss"><td class="line">264</td><td class="hits">0</td><td class="source"> if (this.hasValue(index)) {</td></tr><tr class="miss"><td class="line">265</td><td class="hits">0</td><td class="source"> results.push([prefix, this.value(index)]);</td></tr><tr><td class="line">266</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">267</td><td class="hits">0</td><td class="source"> continue;</td></tr><tr><td class="line">268</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">269</td><td class="hits"></td><td class="source"> // Find all payloads</td></tr><tr class="miss"><td class="line">270</td><td class="hits">0</td><td class="source"> if (this.format == 'words' || this.format == 'probs') {</td></tr><tr class="miss"><td class="line">271</td><td class="hits">0</td><td class="source"> index = this.followByte(1, index); // separator</td></tr><tr class="miss"><td class="line">272</td><td class="hits">0</td><td class="source"> if (index == MISSING) {</td></tr><tr class="miss"><td class="line">273</td><td class="hits">0</td><td class="source"> continue;</td></tr><tr><td class="line">274</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">275</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">276</td><td class="hits">0</td><td class="source"> results.push([prefix, this.iterateAll(index), stutter, typos]);</td></tr><tr class="miss"><td class="line">277</td><td class="hits">0</td><td class="source"> continue;</td></tr><tr><td class="line">278</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">279</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">280</td><td class="hits"></td><td class="source"> // Follow a replacement path</td></tr><tr class="hit"><td class="line">281</td><td class="hits">1</td><td class="source"> if (replaces && str[len] in replaces) {</td></tr><tr class="miss"><td class="line">282</td><td class="hits">0</td><td class="source"> code = replaces[str[len]].charCodeAt(0);</td></tr><tr class="miss"><td class="line">283</td><td class="hits">0</td><td class="source"> if (code in CP1251) {</td></tr><tr class="miss"><td class="line">284</td><td class="hits">0</td><td class="source"> cur = this.followByte(CP1251[code], index);</td></tr><tr class="miss"><td class="line">285</td><td class="hits">0</td><td class="source"> if (cur != MISSING) {</td></tr><tr class="miss"><td class="line">286</td><td class="hits">0</td><td class="source"> prefixes.push([ prefix + replaces[str[len]], len + 1, typos, stutter, cur ]);</td></tr><tr><td class="line">287</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">288</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">289</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">290</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">291</td><td class="hits"></td><td class="source"> // Follow typos path (if not over limit)</td></tr><tr class="hit"><td class="line">292</td><td class="hits">1</td><td class="source"> if (typos < mtypos && !stutter) {</td></tr><tr><td class="line">293</td><td class="hits"></td><td class="source"> // Skip a letter entirely (extra letter)</td></tr><tr class="miss"><td class="line">294</td><td class="hits">0</td><td class="source"> prefixes.push([ prefix, len + 1, typos + 1, stutter, index ]);</td></tr><tr><td class="line">295</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">296</td><td class="hits"></td><td class="source"> // Add a letter (missing) - or - replace a letter</td></tr><tr><td class="line">297</td><td class="hits"></td><td class="source"> // TODO: iterate all childs?</td></tr><tr><td class="line">298</td><td class="hits"></td><td class="source"> // Now it checks only most probable typos (located near to each other on keyboards)</td></tr><tr class="miss"><td class="line">299</td><td class="hits">0</td><td class="source"> var possible = COMMON_TYPOS[str[len]];</td></tr><tr class="miss"><td class="line">300</td><td class="hits">0</td><td class="source"> if (possible) {</td></tr><tr class="miss"><td class="line">301</td><td class="hits">0</td><td class="source"> for (var i = 0; i < possible.length; i++) {</td></tr><tr class="miss"><td class="line">302</td><td class="hits">0</td><td class="source"> code = possible.charCodeAt(i);</td></tr><tr class="miss"><td class="line">303</td><td class="hits">0</td><td class="source"> if (code in CP1251) {</td></tr><tr class="miss"><td class="line">304</td><td class="hits">0</td><td class="source"> cur = this.followByte(CP1251[code], index);</td></tr><tr class="miss"><td class="line">305</td><td class="hits">0</td><td class="source"> if (cur != MISSING) {</td></tr><tr><td class="line">306</td><td class="hits"></td><td class="source"> // for missing letter we need to iterate all childs, not only COMMON_TYPOS</td></tr><tr><td class="line">307</td><td class="hits"></td><td class="source"> // prefixes.push([ prefix + possible[i], len, typos + 1, stutter, cur ]);</td></tr><tr class="miss"><td class="line">308</td><td class="hits">0</td><td class="source"> prefixes.push([ prefix + possible[i], len + 1, typos + 1, stutter, cur ]);</td></tr><tr><td class="line">309</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">310</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">311</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">312</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">313</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">314</td><td class="hits"></td><td class="source"> // Swapped two letters</td></tr><tr><td class="line">315</td><td class="hits"></td><td class="source"> // TODO: support for replacements?</td></tr><tr class="miss"><td class="line">316</td><td class="hits">0</td><td class="source"> if (len < str.length - 1) {</td></tr><tr class="miss"><td class="line">317</td><td class="hits">0</td><td class="source"> code = str.charCodeAt(len + 1);</td></tr><tr class="miss"><td class="line">318</td><td class="hits">0</td><td class="source"> if (code in CP1251) {</td></tr><tr class="miss"><td class="line">319</td><td class="hits">0</td><td class="source"> cur = this.followByte(CP1251[code], index);</td></tr><tr class="miss"><td class="line">320</td><td class="hits">0</td><td class="source"> if (cur != MISSING) {</td></tr><tr class="miss"><td class="line">321</td><td class="hits">0</td><td class="source"> code = str.charCodeAt(len);</td></tr><tr class="miss"><td class="line">322</td><td class="hits">0</td><td class="source"> if (code in CP1251) {</td></tr><tr class="miss"><td class="line">323</td><td class="hits">0</td><td class="source"> cur = this.followByte(CP1251[code], cur);</td></tr><tr class="miss"><td class="line">324</td><td class="hits">0</td><td class="source"> if (cur != MISSING) {</td></tr><tr class="miss"><td class="line">325</td><td class="hits">0</td><td class="source"> prefixes.push([ prefix + str[len + 1] + str[len], len + 2, typos + 1, stutter, cur ]);</td></tr><tr><td class="line">326</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">327</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">328</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">329</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">330</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">331</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">332</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">333</td><td class="hits"></td><td class="source"> // Follow base path</td></tr><tr class="hit"><td class="line">334</td><td class="hits">1</td><td class="source"> code = str.charCodeAt(len);</td></tr><tr class="hit"><td class="line">335</td><td class="hits">1</td><td class="source"> if (code in CP1251) {</td></tr><tr class="hit"><td class="line">336</td><td class="hits">1</td><td class="source"> cur = this.followByte(CP1251[code], index);</td></tr><tr class="hit"><td class="line">337</td><td class="hits">1</td><td class="source"> if (cur != MISSING) {</td></tr><tr class="miss"><td class="line">338</td><td class="hits">0</td><td class="source"> prefixes.push([ prefix + str[len], len + 1, typos, stutter, cur ]);</td></tr><tr><td class="line">339</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">340</td><td class="hits">0</td><td class="source"> while (stutter < mstutter && !typos && len < str.length - 1) {</td></tr><tr><td class="line">341</td><td class="hits"></td><td class="source"> // Follow a simple stutter path (merge two equal letters into one)</td></tr><tr class="miss"><td class="line">342</td><td class="hits">0</td><td class="source"> if (str[len] == str[len + 1]) {</td></tr><tr class="miss"><td class="line">343</td><td class="hits">0</td><td class="source"> prefixes.push([ prefix + str[len], len + 2, typos, stutter + 1, cur ]);</td></tr><tr class="miss"><td class="line">344</td><td class="hits">0</td><td class="source"> len++;</td></tr><tr><td class="line">345</td><td class="hits"></td><td class="source"> } else</td></tr><tr><td class="line">346</td><td class="hits"></td><td class="source"> // Follow a stutter with a dash (д-да)</td></tr><tr class="miss"><td class="line">347</td><td class="hits">0</td><td class="source"> if (len < str.length - 2 && str[len + 1] == '-' && str[len] == str[len + 2]) {</td></tr><tr class="miss"><td class="line">348</td><td class="hits">0</td><td class="source"> prefixes.push([ prefix + str[len], len + 3, typos, stutter + 1, cur ]);</td></tr><tr class="miss"><td class="line">349</td><td class="hits">0</td><td class="source"> len += 2;</td></tr><tr><td class="line">350</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="miss"><td class="line">351</td><td class="hits">0</td><td class="source"> break;</td></tr><tr><td class="line">352</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">353</td><td class="hits">0</td><td class="source"> stutter++;</td></tr><tr><td class="line">354</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">355</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">356</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">357</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">358</td><td class="hits">1</td><td class="source"> return results;</td></tr><tr><td class="line">359</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">360</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">361</td><td class="hits">1</td><td class="source"> return DAWG;</td></tr><tr><td class="line">362</td><td class="hits"></td><td class="source">}));</td></tr><tr class="hit"><td class="line">363</td><td class="hits">1</td><td class="source">;(function (global, factory) {</td></tr><tr class="hit"><td class="line">364</td><td class="hits">1</td><td class="source"> typeof exports === 'object' && typeof module !== 'undefined' ? (module.exports = module.exports || {}) && (module.exports.Morph = factory(module.exports)) :</td></tr><tr><td class="line">365</td><td class="hits"></td><td class="source"> typeof define === 'function' && define.amd ? define('Az.Morph', ['Az', 'Az.DAWG'], factory) :</td></tr><tr><td class="line">366</td><td class="hits"></td><td class="source"> (global.Az = global.Az || {}) && (global.Az.Morph = factory(global.Az))</td></tr><tr class="hit"><td class="line">367</td><td class="hits">1</td><td class="source">}(this, function (Az) { 'use strict';</td></tr><tr class="hit"><td class="line">368</td><td class="hits">1</td><td class="source"> var words,</td></tr><tr><td class="line">369</td><td class="hits"></td><td class="source"> probabilities,</td></tr><tr><td class="line">370</td><td class="hits"></td><td class="source"> predictionSuffixes = new Array(3),</td></tr><tr><td class="line">371</td><td class="hits"></td><td class="source"> prefixes = [ '', 'по', 'наи' ],</td></tr><tr><td class="line">372</td><td class="hits"></td><td class="source"> suffixes,</td></tr><tr><td class="line">373</td><td class="hits"></td><td class="source"> grammemes,</td></tr><tr><td class="line">374</td><td class="hits"></td><td class="source"> paradigms,</td></tr><tr><td class="line">375</td><td class="hits"></td><td class="source"> tags,</td></tr><tr><td class="line">376</td><td class="hits"></td><td class="source"> defaults = {</td></tr><tr><td class="line">377</td><td class="hits"></td><td class="source"> // Замены (работают как в pymorphy2).</td></tr><tr><td class="line">378</td><td class="hits"></td><td class="source"> // false, чтобы отключить.</td></tr><tr><td class="line">379</td><td class="hits"></td><td class="source"> replacements: { 'е': 'ё' },</td></tr><tr><td class="line">380</td><td class="hits"></td><td class="source"> // "Заикание". Устраняет повторения букв (как с дефисом - "не-е-ет", так и без - "нееет").</td></tr><tr><td class="line">381</td><td class="hits"></td><td class="source"> // Infinity не ограничивает максимальное число повторений (суммарно во всем слове).</td></tr><tr><td class="line">382</td><td class="hits"></td><td class="source"> // 0 или false чтобы отключить.</td></tr><tr><td class="line">383</td><td class="hits"></td><td class="source"> stutter: Infinity,</td></tr><tr><td class="line">384</td><td class="hits"></td><td class="source"> // Опечатки. Максимальное количество опечаток в слове.</td></tr><tr><td class="line">385</td><td class="hits"></td><td class="source"> // Опечаткой считается:</td></tr><tr><td class="line">386</td><td class="hits"></td><td class="source"> // - лишняя буква в слове</td></tr><tr><td class="line">387</td><td class="hits"></td><td class="source"> // - (пропущенная буква в слове) (TODO: пока не работает)</td></tr><tr><td class="line">388</td><td class="hits"></td><td class="source"> // - не та буква в слове (если правильная буква стоит рядом на клавиатуре)</td></tr><tr><td class="line">389</td><td class="hits"></td><td class="source"> // - переставленные местами соседние буквы</td></tr><tr><td class="line">390</td><td class="hits"></td><td class="source"> // 0 или false чтобы отключить.</td></tr><tr><td class="line">391</td><td class="hits"></td><td class="source"> // 'auto':</td></tr><tr><td class="line">392</td><td class="hits"></td><td class="source"> // - 0, если слово короче 5 букв</td></tr><tr><td class="line">393</td><td class="hits"></td><td class="source"> // - 1, если слово короче 10 букв (но только если не нашлось варианта разбора без опечаток)</td></tr><tr><td class="line">394</td><td class="hits"></td><td class="source"> // - 2 в противном случае (но только если не нашлось варианта разбора без опечаток или с 1 опечаткой)</td></tr><tr><td class="line">395</td><td class="hits"></td><td class="source"> typos: 0</td></tr><tr><td class="line">396</td><td class="hits"></td><td class="source"> // Совместное появление опечаток и "заикания" считается недопустимым (т.к. это приводит к большому числу вариантов, особенно на словах с "заиканием")</td></tr><tr><td class="line">397</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">398</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">399</td><td class="hits"></td><td class="source"> // Взято из https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze</td></tr><tr class="hit"><td class="line">400</td><td class="hits">1</td><td class="source"> function deepFreeze(obj) {</td></tr><tr class="hit"><td class="line">401</td><td class="hits">29281</td><td class="source"> if (!('freeze' in Object)) {</td></tr><tr class="miss"><td class="line">402</td><td class="hits">0</td><td class="source"> return;</td></tr><tr><td class="line">403</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">404</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">405</td><td class="hits">29281</td><td class="source"> var propNames = Object.getOwnPropertyNames(obj);</td></tr><tr class="hit"><td class="line">406</td><td class="hits">29281</td><td class="source"> propNames.forEach(function(name) {</td></tr><tr class="hit"><td class="line">407</td><td class="hits">252745</td><td class="source"> var prop = obj[name];</td></tr><tr><td class="line">408</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">409</td><td class="hits">252745</td><td class="source"> if (typeof prop == 'object' && prop !== null)</td></tr><tr class="hit"><td class="line">410</td><td class="hits">29280</td><td class="source"> deepFreeze(prop);</td></tr><tr><td class="line">411</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">412</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">413</td><td class="hits">29281</td><td class="source"> return Object.freeze(obj);</td></tr><tr><td class="line">414</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">415</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">416</td><td class="hits"></td><td class="source"> //</td></tr><tr><td class="line">417</td><td class="hits"></td><td class="source"> // Экземпляры Tag могут быть довольно большими, т.к. будут переиспользоваться для всех слов.</td></tr><tr><td class="line">418</td><td class="hits"></td><td class="source"> // Однако это приводит к запрету на любые изменения этих экземпляров. В современных браузерах для этого будет использован метод Object.freeze()</td></tr><tr><td class="line">419</td><td class="hits"></td><td class="source"> // Каждая граммема хранится внутри тега в нескольких местах:</td></tr><tr><td class="line">420</td><td class="hits"></td><td class="source"> // tag[grammeme] = true | false</td></tr><tr><td class="line">421</td><td class="hits"></td><td class="source"> // tag[parent] = grammeme</td></tr><tr><td class="line">422</td><td class="hits"></td><td class="source"> // tag.stat = [grammeme1, grammeme2, ...] // неизменяемые граммемы</td></tr><tr><td class="line">423</td><td class="hits"></td><td class="source"> // tag.flex = [grammeme1, grammeme2, ...] // изменяемые граммемы</td></tr><tr><td class="line">424</td><td class="hits"></td><td class="source"> //</td></tr><tr><td class="line">425</td><td class="hits"></td><td class="source"> //</td></tr><tr><td class="line">426</td><td class="hits"></td><td class="source"> // tag.ext[grammemeCyr] = true | false</td></tr><tr><td class="line">427</td><td class="hits"></td><td class="source"> // tag.ext[parentCyr] = grammemeCyr</td></tr><tr><td class="line">428</td><td class="hits"></td><td class="source"> // tag.ext.stat = [grammemeCyr1, grammemeCyr2, ...] // неизменяемые граммемы</td></tr><tr><td class="line">429</td><td class="hits"></td><td class="source"> // tag.ext.flex = [grammemeCyr1, grammemeCyr2, ...] // изменяемые граммемы</td></tr><tr><td class="line">430</td><td class="hits"></td><td class="source"> //</td></tr><tr><td class="line">431</td><td class="hits"></td><td class="source"> //</td></tr><tr><td class="line">432</td><td class="hits"></td><td class="source"> // Тут grammeme - латинская запись граммемы, grammemeCyr - кириллическая</td></tr><tr><td class="line">433</td><td class="hits"></td><td class="source"> // parent, parentCyr - родительская граммема.</td></tr><tr><td class="line">434</td><td class="hits"></td><td class="source"> //</td></tr><tr class="hit"><td class="line">435</td><td class="hits">1</td><td class="source"> var Tag = function(str) {</td></tr><tr class="hit"><td class="line">436</td><td class="hits">9760</td><td class="source"> var par, pair = str.split(' ');</td></tr><tr class="hit"><td class="line">437</td><td class="hits">9760</td><td class="source"> this.stat = pair[0].split(',');</td></tr><tr class="hit"><td class="line">438</td><td class="hits">9760</td><td class="source"> for (var i = 0; i < this.stat.length; i++) {</td></tr><tr class="hit"><td class="line">439</td><td class="hits">42374</td><td class="source"> this[this.stat[i]] = true;</td></tr><tr class="hit"><td class="line">440</td><td class="hits">42374</td><td class="source"> if (par = grammemes[this.stat[i]].parent) {</td></tr><tr class="hit"><td class="line">441</td><td class="hits">31332</td><td class="source"> this[par] = this.stat[i];</td></tr><tr><td class="line">442</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">443</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">444</td><td class="hits">9760</td><td class="source"> this.flex = pair[1] ? pair[1].split(',') : [];</td></tr><tr class="hit"><td class="line">445</td><td class="hits">9760</td><td class="source"> for (var i = 0; i < this.flex.length; i++) {</td></tr><tr class="hit"><td class="line">446</td><td class="hits">26842</td><td class="source"> this[this.flex[i]] = true;</td></tr><tr class="hit"><td class="line">447</td><td class="hits">26842</td><td class="source"> if (par = grammemes[this.flex[i]].parent) {</td></tr><tr class="hit"><td class="line">448</td><td class="hits">24428</td><td class="source"> this[par] = this.flex[i];</td></tr><tr><td class="line">449</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">450</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">451</td><td class="hits">9760</td><td class="source"> if ('POST' in this) {</td></tr><tr class="hit"><td class="line">452</td><td class="hits">9760</td><td class="source"> this.POS = this.POST;</td></tr><tr><td class="line">453</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">454</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">455</td><td class="hits">1</td><td class="source"> Tag.prototype.toString = function() {</td></tr><tr class="miss"><td class="line">456</td><td class="hits">0</td><td class="source"> return (this.stat.join(',') + ' ' + this.flex.join(',')).trim();</td></tr><tr><td class="line">457</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">458</td><td class="hits"></td><td class="source"> // Проверяет согласованность с конкретными значениями граммем либо со списком граммем из другого тега (или слова)</td></tr><tr><td class="line">459</td><td class="hits"></td><td class="source"> // tag.matches({ 'POS' : 'NOUN', 'GNdr': ['masc', 'neut'] })</td></tr><tr><td class="line">460</td><td class="hits"></td><td class="source"> // Ключи — названия граммем, значения — дочерние граммемы, массивы граммем, либо true/false</td></tr><tr><td class="line">461</td><td class="hits"></td><td class="source"> // tag.matches(otherTag, ['POS', 'GNdr'])</td></tr><tr><td class="line">462</td><td class="hits"></td><td class="source"> // Тег (или слово) + список граммем, значения которых у этих двух тегов должны совпадать</td></tr><tr class="hit"><td class="line">463</td><td class="hits">1</td><td class="source"> Tag.prototype.matches = function(tag, grammemes) {</td></tr><tr class="miss"><td class="line">464</td><td class="hits">0</td><td class="source"> if (!grammemes) {</td></tr><tr><td class="line">465</td><td class="hits"></td><td class="source"> // Match to map</td></tr><tr class="miss"><td class="line">466</td><td class="hits">0</td><td class="source"> for (var k in tag) {</td></tr><tr class="miss"><td class="line">467</td><td class="hits">0</td><td class="source"> if (Object.prototype.toString.call(tag[k]) === '[object Array]') {</td></tr><tr class="miss"><td class="line">468</td><td class="hits">0</td><td class="source"> if (!tag[k].indexOf(this[k])) {</td></tr><tr class="miss"><td class="line">469</td><td class="hits">0</td><td class="source"> return false;</td></tr><tr><td class="line">470</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">471</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="miss"><td class="line">472</td><td class="hits">0</td><td class="source"> if (tag[k] != this[k]) {</td></tr><tr class="miss"><td class="line">473</td><td class="hits">0</td><td class="source"> return false;</td></tr><tr><td class="line">474</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">475</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">476</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">477</td><td class="hits">0</td><td class="source"> return true;</td></tr><tr><td class="line">478</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">479</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">480</td><td class="hits">0</td><td class="source"> if (tag instanceof Word) {</td></tr><tr class="miss"><td class="line">481</td><td class="hits">0</td><td class="source"> tag = tag.tag;</td></tr><tr><td class="line">482</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">483</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">484</td><td class="hits"></td><td class="source"> // Match to another tag</td></tr><tr class="miss"><td class="line">485</td><td class="hits">0</td><td class="source"> for (var i = 0; i < grammemes.length; i++) {</td></tr><tr class="miss"><td class="line">486</td><td class="hits">0</td><td class="source"> if (tag[grammemes[i]] != this[grammemes[i]]) {</td></tr><tr class="miss"><td class="line">487</td><td class="hits">0</td><td class="source"> return false;</td></tr><tr><td class="line">488</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">489</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">490</td><td class="hits">0</td><td class="source"> return true;</td></tr><tr><td class="line">491</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">492</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">493</td><td class="hits">1</td><td class="source"> var Word = function(val, paradigmIdx, formIdx, stutterCnt, typosCnt) {</td></tr><tr class="miss"><td class="line">494</td><td class="hits">0</td><td class="source"> this.val = val;</td></tr><tr class="miss"><td class="line">495</td><td class="hits">0</td><td class="source"> this.paradigmIdx = paradigmIdx;</td></tr><tr class="miss"><td class="line">496</td><td class="hits">0</td><td class="source"> this.paradigm = paradigms[paradigmIdx];</td></tr><tr class="miss"><td class="line">497</td><td class="hits">0</td><td class="source"> var len = this.paradigm.length / 3;</td></tr><tr class="miss"><td class="line">498</td><td class="hits">0</td><td class="source"> this.formIdx = formIdx;</td></tr><tr class="miss"><td class="line">499</td><td class="hits">0</td><td class="source"> this.tag = tags[this.paradigm[len + formIdx]];</td></tr><tr class="miss"><td class="line">500</td><td class="hits">0</td><td class="source"> this.stutterCnt = stutterCnt;</td></tr><tr class="miss"><td class="line">501</td><td class="hits">0</td><td class="source"> this.typosCnt = typosCnt;</td></tr><tr><td class="line">502</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">503</td><td class="hits"></td><td class="source"> // Возвращает основу слова</td></tr><tr class="hit"><td class="line">504</td><td class="hits">1</td><td class="source"> Word.prototype.base = function() {</td></tr><tr class="miss"><td class="line">505</td><td class="hits">0</td><td class="source"> if (this._base) {</td></tr><tr class="miss"><td class="line">506</td><td class="hits">0</td><td class="source"> return this._base;</td></tr><tr><td class="line">507</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">508</td><td class="hits">0</td><td class="source"> var len = this.paradigm.length / 3;</td></tr><tr class="miss"><td class="line">509</td><td class="hits">0</td><td class="source"> return this._base = this.val.substring(prefixes[this.paradigm[(len << 1) + this.formIdx]].length, this.val.length - suffixes[this.paradigm[this.formIdx]].length);</td></tr><tr><td class="line">510</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">511</td><td class="hits"></td><td class="source"> // Приводит к начальной форме. Аргумент keepPOS=true нужен, если требуется не менять часть речи при нормализации (например, не делать из причастия инфинитив).</td></tr><tr><td class="line">512</td><td class="hits"></td><td class="source"> // TODO: некоторые смены частей речи, возможно, стоит делать в любом случае (т.к., например, компаративы, краткие формы причастий и прилагательных разделены, инфинитив отделен от глагола)</td></tr><tr class="hit"><td class="line">513</td><td class="hits">1</td><td class="source"> Word.prototype.normalize = function(keepPOS) {</td></tr><tr class="miss"><td class="line">514</td><td class="hits">0</td><td class="source"> return this.inflect(keepPOS ? { POS: this.tag.POS } : 0);</td></tr><tr><td class="line">515</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">516</td><td class="hits"></td><td class="source"> // Склоняет/спрягает слово так, чтобы оно соответствовало граммемам другого слова, тега или просто конкретным граммемам (подробнее см. Tag.prototype.matches).</td></tr><tr><td class="line">517</td><td class="hits"></td><td class="source"> // Всегда выбирается первый подходящий вариант.</td></tr><tr class="hit"><td class="line">518</td><td class="hits">1</td><td class="source"> Word.prototype.inflect = function(tag, grammemes) {</td></tr><tr class="miss"><td class="line">519</td><td class="hits">0</td><td class="source"> var len = this.paradigm.length / 3;</td></tr><tr class="miss"><td class="line">520</td><td class="hits">0</td><td class="source"> if (!grammemes && typeof tag === 'number') {</td></tr><tr><td class="line">521</td><td class="hits"></td><td class="source"> // Inflect to specific formIdx</td></tr><tr class="miss"><td class="line">522</td><td class="hits">0</td><td class="source"> return [prefixes[this.paradigm[(len << 1) + tag]] + this.base() + suffixes[this.paradigm[tag]], tags[this.paradigm[len + tag]]];</td></tr><tr><td class="line">523</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">524</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">525</td><td class="hits">0</td><td class="source"> for (var formIdx = 0; formIdx < len; formIdx++) {</td></tr><tr class="miss"><td class="line">526</td><td class="hits">0</td><td class="source"> if (tags[this.paradigm[len + formIdx]].matches(tag, grammemes)) {</td></tr><tr class="miss"><td class="line">527</td><td class="hits">0</td><td class="source"> return [prefixes[this.paradigm[(len << 1) + formIdx]] + this.base() + suffixes[this.paradigm[formIdx]], tags[this.paradigm[len + formIdx]]];</td></tr><tr><td class="line">528</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">529</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">530</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">531</td><td class="hits">0</td><td class="source"> return false;</td></tr><tr><td class="line">532</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">533</td><td class="hits"></td><td class="source"> // Аналогично Tag.prototype.matches.</td></tr><tr class="hit"><td class="line">534</td><td class="hits">1</td><td class="source"> Word.prototype.matches = function(tag, grammemes) {</td></tr><tr class="miss"><td class="line">535</td><td class="hits">0</td><td class="source"> return this.tag.matches(tag, grammemes);</td></tr><tr><td class="line">536</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">537</td><td class="hits"></td><td class="source"> // Выводит информацию о слове в консоль.</td></tr><tr class="hit"><td class="line">538</td><td class="hits">1</td><td class="source"> Word.prototype.log = function() {</td></tr><tr class="miss"><td class="line">539</td><td class="hits">0</td><td class="source"> var len = this.paradigm.length / 3;</td></tr><tr class="miss"><td class="line">540</td><td class="hits">0</td><td class="source"> console.group(this.val);</td></tr><tr class="miss"><td class="line">541</td><td class="hits">0</td><td class="source"> console.log('Stutter?', this.stutterCnt, 'Typos?', this.typosCnt);</td></tr><tr class="miss"><td class="line">542</td><td class="hits">0</td><td class="source"> console.log(prefixes[this.paradigm[(len << 1) + this.formIdx]] + '|' + this.base() + '|' + suffixes[this.paradigm[this.formIdx]]);</td></tr><tr class="miss"><td class="line">543</td><td class="hits">0</td><td class="source"> console.log(this.tag.ext.toString());</td></tr><tr class="miss"><td class="line">544</td><td class="hits">0</td><td class="source"> var norm = this.normalize();</td></tr><tr class="miss"><td class="line">545</td><td class="hits">0</td><td class="source"> console.log('=> ', norm[0] + ' (' + norm[1].ext.toString() + ')');</td></tr><tr class="miss"><td class="line">546</td><td class="hits">0</td><td class="source"> var norm = this.normalize(true);</td></tr><tr class="miss"><td class="line">547</td><td class="hits">0</td><td class="source"> console.log('=> ', norm[0] + ' (' + norm[1].ext.toString() + ')');</td></tr><tr class="miss"><td class="line">548</td><td class="hits">0</td><td class="source"> console.groupCollapsed('Все формы: ' + len);</td></tr><tr class="miss"><td class="line">549</td><td class="hits">0</td><td class="source"> for (var formIdx = 0; formIdx < len; formIdx++) {</td></tr><tr class="miss"><td class="line">550</td><td class="hits">0</td><td class="source"> var form = this.inflect(formIdx);</td></tr><tr class="miss"><td class="line">551</td><td class="hits">0</td><td class="source"> console.log(form[0] + ' (' + form[1].ext.toString() + ')');</td></tr><tr><td class="line">552</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">553</td><td class="hits">0</td><td class="source"> console.groupEnd();</td></tr><tr class="miss"><td class="line">554</td><td class="hits">0</td><td class="source"> console.groupEnd();</td></tr><tr><td class="line">555</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">556</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">557</td><td class="hits">1</td><td class="source"> var Morph = function(word, config) {</td></tr><tr class="hit"><td class="line">558</td><td class="hits">1</td><td class="source"> config = config || defaults;</td></tr><tr><td class="line">559</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">560</td><td class="hits">1</td><td class="source"> for (var k in defaults) {</td></tr><tr class="hit"><td class="line">561</td><td class="hits">3</td><td class="source"> if (!(k in config)) {</td></tr><tr class="miss"><td class="line">562</td><td class="hits">0</td><td class="source"> config[k] = defaults[k];</td></tr><tr><td class="line">563</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">564</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">565</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">566</td><td class="hits">1</td><td class="source"> var opts;</td></tr><tr class="hit"><td class="line">567</td><td class="hits">1</td><td class="source"> if (config.typos == 'auto') {</td></tr><tr class="miss"><td class="line">568</td><td class="hits">0</td><td class="source"> opts = words.findAll(word, config.replacements, config.stutter, 0);</td></tr><tr class="miss"><td class="line">569</td><td class="hits">0</td><td class="source"> if (!opts.length && word.length > 4) {</td></tr><tr class="miss"><td class="line">570</td><td class="hits">0</td><td class="source"> opts = words.findAll(word, config.replacements, config.stutter, 1);</td></tr><tr class="miss"><td class="line">571</td><td class="hits">0</td><td class="source"> if (!opts.length && word.length > 9) {</td></tr><tr class="miss"><td class="line">572</td><td class="hits">0</td><td class="source"> opts = words.findAll(word, config.replacements, config.stutter, 2);</td></tr><tr><td class="line">573</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">574</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">575</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">576</td><td class="hits">1</td><td class="source"> opts = words.findAll(word, config.replacements, config.stutter, config.typos);</td></tr><tr><td class="line">577</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">578</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">579</td><td class="hits">1</td><td class="source"> var vars = [];</td></tr><tr><td class="line">580</td><td class="hits"></td><td class="source"> //console.log(opts);</td></tr><tr class="hit"><td class="line">581</td><td class="hits">1</td><td class="source"> for (var i = 0; i < opts.length; i++) {</td></tr><tr class="miss"><td class="line">582</td><td class="hits">0</td><td class="source"> for (var j = 0; j < opts[i][1].length; j++) {</td></tr><tr class="miss"><td class="line">583</td><td class="hits">0</td><td class="source"> var word = new Word(opts[i][0], opts[i][1][j][0], opts[i][1][j][1], opts[i][2], opts[i][3]);</td></tr><tr><td class="line">584</td><td class="hits"></td><td class="source"> //word.log();</td></tr><tr class="miss"><td class="line">585</td><td class="hits">0</td><td class="source"> vars.push(word);</td></tr><tr><td class="line">586</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">587</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">588</td><td class="hits">1</td><td class="source"> return vars;</td></tr><tr><td class="line">589</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">590</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">591</td><td class="hits">1</td><td class="source"> Morph.setDefaults = function(config) {</td></tr><tr class="miss"><td class="line">592</td><td class="hits">0</td><td class="source"> defaults = config;</td></tr><tr><td class="line">593</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">594</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">595</td><td class="hits">1</td><td class="source"> Morph.init = function(path, callback) {</td></tr><tr class="hit"><td class="line">596</td><td class="hits">1</td><td class="source"> var loading = 0;</td></tr><tr class="hit"><td class="line">597</td><td class="hits">1</td><td class="source"> var tagsInt, tagsExt;</td></tr><tr class="hit"><td class="line">598</td><td class="hits">1</td><td class="source"> function loaded() {</td></tr><tr class="hit"><td class="line">599</td><td class="hits">10</td><td class="source"> if (!--loading) {</td></tr><tr class="hit"><td class="line">600</td><td class="hits">1</td><td class="source"> tags = Array(tagsInt.length);</td></tr><tr class="hit"><td class="line">601</td><td class="hits">1</td><td class="source"> for (var i = 0; i < tagsInt.length; i++) {</td></tr><tr class="hit"><td class="line">602</td><td class="hits">4880</td><td class="source"> tags[i] = new Tag(tagsInt[i]);</td></tr><tr class="hit"><td class="line">603</td><td class="hits">4880</td><td class="source"> tags[i].ext = new Tag(tagsExt[i]);</td></tr><tr><td class="line">604</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">605</td><td class="hits">1</td><td class="source"> tags = deepFreeze(tags);</td></tr><tr class="hit"><td class="line">606</td><td class="hits">1</td><td class="source"> callback && callback(null, Morph);</td></tr><tr><td class="line">607</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">608</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">609</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">610</td><td class="hits">1</td><td class="source"> loading++;</td></tr><tr class="hit"><td class="line">611</td><td class="hits">1</td><td class="source"> Az.DAWG.load(path + '/words.dawg', 'words', function(err, dawg) {</td></tr><tr class="hit"><td class="line">612</td><td class="hits">1</td><td class="source"> words = dawg;</td></tr><tr class="hit"><td class="line">613</td><td class="hits">1</td><td class="source"> loaded();</td></tr><tr><td class="line">614</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">615</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">616</td><td class="hits">1</td><td class="source"> for (var prefix = 0; prefix < 3; prefix++) {</td></tr><tr class="hit"><td class="line">617</td><td class="hits">3</td><td class="source"> (function(prefix) {</td></tr><tr class="hit"><td class="line">618</td><td class="hits">3</td><td class="source"> loading++;</td></tr><tr class="hit"><td class="line">619</td><td class="hits">3</td><td class="source"> Az.DAWG.load(path + '/prediction-suffixes-' + prefix + '.dawg', 'probs', function(err, dawg) {</td></tr><tr class="hit"><td class="line">620</td><td class="hits">3</td><td class="source"> predictionSuffixes[prefix] = dawg;</td></tr><tr class="hit"><td class="line">621</td><td class="hits">3</td><td class="source"> loaded();</td></tr><tr><td class="line">622</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">623</td><td class="hits"></td><td class="source"> })(prefix);</td></tr><tr><td class="line">624</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">625</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">626</td><td class="hits">1</td><td class="source"> loading++;</td></tr><tr class="hit"><td class="line">627</td><td class="hits">1</td><td class="source"> Az.DAWG.load(path + '/p_t_given_w.intdawg', 'int', function(err, dawg) {</td></tr><tr class="hit"><td class="line">628</td><td class="hits">1</td><td class="source"> probabilities = dawg;</td></tr><tr class="hit"><td class="line">629</td><td class="hits">1</td><td class="source"> loaded();</td></tr><tr><td class="line">630</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">631</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">632</td><td class="hits">1</td><td class="source"> loading++;</td></tr><tr class="hit"><td class="line">633</td><td class="hits">1</td><td class="source"> Az.load(path + '/grammemes.json', 'json', function(err, json) {</td></tr><tr class="hit"><td class="line">634</td><td class="hits">1</td><td class="source"> grammemes = {};</td></tr><tr class="hit"><td class="line">635</td><td class="hits">1</td><td class="source"> for (var i = 0; i < json.length; i++) {</td></tr><tr class="hit"><td class="line">636</td><td class="hits">113</td><td class="source"> grammemes[json[i][0]] = grammemes[json[i][2]] = {</td></tr><tr><td class="line">637</td><td class="hits"></td><td class="source"> parent: json[i][1],</td></tr><tr><td class="line">638</td><td class="hits"></td><td class="source"> internal: json[i][0],</td></tr><tr><td class="line">639</td><td class="hits"></td><td class="source"> external: json[i][2],</td></tr><tr><td class="line">640</td><td class="hits"></td><td class="source"> externalFull: json[i][3]</td></tr><tr><td class="line">641</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">642</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">643</td><td class="hits">1</td><td class="source"> loaded();</td></tr><tr><td class="line">644</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">645</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">646</td><td class="hits">1</td><td class="source"> loading++;</td></tr><tr class="hit"><td class="line">647</td><td class="hits">1</td><td class="source"> Az.load(path + '/gramtab-opencorpora-int.json', 'json', function(err, json) {</td></tr><tr class="hit"><td class="line">648</td><td class="hits">1</td><td class="source"> tagsInt = json;</td></tr><tr class="hit"><td class="line">649</td><td class="hits">1</td><td class="source"> loaded();</td></tr><tr><td class="line">650</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">651</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">652</td><td class="hits">1</td><td class="source"> loading++;</td></tr><tr class="hit"><td class="line">653</td><td class="hits">1</td><td class="source"> Az.load(path + '/gramtab-opencorpora-ext.json', 'json', function(err, json) {</td></tr><tr class="hit"><td class="line">654</td><td class="hits">1</td><td class="source"> tagsExt = json;</td></tr><tr class="hit"><td class="line">655</td><td class="hits">1</td><td class="source"> loaded();</td></tr><tr><td class="line">656</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">657</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">658</td><td class="hits">1</td><td class="source"> loading++;</td></tr><tr class="hit"><td class="line">659</td><td class="hits">1</td><td class="source"> Az.load(path + '/suffixes.json', 'json', function(err, json) {</td></tr><tr class="hit"><td class="line">660</td><td class="hits">1</td><td class="source"> suffixes = json;</td></tr><tr class="hit"><td class="line">661</td><td class="hits">1</td><td class="source"> loaded();</td></tr><tr><td class="line">662</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">663</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">664</td><td class="hits">1</td><td class="source"> loading++;</td></tr><tr class="hit"><td class="line">665</td><td class="hits">1</td><td class="source"> Az.load(path + '/paradigms.array', 'arraybuffer', function(err, data) {</td></tr><tr class="hit"><td class="line">666</td><td class="hits">1</td><td class="source"> var list = new Uint16Array(data),</td></tr><tr><td class="line">667</td><td class="hits"></td><td class="source"> count = list[0],</td></tr><tr><td class="line">668</td><td class="hits"></td><td class="source"> pos = 1;</td></tr><tr><td class="line">669</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">670</td><td class="hits">1</td><td class="source"> paradigms = [];</td></tr><tr class="hit"><td class="line">671</td><td class="hits">1</td><td class="source"> for (var i = 0; i < count; i++) {</td></tr><tr class="hit"><td class="line">672</td><td class="hits">3256</td><td class="source"> var size = list[pos++];</td></tr><tr class="hit"><td class="line">673</td><td class="hits">3256</td><td class="source"> paradigms.push(list.subarray(pos, pos + size));</td></tr><tr class="hit"><td class="line">674</td><td class="hits">3256</td><td class="source"> pos += size;</td></tr><tr><td class="line">675</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">676</td><td class="hits">1</td><td class="source"> loaded();</td></tr><tr><td class="line">677</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">678</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">679</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">680</td><td class="hits">1</td><td class="source"> return Morph;</td></tr><tr><td class="line">681</td><td class="hits"></td><td class="source">}));</td></tr><tr class="hit"><td class="line">682</td><td class="hits">1</td><td class="source">;(function (global, factory) {</td></tr><tr class="hit"><td class="line">683</td><td class="hits">1</td><td class="source"> typeof exports === 'object' && typeof module !== 'undefined' ? (module.exports = module.exports || {}) && (module.exports.Syntax = factory(module.exports)) :</td></tr><tr><td class="line">684</td><td class="hits"></td><td class="source"> typeof define === 'function' && define.amd ? define('Az.Syntax', ['Az'], factory) :</td></tr><tr><td class="line">685</td><td class="hits"></td><td class="source"> (global.Az = global.Az || {}) && (global.Az.Syntax = factory(global.Az))</td></tr><tr class="hit"><td class="line">686</td><td class="hits">1</td><td class="source">}(this, function (Az) { 'use strict';</td></tr><tr><td class="line">687</td><td class="hits"></td><td class="source"> // TBD: Syntax analyzer</td></tr><tr class="hit"><td class="line">688</td><td class="hits">1</td><td class="source"> var Syntax = function() {</td></tr><tr><td class="line">689</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">690</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">691</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">692</td><td class="hits">1</td><td class="source"> return Syntax;</td></tr><tr><td class="line">693</td><td class="hits"></td><td class="source">}));</td></tr><tr class="hit"><td class="line">694</td><td class="hits">1</td><td class="source">;(function (global, factory) {</td></tr><tr class="hit"><td class="line">695</td><td class="hits">1</td><td class="source"> typeof exports === 'object' && typeof module !== 'undefined' ? (module.exports = module.exports || {}) && (module.exports.Tokens = factory()) :</td></tr><tr><td class="line">696</td><td class="hits"></td><td class="source"> typeof define === 'function' && define.amd ? define('Az.Tokens', ['Az'], factory) :</td></tr><tr><td class="line">697</td><td class="hits"></td><td class="source"> (global.Az = global.Az || {}) && (global.Az.Tokens = factory())</td></tr><tr class="hit"><td class="line">698</td><td class="hits">1</td><td class="source">}(this, function () { 'use strict';</td></tr><tr class="hit"><td class="line">699</td><td class="hits">1</td><td class="source"> var TLDs = 'ac|ad|ae|aero|af|ag|ai|al|am|ao|aq|ar|arpa|as|asia|at|au|aw|ax|az|ba|bb|be|bf|bg|bh|bi|biz|bj|bm|bo|br|bs|bt|bv|bw|by|bz|ca|cat|cc|cd|cf|cg|ch|ci|cl|cm|cn|co|com|coop|cr|cu|cv|cw|cx|cz|de|dj|dk|dm|do|dz|ec|edu|ee|eg|es|et|eu|fi|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gov|gp|gq|gr|gs|gt|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|info|int|io|iq|ir|is|it|je|jo|jobs|jp|kg|ki|km|kn|kp|kr|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mil|mk|ml|mn|mo|mobi|mp|mq|mr|ms|mt|mu|museum|mv|mw|mx|my|na|name|nc|ne|net|nf|ng|nl|no|nr|nu|nz|om|org|pa|pe|pf|ph|pk|pl|pm|pn|post|pr|pro|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tel|tf|tg|th|tj|tk|tl|tm|tn|to|tr|travel|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|yt|امارات|հայ|বাংলা|бел|中国|中國|الجزائر|مصر|ею|გე|ελ|香港|भारत|بھارت|భారత్|ભારત|ਭਾਰਤ|ভারত|இந்தியா|ایران|ايران|عراق|الاردن|한국|қаз|ලංකා|இலங்கை|المغرب|мкд|мон|澳門|澳门|مليسيا|عمان|پاکستان|پاكستان|فلسطين|срб|рф|قطر|السعودية|السعودیة|السعودیۃ|السعوديه|سودان|新加坡|சிங்கப்பூர்|سورية|سوريا|ไทย|تونس|台灣|台湾|臺灣|укр|اليمن|xxx|zm|aaa|aarp|abarth|abb|abbott|abbvie|abc|able|abogado|abudhabi|academy|accenture|accountant|accountants|aco|active|actor|adac|ads|adult|aeg|aetna|afamilycompany|afl|africa|africamagic|agakhan|agency|aig|aigo|airbus|airforce|airtel|akdn|alfaromeo|alibaba|alipay|allfinanz|allstate|ally|alsace|alstom|americanexpress|americanfamily|amex|amfam|amica|amsterdam|analytics|android|anquan|anz|aol|apartments|app|apple|aquarelle|arab|aramco|archi|army|art|arte|asda|associates|athleta|attorney|auction|audi|audible|audio|auspost|author|auto|autos|avianca|aws|axa|azure|baby|baidu|banamex|bananarepublic|band|bank|bar|barcelona|barclaycard|barclays|barefoot|bargains|baseball|basketball|bauhaus|bayern|bbc|bbt|bbva|bcg|bcn|beats|beauty|beer|bentley|berlin|best|bestbuy|bet|bharti|bible|bid|bike|bing|bingo|bio|black|blackfriday|blanco|blockbuster|blog|bloomberg|blue|bms|bmw|bnl|bnpparibas|boats|boehringer|bofa|bom|bond|boo|book|booking|boots|bosch|bostik|boston|bot|boutique|box|bradesco|bridgestone|broadway|broker|brother|brussels|budapest|bugatti|build|builders|business|buy|buzz|bzh|cab|cafe|cal|call|calvinklein|camera|camp|cancerresearch|canon|capetown|capital|capitalone|car|caravan|cards|care|career|careers|cars|cartier|casa|case|caseih|cash|casino|catering|catholic|cba|cbn|cbre|cbs|ceb|center|ceo|cern|cfa|cfd|chanel|channel|chase|chat|cheap|chintai|chloe|christmas|chrome|chrysler|church|cipriani|circle|cisco|citadel|citi|citic|city|cityeats|claims|cleaning|click|clinic|clinique|clothing|cloud|club|clubmed|coach|codes|coffee|college|cologne|comcast|commbank|community|company|compare|computer|comsec|condos|construction|consulting|contact|contractors|cooking|cookingchannel|cool|corsica|country|coupon|coupons|courses|credit|creditcard|creditunion|cricket|crown|crs|cruise|cruises|csc|cuisinella|cymru|cyou|dabur|dad|dance|date|dating|datsun|day|dclk|dds|deal|dealer|deals|degree|delivery|dell|deloitte|delta|democrat|dental|dentist|desi|design|dev|dhl|diamonds|diet|digital|direct|directory|discount|discover|dish|diy|dnp|docs|dodge|dog|doha|domains|dot|download|drive|dstv|dtv|dubai|duck|dunlop|duns|dupont|durban|dvag|dwg|earth|eat|edeka|education|email|emerck|emerson|energy|engineer|engineering|enterprises|epost|epson|equipment|ericsson|erni|esq|estate|esurance|etisalat|eurovision|eus|events|everbank|exchange|expert|exposed|express|extraspace|fage|fail|fairwinds|faith|family|fan|fans|farm|farmers|fashion|fast|fedex|feedback|ferrari|ferrero|fiat|fidelity|fido|film|final|finance|financial|fire|firestone|firmdale|fish|fishing|fit|fitness|flickr|flights|flir|florist|flowers|flsmidth|fly|foo|foodnetwork|football|ford|forex|forsale|forum|foundation|fox|free|fresenius|frl|frogans|frontdoor|frontier|ftr|fujitsu|fujixerox|fun|fund|furniture|futbol|fyi|gal|gallery|gallo|gallup|game|games|gap|garden|gbiz|gdn|gea|gent|genting|george|ggee|gift|gifts|gives|giving|glade|glass|gle|global|globo|gmail|gmbh|gmo|gmx|godaddy|gold|goldpoint|golf|goo|goodhands|goodyear|goog|google|gop|got|gotv|grainger|graphics|gratis|green|gripe|group|guardian|gucci|guge|guide|guitars|guru|hair|hamburg|hangout|haus|hbo|hdfc|hdfcbank|health|healthcare|help|helsinki|here|hermes|hgtv|hiphop|hisamitsu|hitachi|hiv|hkt|hockey|holdings|holiday|homedepot|homegoods|homes|homesense|honda|honeywell|horse|host|hosting|hot|hoteles|hotmail|house|how|hsbc|htc|hughes|hyatt|hyundai|ibm|icbc|ice|icu|ieee|ifm|iinet|ikano|imamat|imdb|immo|immobilien|industries|infiniti|ing|ink|institute|insurance|insure|intel|international|intuit|investments|ipiranga|irish|iselect|ismaili|ist|istanbul|itau|itv|iveco|iwc|jaguar|java|jcb|jcp|jeep|jetzt|jewelry|jio|jlc|jll|jmp|jnj|joburg|jot|joy|jpmorgan|jprs|juegos|juniper|kaufen|kddi|kerryhotels|kerrylogistics|kerryproperties|kfh|kia|kim|kinder|kindle|kitchen|kiwi|koeln|komatsu|kosher|kpmg|kpn|krd|kred|kuokgroup|kyknet|kyoto|lacaixa|ladbrokes|lamborghini|lamer|lancaster|lancia|lancome|land|landrover|lanxess|lasalle|lat|latino|latrobe|law|lawyer|lds|lease|leclerc|lefrak|legal|lego|lexus|lgbt|liaison|lidl|life|lifeinsurance|lifestyle|lighting|like|lilly|limited|limo|lincoln|linde|link|lipsy|live|living|lixil|loan|loans|locker|locus|loft|lol|london|lotte|lotto|love|lpl|lplfinancial|ltd|ltda|lundbeck|lupin|luxe|luxury|macys|madrid|maif|maison|makeup|man|management|mango|market|marketing|markets|marriott|marshalls|maserati|mattel|mba|mcd|mcdonalds|mckinsey|med|media|meet|melbourne|meme|memorial|men|menu|meo|metlife|miami|microsoft|mini|mint|mit|mitsubishi|mlb|mls|mma|mnet|mobily|moda|moe|moi|mom|monash|money|monster|montblanc|mopar|mormon|mortgage|moscow|moto|motorcycles|mov|movie|movistar|msd|mtn|mtpc|mtr|multichoice|mutual|mutuelle|mzansimagic|nab|nadex|nagoya|naspers|nationwide|natura|navy|nba|nec|netbank|netflix|network|neustar|new|newholland|news|next|nextdirect|nexus|nfl|ngo|nhk|nico|nike|nikon|ninja|nissan|nissay|nokia|northwesternmutual|norton|now|nowruz|nowtv|nra|nrw|ntt|nyc|obi|observer|off|office|okinawa|olayan|olayangroup|oldnavy|ollo|omega|one|ong|onl|online|onyourside|ooo|open|oracle|orange|organic|orientexpress|origins|osaka|otsuka|ott|ovh|page|pamperedchef|panasonic|panerai|paris|pars|partners|parts|party|passagens|pay|payu|pccw|pet|pfizer|pharmacy|philips|photo|photography|photos|physio|piaget|pics|pictet|pictures|pid|pin|ping|pink|pioneer|pizza|place|play|playstation|plumbing|plus|pnc|pohl|poker|politie|porn|pramerica|praxi|press|prime|prod|productions|prof|progressive|promo|properties|property|protection|pru|prudential|pub|pwc|qpon|quebec|quest|qvc|racing|raid|read|realestate|realtor|realty|recipes|red|redstone|redumbrella|rehab|reise|reisen|reit|reliance|ren|rent|rentals|repair|report|republican|rest|restaurant|review|reviews|rexroth|rich|richardli|ricoh|rightathome|ril|rio|rip|rmit|rocher|rocks|rodeo|rogers|room|rsvp|ruhr|run|rwe|ryukyu|saarland|safe|safety|sakura|sale|salon|samsclub|samsung|sandvik|sandvikcoromant|sanofi|sap|sapo|sarl|sas|save|saxo|sbi|sbs|sca|scb|schaeffler|schmidt|scholarships|school|schule|schwarz|science|scjohnson|scor|scot|seat|secure|security|seek|select|sener|services|ses|seven|sew|sex|sexy|sfr|shangrila|sharp|shaw|shell|shia|shiksha|shoes|shopping|shouji|show|showtime|shriram|silk|sina|singles|site|ski|skin|sky|skype|sling|smart|smile|sncf|soccer|social|softbank|software|sohu|solar|solutions|song|sony|soy|space|spiegel|spot|spreadbetting|srl|srt|stada|staples|star|starhub|statebank|statefarm|statoil|stc|stcgroup|stockholm|storage|store|stream|studio|study|style|sucks|supersport|supplies|supply|support|surf|surgery|suzuki|swatch|swiftcover|swiss|sydney|symantec|systems|tab|taipei|talk|taobao|target|tatamotors|tatar|tattoo|tax|taxi|tci|tdk|team|tech|technology|telecity|telefonica|temasek|tennis|teva|thd|theater|theatre|theguardian|tiaa|tickets|tienda|tiffany|tips|tires|tirol|tjmaxx|tjx|tkmaxx|tmall|today|tokyo|tools|top|toray|toshiba|total|tours|town|toyota|toys|trade|trading|training|travelchannel|travelers|travelersinsurance|trust|trv|tube|tui|tunes|tushu|tvs|ubank|ubs|uconnect|unicom|university|uno|uol|ups|vacations|vana|vanguard|vegas|ventures|verisign|versicherung|vet|viajes|video|vig|viking|villas|vin|vip|virgin|visa|vision|vista|vistaprint|viva|vivo|vlaanderen|vodka|volkswagen|volvo|vote|voting|voto|voyage|vuelos|wales|walmart|walter|wang|wanggou|warman|watch|watches|weather|weatherchannel|webcam|weber|website|wed|wedding|weibo|weir|whoswho|wien|wiki|williamhill|win|windows|wine|winners|wme|wolterskluwer|woodside|work|works|world|wow|wtc|wtf|xbox|xerox|xfinity|xihuan|xin|कॉम|セール|佛山|慈善|集团|在线|大众汽车|点看|คอม|八卦|موقع|一号店|公益|公司|香格里拉|网站|移动|我爱你|москва|католик|онлайн|сайт|联通|קום|时尚|微博|淡马锡|ファッション|орг|नेट|ストア|삼성|商标|商店|商城|дети|ポイント|新闻|工行|家電|كوم|中文网|中信|娱乐|谷歌|電訊盈科|购物|クラウド|通販|网店|संगठन|餐厅|网络|ком|诺基亚|食品|飞利浦|手表|手机|ارامكو|العليان|اتصالات|بازار|موبايلي|ابوظبي|كاثوليك|همراه|닷컴|政府|شبكة|بيتك|عرب|机构|组织机构|健康|рус|珠宝|大拿|みんな|グーグル|世界|書籍|网址|닷넷|コム|天主教|游戏|vermögensberater|vermögensberatung|企业|信息|嘉里大酒店|嘉里|广东|政务|xperia|xyz|yachts|yahoo|yamaxun|yandex|yodobashi|yoga|yokohama|you|youtube|yun|zappos|zara|zero|zip|zippo|zone|zuerich'.split('|');</td></tr><tr class="hit"><td class="line">700</td><td class="hits">1</td><td class="source"> var defaults = {</td></tr><tr><td class="line">701</td><td class="hits"></td><td class="source"> html: false,</td></tr><tr><td class="line">702</td><td class="hits"></td><td class="source"> wiki: false, // TODO: check all cases</td></tr><tr><td class="line">703</td><td class="hits"></td><td class="source"> markdown: false, // TODO: check all cases</td></tr><tr><td class="line">704</td><td class="hits"></td><td class="source"> hashtags: true,</td></tr><tr><td class="line">705</td><td class="hits"></td><td class="source"> mentions: true,</td></tr><tr><td class="line">706</td><td class="hits"></td><td class="source"> emails: true,</td></tr><tr><td class="line">707</td><td class="hits"></td><td class="source"> links: {</td></tr><tr><td class="line">708</td><td class="hits"></td><td class="source"> protocols: true,</td></tr><tr><td class="line">709</td><td class="hits"></td><td class="source"> www: true,</td></tr><tr><td class="line">710</td><td class="hits"></td><td class="source"> tlds: {}</td></tr><tr><td class="line">711</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">712</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">713</td><td class="hits"></td><td class="source"> /* TODO: add more named HTML entities */</td></tr><tr class="hit"><td class="line">714</td><td class="hits">1</td><td class="source"> var HTML_ENTITIES = { nbsp: ' ', quot: '"', gt: '>', lt: '<', amp: '&' };</td></tr><tr><td class="line">715</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">716</td><td class="hits">1</td><td class="source"> for (var i = 0; i < TLDs.length; i++) {</td></tr><tr class="hit"><td class="line">717</td><td class="hits">1528</td><td class="source"> defaults.links.tlds[TLDs[i]] = true;</td></tr><tr><td class="line">718</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">719</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">720</td><td class="hits"></td><td class="source"> // Start splitting text into tokens</td></tr><tr><td class="line">721</td><td class="hits"></td><td class="source"> // Returns a context, use `done` method to retrieve result</td></tr><tr class="hit"><td class="line">722</td><td class="hits">1</td><td class="source"> var Tokens = function(text, config) {</td></tr><tr class="hit"><td class="line">723</td><td class="hits">8</td><td class="source"> if (this instanceof Tokens) {</td></tr><tr class="hit"><td class="line">724</td><td class="hits">4</td><td class="source"> this.tokens = [];</td></tr><tr class="hit"><td class="line">725</td><td class="hits">4</td><td class="source"> this.config = config || defaults;</td></tr><tr class="hit"><td class="line">726</td><td class="hits">4</td><td class="source"> this.append(text);</td></tr><tr class="hit"><td class="line">727</td><td class="hits">4</td><td class="source"> this.index = -1;</td></tr><tr><td class="line">728</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">729</td><td class="hits">4</td><td class="source"> return new Tokens(text);</td></tr><tr><td class="line">730</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">731</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">732</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">733</td><td class="hits"></td><td class="source"> // Adds more text content</td></tr><tr class="hit"><td class="line">734</td><td class="hits">1</td><td class="source"> Tokens.prototype.append = function(text, config) {</td></tr><tr><td class="line">735</td><td class="hits"></td><td class="source"> // TODO: get rid of 's' field (storing a copy of token)</td></tr><tr><td class="line">736</td><td class="hits"></td><td class="source"> // st + len + en should be enough (check that they are always correct)</td></tr><tr class="hit"><td class="line">737</td><td class="hits">4</td><td class="source"> config = config || this.config;</td></tr><tr class="hit"><td class="line">738</td><td class="hits">4</td><td class="source"> for (var i = 0; i < text.length; i++) {</td></tr><tr class="hit"><td class="line">739</td><td class="hits">94</td><td class="source"> var ch = text.charAt(i);</td></tr><tr class="hit"><td class="line">740</td><td class="hits">94</td><td class="source"> var code = text.charCodeAt(i);</td></tr><tr><td class="line">741</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">742</td><td class="hits">94</td><td class="source"> var append = false;</td></tr><tr class="hit"><td class="line">743</td><td class="hits">94</td><td class="source"> var last = this.tokens.length - 1;</td></tr><tr class="hit"><td class="line">744</td><td class="hits">94</td><td class="source"> var token = this.tokens[last];</td></tr><tr><td class="line">745</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">746</td><td class="hits">94</td><td class="source"> if (config.html && ch == ';') {</td></tr><tr><td class="line">747</td><td class="hits"></td><td class="source"> // </td></tr><tr class="miss"><td class="line">748</td><td class="hits">0</td><td class="source"> if (last > 0 && token.type == 'WORD' && this.tokens[last - 1].s == '&') {</td></tr><tr class="miss"><td class="line">749</td><td class="hits">0</td><td class="source"> var name = token.s.toLowerCase();</td></tr><tr class="miss"><td class="line">750</td><td class="hits">0</td><td class="source"> if (name in HTML_ENTITIES) {</td></tr><tr class="miss"><td class="line">751</td><td class="hits">0</td><td class="source"> ch = HTML_ENTITIES[name];</td></tr><tr class="miss"><td class="line">752</td><td class="hits">0</td><td class="source"> code = ch.charCodeAt(0);</td></tr><tr><td class="line">753</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">754</td><td class="hits">0</td><td class="source"> last -= 2;</td></tr><tr class="miss"><td class="line">755</td><td class="hits">0</td><td class="source"> token = this.tokens[last];</td></tr><tr class="miss"><td class="line">756</td><td class="hits">0</td><td class="source"> this.tokens.length = last + 1;</td></tr><tr><td class="line">757</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">758</td><td class="hits"></td><td class="source"> } else</td></tr><tr><td class="line">759</td><td class="hits"></td><td class="source"> // &x123AF5;</td></tr><tr><td class="line">760</td><td class="hits"></td><td class="source"> // &1234;</td></tr><tr class="miss"><td class="line">761</td><td class="hits">0</td><td class="source"> if (last > 1 && (token.type == 'NUMBER' || (token.type == 'WORD' && token.s[0] == 'x')) && this.tokens[last - 1].s == '#' && this.tokens[last - 2].s == '&') {</td></tr><tr class="miss"><td class="line">762</td><td class="hits">0</td><td class="source"> if (token.s[0] == 'x') {</td></tr><tr class="miss"><td class="line">763</td><td class="hits">0</td><td class="source"> code = parseInt(token.s.substr(1), 16);</td></tr><tr><td class="line">764</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="miss"><td class="line">765</td><td class="hits">0</td><td class="source"> code = parseInt(token.s, 10);</td></tr><tr><td class="line">766</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">767</td><td class="hits">0</td><td class="source"> ch = String.fromCharCode(code);</td></tr><tr><td class="line">768</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">769</td><td class="hits">0</td><td class="source"> last -= 3;</td></tr><tr class="miss"><td class="line">770</td><td class="hits">0</td><td class="source"> token = this.tokens[last];</td></tr><tr class="miss"><td class="line">771</td><td class="hits">0</td><td class="source"> this.tokens.length = last + 1;</td></tr><tr><td class="line">772</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">773</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">774</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">775</td><td class="hits">94</td><td class="source"> var charType = 'OTHER';</td></tr><tr class="hit"><td class="line">776</td><td class="hits">94</td><td class="source"> var charUpper = (ch.toLocaleLowerCase() != ch);</td></tr><tr class="hit"><td class="line">777</td><td class="hits">112</td><td class="source"> if (code >= 0x0400 && code <= 0x04FF) charType = 'CYRIL';</td></tr><tr class="hit"><td class="line">778</td><td class="hits">139</td><td class="source"> if ((code >= 0x0041 && code <= 0x005A) || (code >= 0x0061 && code <= 0x007A) || (code >= 0x00C0 && code <= 0x024F)) charType = 'LATIN';</td></tr><tr class="hit"><td class="line">779</td><td class="hits">97</td><td class="source"> if (code >= 0x0030 && code <= 0x0039) charType = 'DIGIT';</td></tr><tr class="hit"><td class="line">780</td><td class="hits">104</td><td class="source"> if ((code <= 0x0020) || (code >= 0x0080 && code <= 0x00A0)) charType = 'SPACE';</td></tr><tr class="hit"><td class="line">781</td><td class="hits">107</td><td class="source"> if ('‐-−‒–—―.…,:;?!¿¡()[]«»"\'’‘’“”/⁄'.indexOf(ch) > -1) charType = 'PUNCT';</td></tr><tr><td class="line">782</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">783</td><td class="hits">94</td><td class="source"> var tokenType = charType;</td></tr><tr class="hit"><td class="line">784</td><td class="hits">94</td><td class="source"> var tokenSubType = false;</td></tr><tr class="hit"><td class="line">785</td><td class="hits">94</td><td class="source"> if (charType == 'CYRIL' || charType == 'LATIN') {</td></tr><tr class="hit"><td class="line">786</td><td class="hits">63</td><td class="source"> tokenType = 'WORD';</td></tr><tr class="hit"><td class="line">787</td><td class="hits">63</td><td class="source"> tokenSubType = charType;</td></tr><tr><td class="line">788</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">789</td><td class="hits">31</td><td class="source"> if (charType == 'DIGIT') {</td></tr><tr class="hit"><td class="line">790</td><td class="hits">3</td><td class="source"> tokenType = 'NUMBER';</td></tr><tr><td class="line">791</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">792</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">793</td><td class="hits">94</td><td class="source"> var lineStart = !token || token.s[token.s.length - 1] == '\n';</td></tr><tr><td class="line">794</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">795</td><td class="hits">94</td><td class="source"> if (config.wiki) {</td></tr><tr class="miss"><td class="line">796</td><td class="hits">0</td><td class="source"> if (lineStart) {</td></tr><tr class="miss"><td class="line">797</td><td class="hits">0</td><td class="source"> if (':;*#~|'.indexOf(ch) > -1) {</td></tr><tr class="miss"><td class="line">798</td><td class="hits">0</td><td class="source"> tokenType = 'MARKUP';</td></tr><tr class="miss"><td class="line">799</td><td class="hits">0</td><td class="source"> tokenSubType = 'NEWLINE';</td></tr><tr><td class="line">800</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">801</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">802</td><td class="hits">0</td><td class="source"> if ('={[|]}'.indexOf(ch) > -1) {</td></tr><tr class="miss"><td class="line">803</td><td class="hits">0</td><td class="source"> tokenType = 'MARKUP';</td></tr><tr><td class="line">804</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">805</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">806</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">807</td><td class="hits">94</td><td class="source"> if (config.markdown) {</td></tr><tr class="miss"><td class="line">808</td><td class="hits">0</td><td class="source"> if (lineStart) {</td></tr><tr class="miss"><td class="line">809</td><td class="hits">0</td><td class="source"> if ('=-#>+-'.indexOf(ch) > -1) {</td></tr><tr class="miss"><td class="line">810</td><td class="hits">0</td><td class="source"> tokenType = 'MARKUP';</td></tr><tr class="miss"><td class="line">811</td><td class="hits">0</td><td class="source"> tokenSubType = 'NEWLINE';</td></tr><tr><td class="line">812</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">813</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">814</td><td class="hits">0</td><td class="source"> if ('[]*~_`\\'.indexOf(ch) > -1) {</td></tr><tr class="miss"><td class="line">815</td><td class="hits">0</td><td class="source"> tokenType = 'MARKUP';</td></tr><tr><td class="line">816</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">817</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">818</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">819</td><td class="hits">94</td><td class="source"> if (token) {</td></tr><tr class="hit"><td class="line">820</td><td class="hits">91</td><td class="source"> if (config.wiki && ch != '\'' && token.s == '\'' && last > 0 && this.tokens[last - 1].type == 'WORD') {</td></tr><tr class="miss"><td class="line">821</td><td class="hits">0</td><td class="source"> this.tokens[last - 1].s += token.s;</td></tr><tr class="miss"><td class="line">822</td><td class="hits">0</td><td class="source"> this.tokens[last - 1].en = token.en;</td></tr><tr class="miss"><td class="line">823</td><td class="hits">0</td><td class="source"> this.tokens[last - 1].len += token.len;</td></tr><tr><td class="line">824</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">825</td><td class="hits">0</td><td class="source"> last -= 1;</td></tr><tr class="miss"><td class="line">826</td><td class="hits">0</td><td class="source"> this.tokens.length = last + 1;</td></tr><tr class="miss"><td class="line">827</td><td class="hits">0</td><td class="source"> token = this.tokens[last];</td></tr><tr><td class="line">828</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">829</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">830</td><td class="hits"></td><td class="source"> // Preprocess last token</td></tr><tr class="hit"><td class="line">831</td><td class="hits">91</td><td class="source"> if (config.links && config.links.tlds &&</td></tr><tr><td class="line">832</td><td class="hits"></td><td class="source"> (charType == 'PUNCT' || charType == 'SPACE') &&</td></tr><tr><td class="line">833</td><td class="hits"></td><td class="source"> this.tokens.length > 2 &&</td></tr><tr><td class="line">834</td><td class="hits"></td><td class="source"> this.tokens[last - 2].type == 'WORD' &&</td></tr><tr><td class="line">835</td><td class="hits"></td><td class="source"> this.tokens[last - 1].s == '.' &&</td></tr><tr><td class="line">836</td><td class="hits"></td><td class="source"> this.tokens[last].type == 'WORD' &&</td></tr><tr><td class="line">837</td><td class="hits"></td><td class="source"> this.tokens[last].s in config.links.tlds) {</td></tr><tr><td class="line">838</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">839</td><td class="hits"></td><td class="source"> // Merge all subdomains</td></tr><tr class="hit"><td class="line">840</td><td class="hits">2</td><td class="source"> while (last >= 2 &&</td></tr><tr><td class="line">841</td><td class="hits"></td><td class="source"> this.tokens[last - 2].type == 'WORD' &&</td></tr><tr><td class="line">842</td><td class="hits"></td><td class="source"> (this.tokens[last - 1].s == '.' || this.tokens[last - 1].s == '@' || this.tokens[last - 1].s == ':')) {</td></tr><tr class="hit"><td class="line">843</td><td class="hits">2</td><td class="source"> last -= 2;</td></tr><tr class="hit"><td class="line">844</td><td class="hits">2</td><td class="source"> token = this.tokens[last];</td></tr><tr class="hit"><td class="line">845</td><td class="hits">2</td><td class="source"> token.s += this.tokens[last + 1].s + this.tokens[last + 2].s;</td></tr><tr class="hit"><td class="line">846</td><td class="hits">2</td><td class="source"> token.allUpper = token.allUpper && this.tokens[last + 1].allUpper && this.tokens[last + 2].allUpper;</td></tr><tr><td class="line">847</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">848</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">849</td><td class="hits">2</td><td class="source"> if (config.emails && token.s.indexOf('@') > -1 && token.s.indexOf(':') == -1) {</td></tr><tr><td class="line">850</td><td class="hits"></td><td class="source"> // URL can contain a '@' but in that case it should be in form http://[email protected] or user:[email protected]</td></tr><tr><td class="line">851</td><td class="hits"></td><td class="source"> // So if URL has a '@' but no ':' in it, we assume it's a email</td></tr><tr class="miss"><td class="line">852</td><td class="hits">0</td><td class="source"> token.type = 'EMAIL';</td></tr><tr><td class="line">853</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">854</td><td class="hits">2</td><td class="source"> token.type = 'LINK';</td></tr><tr><td class="line">855</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">856</td><td class="hits">2</td><td class="source"> if (ch == '/') {</td></tr><tr class="miss"><td class="line">857</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">858</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">859</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">860</td><td class="hits">2</td><td class="source"> this.tokens.length = last + 1;</td></tr><tr><td class="line">861</td><td class="hits"></td><td class="source"> } else</td></tr><tr><td class="line">862</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">863</td><td class="hits"></td><td class="source"> // Process next char (start new token or append to the previous one)</td></tr><tr class="hit"><td class="line">864</td><td class="hits">89</td><td class="source"> if (token.type == 'LINK') {</td></tr><tr class="hit"><td class="line">865</td><td class="hits">14</td><td class="source"> if (charType != 'SPACE' && ch != ',') {</td></tr><tr class="hit"><td class="line">866</td><td class="hits">12</td><td class="source"> append = true;</td></tr><tr><td class="line">867</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">868</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">869</td><td class="hits">75</td><td class="source"> if (token.type == 'EMAIL') {</td></tr><tr class="miss"><td class="line">870</td><td class="hits">0</td><td class="source"> if (charType == 'CYRIL' || charType == 'LATIN' || ch == '.') {</td></tr><tr class="miss"><td class="line">871</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">872</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">873</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">874</td><td class="hits">75</td><td class="source"> if (token.type == 'HASHTAG' || token.type == 'MENTION') {</td></tr><tr class="hit"><td class="line">875</td><td class="hits">10</td><td class="source"> if (charType == 'CYRIL' || charType == 'LATIN' || charType == 'DIGIT' || ch == '_' || (ch == '@' && token.s.indexOf('@') == -1)) {</td></tr><tr class="hit"><td class="line">876</td><td class="hits">9</td><td class="source"> append = true;</td></tr><tr><td class="line">877</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">878</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">879</td><td class="hits">65</td><td class="source"> if (token.type == 'TAG' && (token.quote || token.s[token.s.length - 1] != '>')) {</td></tr><tr class="miss"><td class="line">880</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr class="miss"><td class="line">881</td><td class="hits">0</td><td class="source"> if (token.quote) {</td></tr><tr class="miss"><td class="line">882</td><td class="hits">0</td><td class="source"> if (ch == token.quote && token.s[token.s.length - 1] != '\\') {</td></tr><tr class="miss"><td class="line">883</td><td class="hits">0</td><td class="source"> delete token.quote;</td></tr><tr><td class="line">884</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">885</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="miss"><td class="line">886</td><td class="hits">0</td><td class="source"> if (ch == '"' || ch == '\'') {</td></tr><tr class="miss"><td class="line">887</td><td class="hits">0</td><td class="source"> token.quote = ch;</td></tr><tr><td class="line">888</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">889</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">890</td><td class="hits">65</td><td class="source"> if (token.type == 'CONTENT') {</td></tr><tr class="miss"><td class="line">891</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr class="miss"><td class="line">892</td><td class="hits">0</td><td class="source"> if (token.quote) {</td></tr><tr class="miss"><td class="line">893</td><td class="hits">0</td><td class="source"> if (ch == token.quote && token.s[token.s.length - 1] != '\\') {</td></tr><tr class="miss"><td class="line">894</td><td class="hits">0</td><td class="source"> delete token.quote;</td></tr><tr><td class="line">895</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">896</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="miss"><td class="line">897</td><td class="hits">0</td><td class="source"> if (ch == '"' || ch == '\'') {</td></tr><tr class="miss"><td class="line">898</td><td class="hits">0</td><td class="source"> token.quote = ch;</td></tr><tr><td class="line">899</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="miss"><td class="line">900</td><td class="hits">0</td><td class="source"> if (ch == '<') {</td></tr><tr class="miss"><td class="line">901</td><td class="hits">0</td><td class="source"> append = false;</td></tr><tr><td class="line">902</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">903</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">904</td><td class="hits">65</td><td class="source"> if (token.type == 'TAG' && ch != '<' && token.s.substr(1, 6).toLowerCase() == 'script') {</td></tr><tr class="miss"><td class="line">905</td><td class="hits">0</td><td class="source"> tokenType = 'CONTENT';</td></tr><tr class="miss"><td class="line">906</td><td class="hits">0</td><td class="source"> tokenSubType = 'SCRIPT';</td></tr><tr><td class="line">907</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">908</td><td class="hits">65</td><td class="source"> if (token.type == 'TAG' && ch != '<' && token.s.substr(1, 5).toLowerCase() == 'style') {</td></tr><tr class="miss"><td class="line">909</td><td class="hits">0</td><td class="source"> tokenType = 'CONTENT';</td></tr><tr class="miss"><td class="line">910</td><td class="hits">0</td><td class="source"> tokenSubType = 'STYLE';</td></tr><tr><td class="line">911</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">912</td><td class="hits">65</td><td class="source"> if (config.html && token.s == '<' && (charType == 'LATIN' || ch == '!' || ch == '/')) {</td></tr><tr class="miss"><td class="line">913</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr class="miss"><td class="line">914</td><td class="hits">0</td><td class="source"> token.type = 'TAG';</td></tr><tr class="miss"><td class="line">915</td><td class="hits">0</td><td class="source"> if (ch == '!') {</td></tr><tr class="miss"><td class="line">916</td><td class="hits">0</td><td class="source"> token.subType = 'COMMENT';</td></tr><tr><td class="line">917</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="miss"><td class="line">918</td><td class="hits">0</td><td class="source"> if (ch == '/') {</td></tr><tr class="miss"><td class="line">919</td><td class="hits">0</td><td class="source"> token.subType = 'CLOSING';</td></tr><tr><td class="line">920</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">921</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">922</td><td class="hits">65</td><td class="source"> if (token.type == 'CONTENT') {</td></tr><tr class="miss"><td class="line">923</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">924</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">925</td><td class="hits">65</td><td class="source"> if (token.type == 'MARKUP' && token.subType == 'TEMPLATE' && (token.s[token.s.length - 1] != '}' || token.s[token.s.length - 2] != '}')) {</td></tr><tr class="miss"><td class="line">926</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">927</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">928</td><td class="hits">65</td><td class="source"> if (token.type == 'MARKUP' && token.type == 'LINK' && token.s[token.s.length - 1] != ')') {</td></tr><tr class="miss"><td class="line">929</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">930</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">931</td><td class="hits">65</td><td class="source"> if (token.type == 'MARKUP' && token.s[0] == '`' && token.subType == 'NEWLINE' && charType == 'LATIN') {</td></tr><tr class="miss"><td class="line">932</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">933</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">934</td><td class="hits">65</td><td class="source"> if (charType == 'CYRIL' || charType == 'LATIN') {</td></tr><tr class="hit"><td class="line">935</td><td class="hits">41</td><td class="source"> if (token.type == 'WORD') {</td></tr><tr class="hit"><td class="line">936</td><td class="hits">28</td><td class="source"> append = true;</td></tr><tr class="hit"><td class="line">937</td><td class="hits">28</td><td class="source"> token.subType = (token.subType == charType) ? token.subType : 'MIXED';</td></tr><tr><td class="line">938</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">939</td><td class="hits">13</td><td class="source"> if (token.type == 'NUMBER') { // Digits + ending</td></tr><tr class="miss"><td class="line">940</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr class="miss"><td class="line">941</td><td class="hits">0</td><td class="source"> token.subType = (token.subType && token.subType != charType) ? 'MIXED' : charType;</td></tr><tr><td class="line">942</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">943</td><td class="hits">13</td><td class="source"> if (config.hashtags && token.s == '#') { // Hashtags</td></tr><tr class="hit"><td class="line">944</td><td class="hits">2</td><td class="source"> append = true;</td></tr><tr class="hit"><td class="line">945</td><td class="hits">2</td><td class="source"> token.type = 'HASHTAG';</td></tr><tr><td class="line">946</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">947</td><td class="hits">11</td><td class="source"> if (config.mentions && token.s == '@' && (last == 0 || this.tokens[last - 1].type == 'SPACE')) { // Mentions</td></tr><tr class="miss"><td class="line">948</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr class="miss"><td class="line">949</td><td class="hits">0</td><td class="source"> token.type = 'MENTION';</td></tr><tr><td class="line">950</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">951</td><td class="hits">11</td><td class="source"> if (charType == 'LATIN' && (token.s == '\'' || token.s == '’')) {</td></tr><tr class="miss"><td class="line">952</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr class="miss"><td class="line">953</td><td class="hits">0</td><td class="source"> token.type = 'WORD';</td></tr><tr class="miss"><td class="line">954</td><td class="hits">0</td><td class="source"> token.subType = 'LATIN';</td></tr><tr><td class="line">955</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">956</td><td class="hits">11</td><td class="source"> if (token.s == '-') { // -цать (?), 3-й</td></tr><tr class="miss"><td class="line">957</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">958</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">959</td><td class="hits">0</td><td class="source"> if (last > 0 && this.tokens[last - 1].type == 'NUMBER') {</td></tr><tr class="miss"><td class="line">960</td><td class="hits">0</td><td class="source"> token = this.tokens[last - 1];</td></tr><tr class="miss"><td class="line">961</td><td class="hits">0</td><td class="source"> token.s += this.tokens[last].s;</td></tr><tr><td class="line">962</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">963</td><td class="hits">0</td><td class="source"> this.tokens.length -= 1;</td></tr><tr><td class="line">964</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">965</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">966</td><td class="hits">0</td><td class="source"> token.type = 'WORD';</td></tr><tr class="miss"><td class="line">967</td><td class="hits">0</td><td class="source"> token.subType = charType;</td></tr><tr><td class="line">968</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">969</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">970</td><td class="hits">24</td><td class="source"> if (charType == 'DIGIT') {</td></tr><tr class="hit"><td class="line">971</td><td class="hits">3</td><td class="source"> if (token.type == 'WORD') {</td></tr><tr class="miss"><td class="line">972</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr class="miss"><td class="line">973</td><td class="hits">0</td><td class="source"> token.subType = 'MIXED';</td></tr><tr><td class="line">974</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">975</td><td class="hits">3</td><td class="source"> if (token.type == 'NUMBER') {</td></tr><tr class="hit"><td class="line">976</td><td class="hits">1</td><td class="source"> append = true;</td></tr><tr><td class="line">977</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">978</td><td class="hits">2</td><td class="source"> if (token.s == '+' || token.s == '-') {</td></tr><tr class="miss"><td class="line">979</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">980</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">981</td><td class="hits">0</td><td class="source"> if (last > 0 && this.tokens[last - 1].type == 'NUMBER') {</td></tr><tr class="miss"><td class="line">982</td><td class="hits">0</td><td class="source"> token = this.tokens[last - 1];</td></tr><tr class="miss"><td class="line">983</td><td class="hits">0</td><td class="source"> token.s += this.tokens[last].s;</td></tr><tr class="miss"><td class="line">984</td><td class="hits">0</td><td class="source"> token.subType = 'RANGE';</td></tr><tr><td class="line">985</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">986</td><td class="hits">0</td><td class="source"> this.tokens.length -= 1;</td></tr><tr><td class="line">987</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">988</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">989</td><td class="hits">0</td><td class="source"> token.type = 'NUMBER';</td></tr><tr><td class="line">990</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">991</td><td class="hits">2</td><td class="source"> if ((token.s == ',' || token.s == '.') && this.tokens.length > 1 && this.tokens[last - 1].type == 'NUMBER') {</td></tr><tr class="miss"><td class="line">992</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">993</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">994</td><td class="hits">0</td><td class="source"> token = this.tokens[last - 1];</td></tr><tr class="miss"><td class="line">995</td><td class="hits">0</td><td class="source"> token.s += this.tokens[last].s;</td></tr><tr><td class="line">996</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">997</td><td class="hits">0</td><td class="source"> this.tokens.length -= 1;</td></tr><tr><td class="line">998</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">999</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1000</td><td class="hits">21</td><td class="source"> if (charType == 'SPACE') {</td></tr><tr class="hit"><td class="line">1001</td><td class="hits">8</td><td class="source"> if (token.type == 'SPACE') {</td></tr><tr class="miss"><td class="line">1002</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">1003</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1004</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1005</td><td class="hits">13</td><td class="source"> if (token.type == 'MARKUP' && token.s[0] == ch && '=-~:*#`\'>_'.indexOf(ch) > -1) {</td></tr><tr class="miss"><td class="line">1006</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">1007</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1008</td><td class="hits">13</td><td class="source"> if (ch == '.') {</td></tr><tr class="hit"><td class="line">1009</td><td class="hits">6</td><td class="source"> if (config.links && config.links.www && token.s.toLocaleLowerCase() == 'www') { // Links without protocol but with www</td></tr><tr class="hit"><td class="line">1010</td><td class="hits">1</td><td class="source"> append = true;</td></tr><tr class="hit"><td class="line">1011</td><td class="hits">1</td><td class="source"> token.type = 'LINK';</td></tr><tr><td class="line">1012</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1013</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1014</td><td class="hits">7</td><td class="source"> if (config.wiki && ch == '\'') {</td></tr><tr class="miss"><td class="line">1015</td><td class="hits">0</td><td class="source"> if (token.s == '\'') {</td></tr><tr class="miss"><td class="line">1016</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr class="miss"><td class="line">1017</td><td class="hits">0</td><td class="source"> token.type = 'MARKUP';</td></tr><tr><td class="line">1018</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="miss"><td class="line">1019</td><td class="hits">0</td><td class="source"> tokenType = 'PUNCT';</td></tr><tr><td class="line">1020</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1021</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1022</td><td class="hits">7</td><td class="source"> if (ch == '-' || ch == '’' || ch == '\'') {</td></tr><tr class="miss"><td class="line">1023</td><td class="hits">0</td><td class="source"> if (token.type == 'WORD') {</td></tr><tr class="miss"><td class="line">1024</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">1025</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1026</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1027</td><td class="hits">7</td><td class="source"> if (ch == '/') {</td></tr><tr class="hit"><td class="line">1028</td><td class="hits">2</td><td class="source"> if (config.links && config.links.protocols &&</td></tr><tr><td class="line">1029</td><td class="hits"></td><td class="source"> this.tokens.length > 2 &&</td></tr><tr><td class="line">1030</td><td class="hits"></td><td class="source"> this.tokens[last - 2].type == 'WORD' &&</td></tr><tr><td class="line">1031</td><td class="hits"></td><td class="source"> this.tokens[last - 2].subType == 'LATIN' &&</td></tr><tr><td class="line">1032</td><td class="hits"></td><td class="source"> this.tokens[last - 1].s == ':' &&</td></tr><tr><td class="line">1033</td><td class="hits"></td><td class="source"> this.tokens[last].s == '/') { // Links (with protocols)</td></tr><tr class="hit"><td class="line">1034</td><td class="hits">1</td><td class="source"> append = true;</td></tr><tr><td class="line">1035</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">1036</td><td class="hits">1</td><td class="source"> token = this.tokens[last - 2];</td></tr><tr class="hit"><td class="line">1037</td><td class="hits">1</td><td class="source"> token.s += this.tokens[last - 1].s + this.tokens[last].s;</td></tr><tr class="hit"><td class="line">1038</td><td class="hits">1</td><td class="source"> token.allUpper = token.allUpper && this.tokens[last - 1].allUpper && this.tokens[last].allUpper;</td></tr><tr class="hit"><td class="line">1039</td><td class="hits">1</td><td class="source"> token.type = 'LINK';</td></tr><tr><td class="line">1040</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">1041</td><td class="hits">1</td><td class="source"> this.tokens.length -= 2;</td></tr><tr><td class="line">1042</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1043</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1044</td><td class="hits">5</td><td class="source"> if (config.html && ch == ';') {</td></tr><tr class="miss"><td class="line">1045</td><td class="hits">0</td><td class="source"> if (last > 0 && token.type == 'WORD' && this.tokens[last - 1].s == '&') {</td></tr><tr class="miss"><td class="line">1046</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">1047</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">1048</td><td class="hits">0</td><td class="source"> token = this.tokens[last - 1];</td></tr><tr class="miss"><td class="line">1049</td><td class="hits">0</td><td class="source"> token.s += this.tokens[last].s;</td></tr><tr class="miss"><td class="line">1050</td><td class="hits">0</td><td class="source"> token.allUpper = token.allUpper && this.tokens[last - 1].allUpper;</td></tr><tr class="miss"><td class="line">1051</td><td class="hits">0</td><td class="source"> token.type = 'ENTITY';</td></tr><tr><td class="line">1052</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">1053</td><td class="hits">0</td><td class="source"> this.tokens.length -= 1;</td></tr><tr><td class="line">1054</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="miss"><td class="line">1055</td><td class="hits">0</td><td class="source"> if (last > 1 && (token.type == 'WORD' || token.type == 'NUMBER') && this.tokens[last - 1].s == '#' && this.tokens[last - 2].s == '&') {</td></tr><tr class="miss"><td class="line">1056</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">1057</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">1058</td><td class="hits">0</td><td class="source"> token = this.tokens[last - 2];</td></tr><tr class="miss"><td class="line">1059</td><td class="hits">0</td><td class="source"> token.s += this.tokens[last - 1].s + this.tokens[last].s;</td></tr><tr class="miss"><td class="line">1060</td><td class="hits">0</td><td class="source"> token.allUpper = token.allUpper && this.tokens[last - 1].allUpper && this.tokens[last].allUpper;</td></tr><tr class="miss"><td class="line">1061</td><td class="hits">0</td><td class="source"> token.type = 'ENTITY';</td></tr><tr><td class="line">1062</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">1063</td><td class="hits">0</td><td class="source"> this.tokens.length -= 2;</td></tr><tr><td class="line">1064</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1065</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1066</td><td class="hits">5</td><td class="source"> if (config.markdown && ch == '[' && token.s == '!') {</td></tr><tr class="miss"><td class="line">1067</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr class="miss"><td class="line">1068</td><td class="hits">0</td><td class="source"> token.type = 'MARKUP';</td></tr><tr><td class="line">1069</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1070</td><td class="hits">5</td><td class="source"> if (config.markdown && ch == '(' && token.s == ']') {</td></tr><tr class="miss"><td class="line">1071</td><td class="hits">0</td><td class="source"> tokenType = 'MARKUP';</td></tr><tr class="miss"><td class="line">1072</td><td class="hits">0</td><td class="source"> tokenSubType = 'LINK';</td></tr><tr><td class="line">1073</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1074</td><td class="hits">5</td><td class="source"> if (config.wiki && ch == '{' && token.s == '{') {</td></tr><tr class="miss"><td class="line">1075</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr class="miss"><td class="line">1076</td><td class="hits">0</td><td class="source"> token.type = 'MARKUP';</td></tr><tr class="miss"><td class="line">1077</td><td class="hits">0</td><td class="source"> token.subType = 'TEMPLATE';</td></tr><tr><td class="line">1078</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1079</td><td class="hits">5</td><td class="source"> if (config.wiki && ch == '[' && token.s == '[') {</td></tr><tr class="miss"><td class="line">1080</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">1081</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1082</td><td class="hits">5</td><td class="source"> if (config.wiki && ch == ']' && token.s == ']') {</td></tr><tr class="miss"><td class="line">1083</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr><td class="line">1084</td><td class="hits"></td><td class="source"> } else</td></tr><tr class="hit"><td class="line">1085</td><td class="hits">5</td><td class="source"> if (config.wiki && ch == '|' && !lineStart) {</td></tr><tr class="miss"><td class="line">1086</td><td class="hits">0</td><td class="source"> var found = -1;</td></tr><tr class="miss"><td class="line">1087</td><td class="hits">0</td><td class="source"> for (var j = last - 1; j >= 0; j--) {</td></tr><tr class="miss"><td class="line">1088</td><td class="hits">0</td><td class="source"> if (this.tokens[j].s == '[[') {</td></tr><tr class="miss"><td class="line">1089</td><td class="hits">0</td><td class="source"> found = j;</td></tr><tr class="miss"><td class="line">1090</td><td class="hits">0</td><td class="source"> break;</td></tr><tr><td class="line">1091</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1092</td><td class="hits">0</td><td class="source"> if (this.tokens[j].s == '|' || this.tokens[j].s.indexOf('\n') > -1) {</td></tr><tr class="miss"><td class="line">1093</td><td class="hits">0</td><td class="source"> break;</td></tr><tr><td class="line">1094</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1095</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1096</td><td class="hits">0</td><td class="source"> if (found > -1) {</td></tr><tr class="miss"><td class="line">1097</td><td class="hits">0</td><td class="source"> append = true;</td></tr><tr class="miss"><td class="line">1098</td><td class="hits">0</td><td class="source"> for (var j = last - 1; j >= found; j--) {</td></tr><tr class="miss"><td class="line">1099</td><td class="hits">0</td><td class="source"> token = this.tokens[j];</td></tr><tr class="miss"><td class="line">1100</td><td class="hits">0</td><td class="source"> token.s += this.tokens[j + 1].s;</td></tr><tr class="miss"><td class="line">1101</td><td class="hits">0</td><td class="source"> token.allUpper = token.allUpper && this.tokens[j + 1].allUpper;</td></tr><tr><td class="line">1102</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1103</td><td class="hits">0</td><td class="source"> last = found;</td></tr><tr class="miss"><td class="line">1104</td><td class="hits">0</td><td class="source"> this.tokens.length = last + 1;</td></tr><tr class="miss"><td class="line">1105</td><td class="hits">0</td><td class="source"> token.subType = 'LINK';</td></tr><tr><td class="line">1106</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1107</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1108</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1109</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">1110</td><td class="hits">94</td><td class="source"> if (append) {</td></tr><tr class="hit"><td class="line">1111</td><td class="hits">54</td><td class="source"> token.s += ch;</td></tr><tr><td class="line">1112</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">1113</td><td class="hits">40</td><td class="source"> token = {</td></tr><tr><td class="line">1114</td><td class="hits"></td><td class="source"> type: tokenType,</td></tr><tr><td class="line">1115</td><td class="hits"></td><td class="source"> s: ch,</td></tr><tr><td class="line">1116</td><td class="hits"></td><td class="source"> st: i,</td></tr><tr><td class="line">1117</td><td class="hits"></td><td class="source"> idx: this.tokens.length,</td></tr><tr><td class="line">1118</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">1119</td><td class="hits"></td><td class="source"> firstUpper: charUpper,</td></tr><tr><td class="line">1120</td><td class="hits"></td><td class="source"> allUpper: charUpper,</td></tr><tr><td class="line">1121</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">1122</td><td class="hits">40</td><td class="source"> if (tokenSubType) {</td></tr><tr class="hit"><td class="line">1123</td><td class="hits">13</td><td class="source"> token.subType = tokenSubType;</td></tr><tr><td class="line">1124</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">1125</td><td class="hits">40</td><td class="source"> this.tokens.push(token);</td></tr><tr><td class="line">1126</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">1127</td><td class="hits">94</td><td class="source"> token.en = i;</td></tr><tr class="hit"><td class="line">1128</td><td class="hits">94</td><td class="source"> token.length = (token.en - token.st) + 1;</td></tr><tr class="hit"><td class="line">1129</td><td class="hits">94</td><td class="source"> token.allUpper = token.allUpper && charUpper;</td></tr><tr><td class="line">1130</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">1131</td><td class="hits">4</td><td class="source"> return this;</td></tr><tr><td class="line">1132</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1133</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">1134</td><td class="hits">1</td><td class="source"> Tokens.prototype.done = function(filter, exclude) {</td></tr><tr><td class="line">1135</td><td class="hits"></td><td class="source"> // Finalize tokenizing, return list of tokens</td></tr><tr><td class="line">1136</td><td class="hits"></td><td class="source"> // For now it just returns tokens, in the future there could be some additional work</td></tr><tr class="hit"><td class="line">1137</td><td class="hits">4</td><td class="source"> if (!filter) {</td></tr><tr class="hit"><td class="line">1138</td><td class="hits">4</td><td class="source"> return this.tokens;</td></tr><tr><td class="line">1139</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1140</td><td class="hits">0</td><td class="source"> var list = [];</td></tr><tr class="miss"><td class="line">1141</td><td class="hits">0</td><td class="source"> for (var i = 0; i < this.tokens.length; i++) {</td></tr><tr class="miss"><td class="line">1142</td><td class="hits">0</td><td class="source"> if ((filter.indexOf(this.tokens[i].type) == -1) == exclude) {</td></tr><tr class="miss"><td class="line">1143</td><td class="hits">0</td><td class="source"> list.push(this.tokens[i]);</td></tr><tr><td class="line">1144</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1145</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1146</td><td class="hits">0</td><td class="source"> return list;</td></tr><tr><td class="line">1147</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1148</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">1149</td><td class="hits">1</td><td class="source"> Tokens.prototype.countTokens = function(filter, exclude) {</td></tr><tr class="miss"><td class="line">1150</td><td class="hits">0</td><td class="source"> if (!skipSpace && !skipPunct) {</td></tr><tr class="miss"><td class="line">1151</td><td class="hits">0</td><td class="source"> return this.tokens.length;</td></tr><tr><td class="line">1152</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1153</td><td class="hits">0</td><td class="source"> var count = 0;</td></tr><tr class="miss"><td class="line">1154</td><td class="hits">0</td><td class="source"> for (var i = 0; i < this.tokens.length; i++) {</td></tr><tr class="miss"><td class="line">1155</td><td class="hits">0</td><td class="source"> if ((filter.indexOf(this.tokens[i].type) == -1) == exclude) {</td></tr><tr class="miss"><td class="line">1156</td><td class="hits">0</td><td class="source"> count++;</td></tr><tr><td class="line">1157</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1158</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1159</td><td class="hits">0</td><td class="source"> return count;</td></tr><tr><td class="line">1160</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1161</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">1162</td><td class="hits">1</td><td class="source"> Tokens.prototype.nextToken = function(moveIndex, filter, exclude) {</td></tr><tr class="miss"><td class="line">1163</td><td class="hits">0</td><td class="source"> var index = this.index;</td></tr><tr class="miss"><td class="line">1164</td><td class="hits">0</td><td class="source"> index++;</td></tr><tr class="miss"><td class="line">1165</td><td class="hits">0</td><td class="source"> while (index < this.tokens.length && filter && (filter.indexOf(this.tokens[index].type) != -1) == exclude) {</td></tr><tr class="miss"><td class="line">1166</td><td class="hits">0</td><td class="source"> index++;</td></tr><tr><td class="line">1167</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1168</td><td class="hits">0</td><td class="source"> if (index < this.tokens.length) {</td></tr><tr class="miss"><td class="line">1169</td><td class="hits">0</td><td class="source"> if (moveIndex) {</td></tr><tr class="miss"><td class="line">1170</td><td class="hits">0</td><td class="source"> this.index = index;</td></tr><tr><td class="line">1171</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1172</td><td class="hits">0</td><td class="source"> return this.tokens[index];</td></tr><tr><td class="line">1173</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1174</td><td class="hits">0</td><td class="source"> return null;</td></tr><tr><td class="line">1175</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1176</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">1177</td><td class="hits">1</td><td class="source"> Tokens.prototype.punctAhead = function() {</td></tr><tr class="miss"><td class="line">1178</td><td class="hits">0</td><td class="source"> var token = this.nextToken(false, ['SPACE'], true);</td></tr><tr class="miss"><td class="line">1179</td><td class="hits">0</td><td class="source"> return token && token.type == 'PUNCT' && token;</td></tr><tr><td class="line">1180</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1181</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">1182</td><td class="hits">1</td><td class="source"> Tokens.prototype.prevToken = function(moveIndex, filter, exclude) {</td></tr><tr class="miss"><td class="line">1183</td><td class="hits">0</td><td class="source"> var index = this.index;</td></tr><tr class="miss"><td class="line">1184</td><td class="hits">0</td><td class="source"> index--;</td></tr><tr class="miss"><td class="line">1185</td><td class="hits">0</td><td class="source"> while (index >= 0 && filter && (filter.indexOf(this.tokens[index].type) != -1) == exclude) {</td></tr><tr class="miss"><td class="line">1186</td><td class="hits">0</td><td class="source"> index--;</td></tr><tr><td class="line">1187</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1188</td><td class="hits">0</td><td class="source"> if (index >= 0) {</td></tr><tr class="miss"><td class="line">1189</td><td class="hits">0</td><td class="source"> if (moveIndex) {</td></tr><tr class="miss"><td class="line">1190</td><td class="hits">0</td><td class="source"> this.index = index;</td></tr><tr><td class="line">1191</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1192</td><td class="hits">0</td><td class="source"> return this.tokens[index];</td></tr><tr><td class="line">1193</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">1194</td><td class="hits">0</td><td class="source"> return null;</td></tr><tr><td class="line">1195</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1196</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">1197</td><td class="hits">1</td><td class="source"> Tokens.prototype.punctBehind = function() {</td></tr><tr class="miss"><td class="line">1198</td><td class="hits">0</td><td class="source"> var token = this.prevToken(false, ['SPACE'], true);</td></tr><tr class="miss"><td class="line">1199</td><td class="hits">0</td><td class="source"> return token && token.type == 'PUNCT' && token;</td></tr><tr><td class="line">1200</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1201</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">1202</td><td class="hits">1</td><td class="source"> Tokens.prototype.hasTokensAhead = function(filter, exclude) {</td></tr><tr class="miss"><td class="line">1203</td><td class="hits">0</td><td class="source"> return this.nextToken(false, filter, exclude) != null;</td></tr><tr><td class="line">1204</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1205</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">1206</td><td class="hits">1</td><td class="source"> Tokens.prototype.hasTokensBehind = function(filter, exclude) {</td></tr><tr class="miss"><td class="line">1207</td><td class="hits">0</td><td class="source"> return this.prevToken(false, filter, exclude) != null;</td></tr><tr><td class="line">1208</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">1209</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">1210</td><td class="hits">1</td><td class="source"> return Tokens;</td></tr><tr><td class="line">1211</td><td class="hits"></td><td class="source">}));</td></tr></tbody></table></div></div></div></body></html>