compromise-speech 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,373 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
+ typeof define === 'function' && define.amd ? define(factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.compromiseStream = factory());
5
+ })(this, (function () { 'use strict';
6
+
7
+ //individual manipulations of the text
8
+ const transformations = {
9
+ dedup: (s) => {
10
+ return s.replace(/([^c])\1/g, '$1')
11
+ },
12
+ dropInitialLetters: (s) => {
13
+ if (s.match(/^(kn|gn|pn|ae|wr)/)) {
14
+ return s.substr(1, s.length - 1)
15
+ }
16
+ return s
17
+ },
18
+ dropBafterMAtEnd: (s) => {
19
+ return s.replace(/mb$/, 'm')
20
+ },
21
+ cchange: (s) => {
22
+ s = s.replace(/([^s]|^)(c)(h)/g, '$1x$3').trim();
23
+ s = s.replace(/cia/g, 'xia');
24
+ s = s.replace(/c([iey])/g, 's$1');
25
+ return s.replace(/c/g, 'k')
26
+ },
27
+ dchange: (s) => {
28
+ s = s.replace(/d(ge|gy|gi)/g, 'j$1');
29
+ return s.replace(/d/g, 't')
30
+ },
31
+ dropG: (s) => {
32
+ // Drop 'G' if followed by 'H' and 'H' is not at the end or before a vowel.
33
+ s = s.replace(/gh(^$|[^aeiou])/g, 'h$1');//eslint-disable-line
34
+ // Drop 'G' if followed by 'N' or 'NED' and is at the end.
35
+ return s.replace(/g(n|ned)$/g, '$1')
36
+ },
37
+ changeG: (s) => {
38
+ s = s.replace(/gh/g, 'f');
39
+ s = s.replace(/([^g]|^)(g)([iey])/g, '$1j$3');
40
+ s = s.replace(/gg/g, 'g');
41
+ return s.replace(/g/g, 'k')
42
+ },
43
+ dropH: (s) => {
44
+ return s.replace(/([aeiou])h([^aeiou]|$)/g, '$1$2')
45
+ },
46
+ changeCK: (s) => {
47
+ return s.replace(/ck/g, 'k')
48
+ },
49
+ changePH: (s) => {
50
+ return s.replace(/ph/g, 'f')
51
+ },
52
+ changeQ: (s) => {
53
+ return s.replace(/q/g, 'k')
54
+ },
55
+ changeS: (s) => {
56
+ return s.replace(/s(h|io|ia)/g, 'x$1')
57
+ },
58
+ changeT: (s) => {
59
+ s = s.replace(/t(ia[^n]|io)/g, 'x$1');
60
+ // return s.replace(/th/, '0')
61
+ return s
62
+ },
63
+ dropT: (s) => {
64
+ return s.replace(/tch/g, 'ch')
65
+ },
66
+ changeV: (s) => {
67
+ return s.replace(/v/g, 'f')
68
+ },
69
+ changeWH: (s) => {
70
+ return s.replace(/^wh/, 'w')
71
+ },
72
+ dropW: (s) => {
73
+ return s.replace(/w([^aeiou]|$)/g, '$1')
74
+ },
75
+ changeX: (s) => {
76
+ s = s.replace(/^x/, 's');
77
+ return s.replace(/x/g, 'ks')
78
+ },
79
+ dropY: (s) => {
80
+ return s.replace(/y([^aeiou]|$)/g, '$1')
81
+ },
82
+ changeZ: (s) => {
83
+ return s.replace(/z/, 's')
84
+ },
85
+ dropVowels: (s) => {
86
+ return s //.charAt(0) + s.substr(1, s.length).replace(/[aeiou]/g, '');
87
+ },
88
+ };
89
+
90
+ //a js version of the metaphone (#1) algorithm
91
+
92
+ const metaphone = function (s) {
93
+ s = transformations.dedup(s);
94
+ s = transformations.dropInitialLetters(s);
95
+ s = transformations.dropBafterMAtEnd(s);
96
+ s = transformations.changeCK(s);
97
+ s = transformations.cchange(s);
98
+ s = transformations.dchange(s);
99
+ s = transformations.dropG(s);
100
+ s = transformations.changeG(s);
101
+ s = transformations.dropH(s);
102
+ s = transformations.changePH(s);
103
+ s = transformations.changeQ(s);
104
+ s = transformations.changeS(s);
105
+ s = transformations.changeX(s);
106
+ s = transformations.changeT(s);
107
+ s = transformations.dropT(s);
108
+ s = transformations.changeV(s);
109
+ s = transformations.changeWH(s);
110
+ s = transformations.dropW(s);
111
+ s = transformations.dropY(s);
112
+ s = transformations.changeZ(s);
113
+ s = transformations.dropVowels(s);
114
+ return s.trim()
115
+ };
116
+
117
+ const soundsLike = function (view) {
118
+ view.docs.forEach(terms => {
119
+ terms.forEach(term => {
120
+ term.soundsLike = metaphone(term.normal || term.text);
121
+ });
122
+ });
123
+ };
124
+
125
+ const starts_with_single_vowel_combos = /^(eu)/i;
126
+ const joining_consonant_vowel = /^[^aeiou]e([^d]|$)/;
127
+ const cvcv_same_consonant = /^([^aeiouy])[aeiouy]\1[aeiouy]/;
128
+ const cvcv_same_vowel = /^[^aeiouy]([aeiouy])[^aeiouy]\1/;
129
+ const cvcv_known_consonants = /^([tg][aeiouy]){2}/;
130
+ const only_one_or_more_c = /^[^aeiouy]+$/;
131
+
132
+ const ends_with_vowel$1 = /[aeiouy]$/;
133
+ const starts_with_consonant_vowel$1 = /^[^aeiouy]h?[aeiouy]/;
134
+
135
+ const ones = [
136
+ /^[^aeiou]?ion/,
137
+ /^[^aeiou]?ised/,
138
+ /^[^aeiou]?iled/,
139
+
140
+ // -ing, -ent
141
+ /[aeiou]n[gt]$/,
142
+
143
+ // -ate, -age
144
+ /\wa[gt]e$/,
145
+ ];
146
+
147
+ //suffix fixes
148
+ const postprocess = function (arr) {
149
+ //trim whitespace
150
+ arr = arr.map(function (w) {
151
+ return w.trim()
152
+ });
153
+ arr = arr.filter(function (w) {
154
+ return w !== ''
155
+ });
156
+ // if (arr.length > 2) {
157
+ // return arr;
158
+ // }
159
+ let l = arr.length;
160
+ if (l > 1) {
161
+ let suffix = arr[l - 2] + arr[l - 1];
162
+ for (let i = 0; i < ones.length; i++) {
163
+ if (suffix.match(ones[i])) {
164
+ arr[l - 2] = arr[l - 2] + arr[l - 1];
165
+ arr.pop();
166
+ }
167
+ }
168
+ }
169
+
170
+ // since the open syllable detection is overzealous,
171
+ // sometimes need to rejoin incorrect splits
172
+ if (arr.length > 1) {
173
+ let first_is_open =
174
+ (arr[0].length === 1 || arr[0].match(starts_with_consonant_vowel$1)) &&
175
+ arr[0].match(ends_with_vowel$1);
176
+ let second_is_joining = arr[1].match(joining_consonant_vowel);
177
+
178
+ if (first_is_open && second_is_joining) {
179
+ let possible_combination = arr[0] + arr[1];
180
+ let probably_separate_syllables =
181
+ possible_combination.match(cvcv_same_consonant) ||
182
+ possible_combination.match(cvcv_same_vowel) ||
183
+ possible_combination.match(cvcv_known_consonants);
184
+
185
+ if (!probably_separate_syllables) {
186
+ arr[0] = arr[0] + arr[1];
187
+ arr.splice(1, 1);
188
+ }
189
+ }
190
+ }
191
+
192
+ if (arr.length > 1) {
193
+ let second_to_last_is_open =
194
+ arr[arr.length - 2].match(starts_with_consonant_vowel$1) &&
195
+ arr[arr.length - 2].match(ends_with_vowel$1);
196
+ let last_is_joining =
197
+ arr[arr.length - 1].match(joining_consonant_vowel) &&
198
+ ones.every(re => !arr[arr.length - 1].match(re));
199
+
200
+ if (second_to_last_is_open && last_is_joining) {
201
+ let possible_combination = arr[arr.length - 2] + arr[arr.length - 1];
202
+ let probably_separate_syllables =
203
+ possible_combination.match(cvcv_same_consonant) ||
204
+ possible_combination.match(cvcv_same_vowel) ||
205
+ possible_combination.match(cvcv_known_consonants);
206
+
207
+ if (!probably_separate_syllables) {
208
+ arr[arr.length - 2] = arr[arr.length - 2] + arr[arr.length - 1];
209
+ arr.splice(arr.length - 1, 1);
210
+ }
211
+ }
212
+ }
213
+
214
+ if (arr.length > 1) {
215
+ let single = arr[0] + arr[1];
216
+ if (single.match(starts_with_single_vowel_combos)) {
217
+ arr[0] = single;
218
+ arr.splice(1, 1);
219
+ }
220
+ }
221
+
222
+ if (arr.length > 1) {
223
+ if (arr[arr.length - 1].match(only_one_or_more_c)) {
224
+ arr[arr.length - 2] = arr[arr.length - 2] + arr[arr.length - 1];
225
+ arr.splice(arr.length - 1, 1);
226
+ }
227
+ }
228
+
229
+ return arr
230
+ };
231
+
232
+ //chop a string into pronounced syllables
233
+
234
+ const all_spaces = / +/g;
235
+ const ends_with_vowel = /[aeiouy]$/;
236
+ const starts_with_consonant_vowel = /^[^aeiouy]h?[aeiouy]/;
237
+ const starts_with_e_then_specials = /^e[sm]/;
238
+ const starts_with_e = /^e/;
239
+ const ends_with_noisy_vowel_combos = /(eo|eu|ia|oa|ua|ui)$/i;
240
+ const aiouy = /[aiouy]/;
241
+ const ends_with_ee = /ee$/;
242
+ // const whitespace_dash = /\s\-/
243
+
244
+ //method is nested because it's called recursively
245
+ const doWord = function (w) {
246
+ let all = [];
247
+ let chars = w.split('');
248
+ let before = '';
249
+ let after = '';
250
+ let current = '';
251
+ for (let i = 0; i < chars.length; i++) {
252
+ before = chars.slice(0, i).join('');
253
+ current = chars[i];
254
+ after = chars.slice(i + 1, chars.length).join('');
255
+ let candidate = before + chars[i];
256
+
257
+ //it's a consonant that comes after a vowel
258
+ if (before.match(ends_with_vowel) && !current.match(ends_with_vowel)) {
259
+ if (after.match(starts_with_e_then_specials)) {
260
+ candidate += 'e';
261
+ after = after.replace(starts_with_e, '');
262
+ }
263
+ all.push(candidate);
264
+ return all.concat(doWord(after))
265
+ }
266
+
267
+ //unblended vowels ('noisy' vowel combinations)
268
+ if (candidate.match(ends_with_noisy_vowel_combos)) {
269
+ //'io' is noisy, not in 'ion'
270
+ all.push(before);
271
+ all.push(current);
272
+ return all.concat(doWord(after)) //recursion
273
+ }
274
+
275
+ // if candidate is followed by a CV, assume consecutive open syllables
276
+ if (candidate.match(ends_with_vowel) && after.match(starts_with_consonant_vowel)) {
277
+ all.push(candidate);
278
+ return all.concat(doWord(after))
279
+ }
280
+ }
281
+ //if still running, end last syllable
282
+ if (w.match(aiouy) || w.match(ends_with_ee)) {
283
+ //allow silent trailing e
284
+ all.push(w);
285
+ } else if (w) {
286
+ let last = all.length - 1;
287
+ if (last < 0) {
288
+ last = 0;
289
+ }
290
+ all[last] = (all[last] || '') + w; //append it to the last one
291
+ }
292
+ return all
293
+ };
294
+
295
+ let syllables$1 = function (str) {
296
+ let all = [];
297
+ if (!str) {
298
+ return all
299
+ }
300
+ str = str.replace(/[.,?]/g, '');
301
+ str.split(all_spaces).map(s => {
302
+ all = all.concat(doWord(s));
303
+ });
304
+
305
+ // str.split(whitespace_dash).forEach(doWord)
306
+ all = postprocess(all);
307
+
308
+ //for words like 'tree' and 'free'
309
+ if (all.length === 0) {
310
+ all = [str];
311
+ }
312
+ //filter blanks
313
+ all = all.filter(s => s);
314
+
315
+ return all
316
+ };
317
+
318
+ // const defaultObj = { normal: true, text: true, terms: false }
319
+
320
+ const syllables = function (view) {
321
+ view.docs.forEach(terms => {
322
+ terms.forEach(term => {
323
+ term.syllables = syllables$1(term.normal || term.text);
324
+ });
325
+ });
326
+ };
327
+
328
+ var compute = {
329
+ soundsLike,
330
+ syllables
331
+ };
332
+
333
+ const api = function (View) {
334
+ /** */
335
+ View.prototype.syllables = function () {
336
+ this.compute('syllables');
337
+ let all = [];
338
+ this.docs.forEach(terms => {
339
+ let some = [];
340
+ terms.forEach(term => {
341
+ some = some.concat(term.syllables);
342
+ });
343
+ if (some.length > 0) {
344
+ all.push(some);
345
+ }
346
+ });
347
+ return all
348
+ };
349
+ /** */
350
+ View.prototype.soundsLike = function () {
351
+ this.compute('soundsLike');
352
+ let all = [];
353
+ this.docs.forEach(terms => {
354
+ let some = [];
355
+ terms.forEach(term => {
356
+ some = some.concat(term.soundsLike);
357
+ });
358
+ if (some.length > 0) {
359
+ all.push(some);
360
+ }
361
+ });
362
+ return all
363
+ };
364
+ };
365
+
366
+ var plugin = {
367
+ api,
368
+ compute
369
+ };
370
+
371
+ return plugin;
372
+
373
+ }));
@@ -0,0 +1 @@
1
+ var e,t;e=this,t=function(){const e=e=>e.replace(/([^c])\1/g,"$1"),t=e=>e.match(/^(kn|gn|pn|ae|wr)/)?e.substr(1,e.length-1):e,a=e=>e.replace(/mb$/,"m"),l=e=>(e=(e=(e=e.replace(/([^s]|^)(c)(h)/g,"$1x$3").trim()).replace(/cia/g,"xia")).replace(/c([iey])/g,"s$1")).replace(/c/g,"k"),c=e=>(e=e.replace(/d(ge|gy|gi)/g,"j$1")).replace(/d/g,"t"),i=e=>(e=e.replace(/gh(^$|[^aeiou])/g,"h$1")).replace(/g(n|ned)$/g,"$1"),n=e=>(e=(e=(e=e.replace(/gh/g,"f")).replace(/([^g]|^)(g)([iey])/g,"$1j$3")).replace(/gg/g,"g")).replace(/g/g,"k"),o=e=>e.replace(/([aeiou])h([^aeiou]|$)/g,"$1$2"),h=e=>e.replace(/ck/g,"k"),r=e=>e.replace(/ph/g,"f"),g=e=>e.replace(/q/g,"k"),u=e=>e.replace(/s(h|io|ia)/g,"x$1"),p=e=>e=e.replace(/t(ia[^n]|io)/g,"x$1"),s=e=>e.replace(/tch/g,"ch"),f=e=>e.replace(/v/g,"f"),m=e=>e.replace(/^wh/,"w"),y=e=>e.replace(/w([^aeiou]|$)/g,"$1"),$=e=>(e=e.replace(/^x/,"s")).replace(/x/g,"ks"),d=e=>e.replace(/y([^aeiou]|$)/g,"$1"),k=e=>e.replace(/z/,"s"),b=e=>e,x=/^(eu)/i,E=/^[^aeiou]e([^d]|$)/,j=/^([^aeiouy])[aeiouy]\1[aeiouy]/,w=/^[^aeiouy]([aeiouy])[^aeiouy]\1/,L=/^([tg][aeiouy]){2}/,v=/^[^aeiouy]+$/,T=/[aeiouy]$/,q=/^[^aeiouy]h?[aeiouy]/,z=[/^[^aeiou]?ion/,/^[^aeiou]?ised/,/^[^aeiou]?iled/,/[aeiou]n[gt]$/,/\wa[gt]e$/],S=/ +/g,A=/[aeiouy]$/,B=/^[^aeiouy]h?[aeiouy]/,C=/^e[sm]/,D=/^e/,F=/(eo|eu|ia|oa|ua|ui)$/i,G=/[aiouy]/,H=/ee$/,I=function(e){let t=[],a=e.split(""),l="",c="",i="";for(let e=0;e<a.length;e++){l=a.slice(0,e).join(""),i=a[e],c=a.slice(e+1,a.length).join("");let n=l+a[e];if(l.match(A)&&!i.match(A))return c.match(C)&&(n+="e",c=c.replace(D,"")),t.push(n),t.concat(I(c));if(n.match(F))return t.push(l),t.push(i),t.concat(I(c));if(n.match(A)&&c.match(B))return t.push(n),t.concat(I(c))}if(e.match(G)||e.match(H))t.push(e);else if(e){let a=t.length-1;a<0&&(a=0),t[a]=(t[a]||"")+e}return t};let J=function(e){let t=[];return e?((e=e.replace(/[.,?]/g,"")).split(S).map(e=>{t=t.concat(I(e))}),t=function(e){let t=(e=(e=e.map((function(e){return e.trim()}))).filter((function(e){return""!==e}))).length;if(t>1){let a=e[t-2]+e[t-1];for(let l=0;l<z.length;l++)a.match(z[l])&&(e[t-2]=e[t-2]+e[t-1],e.pop())}if(e.length>1){let t=(1===e[0].length||e[0].match(q))&&e[0].match(T),a=e[1].match(E);if(t&&a){let t=e[0]+e[1];t.match(j)||t.match(w)||t.match(L)||(e[0]=e[0]+e[1],e.splice(1,1))}}if(e.length>1){let t=e[e.length-2].match(q)&&e[e.length-2].match(T),a=e[e.length-1].match(E)&&z.every(t=>!e[e.length-1].match(t));if(t&&a){let t=e[e.length-2]+e[e.length-1];t.match(j)||t.match(w)||t.match(L)||(e[e.length-2]=e[e.length-2]+e[e.length-1],e.splice(e.length-1,1))}}if(e.length>1){let t=e[0]+e[1];t.match(x)&&(e[0]=t,e.splice(1,1))}return e.length>1&&e[e.length-1].match(v)&&(e[e.length-2]=e[e.length-2]+e[e.length-1],e.splice(e.length-1,1)),e}(t),0===t.length&&(t=[e]),t=t.filter(e=>e),t):t};return{api:function(e){e.prototype.syllables=function(){this.compute("syllables");let e=[];return this.docs.forEach(t=>{let a=[];t.forEach(e=>{a=a.concat(e.syllables)}),a.length>0&&e.push(a)}),e},e.prototype.soundsLike=function(){this.compute("soundsLike");let e=[];return this.docs.forEach(t=>{let a=[];t.forEach(e=>{a=a.concat(e.soundsLike)}),a.length>0&&e.push(a)}),e}},compute:{soundsLike:function(x){x.docs.forEach(x=>{x.forEach(x=>{var E;x.soundsLike=(E=x.normal||x.text,E=e(E),E=t(E),E=a(E),E=h(E),E=l(E),E=c(E),E=i(E),E=n(E),E=o(E),E=r(E),E=g(E),E=u(E),E=$(E),E=p(E),E=s(E),E=f(E),E=m(E),E=y(E),E=d(E),E=k(E),(E=b(E)).trim())})})},syllables:function(e){e.docs.forEach(e=>{e.forEach(e=>{e.syllables=J(e.normal||e.text)})})}}}},"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).compromiseStream=t();
@@ -0,0 +1 @@
1
+ const e=e=>e.replace(/([^c])\1/g,"$1"),t=e=>e.match(/^(kn|gn|pn|ae|wr)/)?e.substr(1,e.length-1):e,a=e=>e.replace(/mb$/,"m"),c=e=>(e=(e=(e=e.replace(/([^s]|^)(c)(h)/g,"$1x$3").trim()).replace(/cia/g,"xia")).replace(/c([iey])/g,"s$1")).replace(/c/g,"k"),l=e=>(e=e.replace(/d(ge|gy|gi)/g,"j$1")).replace(/d/g,"t"),i=e=>(e=e.replace(/gh(^$|[^aeiou])/g,"h$1")).replace(/g(n|ned)$/g,"$1"),h=e=>(e=(e=(e=e.replace(/gh/g,"f")).replace(/([^g]|^)(g)([iey])/g,"$1j$3")).replace(/gg/g,"g")).replace(/g/g,"k"),n=e=>e.replace(/([aeiou])h([^aeiou]|$)/g,"$1$2"),o=e=>e.replace(/ck/g,"k"),r=e=>e.replace(/ph/g,"f"),g=e=>e.replace(/q/g,"k"),u=e=>e.replace(/s(h|io|ia)/g,"x$1"),p=e=>e=e.replace(/t(ia[^n]|io)/g,"x$1"),s=e=>e.replace(/tch/g,"ch"),m=e=>e.replace(/v/g,"f"),f=e=>e.replace(/^wh/,"w"),$=e=>e.replace(/w([^aeiou]|$)/g,"$1"),y=e=>(e=e.replace(/^x/,"s")).replace(/x/g,"ks"),d=e=>e.replace(/y([^aeiou]|$)/g,"$1"),k=e=>e.replace(/z/,"s"),x=e=>e,E=/^(eu)/i,b=/^[^aeiou]e([^d]|$)/,w=/^([^aeiouy])[aeiouy]\1[aeiouy]/,L=/^[^aeiouy]([aeiouy])[^aeiouy]\1/,j=/^([tg][aeiouy]){2}/,v=/^[^aeiouy]+$/,q=/[aeiouy]$/,z=/^[^aeiouy]h?[aeiouy]/,A=[/^[^aeiou]?ion/,/^[^aeiou]?ised/,/^[^aeiou]?iled/,/[aeiou]n[gt]$/,/\wa[gt]e$/],B=/ +/g,C=/[aeiouy]$/,D=/^[^aeiouy]h?[aeiouy]/,F=/^e[sm]/,G=/^e/,H=/(eo|eu|ia|oa|ua|ui)$/i,I=/[aiouy]/,J=/ee$/,K=function(e){let t=[],a=e.split(""),c="",l="",i="";for(let e=0;e<a.length;e++){c=a.slice(0,e).join(""),i=a[e],l=a.slice(e+1,a.length).join("");let h=c+a[e];if(c.match(C)&&!i.match(C))return l.match(F)&&(h+="e",l=l.replace(G,"")),t.push(h),t.concat(K(l));if(h.match(H))return t.push(c),t.push(i),t.concat(K(l));if(h.match(C)&&l.match(D))return t.push(h),t.concat(K(l))}if(e.match(I)||e.match(J))t.push(e);else if(e){let a=t.length-1;a<0&&(a=0),t[a]=(t[a]||"")+e}return t};let M=function(e){let t=[];return e?((e=e.replace(/[.,?]/g,"")).split(B).map(e=>{t=t.concat(K(e))}),t=function(e){let t=(e=(e=e.map((function(e){return e.trim()}))).filter((function(e){return""!==e}))).length;if(t>1){let a=e[t-2]+e[t-1];for(let c=0;c<A.length;c++)a.match(A[c])&&(e[t-2]=e[t-2]+e[t-1],e.pop())}if(e.length>1){let t=(1===e[0].length||e[0].match(z))&&e[0].match(q),a=e[1].match(b);if(t&&a){let t=e[0]+e[1];t.match(w)||t.match(L)||t.match(j)||(e[0]=e[0]+e[1],e.splice(1,1))}}if(e.length>1){let t=e[e.length-2].match(z)&&e[e.length-2].match(q),a=e[e.length-1].match(b)&&A.every(t=>!e[e.length-1].match(t));if(t&&a){let t=e[e.length-2]+e[e.length-1];t.match(w)||t.match(L)||t.match(j)||(e[e.length-2]=e[e.length-2]+e[e.length-1],e.splice(e.length-1,1))}}if(e.length>1){let t=e[0]+e[1];t.match(E)&&(e[0]=t,e.splice(1,1))}return e.length>1&&e[e.length-1].match(v)&&(e[e.length-2]=e[e.length-2]+e[e.length-1],e.splice(e.length-1,1)),e}(t),0===t.length&&(t=[e]),t=t.filter(e=>e),t):t};var N={api:function(e){e.prototype.syllables=function(){this.compute("syllables");let e=[];return this.docs.forEach(t=>{let a=[];t.forEach(e=>{a=a.concat(e.syllables)}),a.length>0&&e.push(a)}),e},e.prototype.soundsLike=function(){this.compute("soundsLike");let e=[];return this.docs.forEach(t=>{let a=[];t.forEach(e=>{a=a.concat(e.soundsLike)}),a.length>0&&e.push(a)}),e}},compute:{soundsLike:function(E){E.docs.forEach(E=>{E.forEach(E=>{var b;E.soundsLike=(b=E.normal||E.text,b=e(b),b=t(b),b=a(b),b=o(b),b=c(b),b=l(b),b=i(b),b=h(b),b=n(b),b=r(b),b=g(b),b=u(b),b=y(b),b=p(b),b=s(b),b=m(b),b=f(b),b=$(b),b=d(b),b=k(b),(b=x(b)).trim())})})},syllables:function(e){e.docs.forEach(e=>{e.forEach(e=>{e.syllables=M(e.normal||e.text)})})}}};export{N as default};
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "compromise-speech",
3
+ "description": "plugin for nlp-compromise",
4
+ "version": "0.0.1",
5
+ "author": "Spencer Kelly <spencermountain@gmail.com> (http://spencermounta.in)",
6
+ "main": "./src/plugin.js",
7
+ "unpkg": "./builds/compromise-speech.min.js",
8
+ "module": "./builds/compromise-speech.mjs",
9
+ "type": "module",
10
+ "types": "types/index.d.ts",
11
+ "sideEffects": false,
12
+ "exports": {
13
+ ".": {
14
+ "import": "./src/plugin.js",
15
+ "require": "./builds/compromise-speech.cjs"
16
+ }
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git://github.com/spencermountain/compromise.git"
21
+ },
22
+ "homepage": "https://github.com/spencermountain/compromise/tree/master/plugins/speech",
23
+ "scripts": {
24
+ "test": "tape \"./tests/**/*.test.js\" | tap-dancer --color always",
25
+ "testb": "TESTENV=prod tape \"./tests/**/*.test.js\" | tap-dancer --color always",
26
+ "watch": "amble ./scratch.js",
27
+ "build": "rollup -c --silent"
28
+ },
29
+ "eslintIgnore": [
30
+ "builds/*.js"
31
+ ],
32
+ "peerDependencies": {
33
+ "compromise": ">=14.0.0"
34
+ },
35
+ "dependencies": {},
36
+ "devDependencies": {},
37
+ "license": "MIT"
38
+ }
@@ -0,0 +1,22 @@
1
+ import { terser } from 'rollup-plugin-terser'
2
+ import sizeCheck from 'rollup-plugin-filesize-check'
3
+
4
+ const opts = { keep_classnames: true, module: true }
5
+
6
+ export default [
7
+ {
8
+ input: 'src/plugin.js',
9
+ output: [{ file: 'builds/compromise-stream.cjs', format: 'umd', name: 'compromiseStream' }],
10
+ plugins: [sizeCheck({ expect: 11, warn: 15 })],
11
+ },
12
+ {
13
+ input: 'src/plugin.js',
14
+ output: [{ file: 'builds/compromise-stream.min.js', format: 'umd', name: 'compromiseStream' }],
15
+ plugins: [terser(opts), sizeCheck({ expect: 4, warn: 15 })],
16
+ },
17
+ {
18
+ input: 'src/plugin.js',
19
+ output: [{ file: 'builds/compromise-stream.mjs', format: 'esm' }],
20
+ plugins: [terser(opts), sizeCheck({ expect: 4, warn: 15 })],
21
+ }
22
+ ]
package/scratch.js ADDED
@@ -0,0 +1,17 @@
1
+ /* eslint-disable no-console, no-unused-vars */
2
+ import nlp from '../../src/three.js'
3
+
4
+ import speechPlugin from './src/plugin.js'
5
+ nlp.plugin(speechPlugin)
6
+ // nlp.verbose(true)
7
+ // nlp.verbose('date')
8
+
9
+ let txt = ''
10
+ txt = 'seventh millenium. white collar'
11
+
12
+ // let doc = nlp(txt).compute(['soundsLike', 'syllables'])
13
+ // console.dir(doc.json()[0], { depth: 5 })
14
+
15
+ let doc = nlp('calgary')
16
+ doc.compute('soundsLike')
17
+ console.log(JSON.stringify(doc.json()[0], null, 2))
package/src/api.js ADDED
@@ -0,0 +1,33 @@
1
+ const api = function (View) {
2
+ /** */
3
+ View.prototype.syllables = function () {
4
+ this.compute('syllables')
5
+ let all = []
6
+ this.docs.forEach(terms => {
7
+ let some = []
8
+ terms.forEach(term => {
9
+ some = some.concat(term.syllables)
10
+ })
11
+ if (some.length > 0) {
12
+ all.push(some)
13
+ }
14
+ })
15
+ return all
16
+ }
17
+ /** */
18
+ View.prototype.soundsLike = function () {
19
+ this.compute('soundsLike')
20
+ let all = []
21
+ this.docs.forEach(terms => {
22
+ let some = []
23
+ terms.forEach(term => {
24
+ some = some.concat(term.soundsLike)
25
+ })
26
+ if (some.length > 0) {
27
+ all.push(some)
28
+ }
29
+ })
30
+ return all
31
+ }
32
+ }
33
+ export default api
@@ -0,0 +1,7 @@
1
+ import soundsLike from './soundsLike/index.js'
2
+ import syllables from './syllables/index.js'
3
+
4
+ export default {
5
+ soundsLike,
6
+ syllables
7
+ }
@@ -0,0 +1,11 @@
1
+ import metaphone from './metaphone.js'
2
+
3
+ const soundsLike = function (view) {
4
+ view.docs.forEach(terms => {
5
+ terms.forEach(term => {
6
+ term.soundsLike = metaphone(term.normal || term.text)
7
+ })
8
+ })
9
+ }
10
+
11
+ export default soundsLike
@@ -0,0 +1,32 @@
1
+ //a js version of the metaphone (#1) algorithm
2
+ //adapted from the work of Chris Umbel
3
+ // https://github.com/NaturalNode/natural/blob/master/lib/natural/phonetics/metaphone.js
4
+
5
+ import m from './transformations.js'
6
+
7
+ const metaphone = function (s) {
8
+ s = m.dedup(s)
9
+ s = m.dropInitialLetters(s)
10
+ s = m.dropBafterMAtEnd(s)
11
+ s = m.changeCK(s)
12
+ s = m.cchange(s)
13
+ s = m.dchange(s)
14
+ s = m.dropG(s)
15
+ s = m.changeG(s)
16
+ s = m.dropH(s)
17
+ s = m.changePH(s)
18
+ s = m.changeQ(s)
19
+ s = m.changeS(s)
20
+ s = m.changeX(s)
21
+ s = m.changeT(s)
22
+ s = m.dropT(s)
23
+ s = m.changeV(s)
24
+ s = m.changeWH(s)
25
+ s = m.dropW(s)
26
+ s = m.dropY(s)
27
+ s = m.changeZ(s)
28
+ s = m.dropVowels(s)
29
+ return s.trim()
30
+ }
31
+
32
+ export default metaphone
@@ -0,0 +1,83 @@
1
+ //individual manipulations of the text
2
+ const transformations = {
3
+ dedup: (s) => {
4
+ return s.replace(/([^c])\1/g, '$1')
5
+ },
6
+ dropInitialLetters: (s) => {
7
+ if (s.match(/^(kn|gn|pn|ae|wr)/)) {
8
+ return s.substr(1, s.length - 1)
9
+ }
10
+ return s
11
+ },
12
+ dropBafterMAtEnd: (s) => {
13
+ return s.replace(/mb$/, 'm')
14
+ },
15
+ cchange: (s) => {
16
+ s = s.replace(/([^s]|^)(c)(h)/g, '$1x$3').trim()
17
+ s = s.replace(/cia/g, 'xia')
18
+ s = s.replace(/c([iey])/g, 's$1')
19
+ return s.replace(/c/g, 'k')
20
+ },
21
+ dchange: (s) => {
22
+ s = s.replace(/d(ge|gy|gi)/g, 'j$1')
23
+ return s.replace(/d/g, 't')
24
+ },
25
+ dropG: (s) => {
26
+ // Drop 'G' if followed by 'H' and 'H' is not at the end or before a vowel.
27
+ s = s.replace(/gh(^$|[^aeiou])/g, 'h$1')//eslint-disable-line
28
+ // Drop 'G' if followed by 'N' or 'NED' and is at the end.
29
+ return s.replace(/g(n|ned)$/g, '$1')
30
+ },
31
+ changeG: (s) => {
32
+ s = s.replace(/gh/g, 'f')
33
+ s = s.replace(/([^g]|^)(g)([iey])/g, '$1j$3')
34
+ s = s.replace(/gg/g, 'g')
35
+ return s.replace(/g/g, 'k')
36
+ },
37
+ dropH: (s) => {
38
+ return s.replace(/([aeiou])h([^aeiou]|$)/g, '$1$2')
39
+ },
40
+ changeCK: (s) => {
41
+ return s.replace(/ck/g, 'k')
42
+ },
43
+ changePH: (s) => {
44
+ return s.replace(/ph/g, 'f')
45
+ },
46
+ changeQ: (s) => {
47
+ return s.replace(/q/g, 'k')
48
+ },
49
+ changeS: (s) => {
50
+ return s.replace(/s(h|io|ia)/g, 'x$1')
51
+ },
52
+ changeT: (s) => {
53
+ s = s.replace(/t(ia[^n]|io)/g, 'x$1')
54
+ // return s.replace(/th/, '0')
55
+ return s
56
+ },
57
+ dropT: (s) => {
58
+ return s.replace(/tch/g, 'ch')
59
+ },
60
+ changeV: (s) => {
61
+ return s.replace(/v/g, 'f')
62
+ },
63
+ changeWH: (s) => {
64
+ return s.replace(/^wh/, 'w')
65
+ },
66
+ dropW: (s) => {
67
+ return s.replace(/w([^aeiou]|$)/g, '$1')
68
+ },
69
+ changeX: (s) => {
70
+ s = s.replace(/^x/, 's')
71
+ return s.replace(/x/g, 'ks')
72
+ },
73
+ dropY: (s) => {
74
+ return s.replace(/y([^aeiou]|$)/g, '$1')
75
+ },
76
+ changeZ: (s) => {
77
+ return s.replace(/z/, 's')
78
+ },
79
+ dropVowels: (s) => {
80
+ return s //.charAt(0) + s.substr(1, s.length).replace(/[aeiou]/g, '');
81
+ },
82
+ }
83
+ export default transformations
@@ -0,0 +1,13 @@
1
+ import getSyllables from './syllables.js'
2
+
3
+ // const defaultObj = { normal: true, text: true, terms: false }
4
+
5
+ const syllables = function (view) {
6
+ view.docs.forEach(terms => {
7
+ terms.forEach(term => {
8
+ term.syllables = getSyllables(term.normal || term.text)
9
+ })
10
+ })
11
+ }
12
+
13
+ export default syllables